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