tty.c 7.0 KB

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