uboot/tools/termios_linux.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0+ */
   2/*
   3 * termios fuctions to support arbitrary baudrates (on Linux)
   4 *
   5 * Copyright (c) 2021 Pali Rohár <pali@kernel.org>
   6 * Copyright (c) 2021 Marek Behún <marek.behun@nic.cz>
   7 */
   8
   9#ifndef _TERMIOS_LINUX_H_
  10#define _TERMIOS_LINUX_H_
  11
  12/*
  13 * We need to use raw TCGETS2/TCSETS2 or TCGETS/TCSETS ioctls with the BOTHER
  14 * flag in struct termios2/termios, defined in Linux headers <asm/ioctls.h>
  15 * (included by <sys/ioctl.h>) and <asm/termbits.h>. Since these headers
  16 * conflict with glibc's header file <termios.h>, it is not possible to use
  17 * libc's termios functions and we need to reimplement them via ioctl() calls.
  18 *
  19 * An arbitrary baudrate is supported when the macro BOTHER is defined. The
  20 * baudrate value itself is then stored into the c_ospeed and c_ispeed members.
  21 * If ioctls TCGETS2/TCSETS2 are defined and supported then these fields are
  22 * present in struct termios2, otherwise these fields are present in struct
  23 * termios.
  24 *
  25 * Note that the Bnnn constants from <termios.h> need not be compatible with Bnnn
  26 * constants from <asm/termbits.h>.
  27 */
  28
  29#include <errno.h>
  30#include <sys/ioctl.h>
  31#include <sys/types.h>
  32#include <asm/termbits.h>
  33
  34#if defined(BOTHER) && defined(TCGETS2)
  35#define termios termios2
  36#endif
  37
  38static inline int tcgetattr(int fd, struct termios *t)
  39{
  40#if defined(BOTHER) && defined(TCGETS2)
  41        return ioctl(fd, TCGETS2, t);
  42#else
  43        return ioctl(fd, TCGETS, t);
  44#endif
  45}
  46
  47static inline int tcsetattr(int fd, int a, const struct termios *t)
  48{
  49        int cmd;
  50
  51        switch (a) {
  52#if defined(BOTHER) && defined(TCGETS2)
  53        case TCSANOW:
  54                cmd = TCSETS2;
  55                break;
  56        case TCSADRAIN:
  57                cmd = TCSETSW2;
  58                break;
  59        case TCSAFLUSH:
  60                cmd = TCSETSF2;
  61                break;
  62#else
  63        case TCSANOW:
  64                cmd = TCSETS;
  65                break;
  66        case TCSADRAIN:
  67                cmd = TCSETSW;
  68                break;
  69        case TCSAFLUSH:
  70                cmd = TCSETSF;
  71                break;
  72#endif
  73        default:
  74                errno = EINVAL;
  75                return -1;
  76        }
  77
  78        return ioctl(fd, cmd, t);
  79}
  80
  81static inline int tcdrain(int fd)
  82{
  83        return ioctl(fd, TCSBRK, 1);
  84}
  85
  86static inline int tcflush(int fd, int q)
  87{
  88        return ioctl(fd, TCFLSH, q);
  89}
  90
  91static inline int tcsendbreak(int fd, int d)
  92{
  93#ifdef TCSBRKP
  94        return ioctl(fd, TCSBRKP, d);
  95#else
  96        return ioctl(fd, TCSBRK, 0);
  97#endif
  98}
  99
 100static inline int tcflow(int fd, int a)
 101{
 102        return ioctl(fd, TCXONC, a);
 103}
 104
 105static inline pid_t tcgetsid(int fd)
 106{
 107        pid_t sid;
 108
 109        if (ioctl(fd, TIOCGSID, &sid) < 0)
 110                return (pid_t)-1;
 111
 112        return sid;
 113}
 114
 115static inline speed_t cfgetospeed(const struct termios *t)
 116{
 117        return t->c_cflag & CBAUD;
 118}
 119
 120static inline int cfsetospeed(struct termios *t, speed_t s)
 121{
 122        if (s & ~CBAUD) {
 123                errno = EINVAL;
 124                return -1;
 125        }
 126
 127        t->c_cflag &= ~CBAUD;
 128        t->c_cflag |= s;
 129
 130        return 0;
 131}
 132
 133#ifdef IBSHIFT
 134static inline speed_t cfgetispeed(const struct termios *t)
 135{
 136        speed_t s = (t->c_cflag >> IBSHIFT) & CBAUD;
 137
 138        if (s == B0)
 139                return cfgetospeed(t);
 140        else
 141                return s;
 142}
 143
 144static inline int cfsetispeed(struct termios *t, speed_t s)
 145{
 146        if (s == 0)
 147                s = B0;
 148
 149        if (s & ~CBAUD) {
 150                errno = EINVAL;
 151                return -1;
 152        }
 153
 154        t->c_cflag &= ~(CBAUD << IBSHIFT);
 155        t->c_cflag |= s << IBSHIFT;
 156
 157        return 0;
 158}
 159#else /* !IBSHIFT */
 160static inline speed_t cfgetispeed(const struct termios *t)
 161{
 162        return cfgetospeed(t);
 163}
 164
 165static inline int cfsetispeed(struct termios *t, speed_t s)
 166{
 167        return cfsetospeed(t, s);
 168}
 169#endif /* !IBSHIFT */
 170
 171static inline int cfsetspeed(struct termios *t, speed_t s)
 172{
 173        if (cfsetospeed(t, s))
 174                return -1;
 175#ifdef IBSHIFT
 176        if (cfsetispeed(t, s))
 177                return -1;
 178#endif
 179
 180        return 0;
 181}
 182
 183static void cfmakeraw(struct termios *t)
 184{
 185        t->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR |
 186                        ICRNL | IXON);
 187        t->c_oflag &= ~OPOST;
 188        t->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
 189        t->c_cflag &= ~(CSIZE | PARENB);
 190        t->c_cflag |= CS8;
 191}
 192
 193#endif /* _TERMIOS_LINUX_H_ */
 194