tty.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021.12.07 linzhenxing first version
  9. */
  10. #include <dfs_file.h>
  11. #include <dfs_fs.h>
  12. #include <lwp.h>
  13. #include <rtdevice.h>
  14. #include <rtthread.h>
  15. #include <tty.h>
  16. #include <tty_ldisc.h>
  17. #if defined(RT_USING_POSIX)
  18. #include <posix_termios.h>
  19. #endif
  20. #define DBG_TAG "TTY"
  21. #ifdef RT_TTY_DEBUG
  22. #define DBG_LVL DBG_LOG
  23. #else
  24. #define DBG_LVL DBG_INFO
  25. #endif /* RT_TTY_DEBUG */
  26. #include <rtdbg.h>
  27. struct termios tty_std_termios = { /* for the benefit of tty drivers */
  28. .c_iflag = IMAXBEL | IUCLC | INLCR | ICRNL | IGNPAR,
  29. .c_oflag = OPOST,
  30. .c_cflag = B38400 | CS8 | CREAD | HUPCL,
  31. .c_lflag = ISIG | ECHOE | TOSTOP | NOFLSH,
  32. RT_NULL,/* .c_line = N_TTY, */
  33. .c_cc = INIT_C_CC,
  34. .__c_ispeed = 38400,
  35. .__c_ospeed = 38400
  36. };
  37. rt_inline int tty_sigismember(lwp_sigset_t *set, int _sig)
  38. {
  39. unsigned long sig = _sig - 1;
  40. if (_LWP_NSIG_WORDS == 1)
  41. {
  42. return 1 & (set->sig[0] >> sig);
  43. }
  44. else
  45. {
  46. return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW));
  47. }
  48. }
  49. static int is_ignored(int sig)
  50. {
  51. return (tty_sigismember(&current->signal, sig) ||
  52. current->signal_handler[sig-1] == SIG_IGN);
  53. }
  54. /**
  55. * tty_check_change - check for POSIX terminal changes
  56. * @tty: tty to check
  57. *
  58. * If we try to write to, or set the state of, a terminal and we're
  59. * not in the foreground, send a SIGTTOU. If the signal is blocked or
  60. * ignored, go ahead and perform the operation. (POSIX 7.2)
  61. *
  62. * Locking: ctrl_lock
  63. */
  64. int __tty_check_change(struct tty_struct *tty, int sig)
  65. {
  66. pid_t pgrp = 0, tty_pgrp = 0;
  67. struct rt_lwp *lwp = tty->foreground;
  68. int ret = 0;
  69. int level = 0;
  70. level = rt_hw_interrupt_disable();
  71. if (current == RT_NULL)
  72. {
  73. return 0;
  74. }
  75. if (current->tty != tty)
  76. {
  77. return 0;
  78. }
  79. pgrp = current->__pgrp;
  80. tty_pgrp = tty->pgrp;
  81. if (tty_pgrp && pgrp != tty->pgrp)
  82. {
  83. if (is_ignored(sig))
  84. {
  85. if (sig == SIGTTIN)
  86. {
  87. ret = -EIO;
  88. }
  89. }
  90. else
  91. {
  92. if (lwp)
  93. {
  94. lwp_kill(lwp_to_pid(lwp), sig);
  95. }
  96. }
  97. }
  98. rt_hw_interrupt_enable(level);
  99. if (!tty_pgrp)
  100. {
  101. LOG_D(tty, "sig=%d, tty->pgrp == -1!\n", sig);
  102. }
  103. return ret;
  104. }
  105. int tty_check_change(struct tty_struct *tty)
  106. {
  107. return __tty_check_change(tty, SIGTTOU);
  108. }
  109. static int tty_open(struct dfs_fd *fd)
  110. {
  111. int ret = 0;
  112. int noctty = 0;
  113. struct tty_struct *tty = RT_NULL;
  114. struct tty_ldisc *ld = RT_NULL;
  115. tty = (struct tty_struct *)fd->fnode->data;
  116. RT_ASSERT(tty != RT_NULL);
  117. ld = tty->ldisc;
  118. if (ld->ops->open)
  119. {
  120. ret = ld->ops->open(fd);
  121. }
  122. noctty = (fd->flags & O_NOCTTY);
  123. rt_device_t device = (rt_device_t)fd->fnode->data;
  124. if (fd->fnode->ref_count == 1)
  125. {
  126. ret = rt_device_open(device, fd->flags);
  127. }
  128. if (current == RT_NULL) //kernel mode not lwp
  129. {
  130. return ret;
  131. }
  132. if (!noctty &&
  133. current->leader &&
  134. !current->tty &&
  135. tty->session == -1)
  136. {
  137. current->tty = tty;
  138. current->tty_old_pgrp = 0;
  139. tty->session = current->session;
  140. tty->pgrp = current->__pgrp;
  141. tty->foreground = current;
  142. }
  143. return ret;
  144. }
  145. static int tty_close(struct dfs_fd *fd)
  146. {
  147. int ret = 0;
  148. struct tty_struct *tty = RT_NULL;
  149. struct tty_ldisc *ld = RT_NULL;
  150. tty = (struct tty_struct *)fd->fnode->data;
  151. RT_ASSERT(tty != RT_NULL);
  152. ld = tty->ldisc;
  153. if (ld->ops->close)
  154. {
  155. //ld->ops->close(tty);
  156. }
  157. if (fd->fnode->ref_count == 1)
  158. {
  159. ret = rt_device_close((rt_device_t)tty);
  160. }
  161. return ret;
  162. }
  163. static int tiocsctty(struct tty_struct *tty, int arg)
  164. {
  165. if (current->leader &&
  166. (current->session == tty->session))
  167. {
  168. return 0;
  169. }
  170. /*
  171. * The process must be a session leader and
  172. * not have a controlling tty already.
  173. */
  174. if (!current->leader || current->tty)
  175. {
  176. return -EPERM;
  177. }
  178. if (tty->session > 0)
  179. {
  180. LOG_E("this tty have control process\n");
  181. }
  182. current->tty = tty;
  183. current->tty_old_pgrp = 0;
  184. tty->session = current->session;
  185. tty->pgrp = current->__pgrp;
  186. tty->foreground = current;
  187. if (tty->type == TTY_DRIVER_TYPE_PTY)
  188. {
  189. tty->other_struct->foreground = current;
  190. }
  191. return 0;
  192. }
  193. static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args)
  194. {
  195. int ret = 0;
  196. struct tty_struct *tty = RT_NULL;
  197. struct tty_struct *real_tty = RT_NULL;
  198. struct tty_ldisc *ld = RT_NULL;
  199. tty = (struct tty_struct *)fd->fnode->data;
  200. RT_ASSERT(tty != RT_NULL);
  201. if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER)
  202. {
  203. real_tty = tty->other_struct;
  204. }
  205. else
  206. {
  207. real_tty = tty;
  208. }
  209. switch (cmd)
  210. {
  211. case TIOCSCTTY:
  212. return tiocsctty(real_tty, 1);
  213. }
  214. ld = tty->ldisc;
  215. if (ld->ops->ioctl)
  216. {
  217. ret = ld->ops->ioctl(fd, cmd, args);
  218. }
  219. return ret;
  220. }
  221. static int tty_read(struct dfs_fd *fd, void *buf, size_t count)
  222. {
  223. int ret = 0;
  224. struct tty_struct *tty = RT_NULL;
  225. struct tty_ldisc *ld = RT_NULL;
  226. tty = (struct tty_struct *)fd->fnode->data;
  227. RT_ASSERT(tty != RT_NULL);
  228. ld = tty->ldisc;
  229. if (ld->ops->read)
  230. {
  231. ret = ld->ops->read(fd, buf, count);
  232. }
  233. return ret;
  234. }
  235. static int tty_write(struct dfs_fd *fd, const void *buf, size_t count)
  236. {
  237. int ret = 0;
  238. struct tty_struct *tty = RT_NULL;
  239. struct tty_ldisc *ld = RT_NULL;
  240. tty = (struct tty_struct *)fd->fnode->data;
  241. RT_ASSERT(tty != RT_NULL);
  242. ld = tty->ldisc;
  243. if (ld->ops->write)
  244. {
  245. ret = ld->ops->write(fd, buf, count);
  246. }
  247. return ret;
  248. }
  249. static int tty_poll(struct dfs_fd *fd, struct rt_pollreq *req)
  250. {
  251. int ret = 0;
  252. struct tty_struct *tty = RT_NULL;
  253. struct tty_ldisc *ld = RT_NULL;
  254. tty = (struct tty_struct *)fd->fnode->data;
  255. RT_ASSERT(tty != RT_NULL);
  256. ld = tty->ldisc;
  257. if (ld->ops->poll)
  258. {
  259. ret = ld->ops->poll(fd, req);
  260. }
  261. return ret;
  262. }
  263. static const struct dfs_file_ops tty_fops =
  264. {
  265. tty_open,
  266. tty_close,
  267. tty_ioctl,
  268. tty_read,
  269. tty_write,
  270. RT_NULL, /* flush */
  271. RT_NULL, /* lseek */
  272. RT_NULL, /* getdents */
  273. tty_poll,
  274. };
  275. static const struct dfs_file_ops console_fops =
  276. {
  277. tty_open,
  278. tty_close,
  279. tty_ioctl,
  280. tty_read,
  281. tty_write,
  282. RT_NULL, /* flush */
  283. RT_NULL, /* lseek */
  284. RT_NULL, /* getdents */
  285. tty_poll,
  286. };
  287. void console_init()
  288. {
  289. n_tty_init();
  290. }
  291. void tty_set_fops(struct dfs_file_ops *fops)
  292. {
  293. *fops = tty_fops;
  294. }
  295. void console_set_fops(struct dfs_file_ops *fops)
  296. {
  297. *fops = console_fops;
  298. }