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