Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.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 //
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                                 foreach (string dev in ttys) {
529                                         if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB"))
530                                                 serial_ports.Add(dev);
531                                 }
532                         } else {
533                                 using (RegistryKey subkey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DEVICEMAP\\SERIALCOMM"))
534                                 {
535                                         if (subkey != null) {
536                                                 string[] names = subkey.GetValueNames();
537                                                 foreach (string value in names) {
538                                                         string port = subkey.GetValue(value, "").ToString();
539                                                         if (port != "")
540                                                                 serial_ports.Add(port);
541                                                 }
542                                         }
543                                 }
544                         }
545                         return serial_ports.ToArray();
546                 }
547
548                 static bool IsWindows {
549                         get {
550                                 PlatformID id =  Environment.OSVersion.Platform;
551                                 return id == PlatformID.Win32Windows || id == PlatformID.Win32NT; // WinCE not supported
552                         }
553                 }
554
555                 public void Open ()
556                 {
557                         if (is_open)
558                                 throw new InvalidOperationException ("Port is already open");
559                         
560 #if !TARGET_JVM
561                         if (IsWindows) // Use windows kernel32 backend
562                                 stream = new WinSerialStream (port_name, baud_rate, data_bits, parity, stop_bits, dtr_enable,
563                                         rts_enable, handshake, read_timeout, write_timeout, readBufferSize, writeBufferSize);
564                         else // Use standard unix backend
565 #endif
566                                 stream = new SerialPortStream (port_name, baud_rate, data_bits, parity, stop_bits, dtr_enable,
567                                         rts_enable, handshake, read_timeout, write_timeout, readBufferSize, writeBufferSize);
568                         
569                         is_open = true;
570                 }
571
572                 public int Read (byte[] buffer, int offset, int count)
573                 {
574                         CheckOpen ();
575                         if (buffer == null)
576                                 throw new ArgumentNullException ("buffer");
577                         if (offset < 0 || count < 0)
578                                 throw new ArgumentOutOfRangeException ("offset or count less than zero.");
579
580                         if (buffer.Length - offset < count )
581                                 throw new ArgumentException ("offset+count",
582                                                               "The size of the buffer is less than offset + count.");
583                         
584                         return stream.Read (buffer, offset, count);
585                 }
586
587                 [MonoTODO("Read of char buffers is currently broken")]
588                 public int Read (char[] buffer, int offset, int count)
589                 {
590                         CheckOpen ();
591                         if (buffer == null)
592                                 throw new ArgumentNullException ("buffer");
593                         if (offset < 0 || count < 0)
594                                 throw new ArgumentOutOfRangeException ("offset or count less than zero.");
595
596                         if (buffer.Length - offset < count )
597                                 throw new ArgumentException ("offset+count",
598                                                               "The size of the buffer is less than offset + count.");
599
600                         // The following code does not work, we nee to reintroduce a buffer stream somewhere
601                         // for this to work;  In addition the code is broken.
602                         byte [] bytes = encoding.GetBytes (buffer, offset, count);
603                         return stream.Read (bytes, 0, bytes.Length);
604                 }
605
606                 internal int read_byte ()
607                 {
608                         byte [] buff = new byte [1];
609                         if (stream.Read (buff, 0, 1) > 0)
610                                 return buff [0];
611
612                         return -1;
613                 }
614                 
615                 public int ReadByte ()
616                 {
617                         CheckOpen ();
618                         return read_byte ();
619                 }
620
621                 public int ReadChar ()
622                 {
623                         CheckOpen ();
624                         
625                         byte [] buffer = new byte [16];
626                         int i = 0;
627
628                         do {
629                                 int b = read_byte ();
630                                 if (b == -1)
631                                         return -1;
632                                 buffer [i++] = (byte) b;
633                                 char [] c = encoding.GetChars (buffer, 0, 1);
634                                 if (c.Length > 0)
635                                         return (int) c [0];
636                         } while (i < buffer.Length);
637
638                         return -1;
639                 }
640
641                 public string ReadExisting ()
642                 {
643                         CheckOpen ();
644                         
645                         int count = BytesToRead;
646                         byte [] bytes = new byte [count];
647                         
648                         int n = stream.Read (bytes, 0, count);
649                         return new String (encoding.GetChars (bytes, 0, n));
650                 }
651
652                 public string ReadLine ()
653                 {
654                         return ReadTo (new_line);
655                 }
656
657                 public string ReadTo (string value)
658                 {
659                         CheckOpen ();
660                         if (value == null)
661                                 throw new ArgumentNullException ("value");
662                         if (value.Length == 0)
663                                 throw new ArgumentException ("value");
664
665                         // Turn into byte array, so we can compare
666                         byte [] byte_value = encoding.GetBytes (value);
667                         int current = 0;
668                         List<byte> seen = new List<byte> ();
669
670                         while (true){
671                                 int n = read_byte ();
672                                 if (n == -1)
673                                         break;
674                                 seen.Add ((byte)n);
675                                 if (n == byte_value [current]){
676                                         current++;
677                                         if (current == byte_value.Length)
678                                                 return encoding.GetString (seen.ToArray (), 0, seen.Count - byte_value.Length);
679                                 } else {
680                                         current = (byte_value [0] == n) ? 1 : 0;
681                                 }
682                         }
683                         return encoding.GetString (seen.ToArray ());
684                 }
685
686                 public void Write (string str)
687                 {
688                         CheckOpen ();
689                         if (str == null)
690                                 throw new ArgumentNullException ("str");
691                         
692                         byte [] buffer = encoding.GetBytes (str);
693                         Write (buffer, 0, buffer.Length);
694                 }
695
696                 public void Write (byte [] buffer, int offset, int count)
697                 {
698                         CheckOpen ();
699                         if (buffer == null)
700                                 throw new ArgumentNullException ("buffer");
701
702                         if (offset < 0 || count < 0)
703                                 throw new ArgumentOutOfRangeException ();
704
705                         if (buffer.Length - offset < count)
706                                 throw new ArgumentException ("offset+count",
707                                                              "The size of the buffer is less than offset + count.");
708
709                         stream.Write (buffer, offset, count);
710                 }
711
712                 public void Write (char [] buffer, int offset, int count)
713                 {
714                         CheckOpen ();
715                         if (buffer == null)
716                                 throw new ArgumentNullException ("buffer");
717
718                         if (offset < 0 || count < 0)
719                                 throw new ArgumentOutOfRangeException ();
720
721                         if (buffer.Length - offset < count)
722                                 throw new ArgumentException ("offset+count",
723                                                              "The size of the buffer is less than offset + count.");
724
725                         byte [] bytes = encoding.GetBytes (buffer, offset, count);
726                         stream.Write (bytes, 0, bytes.Length);
727                 }
728
729                 public void WriteLine (string str)
730                 {
731                         Write (str + new_line);
732                 }
733
734                 void CheckOpen ()
735                 {
736                         if (!is_open)
737                                 throw new InvalidOperationException ("Specified port is not open.");
738                 }
739
740                 internal void OnErrorReceived (SerialErrorReceivedEventArgs args)
741                 {
742                         SerialErrorReceivedEventHandler handler =
743                                 (SerialErrorReceivedEventHandler) Events [error_received];
744
745                         if (handler != null)
746                                 handler (this, args);
747                 }
748
749                 internal void OnDataReceived (SerialDataReceivedEventArgs args)
750                 {
751                         SerialDataReceivedEventHandler handler =
752                                 (SerialDataReceivedEventHandler) Events [data_received];
753
754                         if (handler != null)
755                                 handler (this, args);
756                 }
757                 
758                 internal void OnDataReceived (SerialPinChangedEventArgs args)
759                 {
760                         SerialPinChangedEventHandler handler =
761                                 (SerialPinChangedEventHandler) Events [pin_changed];
762
763                         if (handler != null)
764                                 handler (this, args);
765                 }
766
767                 // events
768                 [MonitoringDescription ("")]
769                 public event SerialErrorReceivedEventHandler ErrorReceived {
770                         add { Events.AddHandler (error_received, value); }
771                         remove { Events.RemoveHandler (error_received, value); }
772                 }
773                 
774                 [MonitoringDescription ("")]
775                 public event SerialPinChangedEventHandler PinChanged {
776                         add { Events.AddHandler (pin_changed, value); }
777                         remove { Events.RemoveHandler (pin_changed, value); }
778                 }
779                 
780                 [MonitoringDescription ("")]
781                 public event SerialDataReceivedEventHandler DataReceived {
782                         add { Events.AddHandler (data_received, value); }
783                         remove { Events.RemoveHandler (data_received, value); }
784                 }
785         }
786
787         public delegate void SerialDataReceivedEventHandler (object sender, SerialDataReceivedEventArgs e);
788         public delegate void SerialPinChangedEventHandler (object sender, SerialPinChangedEventArgs e);
789         public delegate void SerialErrorReceivedEventHandler (object sender, SerialErrorReceivedEventArgs e);
790
791 }
792
793 #endif