vfs_console.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "esp_vfs_console.h"
  7. #include "esp_rom_sys.h"
  8. #include "esp_vfs_cdcacm.h"
  9. #include "esp_vfs_private.h"
  10. #include "esp_vfs_usb_serial_jtag.h"
  11. #include "esp_vfs_dev.h"
  12. #include "esp_private/usb_console.h"
  13. #include "sdkconfig.h"
  14. #define STRINGIFY(s) STRINGIFY2(s)
  15. #define STRINGIFY2(s) #s
  16. /**
  17. * This file is to concentrate all the vfs(UART, USB_SERIAL_JTAG, CDCACM) console into one single file.
  18. * Get the vfs information from their component (i.e. vfs_uart.c) through `esp_vfs_usb_xxx_get_console()`,
  19. * which can help us to output some string to two different ports(i.e both through uart and usb_serial_jtag).
  20. * Usually, we set a port as primary and another as secondary. For primary, it is used for all the features supported by each vfs implementation,
  21. * while the secondary is only used for output.
  22. */
  23. typedef struct {
  24. int fd_primary;
  25. int fd_secondary;
  26. } vfs_console_context_t;
  27. #if CONFIG_VFS_SUPPORT_IO
  28. // Primary register part.
  29. #ifdef CONFIG_ESP_CONSOLE_UART
  30. const static char *primary_path = "/dev/uart";
  31. #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
  32. const static char *primary_path = "/dev/usbserjtag";
  33. #elif CONFIG_ESP_CONSOLE_USB_CDC
  34. const static char *primary_path = "/dev/cdcacm";
  35. #endif
  36. // Secondary register part.
  37. #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  38. const static char *secondary_path = "/dev/secondary";
  39. static int secondary_vfs_index;
  40. #endif // Secondary part
  41. static int primary_vfs_index;
  42. static vfs_console_context_t vfs_console= {0};
  43. int console_open(const char * path, int flags, int mode)
  44. {
  45. // Primary port open
  46. #if CONFIG_ESP_CONSOLE_UART
  47. vfs_console.fd_primary = get_vfs_for_path(primary_path)->vfs.open("/"STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM), flags, mode);
  48. #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
  49. vfs_console.fd_primary = esp_vfs_usb_serial_jtag_get_vfs()->open("/", flags, mode);
  50. #elif CONFIG_ESP_CONSOLE_USB_CDC
  51. vfs_console.fd_primary = esp_vfs_cdcacm_get_vfs()->open("/", flags, mode);
  52. #endif
  53. // Secondary port open
  54. #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  55. vfs_console.fd_secondary = get_vfs_for_path(secondary_path)->vfs.open("/", flags, mode);
  56. #endif
  57. return 0;
  58. }
  59. ssize_t console_write(int fd, const void *data, size_t size)
  60. {
  61. // All function calls are to primary, except from write and close, which will be forwarded to both primary and secondary.
  62. get_vfs_for_index(primary_vfs_index)->vfs.write(vfs_console.fd_primary, data, size);
  63. #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  64. get_vfs_for_index(secondary_vfs_index)->vfs.write(vfs_console.fd_secondary, data, size);
  65. #endif
  66. return size;
  67. }
  68. int console_fstat(int fd, struct stat * st)
  69. {
  70. return get_vfs_for_index(primary_vfs_index)->vfs.fstat(fd, st);
  71. }
  72. int console_close(int fd)
  73. {
  74. // All function calls are to primary, except from write and close, which will be forwarded to both primary and secondary.
  75. get_vfs_for_index(primary_vfs_index)->vfs.close(vfs_console.fd_primary);
  76. #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  77. get_vfs_for_index(secondary_vfs_index)->vfs.close(vfs_console.fd_secondary);
  78. #endif
  79. return 0;
  80. }
  81. ssize_t console_read(int fd, void * dst, size_t size)
  82. {
  83. return get_vfs_for_index(primary_vfs_index)->vfs.read(vfs_console.fd_primary, dst, size);
  84. }
  85. int console_fcntl(int fd, int cmd, int arg)
  86. {
  87. return get_vfs_for_index(primary_vfs_index)->vfs.fcntl(vfs_console.fd_primary, cmd, arg);
  88. }
  89. int console_fsync(int fd)
  90. {
  91. return get_vfs_for_index(primary_vfs_index)->vfs.fsync(vfs_console.fd_primary);
  92. }
  93. #ifdef CONFIG_VFS_SUPPORT_DIR
  94. int console_access(const char *path, int amode)
  95. {
  96. // currently only UART support DIR.
  97. return get_vfs_for_index(primary_vfs_index)->vfs.access("/"STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM), amode);
  98. }
  99. #endif // CONFIG_VFS_SUPPORT_DIR
  100. #ifdef CONFIG_VFS_SUPPORT_SELECT
  101. static esp_err_t console_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
  102. esp_vfs_select_sem_t select_sem, void **end_select_args)
  103. {
  104. return get_vfs_for_index(primary_vfs_index)->vfs.start_select(nfds, readfds, writefds, exceptfds, select_sem, end_select_args);
  105. }
  106. esp_err_t console_end_select(void *end_select_args)
  107. {
  108. return get_vfs_for_index(primary_vfs_index)->vfs.end_select(end_select_args);
  109. }
  110. #endif // CONFIG_VFS_SUPPORT_SELECT
  111. #ifdef CONFIG_VFS_SUPPORT_TERMIOS
  112. int console_tcsetattr(int fd, int optional_actions, const struct termios *p)
  113. {
  114. return get_vfs_for_index(primary_vfs_index)->vfs.tcsetattr(vfs_console.fd_primary, optional_actions, p);
  115. }
  116. int console_tcgetattr(int fd, struct termios *p)
  117. {
  118. return get_vfs_for_index(primary_vfs_index)->vfs.tcgetattr(vfs_console.fd_primary, p);
  119. }
  120. int console_tcdrain(int fd)
  121. {
  122. return get_vfs_for_index(primary_vfs_index)->vfs.tcdrain(vfs_console.fd_primary);
  123. }
  124. int console_tcflush(int fd, int select)
  125. {
  126. return get_vfs_for_index(primary_vfs_index)->vfs.tcflush(vfs_console.fd_primary, select);
  127. }
  128. #endif // CONFIG_VFS_SUPPORT_TERMIOS
  129. static const esp_vfs_t vfs = {
  130. .flags = ESP_VFS_FLAG_DEFAULT,
  131. .write = &console_write,
  132. .open = &console_open,
  133. .fstat = &console_fstat,
  134. .close = &console_close,
  135. .read = &console_read,
  136. .fcntl = &console_fcntl,
  137. .fsync = &console_fsync,
  138. #ifdef CONFIG_VFS_SUPPORT_DIR
  139. .access = &console_access,
  140. #endif // CONFIG_VFS_SUPPORT_DIR
  141. #ifdef CONFIG_VFS_SUPPORT_SELECT
  142. .start_select = &console_start_select,
  143. .end_select = &console_end_select,
  144. #endif // CONFIG_VFS_SUPPORT_SELECT
  145. #ifdef CONFIG_VFS_SUPPORT_TERMIOS
  146. .tcsetattr = &console_tcsetattr,
  147. .tcgetattr = &console_tcgetattr,
  148. .tcdrain = &console_tcdrain,
  149. .tcflush = &console_tcflush,
  150. #endif // CONFIG_VFS_SUPPORT_TERMIOS
  151. };
  152. esp_err_t esp_vfs_dev_console_register(void)
  153. {
  154. return esp_vfs_register("/dev/console", &vfs, NULL);
  155. }
  156. esp_err_t esp_vfs_console_register(void)
  157. {
  158. esp_err_t err = ESP_OK;
  159. // Primary register part.
  160. #ifdef CONFIG_ESP_CONSOLE_UART
  161. const esp_vfs_t *uart_vfs = esp_vfs_uart_get_vfs();
  162. err = esp_vfs_register_common(primary_path, strlen(primary_path), uart_vfs, NULL, &primary_vfs_index);
  163. #elif CONFIG_ESP_CONSOLE_USB_CDC
  164. const esp_vfs_t *cdcacm_vfs = esp_vfs_cdcacm_get_vfs();
  165. err = esp_usb_console_init();
  166. if (err != ESP_OK) {
  167. return err;
  168. }
  169. err = esp_vfs_register_common(primary_path, strlen(primary_path), cdcacm_vfs, NULL, &primary_vfs_index);
  170. #elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
  171. const esp_vfs_t *usb_serial_jtag_vfs = esp_vfs_usb_serial_jtag_get_vfs();
  172. err = esp_vfs_register_common(primary_path, strlen(primary_path), usb_serial_jtag_vfs, NULL, &primary_vfs_index);
  173. #endif // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
  174. if (err != ESP_OK) {
  175. return err;
  176. }
  177. // Secondary register part.
  178. #if CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  179. const esp_vfs_t *usb_serial_jtag_vfs = esp_vfs_usb_serial_jtag_get_vfs();
  180. err = esp_vfs_register_common(secondary_path, strlen(secondary_path), usb_serial_jtag_vfs, NULL, &secondary_vfs_index);
  181. if(err != ESP_OK) {
  182. return err;
  183. }
  184. #endif
  185. err = esp_vfs_dev_console_register();
  186. return err;
  187. }
  188. #endif // CONFIG_VFS_SUPPORT_IO