stdinout.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include "esp_netif.h"
  14. #include "esp_log.h"
  15. #include "driver/uart.h"
  16. #include "esp_console.h"
  17. #include "esp_vfs_dev.h"
  18. #include "linenoise/linenoise.h"
  19. //
  20. // Internal functions declaration referenced in io object
  21. //
  22. static esp_err_t netsuite_io_transmit(void *h, void *buffer, size_t len);
  23. static esp_err_t netsuite_io_attach(esp_netif_t * esp_netif, void * args);
  24. /**
  25. * @brief IO object netif related configuration with data-path function callbacks
  26. * and pointer to the IO object instance (unused as this is a singleton)
  27. */
  28. const esp_netif_driver_ifconfig_t c_driver_ifconfig = {
  29. .driver_free_rx_buffer = NULL,
  30. .transmit = netsuite_io_transmit,
  31. .handle = "netsuite-io-object" // this IO object is a singleton, its handle uses as a name
  32. };
  33. /**
  34. * @brief IO object base structure used to point to internal attach function
  35. */
  36. const esp_netif_driver_base_t s_driver_base = {
  37. .post_attach = netsuite_io_attach
  38. };
  39. /**
  40. * @brief Transmit function called from esp_netif to output network stack data
  41. *
  42. * Note: This API has to conform to esp-netif transmit prototype
  43. *
  44. * @param h Opaque pointer representing the io driver (unused, const string in this case)
  45. * @param data data buffer
  46. * @param length length of data to send
  47. *
  48. * @return ESP_OK on success
  49. */
  50. static esp_err_t netsuite_io_transmit(void *h, void *buffer, size_t len)
  51. {
  52. /* output the packet to stdout */
  53. char *data = buffer;
  54. printf("\nPacketOut:[");
  55. for (size_t i=0; i<len; i++) {
  56. printf("%02x", *data++);
  57. }
  58. printf("]\n");
  59. return ESP_OK;
  60. }
  61. /**
  62. * @brief Post attach adapter for netsuite i/o
  63. *
  64. * Used to exchange internal callbacks and context between esp-netif and the I/O object.
  65. * In case of netsuite I/O, it only updates the driver config with internal callbacks and
  66. * its instance pointer (const string in this case)
  67. *
  68. * @param esp_netif handle to esp-netif object
  69. * @param args pointer to netsuite IO
  70. *
  71. * @return ESP_OK on success
  72. */
  73. static esp_err_t netsuite_io_attach(esp_netif_t * esp_netif, void * args)
  74. {
  75. ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &c_driver_ifconfig));
  76. return ESP_OK;
  77. }
  78. /**
  79. * @brief Process line read from serial input, character by character
  80. *
  81. * Converts from hex string to byte stream, so it can be processed
  82. * in test network interface
  83. *
  84. * @param line
  85. * @param packet
  86. *
  87. * @return size of packet
  88. */
  89. static size_t process_line(char* line, char* packet)
  90. {
  91. size_t count = 0;
  92. size_t i;
  93. for (i=0; i< strlen(line); i++) {
  94. char c = line[i];
  95. // accept both separators between bytes
  96. if (c == '-' || c == ' ') {
  97. ++count;
  98. // Processing numeric characters
  99. } else if (c >= '0' && c <= '9') {
  100. packet[count] *= 16;
  101. packet[count] += c - '0';
  102. // Processing alpha-numeric hex characters
  103. } else if (c >= 'a' && c <= 'f') {
  104. packet[count] *= 16;
  105. packet[count] += c - 'a' + 10;
  106. }
  107. }
  108. if (i>0 && strlen(line)>0) {
  109. count++;
  110. }
  111. return count;
  112. }
  113. /**
  114. * Created (initializes) the i/o object and returns handle ready to be attached to the esp-netif
  115. */
  116. void * netsuite_io_new(void)
  117. {
  118. // Initialize VFS & UART so we can use std::cout/cin
  119. setvbuf(stdin, NULL, _IONBF, 0);
  120. setvbuf(stdout, NULL, _IONBF, 0);
  121. /* Install UART driver for interrupt-driven reads and writes */
  122. ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM,
  123. 256, 0, 0, NULL, 0) );
  124. /* Tell VFS to use UART driver */
  125. esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
  126. esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
  127. /* Move the caret to the beginning of the next line on '\n' */
  128. esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
  129. linenoiseSetDumbMode(1);
  130. return (void *)&s_driver_base;
  131. }
  132. /**
  133. * I/O receive function
  134. */
  135. ssize_t netsuite_io_get_packet(char *packet, size_t max_len)
  136. {
  137. size_t size;
  138. /* read packet from stdin */
  139. char* line = linenoise("");
  140. if (!line) {
  141. return -1;
  142. }
  143. /* convert to binary */
  144. size = process_line(line, packet);
  145. if (size > max_len) {
  146. return -1;
  147. }
  148. linenoiseFree(line);
  149. return size;
  150. }