New tests.
[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 //
4 // This class has several problems:
5 //
6 //   * No buffering, the specification requires that there is buffering, this
7 //     matters because a few methods expose strings and chars and the reading
8 //     is encoding sensitive.   This means that when we do a read of a byte
9 //     sequence that can not be turned into a full string by the current encoding
10 //     we should keep a buffer with this data, and read from it on the next
11 //     iteration.
12 //
13 //   * Calls to read_serial from the unmanaged C do not check for errors,
14 //     like EINTR, that should be retried
15 //
16 //   * Calls to the encoder that do not consume all bytes because of partial
17 //     reads 
18 //
19
20 #if NET_2_0
21
22 using System;
23 using System.Collections.Generic;
24 using System.ComponentModel;
25 using System.Diagnostics;
26 using System.Text;
27 using System.Runtime.InteropServices;
28 using Microsoft.Win32;
29
30 namespace System.IO.Ports
31 {
32         [MonitoringDescription ("")]
33         public class SerialPort : Component
34         {
35                 public const int InfiniteTimeout = -1;
36                 const int DefaultReadBufferSize = 4096;
37                 const int DefaultWriteBufferSize = 2048;
38                 const int DefaultBaudRate = 9600;
39                 const int DefaultDataBits = 8;
40                 const Parity DefaultParity = Parity.None;
41                 const StopBits DefaultStopBits = StopBits.One;
42
43                 bool is_open;
44                 int baud_rate;
45                 Parity parity;
46                 StopBits stop_bits;
47                 Handshake handshake;
48                 int data_bits;
49                 bool break_state = false;
50                 bool dtr_enable = false;
51                 bool rts_enable = false;
52                 ISerialStream stream;
53                 Encoding encoding = Encoding.ASCII;
54                 string new_line = Environment.NewLine;
55                 string port_name;
56                 int read_timeout = InfiniteTimeout;
57                 int write_timeout = InfiniteTimeout;
58                 int readBufferSize = DefaultReadBufferSize;
59                 int writeBufferSize = DefaultWriteBufferSize;
60                 object error_received = new object ();
61                 object data_received = new object ();
62                 object pin_changed = new object ();
63
64                 public SerialPort () : 
65                         this (GetDefaultPortName (), DefaultBaudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
66                 {
67                 }
68
69                 public SerialPort (IContainer container) : this ()
70                 {
71                         // TODO: What to do here?
72                 }
73
74                 public SerialPort (string portName) :
75                         this (portName, DefaultBaudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
76                 {
77                 }
78
79                 public SerialPort (string portName, int baudRate) :
80                         this (portName, baudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
81                 {
82                 }
83
84                 public SerialPort (string portName, int baudRate, Parity parity) :
85                         this (portName, baudRate, parity, DefaultDataBits, DefaultStopBits)
86                 {
87                 }
88
89                 public SerialPort (string portName, int baudRate, Parity parity, int dataBits) :
90                         this (portName, baudRate, parity, dataBits, DefaultStopBits)
91                 {
92                 }
93
94                 public SerialPort (string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) 
95                 {
96                         port_name = portName;
97                         baud_rate = baudRate;
98                         data_bits = dataBits;
99                         stop_bits = stopBits;
100                         this.parity = parity;
101                 }
102
103                 static string GetDefaultPortName ()
104                 {
105                         string[] ports = GetPortNames();
106                         if (ports.Length > 0) {
107                                 return ports[0];
108                         } else {
109                                 int p = (int)Environment.OSVersion.Platform;
110                                 if (p == 4 || p == 128 || p == 6)
111                                         return "ttyS0"; // Default for Unix
112                                 else
113                                         return "COM1"; // Default for Windows
114                         }
115                 }
116
117                 [Browsable (false)]
118                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
119                 public Stream BaseStream {
120                         get {
121                                 CheckOpen ();
122                                 return (Stream) stream;
123                         }
124                 }
125
126                 [DefaultValueAttribute (DefaultBaudRate)]
127                 [Browsable (true)]
128                 [MonitoringDescription ("")]
129                 public int BaudRate {
130                         get {
131                                 return baud_rate;
132                         }
133                         set {
134                                 if (value <= 0)
135                                         throw new ArgumentOutOfRangeException ("value");
136                                 
137                                 if (is_open)
138                                         stream.SetAttributes (value, parity, data_bits, stop_bits, handshake);
139                                 
140                                 baud_rate = value;
141                         }
142                 }
143
144                 [Browsable (false)]
145                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
146                 public bool BreakState {
147                         get {
148                                 return break_state;
149                         }
150                         set {
151                                 CheckOpen ();
152                                 if (value == break_state)
153                                         return; // Do nothing.
154
155                                 stream.SetBreakState (value);
156                                 break_state = value;
157                         }
158                 }
159
160                 [Browsable (false)]
161                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
162                 public int BytesToRead {
163                         get {
164                                 CheckOpen ();
165                                 return stream.BytesToRead;
166                         }
167                 }
168
169                 [Browsable (false)]
170                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
171                 public int BytesToWrite {
172                         get {
173                                 CheckOpen ();
174                                 return stream.BytesToWrite;
175                         }
176                 }
177
178                 [Browsable (false)]
179                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
180                 public bool CDHolding {
181                         get {
182                                 CheckOpen ();
183                                 return (stream.GetSignals () & SerialSignal.Cd) != 0;
184                         }
185                 }
186
187                 [Browsable (false)]
188                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
189                 public bool CtsHolding {
190                         get {
191                                 CheckOpen ();
192                                 return (stream.GetSignals () & SerialSignal.Cts) != 0;
193                         }
194                 }
195
196                 [DefaultValueAttribute(DefaultDataBits)]
197                 [Browsable (true)]
198                 [MonitoringDescription ("")]
199                 public int DataBits {
200                         get {
201                                 return data_bits;
202                         }
203                         set {
204                                 if (value < 5 || value > 8)
205                                         throw new ArgumentOutOfRangeException ("value");
206
207                                 if (is_open)
208                                         stream.SetAttributes (baud_rate, parity, value, stop_bits, handshake);
209                                 
210                                 data_bits = value;
211                         }
212                 }
213
214                 [MonoTODO("Not implemented")]
215                 [Browsable (true)]
216                 [MonitoringDescription ("")]
217                 [DefaultValue (false)]
218                 public bool DiscardNull {
219                         get {
220                                 throw new NotImplementedException ();
221                         }
222                         set {
223                                 // LAMESPEC: Msdn states that an InvalidOperationException exception
224                                 // is fired if the port is not open, which is *not* happening.
225
226                                 throw new NotImplementedException ();
227                         }
228                 }
229
230                 [Browsable (false)]
231                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
232                 public bool DsrHolding {
233                         get {
234                                 CheckOpen ();
235                                 return (stream.GetSignals () & SerialSignal.Dsr) != 0;
236                         }
237                 }
238
239                 [DefaultValueAttribute(false)]
240                 [Browsable (true)]
241                 [MonitoringDescription ("")]
242                 public bool DtrEnable {
243                         get {
244                                 return dtr_enable;
245                         }
246                         set {
247                                 if (value == dtr_enable)
248                                         return;
249                                 if (is_open)
250                                         stream.SetSignal (SerialSignal.Dtr, value);
251                                 
252                                 dtr_enable = value;
253                         }
254                 }
255
256                 [Browsable (false)]
257                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
258                 [MonitoringDescription ("")]
259                 public Encoding Encoding {
260                         get {
261                                 return encoding;
262                         }
263                         set {
264                                 if (value == null)
265                                         throw new ArgumentNullException ("value");
266
267                                 encoding = value;
268                         }
269                 }
270
271                 [DefaultValueAttribute(Handshake.None)]
272                 [Browsable (true)]
273                 [MonitoringDescription ("")]
274                 public Handshake Handshake {
275                         get {
276                                 return handshake;
277                         }
278                         set {
279                                 if (value < Handshake.None || value > Handshake.RequestToSendXOnXOff)
280                                         throw new ArgumentOutOfRangeException ("value");
281
282                                 if (is_open)
283                                         stream.SetAttributes (baud_rate, parity, data_bits, stop_bits, value);
284                                 
285                                 handshake = value;
286                         }
287                 }
288
289                 [Browsable (false)]
290                 public bool IsOpen {
291                         get {
292                                 return is_open;
293                         }
294                 }
295
296                 [DefaultValueAttribute("\n")]
297                 [Browsable (false)]
298                 [MonitoringDescription ("")]
299                 public string NewLine {
300                         get {
301                                 return new_line;
302                         }
303                         set {
304                                 if (value == null)
305                                         throw new ArgumentNullException ("value");
306                                 if (value.Length == 0)
307                                         throw new ArgumentException ("NewLine cannot be null or empty.", "value");
308                                 
309                                 new_line = value;
310                         }
311                 }
312
313                 [DefaultValueAttribute(DefaultParity)]
314                 [Browsable (true)]
315                 [MonitoringDescription ("")]
316                 public Parity Parity {
317                         get {
318                                 return parity;
319                         }
320                         set {
321                                 if (value < Parity.None || value > Parity.Space)
322                                         throw new ArgumentOutOfRangeException ("value");
323
324                                 if (is_open)
325                                         stream.SetAttributes (baud_rate, value, data_bits, stop_bits, handshake);
326                                 
327                                 parity = value;
328                         }
329                 }
330
331                 [MonoTODO("Not implemented")]
332                 [Browsable (true)]
333                 [MonitoringDescription ("")]
334                 [DefaultValue (63)]
335                 public byte ParityReplace {
336                         get {
337                                 throw new NotImplementedException ();
338                         }
339                         set {
340                                 throw new NotImplementedException ();
341                         }
342                 }
343
344                 
345                 [Browsable (true)]
346                 [MonitoringDescription ("")]
347                 [DefaultValue ("COM1")] // silly Windows-ism. We should ignore it.
348                 public string PortName {
349                         get {
350                                 return port_name;
351                         }
352                         set {
353                                 if (is_open)
354                                         throw new InvalidOperationException ("Port name cannot be set while port is open.");
355                                 if (value == null)
356                                         throw new ArgumentNullException ("value");
357                                 if (value.Length == 0 || value.StartsWith ("\\\\"))
358                                         throw new ArgumentException ("value");
359
360                                 port_name = value;
361                         }
362                 }
363
364                 [DefaultValueAttribute(DefaultReadBufferSize)]
365                 [Browsable (true)]
366                 [MonitoringDescription ("")]
367                 public int ReadBufferSize {
368                         get {
369                                 return readBufferSize;
370                         }
371                         set {
372                                 if (is_open)
373                                         throw new InvalidOperationException ();
374                                 if (value <= 0)
375                                         throw new ArgumentOutOfRangeException ("value");
376                                 if (value <= DefaultReadBufferSize)
377                                         return;
378
379                                 readBufferSize = value;
380                         }
381                 }
382
383                 [DefaultValueAttribute(InfiniteTimeout)]
384                 [Browsable (true)]
385                 [MonitoringDescription ("")]
386                 public int ReadTimeout {
387                         get {
388                                 return read_timeout;
389                         }
390                         set {
391                                 if (value <= 0 && value != InfiniteTimeout)
392                                         throw new ArgumentOutOfRangeException ("value");
393
394                                 if (is_open)
395                                         stream.ReadTimeout = value;
396                                 
397                                 read_timeout = value;
398                         }
399                 }
400
401                 [MonoTODO("Not implemented")]
402                 [DefaultValueAttribute(1)]
403                 [Browsable (true)]
404                 [MonitoringDescription ("")]
405                 public int ReceivedBytesThreshold {
406                         get {
407                                 throw new NotImplementedException ();
408                         }
409                         set {
410                                 if (value <= 0)
411                                         throw new ArgumentOutOfRangeException ("value");
412
413                                 throw new NotImplementedException ();
414                         }
415                 }
416
417                 [DefaultValueAttribute(false)]
418                 [Browsable (true)]
419                 [MonitoringDescription ("")]
420                 public bool RtsEnable {
421                         get {
422                                 return rts_enable;
423                         }
424                         set {
425                                 if (value == rts_enable)
426                                         return;
427                                 if (is_open)
428                                         stream.SetSignal (SerialSignal.Rts, value);
429                                 
430                                 rts_enable = value;
431                         }
432                 }
433
434                 [DefaultValueAttribute(DefaultStopBits)]
435                 [Browsable (true)]
436                 [MonitoringDescription ("")]
437                 public StopBits StopBits {
438                         get {
439                                 return stop_bits;
440                         }
441                         set {
442                                 if (value < StopBits.One || value > StopBits.OnePointFive)
443                                         throw new ArgumentOutOfRangeException ("value");
444                                 
445                                 if (is_open)
446                                         stream.SetAttributes (baud_rate, parity, data_bits, value, handshake);
447                                 
448                                 stop_bits = value;
449                         }
450                 }
451
452                 [DefaultValueAttribute(DefaultWriteBufferSize)]
453                 [Browsable (true)]
454                 [MonitoringDescription ("")]
455                 public int WriteBufferSize {
456                         get {
457                                 return writeBufferSize;
458                         }
459                         set {
460                                 if (is_open)
461                                         throw new InvalidOperationException ();
462                                 if (value <= 0)
463                                         throw new ArgumentOutOfRangeException ("value");
464                                 if (value <= DefaultWriteBufferSize)
465                                         return;
466
467                                 writeBufferSize = value;
468                         }
469                 }
470
471                 [DefaultValueAttribute(InfiniteTimeout)]
472                 [Browsable (true)]
473                 [MonitoringDescription ("")]
474                 public int WriteTimeout {
475                         get {
476                                 return write_timeout;
477                         }
478                         set {
479                                 if (value <= 0 && value != InfiniteTimeout)
480                                         throw new ArgumentOutOfRangeException ("value");
481
482                                 if (is_open)
483                                         stream.WriteTimeout = value;
484                                 
485                                 write_timeout = value;
486                         }
487                 }
488
489                 // methods
490
491                 public void Close ()
492                 {
493                         Dispose (true);
494                 }
495
496                 protected override void Dispose (bool disposing)
497                 {
498                         if (!is_open)
499                                 return;
500                         
501                         is_open = false;
502                         // Do not close the base stream when the finalizer is run; the managed code can still hold a reference to it.
503                         if (disposing)
504                                 stream.Close ();
505                         stream = null;
506                 }
507
508                 public void DiscardInBuffer ()
509                 {
510                         CheckOpen ();
511                         stream.DiscardInBuffer ();
512                 }
513
514                 public void DiscardOutBuffer ()
515                 {
516                         CheckOpen ();
517                         stream.DiscardOutBuffer ();
518                 }
519
520                 public static string [] GetPortNames ()
521                 {
522                         int p = (int) Environment.OSVersion.Platform;
523                         List<string> serial_ports = new List<string>();
524                         
525                         // Are we on Unix?
526                         if (p == 4 || p == 128 || p == 6) {
527                                 string[] ttys = Directory.GetFiles("/dev/", "tty*");
528                                 bool linux_style = false;
529
530                                 //
531                                 // Probe for Linux-styled devices: /dev/ttyS* or /dev/ttyUSB*
532                                 // 
533                                 foreach (string dev in ttys) {
534                                         if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB")){
535                                                 linux_style = true;
536                                                 break;
537                                         }
538                                 }
539
540                                 foreach (string dev in ttys) {
541                                         if (linux_style){
542                                                 if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB"))
543                                                         serial_ports.Add (dev);
544                                         } else {
545                                                 if (dev != "/dev/tty" && dev.StartsWith ("/dev/tty") && !dev.StartsWith ("/dev/ttyC"))
546                                                         serial_ports.Add (dev);
547                                         }
548                                 }
549                         } else {
550                                 using (RegistryKey subkey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DEVICEMAP\\SERIALCOMM"))
551                                 {
552                                         if (subkey != null) {
553                                                 string[] names = subkey.GetValueNames();
554                                                 foreach (string value in names) {
555                                                         string port = subkey.GetValue(value, "").ToString();
556                                                         if (port != "")
557                                                                 serial_ports.Add(port);
558                                                 }
559                                         }
560                                 }
561                         }
562                         return serial_ports.ToArray();
563                 }
564
565                 static bool IsWindows {
566                         get {
567                                 PlatformID id =  Environment.OSVersion.Platform;
568                                 return id == PlatformID.Win32Windows || id == PlatformID.Win32NT; // WinCE not supported
569                         }
570                 }
571
572                 public void Open ()
573                 {
574                         if (is_open)
575                                 throw new InvalidOperationException ("Port is already open");
576                         
577 #if !TARGET_JVM
578                         if (IsWindows) // Use windows kernel32 backend
579                                 stream = new WinSerialStream (port_name, baud_rate, data_bits, parity, stop_bits, dtr_enable,
580                                         rts_enable, handshake, read_timeout, write_timeout, readBufferSize, writeBufferSize);
581                         else // Use standard unix backend
582 #endif
583                                 stream = new SerialPortStream (port_name, baud_rate, data_bits, parity, stop_bits, dtr_enable,
584                                         rts_enable, handshake, read_timeout, write_timeout, readBufferSize, writeBufferSize);
585                         
586                         is_open = true;
587                 }
588
589                 public int Read (byte[] buffer, int offset, int count)
590                 {
591                         CheckOpen ();
592                         if (buffer == null)
593                                 throw new ArgumentNullException ("buffer");
594                         if (offset < 0 || count < 0)
595                                 throw new ArgumentOutOfRangeException ("offset or count less than zero.");
596
597                         if (buffer.Length - offset < count )
598                                 throw new ArgumentException ("offset+count",
599                                                               "The size of the buffer is less than offset + count.");
600                         
601                         return stream.Read (buffer, offset, count);
602                 }
603
604                 [MonoTODO("Read of char buffers is currently broken")]
605                 public int Read (char[] buffer, int offset, int count)
606                 {
607                         CheckOpen ();
608                         if (buffer == null)
609                                 throw new ArgumentNullException ("buffer");
610                         if (offset < 0 || count < 0)
611                                 throw new ArgumentOutOfRangeException ("offset or count less than zero.");
612
613                         if (buffer.Length - offset < count )
614                                 throw new ArgumentException ("offset+count",
615                                                               "The size of the buffer is less than offset + count.");
616
617                         // The following code does not work, we nee to reintroduce a buffer stream somewhere
618                         // for this to work;  In addition the code is broken.
619                         byte [] bytes = encoding.GetBytes (buffer, offset, count);
620                         return stream.Read (bytes, 0, bytes.Length);
621                 }
622
623                 internal int read_byte ()
624                 {
625                         byte [] buff = new byte [1];
626                         if (stream.Read (buff, 0, 1) > 0)
627                                 return buff [0];
628
629                         return -1;
630                 }
631                 
632                 public int ReadByte ()
633                 {
634                         CheckOpen ();
635                         return read_byte ();
636                 }
637
638                 public int ReadChar ()
639                 {
640                         CheckOpen ();
641                         
642                         byte [] buffer = new byte [16];
643                         int i = 0;
644
645                         do {
646                                 int b = read_byte ();
647                                 if (b == -1)
648                                         return -1;
649                                 buffer [i++] = (byte) b;
650                                 char [] c = encoding.GetChars (buffer, 0, 1);
651                                 if (c.Length > 0)
652                                         return (int) c [0];
653                         } while (i < buffer.Length);
654
655                         return -1;
656                 }
657
658                 public string ReadExisting ()
659                 {
660                         CheckOpen ();
661                         
662                         int count = BytesToRead;
663                         byte [] bytes = new byte [count];
664                         
665                         int n = stream.Read (bytes, 0, count);
666                         return new String (encoding.GetChars (bytes, 0, n));
667                 }
668
669                 public string ReadLine ()
670                 {
671                         return ReadTo (new_line);
672                 }
673
674                 public string ReadTo (string value)
675                 {
676                         CheckOpen ();
677                         if (value == null)
678                                 throw new ArgumentNullException ("value");
679                         if (value.Length == 0)
680                                 throw new ArgumentException ("value");
681
682                         // Turn into byte array, so we can compare
683                         byte [] byte_value = encoding.GetBytes (value);
684                         int current = 0;
685                         List<byte> seen = new List<byte> ();
686
687                         while (true){
688                                 int n = read_byte ();
689                                 if (n == -1)
690                                         break;
691                                 seen.Add ((byte)n);
692                                 if (n == byte_value [current]){
693                                         current++;
694                                         if (current == byte_value.Length)
695                                                 return encoding.GetString (seen.ToArray (), 0, seen.Count - byte_value.Length);
696                                 } else {
697                                         current = (byte_value [0] == n) ? 1 : 0;
698                                 }
699                         }
700                         return encoding.GetString (seen.ToArray ());
701                 }
702
703                 public void Write (string str)
704                 {
705                         CheckOpen ();
706                         if (str == null)
707                                 throw new ArgumentNullException ("str");
708                         
709                         byte [] buffer = encoding.GetBytes (str);
710                         Write (buffer, 0, buffer.Length);
711                 }
712
713                 public void Write (byte [] buffer, int offset, int count)
714                 {
715                         CheckOpen ();
716                         if (buffer == null)
717                                 throw new ArgumentNullException ("buffer");
718
719                         if (offset < 0 || count < 0)
720                                 throw new ArgumentOutOfRangeException ();
721
722                         if (buffer.Length - offset < count)
723                                 throw new ArgumentException ("offset+count",
724                                                              "The size of the buffer is less than offset + count.");
725
726                         stream.Write (buffer, offset, count);
727                 }
728
729                 public void Write (char [] buffer, int offset, int count)
730                 {
731                         CheckOpen ();
732                         if (buffer == null)
733                                 throw new ArgumentNullException ("buffer");
734
735                         if (offset < 0 || count < 0)
736                                 throw new ArgumentOutOfRangeException ();
737
738                         if (buffer.Length - offset < count)
739                                 throw new ArgumentException ("offset+count",
740                                                              "The size of the buffer is less than offset + count.");
741
742                         byte [] bytes = encoding.GetBytes (buffer, offset, count);
743                         stream.Write (bytes, 0, bytes.Length);
744                 }
745
746                 public void WriteLine (string str)
747                 {
748                         Write (str + new_line);
749                 }
750
751                 void CheckOpen ()
752                 {
753                         if (!is_open)
754                                 throw new InvalidOperationException ("Specified port is not open.");
755                 }
756
757                 internal void OnErrorReceived (SerialErrorReceivedEventArgs args)
758                 {
759                         SerialErrorReceivedEventHandler handler =
760                                 (SerialErrorReceivedEventHandler) Events [error_received];
761
762                         if (handler != null)
763                                 handler (this, args);
764                 }
765
766                 internal void OnDataReceived (SerialDataReceivedEventArgs args)
767                 {
768                         SerialDataReceivedEventHandler handler =
769                                 (SerialDataReceivedEventHandler) Events [data_received];
770
771                         if (handler != null)
772                                 handler (this, args);
773                 }
774                 
775                 internal void OnDataReceived (SerialPinChangedEventArgs args)
776                 {
777                         SerialPinChangedEventHandler handler =
778                                 (SerialPinChangedEventHandler) Events [pin_changed];
779
780                         if (handler != null)
781                                 handler (this, args);
782                 }
783
784                 // events
785                 [MonitoringDescription ("")]
786                 public event SerialErrorReceivedEventHandler ErrorReceived {
787                         add { Events.AddHandler (error_received, value); }
788                         remove { Events.RemoveHandler (error_received, value); }
789                 }
790                 
791                 [MonitoringDescription ("")]
792                 public event SerialPinChangedEventHandler PinChanged {
793                         add { Events.AddHandler (pin_changed, value); }
794                         remove { Events.RemoveHandler (pin_changed, value); }
795                 }
796                 
797                 [MonitoringDescription ("")]
798                 public event SerialDataReceivedEventHandler DataReceived {
799                         add { Events.AddHandler (data_received, value); }
800                         remove { Events.RemoveHandler (data_received, value); }
801                 }
802         }
803
804         public delegate void SerialDataReceivedEventHandler (object sender, SerialDataReceivedEventArgs e);
805         public delegate void SerialPinChangedEventHandler (object sender, SerialPinChangedEventArgs e);
806         public delegate void SerialErrorReceivedEventHandler (object sender, SerialErrorReceivedEventArgs e);
807
808 }
809
810 #endif