serial/termios: support custom baud rate setting

N/A

Change-Id: I0cc00f6d0fda852533bd4a38ea6fc39e0d0059da
Signed-off-by: dongjiuzhu <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu 2020-10-21 11:23:43 +08:00 committed by David Sidrane
parent d90ef8374b
commit 2b5be56bd0
2 changed files with 72 additions and 54 deletions

View file

@ -250,6 +250,13 @@ struct termios
tcflag_t c_cflag; /* Control modes */ tcflag_t c_cflag; /* Control modes */
tcflag_t c_lflag; /* Local modes */ tcflag_t c_lflag; /* Local modes */
cc_t c_cc[NCCS]; /* Control chars */ cc_t c_cc[NCCS]; /* Control chars */
/* Implementation specific fields. For portability reasons, these fields
* should not be accessed directly, but rather through only through the
* cf[set|get][o|i]speed() POSIX interfaces.
*/
speed_t c_speed; /* Input/output speed (non-POSIX) */
}; };
/**************************************************************************** /****************************************************************************

View file

@ -32,11 +32,20 @@
****************************************************************************/ ****************************************************************************/
#define CBAUD 0010017 /* Baud speed mask (not in POSIX) */ #define CBAUD 0010017 /* Baud speed mask (not in POSIX) */
#define CBAUDEX 0010000 /* Extra baud speed mask, included in CBAUD. #define BOTHER 0010000 /* Magic token for custom baud rate */
* (not in POSIX) */
#define ARRAYSIZE(a) (sizeof((a))/sizeof(a[0])) #define ARRAYSIZE(a) (sizeof((a))/sizeof(a[0]))
/****************************************************************************
* Private Type Definitions
****************************************************************************/
struct speed_s
{
speed_t value;
speed_t mask;
};
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
@ -47,51 +56,41 @@
* include/termios.h file. * include/termios.h file.
*/ */
static const speed_t g_baud_table[] = static const struct speed_s g_baud_table[] =
{ {
0, 50, 75, 110, 134, { 0, B0 },
150, 200, 300, 600, 1200, { 50, B50 },
1800, 2400, 4800, 9600, 19200, { 75, B75 },
38400, 57600, 115200, 230400, 460800, { 110, B110 },
500000, 576000, 921600, 1000000, 1152000, { 134, B134 },
1500000, 2000000, 2500000, 3000000, 3500000, { 150, B150 },
4000000 { 200, B200 },
{ 300, B300 },
{ 600, B600 },
{ 1200, B1200 },
{ 1800, B1800 },
{ 2400, B2400 },
{ 4800, B4800 },
{ 9600, B9600 },
{ 19200, B19200 },
{ 38400, B38400 },
{ 57600, B57600 },
{ 115200, B115200 },
{ 230400, B230400 },
{ 460800, B460800 },
{ 500000, B500000 },
{ 576000, B576000 },
{ 921600, B921600 },
{ 1000000, B1000000 },
{ 1152000, B1152000 },
{ 1500000, B1500000 },
{ 2000000, B2000000 },
{ 2500000, B2500000 },
{ 3000000, B3000000 },
{ 3500000, B3500000 },
{ 4000000, B4000000 }
}; };
/****************************************************************************
* Private Functions
****************************************************************************/
static int baud_mask(speed_t speed)
{
speed_t idx = 0;
for (; idx < ARRAYSIZE(g_baud_table); idx++)
{
if (speed == g_baud_table[idx])
{
break;
}
}
/* we don't find the speed value, it could be mask */
if (idx == ARRAYSIZE(g_baud_table))
{
return (speed & ~CBAUD) ? -1 : speed;
}
/* If idx > B38400, we should will idx minus 15, and or CBAUDEX */
if (idx > B38400)
{
idx -= B38400;
idx |= CBAUDEX;
}
return idx;
}
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@ -145,17 +144,33 @@ static int baud_mask(speed_t speed)
int cfsetspeed(FAR struct termios *termiosp, speed_t speed) int cfsetspeed(FAR struct termios *termiosp, speed_t speed)
{ {
int mask = baud_mask(speed); size_t idx;
DEBUGASSERT(termiosp); DEBUGASSERT(termiosp);
if (mask == -1) for (idx = 0; idx < ARRAYSIZE(g_baud_table); idx++)
{ {
set_errno(EINVAL); if (speed == g_baud_table[idx].mask)
return mask; {
termiosp->c_speed = g_baud_table[idx].value;
break;
}
else if (speed == g_baud_table[idx].value)
{
termiosp->c_speed = speed;
speed = g_baud_table[idx].mask;
break;
}
}
if (idx == ARRAYSIZE(g_baud_table))
{
termiosp->c_speed = speed;
speed = BOTHER;
} }
termiosp->c_cflag &= ~CBAUD; termiosp->c_cflag &= ~CBAUD;
termiosp->c_cflag |= mask; termiosp->c_cflag |= speed;
return 0; return 0;
} }
@ -187,10 +202,6 @@ int cfsetspeed(FAR struct termios *termiosp, speed_t speed)
speed_t cfgetspeed(FAR const struct termios *termiosp) speed_t cfgetspeed(FAR const struct termios *termiosp)
{ {
int idx;
DEBUGASSERT(termiosp); DEBUGASSERT(termiosp);
idx = termiosp->c_cflag & CBAUD & ~CBAUDEX; return termiosp->c_speed;
idx += (termiosp->c_cflag & CBAUDEX) ? 15 : 0;
return g_baud_table[idx];
} }