1
0
mirror of https://github.com/UzixLS/picocom.git synced 2025-07-19 07:21:18 +03:00

Disable custom baudrate support at runtime (Linux)

If picocom is compiled *with* custom-baudrate support (USE_CUSTOM_BAUD)
for Linux, then it uses a new set of ioctl's (TCGETS2 vs TCGETS, etc) to
access the serial ports. This patch allows the custom baudrate support
to be disabled at runtime (without recompiling), and picocom to switch
to using the old ioctl's.

To disable custom baudrate support (and switch back to the "old" ioctls)
simply define the environment variable NO_CUSTOM_BAUD, before starting
picocom.

This applies only to Linux and, obviously, only when picocom has been
compiled with custom baudrate support (USE_CUSTOM_BAUD).
This commit is contained in:
Nick Patavalis
2018-02-20 01:31:34 +02:00
parent 8814974ac7
commit ee23af0cb9
11 changed files with 179 additions and 29 deletions

View File

@ -49,7 +49,7 @@ linenoise-1.0/linenoise.o : linenoise-1.0/linenoise.c linenoise-1.0/linenoise.h
#CPPFLAGS += -DNO_HELP
OBJS += picocom.o term.o fdio.o split.o termios2.o custbaud_bsd.o
OBJS += picocom.o term.o fdio.o split.o custbaud.o termios2.o custbaud_bsd.o
picocom : $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
@ -59,6 +59,7 @@ split.o : split.c split.h
fdio.o : fdio.c fdio.h
termios2.o : termios2.c termios2.h termbits2.h custbaud.h
custbaud_bsd.o : custbaud_bsd.c custbaud_bsd.h custbaud.h
custbaud.o : custbaud.c custbaud.h
.c.o :
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
@ -90,7 +91,7 @@ picocom.1.pdf : picocom.1
clean:
rm -f picocom.o term.o fdio.o split.o
rm -f linenoise-1.0/linenoise.o
rm -f termios2.o custbaud_bsd.o
rm -f custbaud.o termios2.o custbaud_bsd.o
rm -f *~
rm -f \#*\#

View File

@ -326,3 +326,45 @@ Some interesting points:
Again, this is only *one* possible setup. There are countless other
variations and elaborations you can try. Be creative!
## Some notes on custom baudrate support
Custom baudrate support gives you the ability to set arbitrary
baudrate values (like 1234, or 42000, etc) to a serial port, provided
that the underlying driver can handle this. Since release 2.0, picocom
can be compiled with custom baudrate support for some systems. Since
release 3.1 picocom is compiled with custom baudrate support enabled
by default on some systems (like Linux, kernels > 2.6, on ix86 and
ix86_64, modern intel macs, and some other BSDs). In any case, you can
explicitly ask for custom baudrate support to be enabled by compiling
picocom like this:
CPPFLAGS=-DUSE_CUSTOM_BAUD make clean
CPPFLAGS=-DUSE_CUSTOM_BAUD make
If custom baudrate support is not available for your system, the
compilation will fail. Similarly, you can ask for custom baudrate
support to be disabled by compiling like:
CPPFLAGS=-DNO_CUSTOM_BAUD make clean
CPPFLAGS=-DNO_CUSTOM_BAUD make
When picocom is compiled with custom baudrate support on Linux, it
uses a new set of ioctl's (TCGETS2, TCSETSF2 vs TCGETS, TCSETSF, etc)
to access the serial ports. It is not impossible that some serial
devices may not accept these new ioctl's (though they should). In
order to be able to use picocom even with such devices, and without
recompiling it, you can disable the custom baudrate support at
runtime, and force picocom to use the "old" ioctls. To do this
(starting with release 3.2) just define the environment variable
`NO_CUSTOM_BAUD` before running picocom. Something like this:
NO_CUSTOM_BAUD=1 picocom ...
This only applies to Linux, and to picocom binaries that have been
compiled with custom baudrate support.
To see if your binary has been compiled with custom baudrate support,
and / or if it has detected the `NO_CUSTOM_BAUD` variable, run it with
the **--help** option, and take a look at the first few lines of
output.

62
custbaud.c Normal file
View File

@ -0,0 +1,62 @@
/* vi: set sw=4 ts=4:
*
* custbaud.c
*
* by Nick Patavalis (npat@efault.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "custbaud.h"
#ifndef USE_CUSTOM_BAUD
int use_custom_baud() { return 0; }
int cfsetispeed_custom(struct termios *tios, int speed) { errno = EINVAL; return -1; }
int cfsetospeed_custom(struct termios *tios, int speed) { errno = EINVAL; return -1; }
int cfgetispeed_custom(const struct termios *tios) { errno = EINVAL; return -1; }
int cfgetospeed_custom(const struct termios *tios) { errno = EINVAL; return -1; }
#else /* USE_CUSTOM_BAUD */
int
use_custom_baud()
{
#ifdef __linux__
static int use = -1;
if ( use < 0 )
use = getenv("NO_CUSTOM_BAUD") ? 0 : 1;
return use;
#else
return 1;
#endif
}
#endif /* of ndef USE_CUSTOM_BAUD */
/**************************************************************************/
/*
* Local Variables:
* mode:c
* tab-width: 4
* c-basic-offset: 4
* End:
*/

View File

@ -87,6 +87,14 @@
#endif /* of ndef NO_CUSTOM_BAUD else */
#include <termios.h>
int use_custom_baud();
int cfsetispeed_custom(struct termios *tios, int speed);
int cfsetospeed_custom(struct termios *tios, int speed);
int cfgetispeed_custom(const struct termios *tios);
int cfgetospeed_custom(const struct termios *tios);
#endif /* CUSTBAUD_H */
/**************************************************************************/

View File

@ -71,11 +71,11 @@ int cfsetispeed_custom(struct termios *tiop, int speed) {
return cfsetispeed(tiop, speed);
}
int cfgetospeed_custom(struct termios *tiop) {
int cfgetospeed_custom(const struct termios *tiop) {
return cfgetospeed(tiop);
}
int cfgetispeed_custom(struct termios *tiop) {
int cfgetispeed_custom(const struct termios *tiop) {
return cfgetispeed(tiop);
}

View File

@ -87,8 +87,8 @@
int cfsetospeed_custom(struct termios *tiop, int speed);
int cfsetispeed_custom(struct termios *tiop, int speed);
int cfgetospeed_custom(struct termios *tiop);
int cfgetispeed_custom(struct termios *tiop);
int cfgetospeed_custom(const struct termios *tiop);
int cfgetispeed_custom(const struct termios *tiop);
/***************************************************************************/

View File

@ -1626,6 +1626,8 @@ show_usage(char *name)
#endif
#ifdef USE_CUSTOM_BAUD
printf(" USE_CUSTOM_BAUD is enabled\n");
if ( ! use_custom_baud() )
printf(" NO_CUSTOM_BAUD is set\n");
#endif
printf("\nUsage is: %s [options] <tty port device>\n", s);

30
term.c
View File

@ -312,11 +312,10 @@ Bspeed(speed_t code)
int
term_baud_ok(int baud)
{
#ifndef USE_CUSTOM_BAUD
return (Bcode(baud) != BNONE) ? 1 : 0;
#else
if ( use_custom_baud() )
return (baud >= 0);
#endif
else
return (Bcode(baud) != BNONE) ? 1 : 0;
}
int
@ -817,7 +816,11 @@ term_set_baudrate (int fd, int baudrate)
/* ispeed = 0, means same as ospeed (see POSIX) */
cfsetispeed(&tio, B0);
} else {
#ifdef USE_CUSTOM_BAUD
if ( ! use_custom_baud() ) {
term_errno = TERM_EBAUD;
rval = -1;
break;
}
r = cfsetospeed_custom(&tio, baudrate);
if ( r < 0 ) {
term_errno = TERM_ESETOSPEED;
@ -826,11 +829,6 @@ term_set_baudrate (int fd, int baudrate)
}
/* ispeed = 0, means same as ospeed (see POSIX) */
cfsetispeed(&tio, B0);
#else /* ! defined USE_CUSTOM_BAUD */
term_errno = TERM_EBAUD;
rval = -1;
break;
#endif /* of USE_CUSTOM_BAUD */
}
term.nexttermios[i] = tio;
@ -857,23 +855,23 @@ term_get_baudrate (int fd, int *ispeed)
if ( ispeed ) {
code = cfgetispeed(&term.currtermios[i]);
*ispeed = Bspeed(code);
#ifdef USE_CUSTOM_BAUD
if ( use_custom_baud() ) {
if ( *ispeed < 0 ) {
*ispeed = cfgetispeed_custom(&term.currtermios[i]);
}
#endif
}
}
code = cfgetospeed(&term.currtermios[i]);
ospeed = Bspeed(code);
if ( ospeed < 0 ) {
#ifdef USE_CUSTOM_BAUD
if ( ! use_custom_baud() ) {
term_errno = TERM_EGETSPEED;
break;
}
ospeed = cfgetospeed_custom(&term.currtermios[i]);
if ( ospeed < 0 ) {
term_errno = TERM_EGETSPEED;
}
#else
term_errno = TERM_EGETSPEED;
#endif
}
} while (0);

View File

@ -59,6 +59,8 @@ tc2setattr(int fd, int optional_actions, const struct termios *tios)
struct termios2 t2;
int cmd;
if ( ! use_custom_baud() ) return tcsetattr(fd, optional_actions, tios);
switch (optional_actions) {
case TCSANOW:
cmd = IOCTL_SETS;
@ -93,6 +95,8 @@ tc2getattr(int fd, struct termios *tios)
size_t i;
int r;
if ( ! use_custom_baud() ) return tcgetattr(fd, tios);
r = ioctl(fd, IOCTL_GETS, &t2);
if (r < 0) return r;
@ -126,6 +130,8 @@ tc2getattr(int fd, struct termios *tios)
int
cf2setispeed(struct termios *tios, speed_t speed)
{
if ( ! use_custom_baud() ) return cfsetispeed(tios, speed);
if ( (speed & ~CBAUD) != 0
&& (speed < B57600 || speed > __MAX_BAUD) ) {
errno = EINVAL;
@ -139,8 +145,10 @@ cf2setispeed(struct termios *tios, speed_t speed)
}
speed_t
cf2getispeed(struct termios *tios)
cf2getispeed(const struct termios *tios)
{
if ( ! use_custom_baud() ) return cfgetispeed(tios);
return (tios->c_cflag >> IBSHIFT) & (CBAUD | CBAUDEX);
}
@ -150,6 +158,8 @@ cf2getispeed(struct termios *tios)
int
cf2setospeed_custom(struct termios *tios, int speed)
{
if ( ! use_custom_baud() ) { errno = EINVAL; return -1; }
if ( speed <= 0 ) {
errno = EINVAL;
return -1;
@ -164,6 +174,8 @@ cf2setospeed_custom(struct termios *tios, int speed)
int
cf2setispeed_custom(struct termios *tios, int speed)
{
if ( ! use_custom_baud() ) { errno = EINVAL; return -1; }
if ( speed < 0 ) {
errno = EINVAL;
return -1;

View File

@ -55,12 +55,12 @@ int tc2getattr(int fd, struct termios *tios);
* old one, supports different input and output speeds for a
* device. The "speed" argument must be (and the return value will be)
* one of the standard "Bxxxx" macros. If cf2getispeed() or
* cfgetospeed(3) return CBAUDEX, then the respective baudrate is a
* cfgetospeed(3) return BOTHER, then the respective baudrate is a
* custom one. Read the "termios.c_ispeed" / "termios.c_ospeed" fields
* to get the custom value (as a numeric speed). */
int cf2setispeed(struct termios *tios, speed_t speed);
speed_t cf2getispeed(struct termios *tios);
speed_t cf2getispeed(const struct termios *tios);
/* Use these to set *custom* input and output baudrates for a
* device. The "speed" argument must be a numeric baudrate value

View File

@ -72,7 +72,8 @@ called: "the CIBAUD field"), together with field "c_ispeed" control
the input baudrate.
BTW: Usually CBAUD & CBAUDEX == CBAUD. That is, CBAUDEX *is*
one of the CBAUD bits.
one of the CBAUD bits. See end of this file for more on the usual
relationship of CBAUD, CBAUDEX, BOTHER
When issuing one of the TCSETS*2 ioctls, everything contained in the
"termios2" structure is copied to a kernel-resident structure and the
@ -147,3 +148,27 @@ baudrate values supplied by the serial drivers can be seen in file
"tty_termios_encode_baud_rate()" which is what the serial drivers call
to notify the kernel about the effective baudrate.
Baud-codes, CBAUD, CBAUDEX, and BOTHER
--------------------------------------
CBAUD = 0010017 ---> 0001 0000 0000 1111 mask
CBUADEX = 0010000 ---> 0001 0000 0000 0000 extender bit
BOTHER = 0010000 ---> 0001 0000 0000 0000 a reserved code
Usually CBAUD includes CBAUDEX. In any case the mask is always CBAUD &
CBAUDEX (which is usually == CBAUD)
Basic codes (Bxxx & CBAUDEX == 0)
B0 > ---0 ---- ---- 0000
B50 > ---0 ---- ---- 0001
... 16 in total ...
B38400 > ---0 ---- ---- 1111
Extended codes (Bxxx & CBAUDEX == 1)
CBAUDEX / BOTHER > ---1 ---- ---- 0000
B57600 > ---1 ---- ---- 0001
... 16 in total ...
B4000000 > ---1 ---- ---- 1111