Sparkler
Sparkler

Reputation: 2913

How to efficiently convert baudrate from int to speed_t?

The functions cfsetospeed and cfsetispeed take baud rate as type speed_t:

int cfsetispeed(struct termios *termios_p, speed_t speed);
int cfsetospeed(struct termios *termios_p, speed_t speed);

The type speed_t is basically an integer, but casting is not a solution, as can be seen from the baudrate definitions in termios.h:

#define B0  0x00000000
#define B50 0x00000001
#define B75 0x00000002
// ...
#define B9600   0x0000000d
#define B19200  0x0000000e
#define B38400  0x0000000f

When I process user input (e.g. from file), I convert a string such as "9600" to integer 9600, and then to B9600. I'm basically looking for a generic way to convert the following:

// 0 -> B0
// 50 -> B50
// 75 -> B75
// ...
// 9600 -> B9600 
// 19200 -> B19200
// 38400 -> B38400

One way to convert from int (such as 9600) to speed_t (such as B9600) is a switch-case structure. Is there a better way to achieve this?

Upvotes: 8

Views: 7171

Answers (3)

Brian White
Brian White

Reputation: 457

I use a big ternary. I don't love it but I like it better than ifs or switch because it's a single return.

If speed matters, reorder to put the most likely first.

// int-to-baud - given int 9600 return macro B9600
speed_t itobaud (uint32_t i) {
    return
        i==0?B0:
        i==50?B50:
        i==75?B75:
        i==110?B110:
        i==134?B134:
        i==150?B150:
        i==200?B200:
        i==300?B300:
        i==600?B600:
        i==1200?B1200:
        i==1800?B1800:
        i==2400?B2400:
        i==4800?B4800:
        i==9600?B9600:
        i==19200?B19200:
        i==38400?B38400:
#ifdef B57600
        i==57600?B57600:
#endif
#ifdef B76800
        i==76800?B76800:
#endif
#ifdef B115200
        i==115200?B115200:
#endif
#ifdef B153600
        i==153600?B153600:
#endif
#ifdef B230400
        i==230400?B230400:
#endif
#ifdef B307200
        i==307200?B307200:
#endif
#ifdef B460800
        i==460800?B460800:
#endif
#ifdef B500000
        i==500000?B500000:
#endif
#ifdef B576000
        i==576000?B576000:
#endif
#ifdef B614400
        i==614400?B614400:
#endif
#ifdef B921600
        i==921600?B921600:
#endif
#ifdef B1000000
        i==1000000?B1000000:
#endif
#ifdef B1152000
        i==1152000?B1152000:
#endif
#ifdef B1500000
        i==1500000?B1500000:
#endif
#ifdef B2000000
        i==2000000?B2000000:
#endif
#ifdef B2500000
        i==2500000?B2500000:
#endif
#ifdef B3000000
        i==3000000?B3000000:
#endif
#ifdef B3500000
        i==3500000?B3500000:
#endif
#ifdef B4000000
        i==4000000?B4000000:
#endif
        0;
}

Upvotes: 1

Noel
Noel

Reputation: 3980

I came across needing this. Pasting the switch case statement here for you to copy.

int get_baud(int baud)
{
    switch (baud) {
    case 9600:
        return B9600;
    case 19200:
        return B19200;
    case 38400:
        return B38400;
    case 57600:
        return B57600;
    case 115200:
        return B115200;
    case 230400:
        return B230400;
    case 460800:
        return B460800;
    case 500000:
        return B500000;
    case 576000:
        return B576000;
    case 921600:
        return B921600;
    case 1000000:
        return B1000000;
    case 1152000:
        return B1152000;
    case 1500000:
        return B1500000;
    case 2000000:
        return B2000000;
    case 2500000:
        return B2500000;
    case 3000000:
        return B3000000;
    case 3500000:
        return B3500000;
    case 4000000:
        return B4000000;
    default: 
        return -1;
    }
}

Upvotes: 10

Jabberwocky
Jabberwocky

Reputation: 50883

You need a lookup table, but not a naive one:

#include <stdio.h>    
#include <termios.h>       

struct
{
  int rawrate;
  int termiosrate;
} conversiontable[] =
{
  {0, B0},
  {50, B50},
  {75, B75},
  // you need to complete the table with B110 to B38400
};

int convertbaudrate(int rawrate)
{
  for (int i = 0; i < sizeof(conversiontable) / sizeof(conversiontable[0]); i++)
  {
    if (conversiontable[i].rawrate == rawrate)
    {
      return conversiontable[i].termiosrate;
    }
  }

  return -1;    // invalid baud rate
}

int main()
{
  printf("%d -> %d\n", 50, convertbaudrate(50));
  printf("%d -> %d\n", 75, convertbaudrate(75));
}

That should autoexplain. If not, please comment.

Upvotes: 4

Related Questions