Darien Figueroa / Mbed 2 deprecated repo3

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SerialPortTester.cs Source File

SerialPortTester.cs

00001 // Copyright 2010-2014 Zach Saw
00002 // 
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 // 
00007 //     http://www.apache.org/licenses/LICENSE-2.0
00008 // 
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 using System;
00016 using System.IO;
00017 using System.IO.Ports;
00018 using System.Runtime.InteropServices;
00019 using System.Text;
00020 using Microsoft.Win32.SafeHandles;
00021 
00022 namespace SerialPortTester
00023 {
00024     public class SerialPortFixer : IDisposable
00025     {
00026         public static void Execute(string portName)
00027         {
00028             using (new SerialPortFixer(portName))
00029             {
00030             }
00031         }
00032         #region IDisposable Members
00033 
00034         public void Dispose()
00035         {
00036             if (m_Handle != null)
00037             {
00038                 m_Handle.Close();
00039                 m_Handle = null;
00040             }
00041         }
00042 
00043         #endregion
00044 
00045         #region Implementation
00046 
00047         private const int DcbFlagAbortOnError = 14;
00048         private const int CommStateRetries = 10;
00049         private SafeFileHandle m_Handle;
00050 
00051         private SerialPortFixer(string portName)
00052         {
00053             const int dwFlagsAndAttributes = 0x40000000;
00054             const int dwAccess = unchecked((int) 0xC0000000); 
00055  
00056             if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
00057             {
00058                 throw new ArgumentException("Invalid Serial Port", "portName");
00059             }
00060             SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
00061                                               IntPtr.Zero);
00062             if (hFile.IsInvalid)
00063             {
00064                 WinIoError();
00065             }
00066             try
00067             {
00068                 int fileType = GetFileType(hFile);
00069                 if ((fileType != 2) && (fileType != 0))
00070                 {
00071                      throw new ArgumentException("Invalid Serial Port", "portName");
00072                 }
00073                 m_Handle = hFile;
00074                 InitializeDcb();
00075             }
00076             catch
00077             {
00078                 hFile.Close();
00079                 m_Handle = null;
00080                 throw;
00081             }
00082         }
00083 
00084         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
00085         private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
00086                                                 StringBuilder lpBuffer, int nSize, IntPtr arguments);
00087 
00088         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
00089         private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
00090 
00091         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
00092         private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
00093 
00094         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
00095         private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
00096 
00097         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
00098         private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
00099                                                         IntPtr securityAttrs, int dwCreationDisposition,
00100                                                         int dwFlagsAndAttributes, IntPtr hTemplateFile);
00101 
00102         [DllImport("kernel32.dll", SetLastError = true)]
00103         private static extern int GetFileType(SafeFileHandle hFile);
00104 
00105         private void InitializeDcb()
00106         {
00107             Dcb dcb = new Dcb();
00108             GetCommStateNative(ref dcb);
00109             dcb.Flags &= ~(1u << DcbFlagAbortOnError);
00110             SetCommStateNative(ref dcb);
00111         }
00112 
00113         private static string GetMessage(int errorCode)
00114         {
00115             StringBuilder lpBuffer = new StringBuilder(0x200);
00116             if (
00117                 FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
00118                               IntPtr.Zero) != 0)
00119             {
00120                 return lpBuffer.ToString();
00121             }
00122             return "Unknown Error";
00123         }
00124 
00125         private static int MakeHrFromErrorCode(int errorCode)
00126         {
00127             return (int) (0x80070000 | (uint) errorCode);
00128         }
00129 
00130         private static void WinIoError()
00131         {
00132             int errorCode = Marshal.GetLastWin32Error();
00133             throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
00134         }
00135 
00136         private void GetCommStateNative(ref Dcb lpDcb)
00137         {
00138             int commErrors = 0;
00139             Comstat comStat = new Comstat();
00140 
00141             for (int i = 0; i < CommStateRetries; i++)
00142             {
00143                 if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
00144                 {
00145                      WinIoError();
00146                 }
00147                 if (GetCommState(m_Handle, ref lpDcb))
00148                 {
00149                      break;
00150                 }
00151                 if (i == CommStateRetries - 1)
00152                 {
00153                      WinIoError();
00154                 }
00155             }
00156         } 
00157  
00158         private void SetCommStateNative(ref Dcb lpDcb)
00159         {
00160             int commErrors = 0;
00161             Comstat comStat = new Comstat(); 
00162  
00163             for (int i = 0; i < CommStateRetries; i++)
00164             {
00165                  if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
00166                  {
00167                      WinIoError();
00168                  }
00169                  if (SetCommState(m_Handle, ref lpDcb))
00170                  {
00171                      break;
00172                  }
00173                  if (i == CommStateRetries - 1)
00174                  {
00175                      WinIoError();
00176                  }
00177             }
00178         }
00179 
00180         #region Nested type: COMSTAT
00181 
00182         [StructLayout(LayoutKind.Sequential)]
00183         private struct Comstat
00184         {
00185             public readonly uint Flags;
00186             public readonly uint cbInQue;
00187             public readonly uint cbOutQue;
00188         }
00189 
00190         #endregion
00191 
00192         #region Nested type: DCB
00193 
00194         [StructLayout(LayoutKind.Sequential)]
00195         private struct Dcb
00196         {
00197             public readonly uint DCBlength;
00198             public readonly uint BaudRate;
00199             public uint Flags;
00200             public readonly ushort wReserved;
00201             public readonly ushort XonLim;
00202             public readonly ushort XoffLim;
00203             public readonly byte ByteSize;
00204             public readonly byte Parity;
00205             public readonly byte StopBits;
00206             public readonly byte XonChar;
00207             public readonly byte XoffChar;
00208             public readonly byte ErrorChar;
00209             public readonly byte EofChar;
00210             public readonly byte EvtChar;
00211             public readonly ushort wReserved1;
00212         }
00213 
00214         #endregion
00215 
00216         #endregion
00217     }
00218 
00219     internal class Program
00220     {
00221         private static void Main(string[] args)
00222         {
00223             SerialPortFixer.Execute("COM1");
00224             using (SerialPort port = new SerialPort("COM1"))
00225             {
00226                 port.Write("test");
00227             }
00228         }
00229     }
00230 }