Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically find all available Baudrates in C# (serialPort class)

Is there a way to find out all the available baud rates that a particular system supports via C#? This is available through Device Manager-->Ports but I want to list these programmatically.

like image 752
HiteshP Avatar asked Jul 22 '09 14:07

HiteshP


1 Answers

I have found a couple of ways to do this. The following two documents were a starting point

  • http://support.microsoft.com/default.aspx/kb/99026
  • http://msdn.microsoft.com/en-us/library/aa363189(VS.85).aspx

The clue is in the following paragraph from the first document

The simplest way to determine what baud rates are available on a particular serial port is to call the GetCommProperties() application programming interface (API) and examine the COMMPROP.dwSettableBaud bitmask to determine what baud rates are supported on that serial port.

At this stage there are two choices to do this in C#:

1.0 Use interop (P/Invoke) as follows:

Define the following data structure

[StructLayout(LayoutKind.Sequential)]
struct COMMPROP
{
    short wPacketLength;
    short wPacketVersion;
    int dwServiceMask;
    int dwReserved1;
    int dwMaxTxQueue;
    int dwMaxRxQueue;
    int dwMaxBaud;
    int dwProvSubType;
    int dwProvCapabilities;
    int dwSettableParams;
    int dwSettableBaud;
    short wSettableData;
    short wSettableStopParity;
    int dwCurrentTxQueue;
    int dwCurrentRxQueue;
    int dwProvSpec1;
    int dwProvSpec2;
    string wcProvChar;
}

Then define the following signatures

[DllImport("kernel32.dll")]
static extern bool GetCommProperties(IntPtr hFile, ref COMMPROP lpCommProp);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess,
           int dwShareMode, IntPtr securityAttrs, int dwCreationDisposition, 
           int dwFlagsAndAttributes, IntPtr hTemplateFile);

Now make the following calls (refer to http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx)

   COMMPROP _commProp = new COMMPROP();
   IntPtr hFile = CreateFile(@"\\.\" + portName, 0, 0, IntPtr.Zero, 3, 0x80, IntPtr.Zero);
   GetCommProperties(hFile, ref commProp);

Where portName is something like COM?? (COM1, COM2, etc). commProp.dwSettableBaud should now contain the desired information.

2.0 Use C# reflection

Reflection can be used to access the SerialPort BaseStream and thence the required data as follows:

   _port = new SerialPort(portName);
   _port.Open();
   object p = _port.BaseStream.GetType().GetField("commProp", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_port.BaseStream);
   Int32 bv = (Int32)p.GetType().GetField("dwSettableBaud", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(p);

Note that in both the methods above the port(s) has to be opened at least once to get this data.


like image 175
HiteshP Avatar answered Oct 13 '22 20:10

HiteshP