[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#683826: cfsetspeed, real baud rates, custom baud rates (BOTHER)



Package: libc6
Version: 2.13-33

In summary, please:

   - Fix the documentation so that it no longer claims that
     tcgetispeed and tcgetospeed return actual baud rates.

   - Provide new functions tcgetispeedbps and tcgetospeedbps
     which do return actual baud rates.

   - Make all the tc*speed* functions support arbitrary baud
     rates using (c_cflags&CBAUD)==BOTHER / c_ispeed / c_ospeed.

   - When on Linux use TCSETS2 if (c_cflags&CBAUD)==BOTHER.
     Use TCGETS2 when it is available, or at least when necessary.


According to the info manual for glibc, node `(libc) Line Speed':

     *Portability note:* In the GNU library, the functions above accept
  speeds measured in bits per second as input, and return speed values
  measured in bits per second.  Other libraries require speeds to be
  indicated by special codes.  For POSIX.1 portability, you must use one
  of the following symbols to represent the speed; their precise numeric
  values are system-dependent, but each name has a fixed meaning: `B110'
  stands for 110 bps, `B300' for 300 bps, and so on.  There is no
  portable way to represent any speed but these, but these are the only
  speeds that typical serial lines can support.

However, actually, this does not work as described.  cfgetspeed
returns a traditional B9600 value, not the number 9600 (or whatever).
(cfsetspeed does accept baud rates in bps as documented and converts
them to magic constants in the struct termios).

The only way to make this work as documented in the glibc manual would
be to change the Bnnnn #defines each to have the value nnnn.  That
would break compatibility with programs which know about setting
c_cflags&CBAUD to Bnnnn.  (I think such programs will exist.)

I therefore suggest that the specification is wrong.  cfget{i,o}speed
are defined in POSIX to return these Bnnnn constants, and the values
of the constants can't be changed, so users of cfget{i,o} speed will
never be able to expect speeds.  cfgetispeed and cfgetospeed have to
continue to return magic constants rather than baud rates.

There should however be a function with the semantics described.  This
is useful because (i) we would like to be able to easily print out or
compare or compute with the actual baud rate without having a Bnnnn
table in the application and (ii) the application may want to set
nonstandard baud rates (see below).

I therefore propose that we should introduce:

 -- Function: speed_t cfgetispeedbps (struct termios *TERMIOS-P)
     This function returns the input line speed stored in the
     structure `*TERMIOS-P' as a number of bits per second.

and the corresponding cfgetospeedbps.

Also it would be very desirable to be able to support arbitrary baud
rates.  At least Linux does support arbitrary baud rates where the
hardware can do it: you are supposed to set c_cflags&CBAUD to BOTHER
and c_ispeed and c_ospeed to the desired rates in bps.

This does not currently work properly with glibc on Linux even if you
do it by hand because glibc uses the Linux ioctls TGGETS/TCSETS whose
Linux termios struct does not contain c_ispeed and c_ospeed.  (glibc
appears to convert between its idea of termios and the kernel's.)  If
glibc used TCGETS2/TCSETS2 where available or where necessary, then
arbitrary baud rates would work.

TCSETS2 needs to be used if (c_cflag&CBAUD)==BOTHER.  Otherwise I
think TCSETS is sufficient (but there may be other reasons why TCSETS
is insufficient - I haven't checked).  For getting ideally TCGETS2
would be used all the time but some old kernels don't support it so
glibc should try TCGETS2 first and then TCGETS, probably.

Ian.


Reply to: