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. unsigned long flags = 0;
  67. pid_t pgrp = 0, tty_pgrp = 0;
  68. struct rt_lwp *lwp = tty->foreground;
  69. int ret = 0;
  70. int level = 0;
  71. level = rt_hw_interrupt_disable();
  72. if (current == RT_NULL)
  73. {
  74. return 0;
  75. }
  76. if (current->tty != tty)
  77. {
  78. return 0;
  79. }
  80. pgrp = current->__pgrp;
  81. tty_pgrp = tty->pgrp;
  82. if (tty_pgrp && pgrp != tty->pgrp)
  83. {
  84. if (is_ignored(sig))
  85. {
  86. if (sig == SIGTTIN)
  87. {
  88. ret = -EIO;
  89. }
  90. }
  91. else
  92. {
  93. if (lwp)
  94. {
  95. lwp_kill(lwp_to_pid(lwp), sig);
  96. }
  97. }
  98. }
  99. rt_hw_interrupt_enable(level);
  100. if (!tty_pgrp)
  101. {
  102. LOG_D(tty, "sig=%d, tty->pgrp == -1!\n", sig);
  103. }
  104. return ret;
  105. }
  106. int tty_check_change(struct tty_struct *tty)
  107. {
  108. return __tty_check_change(tty, SIGTTOU);
  109. }
  110. static int tty_open(struct dfs_fd *fd)
  111. {
  112. int ret = 0;
  113. int noctty = 0;
  114. struct tty_struct *tty = RT_NULL;
  115. struct tty_ldisc *ld = RT_NULL;
  116. tty = (struct tty_struct *)fd->fnode->data;
  117. RT_ASSERT(tty != RT_NULL);
  118. ld = tty->ldisc;
  119. if (ld->ops->open)
  120. {
  121. ret = ld->ops->open(fd);
  122. }
  123. noctty = (fd->flags & O_NOCTTY);
  124. rt_device_t device = (rt_device_t)fd->fnode->data;
  125. if (fd->fnode->ref_count == 1)
  126. {
  127. ret = rt_device_open(device, fd->flags);
  128. }
  129. if (current == RT_NULL) //kernel mode not lwp
  130. {
  131. return ret;
  132. }
  133. if (!noctty &&
  134. current->leader &&
  135. !current->tty &&
  136. tty->session == -1)
  137. {
  138. current->tty = tty;
  139. current->tty_old_pgrp = 0;
  140. tty->session = current->session;
  141. tty->pgrp = current->__pgrp;
  142. tty->foreground = current;
  143. }
  144. return ret;
  145. }
  146. static int tty_close(struct dfs_fd *fd)
  147. {
  148. int ret = 0;
  149. struct tty_struct *tty = RT_NULL;
  150. struct tty_ldisc *ld = RT_NULL;
  151. tty = (struct tty_struct *)fd->fnode->data;
  152. RT_ASSERT(tty != RT_NULL);
  153. ld = tty->ldisc;
  154. if (ld->ops->close)
  155. {
  156. //ld->ops->close(tty);
  157. }
  158. if (fd->fnode->ref_count == 1)
  159. {
  160. ret = rt_device_close((rt_device_t)tty);
  161. }
  162. return ret;
  163. }
  164. static int tiocsctty(struct tty_struct *tty, int arg)
  165. {
  166. if (current->leader &&
  167. (current->session == tty->session))
  168. {
  169. return 0;
  170. }
  171. /*
  172. * The process must be a session leader and
  173. * not have a controlling tty already.
  174. */
  175. if (!current->leader || current->tty)
  176. {
  177. return -EPERM;
  178. }
  179. if (tty->session > 0)
  180. {
  181. LOG_E("this tty have control process\n");
  182. }
  183. current->tty = tty;
  184. current->tty_old_pgrp = 0;
  185. tty->session = current->session;
  186. tty->pgrp = current->__pgrp;
  187. tty->foreground = current;
  188. if (tty->type == TTY_DRIVER_TYPE_PTY)
  189. {
  190. tty->other_struct->foreground = current;
  191. }
  192. return 0;
  193. }
  194. static int tty_ioctl(struct dfs_fd *fd, int cmd, void *args)
  195. {
  196. int ret = 0;
  197. struct tty_struct *tty = RT_NULL;
  198. struct tty_struct *real_tty = RT_NULL;
  199. struct tty_ldisc *ld = RT_NULL;
  200. tty = (struct tty_struct *)fd->fnode->data;
  201. RT_ASSERT(tty != RT_NULL);
  202. if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER)
  203. {
  204. real_tty = tty->other_struct;
  205. }
  206. else
  207. {
  208. real_tty = tty;
  209. }
  210. switch (cmd)
  211. {
  212. case TIOCSCTTY:
  213. return tiocsctty(real_tty, 1);
  214. }
  215. ld = tty->ldisc;
  216. if (ld->ops->ioctl)
  217. {
  218. ret = ld->ops->ioctl(fd, cmd, args);
  219. }
  220. return ret;
  221. }
  222. static int tty_read(struct dfs_fd *fd, void *buf, size_t count)
  223. {
  224. int ret = 0;
  225. struct tty_struct *tty = RT_NULL;
  226. struct tty_ldisc *ld = RT_NULL;
  227. tty = (struct tty_struct *)fd->fnode->data;
  228. RT_ASSERT(tty != RT_NULL);
  229. ld = tty->ldisc;
  230. if (ld->ops->read)
  231. {
  232. ret = ld->ops->read(fd, buf, count);
  233. }
  234. return ret;
  235. }
  236. static int tty_write(struct dfs_fd *fd, const void *buf, size_t count)
  237. {
  238. int ret = 0;
  239. struct tty_struct *tty = RT_NULL;
  240. struct tty_ldisc *ld = RT_NULL;
  241. tty = (struct tty_struct *)fd->fnode->data;
  242. RT_ASSERT(tty != RT_NULL);
  243. ld = tty->ldisc;
  244. if (ld->ops->write)
  245. {
  246. ret = ld->ops->write(fd, buf, count);
  247. }
  248. return ret;
  249. }
  250. static int tty_poll(struct dfs_fd *fd, struct rt_pollreq *req)
  251. {
  252. int ret = 0;
  253. struct tty_struct *tty = RT_NULL;
  254. struct tty_ldisc *ld = RT_NULL;
  255. tty = (struct tty_struct *)fd->fnode->data;
  256. RT_ASSERT(tty != RT_NULL);
  257. ld = tty->ldisc;
  258. if (ld->ops->poll)
  259. {
  260. ret = ld->ops->poll(fd, req);
  261. }
  262. return ret;
  263. }
  264. static const struct dfs_file_ops tty_fops =
  265. {
  266. tty_open,
  267. tty_close,
  268. tty_ioctl,
  269. tty_read,
  270. tty_write,
  271. RT_NULL, /* flush */
  272. RT_NULL, /* lseek */
  273. RT_NULL, /* getdents */
  274. tty_poll,
  275. };
  276. static const struct dfs_file_ops console_fops =
  277. {
  278. tty_open,
  279. tty_close,
  280. tty_ioctl,
  281. tty_read,
  282. tty_write,
  283. RT_NULL, /* flush */
  284. RT_NULL, /* lseek */
  285. RT_NULL, /* getdents */
  286. tty_poll,
  287. };
  288. void console_init()
  289. {
  290. n_tty_init();
  291. }
  292. void tty_set_fops(struct dfs_file_ops *fops)
  293. {
  294. *fops = tty_fops;
  295. }
  296. void console_set_fops(struct dfs_file_ops *fops)
  297. {
  298. *fops = console_fops;
  299. }