19

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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
HiteshP
  • 757
  • 2
  • 8
  • 15

3 Answers3

16

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

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.


HiteshP
  • 757
  • 2
  • 8
  • 15
  • 1
    I think you need to close the handle when you're done using it by calling CloseHandle(hFile) – Jakub Kaleta Dec 19 '11 at 23:36
  • 1
    @ HiteshP: To anyone using Windows CE, make the following two changes: (1) change "string wcProvChar" to "char wcProvChar" in the COMMPROP structure and (2) use "coredll.dll" instead of "kernel32.dll" for both P/Invokes. Note you should also close the file handle to the COM port afterwards as Jakub points out. – AlainD Feb 20 '15 at 15:54
0

I don't think you can.

I recently had this problem, and ended up hard coding the baud rates I wanted to use.

MSDN simply states, "The baud rate must be supported by the user's serial driver".

Bryan
  • 3,224
  • 9
  • 41
  • 58
  • I also read the same thing. However, I suspect there is a way to do this since the device manager displays these. – HiteshP Jul 22 '09 at 14:53
  • I suspect this may be hard coded also I have a couple of different serial cards in this computer, both different chipsets, and the list of baud rates is identical. Of course, it could be that case that they both just happen to support exactly the same baud rates. Look at this Win32 structure , it also has hard coded values. – Bryan Jul 22 '09 at 15:04
  • Sorry, I messed up the link http://msdn.microsoft.com/en-us/library/aa363214(VS.85).aspx – Bryan Jul 22 '09 at 15:05
  • 1
    Just FYI, I've got a system (Win 7) with an external USB<->Serial device. The internal comm ports only list bauds up to 128000 in the device manager, while the external device has bauds up to 921600. Also, it should be noted that the external device doesn't support a lot of baud rates that the internal does support. So the list is not hard coded. – Michael Kohne Aug 16 '12 at 16:56
  • @MichaelKohne Thanks for that. I hadn't seen HiteshP's answer until now. – Bryan Aug 16 '12 at 20:39
0
dwSettableBaud  gives 268894207 int (0x1006ffff)
while dwMaxBaud gives 268435456 int (0x10000000)

Obviously, this doesn't help me. So this is what I am currently relying upon:

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;


  public static readonly List<string> SupportedBaudRates = new List<string>
{
    "300",
    "600",
    "1200",
    "2400",
    "4800",
    "9600",
    "19200",
    "38400",
    "57600",
    "115200",
    "230400",
    "460800",
    "921600"
};

    public static int MaxBaudRate(string portName)
    {
        var maxBaudRate = 0;
        try
        {
            //SupportedBaudRates has the commonly used baudRate rates in it
            //flavor to taste
            foreach (var baudRate in ConstantsType.SupportedBaudRates)
            {
                var intBaud = Convert.ToInt32(baudRate);
                using (var port = new SerialPort(portName))
                {
                    port.BaudRate = intBaud;
                    port.Open();
                }
                maxBaudRate = intBaud;
            }
        }
        catch
        {
            //ignored - traps exception generated by
            //baudRate rate not supported
        }

        return maxBaudRate;
    }

The baud rates are in strings because they are destined for a combo box.

    private void CommPorts_SelectedIndexChanged(object sender, EventArgs e)
    {
        var combo = sender as ComboBox;
        if (combo != null)
        {
            var port = combo.Items[combo.SelectedIndex].ToString();
            var maxBaud = AsyncSerialPortType.MaxBaudRate(port);
            var baudRates = ConstantsType.SupportedBaudRates;
            var f = (SerialPortOpenFormType)(combo.Parent);
            f.Baud.Items.Clear();
            f.Baud.Items.AddRange(baudRates.Where(baud => Convert.ToInt32(baud) <= maxBaud).ToArray());
        }
    }

You can improve on performance if you know the minimum baud rate supported by all of the serial ports you plan to open. For instance, starting with 115,200 seems like a safe lower limit for serial ports manufactured in this century.

Max Euwe
  • 431
  • 3
  • 9
  • `dwSettableBaud` would help you if you used a 'bitwise and' operator to detect all the baud rate values it includes (e.g. check the source code of [this project](https://www.codeproject.com/Articles/75770/Basic-serial-port-listening-application)). – Mehdi Mar 26 '21 at 08:07