termios_linux.h 3.7 KB

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