drv_Vterm.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include "RT_Vterm.h"
  2. #include "shell.h"
  3. #include "string.h"
  4. #include <ctype.h>
  5. #include <rtdevice.h>
  6. #include <rtthread.h>
  7. #include <stdio.h>
  8. /**< Maximum number of registered Vterm commands */
  9. #define Vterm_CMD_MAX 8
  10. /**< Size of input buffer for Vterm command processing */
  11. #define Vterm_INPUT_BUF_SIZE 128
  12. /**< Table storing registered Vterm commands and their callbacks */
  13. static vterm_cmd_entry_t vterm_cmd_table[Vterm_CMD_MAX];
  14. /**< Current count of registered Vterm commands */
  15. static int vterm_cmd_count = 0;
  16. /**
  17. * @struct vterm_device
  18. * @brief Virtual terminal device structure, extending RT-Thread device
  19. */
  20. struct vterm_device
  21. {
  22. struct rt_device parent; /**< Inherited RT-Thread device base */
  23. rt_device_t original_console; /**< Original console device (for restoration) */
  24. rt_device_t original_finsh; /**< Original FinSH device (for restoration) */
  25. };
  26. /**< Global instance of virtual terminal device */
  27. static struct vterm_device vterm_dev;
  28. extern struct finsh_shell *shell; /**< External reference to FinSH shell instance */
  29. /****************************************/
  30. /**
  31. * @brief Open virtual terminal device
  32. *
  33. * @param[in] dev Pointer to RT-Thread device structure
  34. * @param[in] oflag Open flags (unused in this implementation)
  35. *
  36. * @retval rt_err_t RT_EOK always (success)
  37. *
  38. * @note No special initialization needed for open operation
  39. */
  40. static rt_err_t vterm_open(rt_device_t dev, rt_uint16_t oflag)
  41. {
  42. return RT_EOK; // Vterm open requires no specific setup
  43. }
  44. /**
  45. * @brief Write data to virtual terminal
  46. *
  47. * @param[in] dev Pointer to RT-Thread device structure
  48. * @param[in] pos Offset (unused for character devices)
  49. * @param[in] buffer Pointer to data buffer to write
  50. * @param[in] size Number of bytes to write
  51. *
  52. * @retval rt_size_t Number of bytes written (always equals input size)
  53. *
  54. * @note 1. Converts '\n' to "\r\n" for proper line endings
  55. * 2. Uses RT_Vterm_PutChar for actual data transmission
  56. */
  57. static rt_ssize_t vterm_write(rt_device_t dev, rt_off_t pos,
  58. const void *buffer, rt_size_t size)
  59. {
  60. const char *ptr = (const char *)buffer;
  61. rt_size_t i;
  62. // Write each character, converting newline to CRLF
  63. for (i = 0; i < size; i++)
  64. {
  65. if (ptr[i] == '\n')
  66. {
  67. RT_Vterm_PutChar('\r'); // Prepend carriage return before newline
  68. }
  69. RT_Vterm_PutChar(ptr[i]);
  70. }
  71. return size; // All bytes are written (logical success)
  72. }
  73. /**
  74. * @brief Read data from virtual terminal
  75. *
  76. * @param[in] dev Pointer to RT-Thread device structure
  77. * @param[in] pos Offset (unused for character devices)
  78. * @param[out] buffer Pointer to buffer to store read data
  79. * @param[in] size Maximum number of bytes to read
  80. *
  81. * @retval rt_ssize_t Number of bytes actually read
  82. *
  83. * @note Wraps RT_Vterm_Read for data retrieval from downstream buffer
  84. */
  85. static rt_ssize_t vterm_read(rt_device_t dev, rt_off_t pos,
  86. void *buffer, rt_size_t size)
  87. {
  88. rt_size_t ret = (rt_size_t)RT_Vterm_Read(buffer, size);
  89. return ret;
  90. }
  91. /****************************************/
  92. /**
  93. * @brief Indicate received data to FinSH shell
  94. *
  95. * @param[in] dev Pointer to RT-Thread device structure (unused)
  96. * @param[in] size Size of received data (unused)
  97. *
  98. * @retval rt_err_t RT_EOK if shell semaphore is released successfully
  99. *
  100. * @note Triggers FinSH processing by releasing its receive semaphore
  101. */
  102. static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size)
  103. {
  104. if (shell)
  105. rt_sem_release(&shell->rx_sem); // Notify shell of available data
  106. return RT_EOK;
  107. }
  108. /****************************************/
  109. /**
  110. * @brief Switch all I/O (console and FinSH) to virtual terminal
  111. *
  112. * @note 1. Saves original console and FinSH devices for later restoration
  113. * 2. Redirects console and FinSH output to "vterm_buffer" device
  114. * 3. Prints confirmation message via original console
  115. */
  116. void vterm_console(void)
  117. {
  118. /* Save original I/O devices */
  119. vterm_dev.original_console = rt_console_get_device();
  120. vterm_dev.original_finsh = rt_device_find(finsh_get_device());
  121. /* Redirect console and FinSH to Vterm */
  122. rt_console_set_device("vterm");
  123. finsh_set_device("vterm");
  124. rt_kprintf("[OK] All I/O now via Vterm\n"); // Confirmation message
  125. }
  126. MSH_CMD_EXPORT(vterm_console, Switch ALL I / O to Vterm);
  127. /****************************************/
  128. /**
  129. * @brief Restore original I/O devices (console and FinSH)
  130. *
  131. * @note 1. Restores console and FinSH to their original devices
  132. * 2. Does nothing if original devices are not saved
  133. * 3. Prints confirmation message via restored console
  134. */
  135. void restore_original(void)
  136. {
  137. if (vterm_dev.original_console)
  138. {
  139. rt_console_set_device(vterm_dev.original_console->parent.name);
  140. }
  141. if (vterm_dev.original_finsh)
  142. {
  143. finsh_set_device(vterm_dev.original_finsh->parent.name);
  144. }
  145. rt_kprintf("[OK] Restored original I/O devices\n"); // Confirmation message
  146. }
  147. MSH_CMD_EXPORT(restore_original, Restore original I / O devices);
  148. /****************************************/
  149. /**
  150. * @brief Thread entry for polling Vterm data and notifying FinSH
  151. *
  152. * @param[in] p Unused (thread parameter placeholder)
  153. *
  154. * @note 1. Runs indefinitely, checking for downstream data every 10ms
  155. * 2. Triggers FinSH data processing via finsh_rx_ind when data is available
  156. */
  157. static void vterm_check(void)
  158. {
  159. if (RT_Vterm_HasData()) // Check if downstream buffer has data
  160. finsh_rx_ind(&vterm_dev.parent, 1); // Notify FinSH of new data
  161. }
  162. /****************************************/
  163. /**
  164. * @brief Initialize Vterm buffer device and related components
  165. *
  166. * @retval int RT_EOK on success, error code otherwise
  167. *
  168. * @note 1. Registers "vterm" as a character device
  169. * 2. Sets up device operations (open, read, write)
  170. * 3. Sets an idle hook for data detection
  171. */
  172. int vterm_device_init(void)
  173. {
  174. rt_err_t ret;
  175. // Initialize Vterm device structure
  176. vterm_dev.parent.type = RT_Device_Class_Char;
  177. vterm_dev.parent.open = vterm_open;
  178. vterm_dev.parent.read = vterm_read;
  179. vterm_dev.parent.write = vterm_write;
  180. // Register Vterm device with RT-Thread device manager
  181. ret = rt_device_register(&vterm_dev.parent, "vterm", RT_DEVICE_FLAG_RDWR);
  182. if (ret != RT_EOK)
  183. {
  184. return ret;
  185. }
  186. rt_thread_idle_sethook(vterm_check);
  187. return RT_EOK;
  188. }
  189. MSH_CMD_EXPORT(vterm_device_init, Initialize Vterm buffer device);
  190. /****************************************/
  191. /**
  192. * @brief Switch the device of the shell terminal to vterm
  193. *
  194. * @retval int RT_EOK on success, error code otherwise
  195. *
  196. * @note 1. Initialize Vterm buffer device and related components
  197. * 2. Switch all I/O (console and FinSH) to virtual terminal
  198. */
  199. int rt_hw_vterm_console_init(void)
  200. {
  201. int ret = vterm_device_init();
  202. if (ret != RT_EOK)
  203. {
  204. return ret;
  205. }
  206. vterm_console();
  207. return RT_EOK;
  208. }
  209. MSH_CMD_EXPORT(rt_hw_vterm_console_init, Initialize Vterm buffer device);