termios_linux.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 <kabel@kernel.org>
  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/ioctls.h>
  30. #include <asm/termbits.h>
  31. #if defined(BOTHER) && defined(TCGETS2)
  32. #define termios termios2
  33. #endif
  34. static inline int tcgetattr(int fd, struct termios *t)
  35. {
  36. #if defined(BOTHER) && defined(TCGETS2)
  37. return ioctl(fd, TCGETS2, t);
  38. #else
  39. return ioctl(fd, TCGETS, t);
  40. #endif
  41. }
  42. static inline int tcsetattr(int fd, int a, const struct termios *t)
  43. {
  44. int cmd;
  45. switch (a) {
  46. #if defined(BOTHER) && defined(TCGETS2)
  47. case TCSANOW:
  48. cmd = TCSETS2;
  49. break;
  50. case TCSADRAIN:
  51. cmd = TCSETSW2;
  52. break;
  53. case TCSAFLUSH:
  54. cmd = TCSETSF2;
  55. break;
  56. #else
  57. case TCSANOW:
  58. cmd = TCSETS;
  59. break;
  60. case TCSADRAIN:
  61. cmd = TCSETSW;
  62. break;
  63. case TCSAFLUSH:
  64. cmd = TCSETSF;
  65. break;
  66. #endif
  67. default:
  68. errno = EINVAL;
  69. return -1;
  70. }
  71. return ioctl(fd, cmd, t);
  72. }
  73. static inline int tcdrain(int fd)
  74. {
  75. return ioctl(fd, TCSBRK, 1);
  76. }
  77. static inline int tcflush(int fd, int q)
  78. {
  79. return ioctl(fd, TCFLSH, q);
  80. }
  81. static inline int tcsendbreak(int fd, int d)
  82. {
  83. #ifdef TCSBRKP
  84. return ioctl(fd, TCSBRKP, d);
  85. #else
  86. return ioctl(fd, TCSBRK, 0);
  87. #endif
  88. }
  89. static inline int tcflow(int fd, int a)
  90. {
  91. return ioctl(fd, TCXONC, a);
  92. }
  93. static inline pid_t tcgetsid(int fd)
  94. {
  95. pid_t sid;
  96. if (ioctl(fd, TIOCGSID, &sid) < 0)
  97. return (pid_t)-1;
  98. return sid;
  99. }
  100. static inline speed_t cfgetospeed(const struct termios *t)
  101. {
  102. return t->c_cflag & CBAUD;
  103. }
  104. static inline int cfsetospeed(struct termios *t, speed_t s)
  105. {
  106. if (s & ~CBAUD) {
  107. errno = EINVAL;
  108. return -1;
  109. }
  110. t->c_cflag &= ~CBAUD;
  111. t->c_cflag |= s;
  112. return 0;
  113. }
  114. #ifdef IBSHIFT
  115. static inline speed_t cfgetispeed(const struct termios *t)
  116. {
  117. speed_t s = (t->c_cflag >> IBSHIFT) & CBAUD;
  118. if (s == B0)
  119. return cfgetospeed(t);
  120. else
  121. return s;
  122. }
  123. static inline int cfsetispeed(struct termios *t, speed_t s)
  124. {
  125. if (s == 0)
  126. s = B0;
  127. if (s & ~CBAUD) {
  128. errno = EINVAL;
  129. return -1;
  130. }
  131. t->c_cflag &= ~(CBAUD << IBSHIFT);
  132. t->c_cflag |= s << IBSHIFT;
  133. return 0;
  134. }
  135. #else /* !IBSHIFT */
  136. static inline speed_t cfgetispeed(const struct termios *t)
  137. {
  138. return cfgetospeed(t);
  139. }
  140. static inline int cfsetispeed(struct termios *t, speed_t s)
  141. {
  142. return cfsetospeed(t, s);
  143. }
  144. #endif /* !IBSHIFT */
  145. static inline int cfsetspeed(struct termios *t, speed_t s)
  146. {
  147. if (cfsetospeed(t, s))
  148. return -1;
  149. #ifdef IBSHIFT
  150. if (cfsetispeed(t, s))
  151. return -1;
  152. #endif
  153. return 0;
  154. }
  155. static void cfmakeraw(struct termios *t)
  156. {
  157. t->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR |
  158. ICRNL | IXON);
  159. t->c_oflag &= ~OPOST;
  160. t->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  161. t->c_cflag &= ~(CSIZE | PARENB);
  162. t->c_cflag |= CS8;
  163. }
  164. #endif /* _TERMIOS_LINUX_H_ */