2006-04-06 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / System / System.IO.Ports / SerialPort.cs
1 /* -*- Mode: Csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 #if NET_2_0
4
5 using System;
6 using System.ComponentModel;
7 using System.Text;
8 using System.Runtime.InteropServices;
9
10 namespace System.IO.Ports
11 {
12         public class SerialPort : Component
13         {
14                 public const int InfiniteTimeout = -1;
15                 const int DefaultReadBufferSize = 4096;
16                 const int DefaultWriteBufferSize = 2048;
17                 const int DefaultBaudRate = 9600;
18                 const int DefaultDataBits = 8;
19                 const Parity DefaultParity = Parity.None;
20                 const StopBits DefaultStopBits = StopBits.One;
21
22                 bool isOpen;
23                 int baudRate;
24                 Parity parity;
25                 StopBits stopBits;
26                 Handshake handshake = Handshake.None;
27                 int dataBits;
28                 bool breakState = false;
29                 bool dtr_enable = false;
30                 bool rts_enable = false;
31                 SerialPortStream stream;
32                 Encoding encoding = Encoding.ASCII;
33                 string newLine = Environment.NewLine;
34                 string portName;
35                 int readTimeout = InfiniteTimeout;
36                 int writeTimeout = InfiniteTimeout;
37                 int readBufferSize = DefaultReadBufferSize;
38                 int writeBufferSize = DefaultWriteBufferSize;
39                 object error_received = new object ();
40                 object data_received = new object ();
41                 object pin_changed = new object ();
42                 
43                 static string default_port_name = "ttyS0";
44
45                 public SerialPort () : 
46                         this (GetDefaultPortName (), DefaultBaudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
47                 {
48                 }
49
50                 /*
51                   IContainer is in 2.0?
52                   public SerialPort (IContainer container) {
53                   }
54                 */
55
56                 public SerialPort (string portName) :
57                         this (portName, DefaultBaudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
58                 {
59                 }
60
61                 public SerialPort (string portName, int baudRate) :
62                         this (portName, baudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
63                 {
64                 }
65
66                 public SerialPort (string portName, int baudRate, Parity parity) :
67                         this (portName, baudRate, parity, DefaultDataBits, DefaultStopBits)
68                 {
69                 }
70
71                 public SerialPort (string portName, int baudRate, Parity parity, int dataBits) :
72                         this (portName, baudRate, parity, dataBits, DefaultStopBits)
73                 {
74                 }
75
76                 public SerialPort (string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) 
77                 {
78                         this.portName = portName;
79                         this.baudRate = baudRate;
80                         this.parity = parity;
81                         this.dataBits = dataBits;
82                         this.stopBits = stopBits;
83                 }
84
85                 static string GetDefaultPortName ()
86                 {
87                         return default_port_name;
88                 }
89
90                 public Stream BaseStream {
91                         get {
92                                 if (!isOpen)
93                                         throw new InvalidOperationException ();
94
95                                 return stream;
96                         }
97                 }
98
99                 public int BaudRate {
100                         get {
101                                 return baudRate;
102                         }
103                         set {
104                                 if (value <= 0)
105                                         throw new ArgumentOutOfRangeException ("value");
106                                 
107                                 baudRate = value;
108                                 if (isOpen)
109                                         stream.BaudRate = value;
110                         }
111                 }
112
113                 public bool BreakState {
114                         get {
115                                 return breakState;
116                         }
117                         set {
118                                 CheckOpen ();
119                                 if (value == breakState)
120                                         return; // Do nothing.
121
122                                 breakState = value;
123                                 // Update the state
124                         }
125                 }
126
127                 public int BytesToRead {
128                         get {
129                                 CheckOpen ();
130                                 return stream.BytesToRead;
131                         }
132                 }
133
134                 public int BytesToWrite {
135                         get {
136                                 CheckOpen ();
137                                 return stream.BytesToWrite;
138                         }
139                 }
140
141                 public bool CDHolding {
142                         get {
143                                 CheckOpen ();
144                                 return stream.GetSignal (SerialSignal.Cd);
145                         }
146                 }
147
148                 public bool CtsHolding {
149                         get {
150                                 CheckOpen ();
151                                 return stream.GetSignal (SerialSignal.Cts);
152                         }
153                 }
154
155                 public int DataBits {
156                         get {
157                                 return dataBits;
158                         }
159                         set {
160                                 if (value < 5 || value > 8)
161                                         throw new ArgumentOutOfRangeException ("value");
162
163                                 dataBits = value;
164                                 if (isOpen)
165                                         stream.DataBits = value;
166                         }
167                 }
168
169                 public bool DiscardNull {
170                         get {
171                                 CheckOpen ();
172                                 throw new NotImplementedException ();
173                         }
174                         set {
175                                 CheckOpen ();
176                                 throw new NotImplementedException ();
177                         }
178                 }
179
180                 public bool DsrHolding {
181                         get {
182                                 CheckOpen ();
183                                 return stream.GetSignal (SerialSignal.Dsr);
184                         }
185                 }
186
187                 public bool DtrEnable {
188                         get {
189                                 return dtr_enable;
190                         }
191                         set {
192                                 if (value == dtr_enable)
193                                         return;
194                                 if (isOpen)
195                                         stream.SetSignal (SerialSignal.Dtr, value);
196                                 
197                                 dtr_enable = value;
198                         }
199                 }
200
201                 public Encoding Encoding {
202                         get {
203                                 return encoding;
204                         }
205                         set {
206                                 if (value == null)
207                                         throw new ArgumentNullException ("value");
208
209                                 encoding = value;
210                         }
211                 }
212
213                 public Handshake Handshake {
214                         get {
215                                 return handshake;
216                         }
217                         set {
218                                 if (value < Handshake.None || value > Handshake.RequestToSendXOnXOff)
219                                         throw new ArgumentOutOfRangeException ("value");
220
221                                 handshake = value;
222                                 if (isOpen)
223                                         stream.Handshake = value;
224                         }
225                 }
226
227                 public bool IsOpen {
228                         get {
229                                 return isOpen;
230                         }
231                 }
232
233                 public string NewLine {
234                         get {
235                                 return newLine;
236                         }
237                         set {
238                                 if (value == null)
239                                         throw new ArgumentNullException ("value");
240                                 
241                                 newLine = value;
242                         }
243                 }
244
245                 public Parity Parity {
246                         get {
247                                 return parity;
248                         }
249                         set {
250                                 if (value < Parity.None || value > Parity.Space)
251                                         throw new ArgumentOutOfRangeException ("value");
252
253                                 parity = value;
254                                 if (isOpen)
255                                         stream.Parity = value;
256                         }
257                 }
258
259                 public byte ParityReplace {
260                         get {
261                                 throw new NotImplementedException ();
262                         }
263                         set {
264                                 throw new NotImplementedException ();
265                         }
266                 }
267
268                 public string PortName {
269                         get {
270                                 return portName;
271                         }
272                         set {
273                                 if (isOpen)
274                                         throw new InvalidOperationException ("Port name cannot be set while port is open.");
275                                 if (value == null)
276                                         throw new ArgumentNullException ("value");
277                                 if (value.Length == 0 || value.StartsWith ("\\\\"))
278                                         throw new ArgumentException ("value");
279
280                                 portName = value;
281                         }
282                 }
283
284                 public int ReadBufferSize {
285                         get {
286                                 return readBufferSize;
287                         }
288                         set {
289                                 if (isOpen)
290                                         throw new InvalidOperationException ();
291                                 if (value <= 0)
292                                         throw new ArgumentOutOfRangeException ("value");
293                                 if (value <= DefaultReadBufferSize)
294                                         return;
295
296                                 readBufferSize = value;
297                         }
298                 }
299
300                 public int ReadTimeout {
301                         get {
302                                 return readTimeout;
303                         }
304                         set {
305                                 if (value <= 0 && value != InfiniteTimeout)
306                                         throw new ArgumentOutOfRangeException ("value");
307
308                                 readTimeout = value;
309                                 if (isOpen)
310                                         stream.ReadTimeout = value;
311                         }
312                 }
313
314                 public int ReceivedBytesThreshold {
315                         get {
316                                 throw new NotImplementedException ();
317                         }
318                         set {
319                                 if (value <= 0)
320                                         throw new ArgumentOutOfRangeException ("value");
321
322                                 throw new NotImplementedException ();
323                         }
324                 }
325
326                 public bool RtsEnable {
327                         get {
328                                 return rts_enable;
329                         }
330                         set {
331                                 if (value == rts_enable)
332                                         return;
333                                 if (isOpen)
334                                         stream.SetSignal (SerialSignal.Rts, value);
335                                 
336                                 rts_enable = value;
337                         }
338                 }
339
340                 public StopBits StopBits {
341                         get {
342                                 return stopBits;
343                         }
344                         set {
345                                 if (value < StopBits.One || value > StopBits.OnePointFive)
346                                         throw new ArgumentOutOfRangeException ("value");
347                                 
348                                 stopBits = value;
349                                 if (isOpen)
350                                         stream.StopBits = value;
351                         }
352                 }
353
354                 public int WriteBufferSize {
355                         get {
356                                 return writeBufferSize;
357                         }
358                         set {
359                                 if (isOpen)
360                                         throw new InvalidOperationException ();
361                                 if (value <= 0)
362                                         throw new ArgumentOutOfRangeException ("value");
363                                 if (value <= DefaultWriteBufferSize)
364                                         return;
365
366                                 writeBufferSize = value;
367                         }
368                 }
369
370                 public int WriteTimeout {
371                         get {
372                                 return writeTimeout;
373                         }
374                         set {
375                                 if (value <= 0 && value != InfiniteTimeout)
376                                         throw new ArgumentOutOfRangeException ("value");
377
378                                 writeTimeout = value;
379                                 if (isOpen)
380                                         stream.WriteTimeout = value;
381                         }
382                 }
383
384                 // methods
385
386                 public void Close ()
387                 {
388                         Dispose (false);
389                 }
390
391                 protected override void Dispose (bool disposing)
392                 {
393                         if (!isOpen)
394                                 return;
395                         
396                         isOpen = false;
397                         stream.Close ();
398                         stream = null;
399                 }
400
401                 public void DiscardInBuffer ()
402                 {
403                         CheckOpen ();
404                         stream.DiscardInputBuffer ();
405                 }
406
407                 public void DiscardOutBuffer ()
408                 {
409                         CheckOpen ();
410                         stream.DiscardOutputBuffer ();
411                 }
412
413                 public static string [] GetPortNames ()
414                 {
415                         int p = (int) Environment.OSVersion.Platform;
416                         if (p == 4 || p == 128) // Are we on Unix?
417                                 return Directory.GetFiles ("/dev/", "ttyS*");
418
419                         throw new NotImplementedException ("Detection of ports is not implemented for this platform yet.");
420                 }
421
422                 public void Open ()
423                 {
424                         if (isOpen)
425                                 throw new InvalidOperationException ("Port is already open");
426                         
427                         stream = new SerialPortStream (portName, baudRate, dataBits, parity, stopBits, dtr_enable,
428                                         rts_enable, handshake, readTimeout, writeTimeout, readBufferSize, writeBufferSize);
429                         isOpen = true;
430                 }
431
432                 public int Read (byte[] buffer, int offset, int count)
433                 {
434                         CheckOpen ();
435                         if (buffer == null)
436                                 throw new ArgumentNullException ("buffer");
437                         if (offset < 0 || offset >= buffer.Length)
438                                 throw new ArgumentOutOfRangeException ("offset");
439                         if (count < 0 || count > buffer.Length)
440                                 throw new ArgumentOutOfRangeException ("count");
441                         if (count > buffer.Length - offset)
442                                 throw new ArgumentException ("count > buffer.Length - offset");
443                         
444                         return stream.Read (buffer, offset, count);
445                 }
446
447                 public int Read (char[] buffer, int offset, int count)
448                 {
449                         CheckOpen ();
450                         if (buffer == null)
451                                 throw new ArgumentNullException ("buffer");
452                         if (offset < 0 || offset >= buffer.Length)
453                                 throw new ArgumentOutOfRangeException ("offset");
454                         if (count < 0 || count > buffer.Length)
455                                 throw new ArgumentOutOfRangeException ("count");
456                         if (count > buffer.Length - offset)
457                                 throw new ArgumentException ("count > buffer.Length - offset");
458
459                         byte [] bytes = encoding.GetBytes (buffer, offset, count);
460                         return stream.Read (bytes, 0, bytes.Length);
461                 }
462
463                 public int ReadByte ()
464                 {
465                         byte [] buff = new byte [1];
466                         if (Read (buff, 0, 1) > 0)
467                                 return buff [0];
468
469                         return -1;
470                 }
471
472                 public int ReadChar ()
473                 {
474                         throw new NotImplementedException ();
475                 }
476
477                 public string ReadExisting ()
478                 {
479                         throw new NotImplementedException ();
480                 }
481
482                 public string ReadLine ()
483                 {
484                         return ReadTo (newLine);
485                 }
486
487                 public string ReadTo (string value)
488                 {
489                         CheckOpen ();
490                         if (value == null)
491                                 throw new ArgumentNullException ("value");
492                         if (value.Length == 0)
493                                 throw new ArgumentException ("value");
494
495                         throw new NotImplementedException ();
496                 }
497
498                 public void Write (string str)
499                 {
500                         CheckOpen ();
501                         if (str == null)
502                                 throw new ArgumentNullException ("str");
503                         
504                         byte [] buffer = encoding.GetBytes (str);
505                         Write (buffer, 0, buffer.Length);
506                 }
507
508                 public void Write (byte [] buffer, int offset, int count)
509                 {
510                         CheckOpen ();
511                         if (buffer == null)
512                                 throw new ArgumentNullException ("buffer");
513                         if (offset < 0 || offset >= buffer.Length)
514                                 throw new ArgumentOutOfRangeException ("offset");
515                         if (count < 0 || count > buffer.Length)
516                                 throw new ArgumentOutOfRangeException ("count");
517                         if (count > buffer.Length - offset)
518                                 throw new ArgumentException ("count > buffer.Length - offset");
519
520                         stream.Write (buffer, offset, count);
521                 }
522
523                 public void Write (char [] buffer, int offset, int count)
524                 {
525                         CheckOpen ();
526                         if (buffer == null)
527                                 throw new ArgumentNullException ("buffer");
528                         if (offset < 0 || offset >= buffer.Length)
529                                 throw new ArgumentOutOfRangeException ("offset");
530                         if (count < 0 || count > buffer.Length)
531                                 throw new ArgumentOutOfRangeException ("count");
532                         if (count > buffer.Length - offset)
533                                 throw new ArgumentException ("count > buffer.Length - offset");
534
535                         byte [] bytes = encoding.GetBytes (buffer, offset, count);
536                         stream.Write (bytes, 0, bytes.Length);
537                 }
538
539                 public void WriteLine (string str)
540                 {
541                         Write (str + newLine);
542                 }
543
544                 void CheckOpen ()
545                 {
546                         if (!isOpen)
547                                 throw new InvalidOperationException ("Specified port is not open.");
548                 }
549
550                 internal void OnErrorReceived (SerialErrorReceivedEventArgs args)
551                 {
552                         SerialErrorReceivedEventHandler handler =
553                                 (SerialErrorReceivedEventHandler) Events [error_received];
554
555                         if (handler != null)
556                                 handler (this, args);
557                 }
558
559                 internal void OnDataReceived (SerialDataReceivedEventArgs args)
560                 {
561                         SerialDataReceivedEventHandler handler =
562                                 (SerialDataReceivedEventHandler) Events [data_received];
563
564                         if (handler != null)
565                                 handler (this, args);
566                 }
567                 
568                 internal void OnDataReceived (SerialPinChangedEventArgs args)
569                 {
570                         SerialPinChangedEventHandler handler =
571                                 (SerialPinChangedEventHandler) Events [pin_changed];
572
573                         if (handler != null)
574                                 handler (this, args);
575                 }
576
577                 // events
578                 public event SerialErrorReceivedEventHandler ErrorReceived {
579                         add { Events.AddHandler (error_received, value); }
580                         remove { Events.RemoveHandler (error_received, value); }
581                 }
582                 
583                 public event SerialPinChangedEventHandler PinChanged {
584                         add { Events.AddHandler (pin_changed, value); }
585                         remove { Events.RemoveHandler (pin_changed, value); }
586                 }
587                 
588                 public event SerialDataReceivedEventHandler DataReceived {
589                         add { Events.AddHandler (data_received, value); }
590                         remove { Events.RemoveHandler (data_received, value); }
591                 }
592         }
593
594         public delegate void SerialDataReceivedEventHandler (object sender, SerialDataReceivedEventArgs e);
595         public delegate void SerialPinChangedEventHandler (object sender, SerialPinChangedEventArgs e);
596         public delegate void SerialErrorReceivedEventHandler (object sender, SerialErrorReceivedEventArgs e);
597
598 }
599
600 #endif