1

Does anybody know of a good serial communication library that is a decent alternative to boost::asio::serialport?

Boost::Asio::SerialPort does not seem to support non-standard baud rates - like 31250 (it definitely does not seem to work on Mac OS 10.6 with boost 1.48.0)

I need the library to work on a minimum of Mac OS X and Windows

Mike
  • 47,263
  • 29
  • 113
  • 177
Carl
  • 43,122
  • 10
  • 80
  • 104
  • FYI, the [native Windows serial port configuration](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214.aspx) does not officially support this baud rate, though it does say that you can set "an actual baud rate value". I guess you have to make sure your serial port hardware and driver support this custom baud rate. – André Caron Feb 20 '12 at 22:08

3 Answers3

3

The easiest workaround is to create the asio::serial_port instance for the appropriate device, and then call serial_port.native_native() and use the returned handle to call ioctl() or SetCommState() to set the speed.

That way you can use asio for everything except setting the line speed, and you can get the line speed you want with minimal special code.

You will need this code to be special for each operating system, but at least everything else is common.

However: The bug you reference is for a specific workaround on a specific version of Linux/glibc. Are you having this problem on Windows and OSX as well?

janm
  • 17,976
  • 1
  • 43
  • 61
  • Thanks. This is what I ended up doing. Got the native handle from boost, added in IOKit and then used ioctl to set the baud rate. Once done, I used boost to verify that it actually stayed set. – Carl Feb 21 '12 at 20:25
1

That's the MIDI baudrate. Always struck me as a rate optimized to ensure you're forced to buy hardware from the music instrument vendors. Shop for the hardware first, the software usually comes with it. So you don't end up doing this to your nice Apple machine:

enter image description here

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • You're right. However, changing the hardware at this stage isn't an option, which means I need to look for a cross platform library that supports custom baud rates. – Carl Feb 20 '12 at 19:57
  • 3
    You are missing the point. I'm fairly sure you are having trouble with the software because your *hardware* doesn't support the baudrate. So the software doesn't either. I don't know Apple hardware well enough but at least the legacy Intel motherboards designs don't have an oscillator frequency that allows an integer divisor to generate the frequency. – Hans Passant Feb 20 '12 at 20:04
  • Just checked. I can actually set the baud rate to 31250 in software using ioctl calls. So that seems to imply that when I pass 31250 to boost asio and get an invalid argument error, that boost is at fault. https://developer.apple.com/library/mac/#samplecode/SerialPortSample/Listings/SerialPortSample_c.html seems to state from 10.4 onwards, you can set arbitrary baud rates. – Carl Feb 21 '12 at 01:07
  • How unusual. Just as a sanity check: does a random value like 33333 work as well? – Hans Passant Feb 21 '12 at 06:09
1

You can use ioctl and termios to directly control the baud rate and serial port parameters. Its not terribly difficult.

If you only need a simple serial port and do not need the asynchronous IO components you can try: https://github.com/wjwwood/serial its a library a friend of mine wrote for some of his projects. Be sure to use the boostless branch. I know the OS X drivers support custom baud rates, I have tested those, and custom baud rates should work in Linux as well. It doesn't currently support Windows, so if you need Windows support, its won't be much help at the moment.

If you only want to use ioctl and termios you can do:

#define IOSSIOSPEED _IOW('T', 2, speed_t)
int new_baud = static_cast<int> (baudrate_);
ioctl (fd_, IOSSIOSPEED, &new_baud, 1);

And it will let you set the baud rate to any value in OS X, but that is OS specific. for Linux you need to do:

struct serial_struct ser;
ioctl (fd_, TIOCGSERIAL, &ser);
// set custom divisor
ser.custom_divisor = ser.baud_base / baudrate_;
// update flags
ser.flags &= ~ASYNC_SPD_MASK;
ser.flags |= ASYNC_SPD_CUST;

if (ioctl (fd_, TIOCSSERIAL, ser) < 0)
{
  // error
}

For any other OS your gonna have to go read some man pages or it might not even work at all, its very OS dependent.

ash
  • 521
  • 1
  • 4
  • 8
  • Thanks for this. I do need Windows support too, so it looks like I might end up rolling my own if I don't find one soon. – Carl Feb 20 '12 at 19:57
  • Look at [pyserial](https://pyserial.svn.sourceforge.net/svnroot/pyserial/trunk/pyserial/), thats what the library my friend wrote is based off. pyserial supports a number of OSes, including Windows. Eventually we were going to write windows support the the Serial library but it currently does not work. – ash Feb 20 '12 at 20:01