console.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Copyright (c) 2006-2023, 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 <rtthread.h>
  11. #include <dfs_file.h>
  12. #include <dfs_fs.h>
  13. #include <tty.h>
  14. #define DBG_TAG "CONSOLE"
  15. #ifdef RT_TTY_DEBUG
  16. #define DBG_LVL DBG_LOG
  17. #else
  18. #define DBG_LVL DBG_INFO
  19. #endif /* RT_TTY_DEBUG */
  20. #include <rtdbg.h>
  21. static struct tty_struct console_dev;
  22. static void console_rx_notify(struct rt_device *dev)
  23. {
  24. struct tty_struct *console = NULL;
  25. int len = 0;
  26. int lens = 0;
  27. char ch = 0;
  28. char buf[1024] = {0};
  29. console = (struct tty_struct *)dev;
  30. RT_ASSERT(console != RT_NULL);
  31. while (1)
  32. {
  33. len = rt_device_read(console->io_dev, -1, &ch, 1);
  34. if (len == 0)
  35. {
  36. break;
  37. }
  38. lens += len;
  39. buf[lens-1] = ch;
  40. if (lens > 1024)
  41. {
  42. break;
  43. }
  44. }
  45. if (console->ldisc->ops->receive_buf)
  46. {
  47. console->ldisc->ops->receive_buf((struct tty_struct *)console, buf, lens);
  48. }
  49. }
  50. struct tty_struct *console_tty_get(void)
  51. {
  52. return &console_dev;
  53. }
  54. static void iodev_close(struct tty_struct *console)
  55. {
  56. struct rt_device_notify rx_notify;
  57. rx_notify.notify = RT_NULL;
  58. rx_notify.dev = RT_NULL;
  59. /* clear notify */
  60. rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
  61. rt_device_close(console->io_dev);
  62. }
  63. static rt_err_t iodev_open(struct tty_struct *console)
  64. {
  65. rt_err_t ret = RT_EOK;
  66. struct rt_device_notify rx_notify;
  67. rt_uint16_t oflags = 0;
  68. rt_device_control(console->io_dev, RT_DEVICE_CTRL_CONSOLE_OFLAG, &oflags);
  69. ret = rt_device_open(console->io_dev, oflags);
  70. if (ret != RT_EOK)
  71. {
  72. return -RT_ERROR;
  73. }
  74. rx_notify.notify = console_rx_notify;
  75. rx_notify.dev = (struct rt_device *)console;
  76. rt_device_control(console->io_dev, RT_DEVICE_CTRL_NOTIFY_SET, &rx_notify);
  77. return RT_EOK;
  78. }
  79. struct rt_device *console_get_iodev(void)
  80. {
  81. rt_base_t level = 0;
  82. struct rt_device *iodev = RT_NULL;
  83. level = rt_hw_interrupt_disable();
  84. iodev = console_dev.io_dev;
  85. rt_hw_interrupt_enable(level);
  86. return iodev;
  87. }
  88. struct rt_device *console_set_iodev(struct rt_device *iodev)
  89. {
  90. rt_base_t level = 0;
  91. struct rt_device *io_before = RT_NULL;
  92. struct tty_struct *console = RT_NULL;
  93. RT_ASSERT(iodev != RT_NULL);
  94. console = &console_dev;
  95. level = rt_hw_interrupt_disable();
  96. RT_ASSERT(console->init_flag >= TTY_INIT_FLAG_REGED);
  97. io_before = console->io_dev;
  98. if (iodev == io_before)
  99. {
  100. goto exit;
  101. }
  102. if (console->init_flag >= TTY_INIT_FLAG_INITED)
  103. {
  104. /* close old device */
  105. iodev_close(console);
  106. }
  107. console->io_dev = iodev;
  108. if (console->init_flag >= TTY_INIT_FLAG_INITED)
  109. {
  110. rt_err_t ret;
  111. /* open new device */
  112. ret = iodev_open(console);
  113. RT_ASSERT(ret == RT_EOK);
  114. }
  115. exit:
  116. rt_hw_interrupt_enable(level);
  117. return io_before;
  118. }
  119. /* RT-Thread Device Interface */
  120. /*
  121. * This function initializes console device.
  122. */
  123. static rt_err_t rt_console_init(struct rt_device *dev)
  124. {
  125. rt_base_t level = 0;
  126. rt_err_t result = RT_EOK;
  127. struct tty_struct *console = RT_NULL;
  128. RT_ASSERT(dev != RT_NULL);
  129. console = (struct tty_struct *)dev;
  130. level = rt_hw_interrupt_disable();
  131. RT_ASSERT(console->init_flag == TTY_INIT_FLAG_REGED);
  132. result = iodev_open(console);
  133. if (result != RT_EOK)
  134. {
  135. goto exit;
  136. }
  137. console->init_flag = TTY_INIT_FLAG_INITED;
  138. exit:
  139. rt_hw_interrupt_enable(level);
  140. return result;
  141. }
  142. static rt_err_t rt_console_open(struct rt_device *dev, rt_uint16_t oflag)
  143. {
  144. rt_err_t result = RT_EOK;
  145. struct tty_struct *console = RT_NULL;
  146. RT_ASSERT(dev != RT_NULL);
  147. console = (struct tty_struct *)dev;
  148. RT_ASSERT(console != RT_NULL);
  149. RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
  150. return result;
  151. }
  152. static rt_err_t rt_console_close(struct rt_device *dev)
  153. {
  154. rt_err_t result = RT_EOK;
  155. struct tty_struct *console = RT_NULL;
  156. console = (struct tty_struct *)dev;
  157. RT_ASSERT(console != RT_NULL);
  158. RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
  159. return result;
  160. }
  161. static rt_ssize_t rt_console_read(struct rt_device *dev,
  162. rt_off_t pos,
  163. void *buffer,
  164. rt_size_t size)
  165. {
  166. rt_size_t len = 0;
  167. return len;
  168. }
  169. static rt_ssize_t rt_console_write(struct rt_device *dev,
  170. rt_off_t pos,
  171. const void *buffer,
  172. rt_size_t size)
  173. {
  174. rt_size_t len = 0;
  175. struct tty_struct *console = RT_NULL;
  176. console = (struct tty_struct *)dev;
  177. RT_ASSERT(console != RT_NULL);
  178. RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
  179. len = rt_device_write((struct rt_device *)console->io_dev, -1, buffer, size);
  180. return len;
  181. }
  182. static rt_err_t rt_console_control(rt_device_t dev, int cmd, void *args)
  183. {
  184. rt_size_t len = 0;
  185. struct tty_struct *console = RT_NULL;
  186. console = (struct tty_struct *)dev;
  187. RT_ASSERT(console != RT_NULL);
  188. RT_ASSERT(console->init_flag == TTY_INIT_FLAG_INITED);
  189. len = rt_device_control((struct rt_device *)console->io_dev, cmd, args);
  190. return len;
  191. }
  192. #ifdef RT_USING_DEVICE_OPS
  193. const static struct rt_device_ops console_ops =
  194. {
  195. rt_console_init,
  196. rt_console_open,
  197. rt_console_close,
  198. rt_console_read,
  199. rt_console_write,
  200. rt_console_control,
  201. };
  202. #endif
  203. /*
  204. * console register
  205. */
  206. static struct dfs_file_ops con_fops;
  207. rt_err_t console_register(const char *name, struct rt_device *iodev)
  208. {
  209. rt_err_t ret = RT_EOK;
  210. struct rt_device *device = RT_NULL;
  211. struct tty_struct *console = &console_dev;
  212. RT_ASSERT(iodev != RT_NULL);
  213. RT_ASSERT(console->init_flag == TTY_INIT_FLAG_NONE);
  214. tty_init(console, TTY_DRIVER_TYPE_CONSOLE, SERIAL_TYPE_NORMAL, iodev);
  215. console_ldata_init(console);
  216. device = &(console->parent);
  217. device->type = RT_Device_Class_Char;
  218. #ifdef RT_USING_DEVICE_OPS
  219. device->ops = &console_ops;
  220. #else
  221. device->init = rt_console_init;
  222. device->open = rt_console_open;
  223. device->close = rt_console_close;
  224. device->read = rt_console_read;
  225. device->write = rt_console_write;
  226. device->control = rt_console_control;
  227. #endif
  228. /* register a character device */
  229. ret = rt_device_register(device, name, 0);
  230. if (ret != RT_EOK)
  231. {
  232. LOG_E("console driver register fail\n");
  233. }
  234. else
  235. {
  236. #ifdef RT_USING_POSIX_DEVIO
  237. /* set fops */
  238. memcpy(&con_fops, tty_get_fops(), sizeof(struct dfs_file_ops));
  239. device->fops = &con_fops;
  240. #endif
  241. }
  242. return ret;
  243. }