cederom commented on code in PR #2820: URL: https://github.com/apache/nuttx-apps/pull/2820#discussion_r1957463372
########## examples/spislv_test/spislv_test.c: ########## @@ -22,81 +22,559 @@ * Included Files ****************************************************************************/ -#include <nuttx/config.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <fcntl.h> -#include <unistd.h> #include <errno.h> -#include <string.h> -#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/select.h> -#define SOURCE_FILE "/dev/spislv2" -#define BUFFER_SIZE 256 +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Define buffer sizes */ +#define RX_BUFFER_SIZE 64 +#define TX_BUFFER_SIZE 64 +#define SOURCE_FILE "dev/spislv2" /* SPI device path */ + +/* Enumeration for operation modes */ + +typedef enum +{ + MODE_WRITE, + MODE_LISTEN, + MODE_ECHO, + MODE_INVALID +} operation_mode_t; /**************************************************************************** - * Public Functions + * Structure to hold program configurations ****************************************************************************/ +typedef struct +{ + operation_mode_t mode; + int num_bytes; /* Applicable for write mode */ + int timeout_seconds; /* Applicable for all modes */ + unsigned char tx_buffer[TX_BUFFER_SIZE]; +} program_config_t; + /**************************************************************************** - * spislv_test + * Private Functions ****************************************************************************/ -int main(int argc, FAR char *argv[]) +/** + * @brief Converts a single hexadecimal character to its byte value. + * + * @param c The hexadecimal character. + * @return The byte value of the hexadecimal character, or -1 if invalid. + */ + +static int hexchar_to_byte(char c) { - int fd; - char buffer[BUFFER_SIZE]; - ssize_t bytes_read; - ssize_t i; + if (c >= '0' && c <= '9') + { + return c - '0'; + } - printf("Slave started!!\n"); - fd = open(SOURCE_FILE, O_RDWR); + c = tolower(c); - if (fd < 0) + if (c >= 'a' && c <= 'f') { - printf("Failed to open %s: %s\n", SOURCE_FILE, strerror(errno)); - return 0; + return c - 'a' + 10; } - while (1) + return -1; +} + +/** + * @brief Converts a hexadecimal string to a byte array. + * + * @param hexstr The input hexadecimal string. + * @param bytes The output byte array. + * @param max_bytes The maximum number of bytes to convert. + * @return The number of bytes converted, or -1 on error. + */ + +static int hexstr_to_bytes(const char *hexstr, unsigned char *bytes, + size_t max_bytes) +{ + int len; + int i; + + len = strlen(hexstr); + if (len % 2 != 0 || len / 2 > max_bytes) + { + return -1; + } + + for (i = 0; i < len / 2; i++) + { + int high = hexchar_to_byte(hexstr[2 * i]); + int low = hexchar_to_byte(hexstr[2 * i + 1]); + + if (high == -1 || low == -1) + { + return -1; + } + + bytes[i] = (high << 4) | low; + } + + return len / 2; +} + +/** + * @brief Parses and validates command-line arguments. + * + * @param argc Argument count. + * @param argv Argument vector. + * @param config Pointer to the program configuration structure. + * @return 0 on success, -1 on failure. + */ + +static int parse_arguments(int argc, char *argv[], + program_config_t *config) +{ + int opt; + + /* Set default configurations */ + + config->mode = MODE_INVALID; + config->num_bytes = 0; + config->timeout_seconds = 10; /* Default timeout */ + + /* Parse command-line options */ + + while ((opt = getopt(argc, argv, "x:t:le")) != -1) + { + switch (opt) + { + case 'x': + if (config->mode != MODE_INVALID) + { + fprintf(stderr, + "Error: Multiple operation modes specified.\n"); + return -1; + } + + config->mode = MODE_WRITE; + config->num_bytes = atoi(optarg); + if (config->num_bytes <= 0 || + config->num_bytes > TX_BUFFER_SIZE) + { + fprintf(stderr, + "Error: Invalid number of bytes for write mode.\n"); + return -1; + } + + break; + + case 't': + config->timeout_seconds = atoi(optarg); + if (config->timeout_seconds <= 0) + { + fprintf(stderr, + "Error: Timeout must be a positive integer.\n"); + return -1; + } + break; + + case 'l': + if (config->mode != MODE_INVALID) + { + fprintf(stderr, + "Error: Multiple operation modes specified.\n"); + return -1; + } + + config->mode = MODE_LISTEN; + break; + + case 'e': + if (config->mode != MODE_INVALID) + { + fprintf(stderr, + "Error: Multiple operation modes specified.\n"); + return -1; + } + + config->mode = MODE_ECHO; + break; + + default: + fprintf(stderr, "Usage:\n"); + fprintf(stderr, + " %s -x <num_bytes> [-t <timeout_seconds>] <hex_bytes>\n", + argv[0]); + fprintf(stderr, + " %s -l [-t <timeout_seconds>]\n", argv[0]); + fprintf(stderr, + " %s -e [-t <timeout_seconds>]\n", argv[0]); + printf("Examples:\n"); + printf(" spislv -x 2 abba\n"); + printf(" spislv -l -t 5\n"); + printf(" spislv -e -t 10\n\n"); + return -1; + } + } + + /* Validate mutual exclusivity and required arguments */ + + if (config->mode == MODE_WRITE) { - /* Read the number from the source file */ + if (optind >= argc) + { + fprintf(stderr, + "Error: Missing hexadecimal bytes to send.\n"); + fprintf(stderr, + "Usage: %s -x <num_bytes> [-t <timeout_seconds>] <hex_bytes>\n", + argv[0]); + return -1; + } + + char *hex_input = argv[optind]; - printf("Slave: Reading from %s\n", SOURCE_FILE); - bytes_read = read(fd, buffer, BUFFER_SIZE - 1); + /* Verify the hexadecimal string length */ - if (bytes_read < 0) + if (strlen(hex_input) != (size_t)(config->num_bytes * 2)) { - printf("Failed to read from %s: %s\n", - SOURCE_FILE, strerror(errno)); - close(fd); - return 0; + fprintf(stderr, + "Error: Hex string length must be %d characters\n" + "for %d bytes.\n", + config->num_bytes * 2, config->num_bytes); + return -1; } - else if (bytes_read > 0) + + /* Convert hexadecimal string to byte array */ + + int converted = hexstr_to_bytes(hex_input, config->tx_buffer, + TX_BUFFER_SIZE); + if (converted != config->num_bytes) { - buffer[bytes_read] = '\0'; + fprintf(stderr, "Error: Invalid hexadecimal string.\n"); + return -1; + } + } + + else if (config->mode == MODE_INVALID) + { + fprintf(stderr, "Error: No operation mode specified.\n"); + fprintf(stderr, "Usage:\n"); + fprintf(stderr, + " %s -x <num_bytes> [-t <timeout_seconds>] <hex_bytes>\n", + argv[0]); + fprintf(stderr, + " %s -l [-t <timeout_seconds>]\n", argv[0]); + fprintf(stderr, + " %s -e [-t <timeout_seconds>]\n", argv[0]); + printf("Examples:\n"); + printf(" spislv -x 2 abba\n"); + printf(" spislv -l -t 5\n"); + printf(" spislv -e -t 10\n"); + return -1; + } + + return 0; +} + +/** + * @brief Executes the write mode: sends specified bytes to the master. + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure. + */ + +static int write_mode(program_config_t *config, int fd) +{ + ssize_t bytes_written; + char data_str[3 * TX_BUFFER_SIZE + 1]; /* Buffer for debug string */ + char *ptr = data_str; + int len; + int i; + + for (i = 0; i < config->num_bytes; i++) + { + len = snprintf(ptr, sizeof(data_str) - (ptr - data_str), + "%02X ", config->tx_buffer[i]); + if (len < 0 || len >= (int)(sizeof(data_str) - (ptr - data_str))) + { + break; + } + + ptr += len; + } + + *ptr = '\0'; + + printf("Slave: Queuing %d bytes for sending to master: %s\n", + config->num_bytes, data_str); + + bytes_written = write(fd, config->tx_buffer, config->num_bytes); + if (bytes_written < 0) + { + fprintf(stderr, "Error: Failed to write to %s: %s\n", + SOURCE_FILE, strerror(errno)); + return -1; + } + + else if (bytes_written != config->num_bytes) + { + fprintf(stderr, "Error: Incomplete write. Expected %d, got %zd\n", + config->num_bytes, bytes_written); + return -1; + } + + return 0; +} + +/** + * @brief Executes the listen-only mode: waits for data from the master. + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure. + */ + +static int listen_mode(program_config_t *config, int fd) +{ + printf("Slave: Listen-only mode activated. Waiting for data\n" + " from master.\n"); + + return 0; +} + +/** + * @brief Executes the echo mode: continuously echoes received data to + * the master. + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure. + */ + +static int echo_mode_func(program_config_t *config, int fd) +{ + printf("Slave: Echo mode activated. Will echo received data until\n" + " timeout.\n"); - /* Print buffer in hexadecimal format */ + return 0; +} + +/** + * @brief Reads data from the SPI device with a specified timeout. + * Depending on the mode, it either exits after the first read or + * continues (echo mode). + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure or timeout. + */ + +static int read_with_timeout(program_config_t *config, int fd) +{ + unsigned char buffer_rx[RX_BUFFER_SIZE]; + ssize_t bytes_read; + ssize_t bytes_written; + int select_ret; + + while (1) + { + fd_set read_fds; + struct timeval timeout; + + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + timeout.tv_sec = config->timeout_seconds; + timeout.tv_usec = 0; - printf("Slave: Read value in hex: "); - for (i = 0; i < bytes_read; ++i) + select_ret = select(fd + 1, &read_fds, + NULL, NULL, &timeout); + if (select_ret == -1) + { + fprintf(stderr, "Error: Select failed: %s\n", + strerror(errno)); + return -1; + } + else if (select_ret == 0) + { + if (config->mode == MODE_ECHO) + { + printf("Communication timeout after %d seconds. No more\n" + "data received from master.\n", + config->timeout_seconds); + } + else { - printf("%02x ", (unsigned char)buffer[i]); + printf("Communication timeout after %d seconds. No data\n" + "received from master.\n", + config->timeout_seconds); } - printf("\n"); + return -1; + } + else + { + bytes_read = read(fd, buffer_rx, RX_BUFFER_SIZE); + if (bytes_read < 0) + { + fprintf(stderr, "Error: Failed to read from %s: %s\n", + SOURCE_FILE, strerror(errno)); + return -1; + } - /* Write the same value back */ + else if (bytes_read == 0) + { + printf("No data received from master.\n"); + } - printf("Slave: Writing %d bytes back to %s\n", - bytes_read, SOURCE_FILE); - ssize_t bytes_written = write(fd, buffer, bytes_read); - if (bytes_written < 0) + else { - printf("Failed to write to %s: %s\n", - SOURCE_FILE, strerror(errno)); - close(fd); - return 0; + printf("Data received from master (%zd bytes): ", + bytes_read); + for (int i = 0; i < bytes_read; i++) + { + printf("%02X ", buffer_rx[i]); + } + + printf("\n"); + if (config->mode == MODE_ECHO) + { + bytes_written = write(fd, buffer_rx, + bytes_read); + if (bytes_written < 0) + { + fprintf(stderr, + "Error: Failed to write to %s: %s\n", + SOURCE_FILE, strerror(errno)); + return -1; + } + else if (bytes_written != bytes_read) + { + printf("Error: Incomplete write during echo. "); + fprintf(stderr, "Expected %zd, got %zd\n", + bytes_read, bytes_written); + return -1; + } + + printf("Echoed back %zd bytes to master.\n", + bytes_written); + } + + if (config->mode != MODE_ECHO) + { + break; + } } } + Review Comment: no more style complains :-) thanks @FelipeMdeO :-) ########## examples/spislv_test/spislv_test.c: ########## @@ -22,81 +22,559 @@ * Included Files ****************************************************************************/ -#include <nuttx/config.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <fcntl.h> -#include <unistd.h> #include <errno.h> -#include <string.h> -#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/select.h> -#define SOURCE_FILE "/dev/spislv2" -#define BUFFER_SIZE 256 +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Define buffer sizes */ +#define RX_BUFFER_SIZE 64 +#define TX_BUFFER_SIZE 64 +#define SOURCE_FILE "dev/spislv2" /* SPI device path */ + +/* Enumeration for operation modes */ + +typedef enum +{ + MODE_WRITE, + MODE_LISTEN, + MODE_ECHO, + MODE_INVALID +} operation_mode_t; /**************************************************************************** - * Public Functions + * Structure to hold program configurations ****************************************************************************/ +typedef struct +{ + operation_mode_t mode; + int num_bytes; /* Applicable for write mode */ + int timeout_seconds; /* Applicable for all modes */ + unsigned char tx_buffer[TX_BUFFER_SIZE]; +} program_config_t; + /**************************************************************************** - * spislv_test + * Private Functions ****************************************************************************/ -int main(int argc, FAR char *argv[]) +/** + * @brief Converts a single hexadecimal character to its byte value. + * + * @param c The hexadecimal character. + * @return The byte value of the hexadecimal character, or -1 if invalid. + */ + +static int hexchar_to_byte(char c) { - int fd; - char buffer[BUFFER_SIZE]; - ssize_t bytes_read; - ssize_t i; + if (c >= '0' && c <= '9') + { + return c - '0'; + } - printf("Slave started!!\n"); - fd = open(SOURCE_FILE, O_RDWR); + c = tolower(c); - if (fd < 0) + if (c >= 'a' && c <= 'f') { - printf("Failed to open %s: %s\n", SOURCE_FILE, strerror(errno)); - return 0; + return c - 'a' + 10; } - while (1) + return -1; +} + +/** + * @brief Converts a hexadecimal string to a byte array. + * + * @param hexstr The input hexadecimal string. + * @param bytes The output byte array. + * @param max_bytes The maximum number of bytes to convert. + * @return The number of bytes converted, or -1 on error. + */ + +static int hexstr_to_bytes(const char *hexstr, unsigned char *bytes, + size_t max_bytes) +{ + int len; + int i; + + len = strlen(hexstr); + if (len % 2 != 0 || len / 2 > max_bytes) + { + return -1; + } + + for (i = 0; i < len / 2; i++) + { + int high = hexchar_to_byte(hexstr[2 * i]); + int low = hexchar_to_byte(hexstr[2 * i + 1]); + + if (high == -1 || low == -1) + { + return -1; + } + + bytes[i] = (high << 4) | low; + } + + return len / 2; +} + +/** + * @brief Parses and validates command-line arguments. + * + * @param argc Argument count. + * @param argv Argument vector. + * @param config Pointer to the program configuration structure. + * @return 0 on success, -1 on failure. + */ + +static int parse_arguments(int argc, char *argv[], + program_config_t *config) +{ + int opt; + + /* Set default configurations */ + + config->mode = MODE_INVALID; + config->num_bytes = 0; + config->timeout_seconds = 10; /* Default timeout */ + + /* Parse command-line options */ + + while ((opt = getopt(argc, argv, "x:t:le")) != -1) + { + switch (opt) + { + case 'x': + if (config->mode != MODE_INVALID) + { + fprintf(stderr, + "Error: Multiple operation modes specified.\n"); + return -1; + } + + config->mode = MODE_WRITE; + config->num_bytes = atoi(optarg); + if (config->num_bytes <= 0 || + config->num_bytes > TX_BUFFER_SIZE) + { + fprintf(stderr, + "Error: Invalid number of bytes for write mode.\n"); + return -1; + } + + break; + + case 't': + config->timeout_seconds = atoi(optarg); + if (config->timeout_seconds <= 0) + { + fprintf(stderr, + "Error: Timeout must be a positive integer.\n"); + return -1; + } + break; + + case 'l': + if (config->mode != MODE_INVALID) + { + fprintf(stderr, + "Error: Multiple operation modes specified.\n"); + return -1; + } + + config->mode = MODE_LISTEN; + break; + + case 'e': + if (config->mode != MODE_INVALID) + { + fprintf(stderr, + "Error: Multiple operation modes specified.\n"); + return -1; + } + + config->mode = MODE_ECHO; + break; + + default: + fprintf(stderr, "Usage:\n"); + fprintf(stderr, + " %s -x <num_bytes> [-t <timeout_seconds>] <hex_bytes>\n", + argv[0]); + fprintf(stderr, + " %s -l [-t <timeout_seconds>]\n", argv[0]); + fprintf(stderr, + " %s -e [-t <timeout_seconds>]\n", argv[0]); + printf("Examples:\n"); + printf(" spislv -x 2 abba\n"); + printf(" spislv -l -t 5\n"); + printf(" spislv -e -t 10\n\n"); + return -1; + } + } + + /* Validate mutual exclusivity and required arguments */ + + if (config->mode == MODE_WRITE) { - /* Read the number from the source file */ + if (optind >= argc) + { + fprintf(stderr, + "Error: Missing hexadecimal bytes to send.\n"); + fprintf(stderr, + "Usage: %s -x <num_bytes> [-t <timeout_seconds>] <hex_bytes>\n", + argv[0]); + return -1; + } + + char *hex_input = argv[optind]; - printf("Slave: Reading from %s\n", SOURCE_FILE); - bytes_read = read(fd, buffer, BUFFER_SIZE - 1); + /* Verify the hexadecimal string length */ - if (bytes_read < 0) + if (strlen(hex_input) != (size_t)(config->num_bytes * 2)) { - printf("Failed to read from %s: %s\n", - SOURCE_FILE, strerror(errno)); - close(fd); - return 0; + fprintf(stderr, + "Error: Hex string length must be %d characters\n" + "for %d bytes.\n", + config->num_bytes * 2, config->num_bytes); + return -1; } - else if (bytes_read > 0) + + /* Convert hexadecimal string to byte array */ + + int converted = hexstr_to_bytes(hex_input, config->tx_buffer, + TX_BUFFER_SIZE); + if (converted != config->num_bytes) { - buffer[bytes_read] = '\0'; + fprintf(stderr, "Error: Invalid hexadecimal string.\n"); + return -1; + } + } + + else if (config->mode == MODE_INVALID) + { + fprintf(stderr, "Error: No operation mode specified.\n"); + fprintf(stderr, "Usage:\n"); + fprintf(stderr, + " %s -x <num_bytes> [-t <timeout_seconds>] <hex_bytes>\n", + argv[0]); + fprintf(stderr, + " %s -l [-t <timeout_seconds>]\n", argv[0]); + fprintf(stderr, + " %s -e [-t <timeout_seconds>]\n", argv[0]); + printf("Examples:\n"); + printf(" spislv -x 2 abba\n"); + printf(" spislv -l -t 5\n"); + printf(" spislv -e -t 10\n"); + return -1; + } + + return 0; +} + +/** + * @brief Executes the write mode: sends specified bytes to the master. + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure. + */ + +static int write_mode(program_config_t *config, int fd) +{ + ssize_t bytes_written; + char data_str[3 * TX_BUFFER_SIZE + 1]; /* Buffer for debug string */ + char *ptr = data_str; + int len; + int i; + + for (i = 0; i < config->num_bytes; i++) + { + len = snprintf(ptr, sizeof(data_str) - (ptr - data_str), + "%02X ", config->tx_buffer[i]); + if (len < 0 || len >= (int)(sizeof(data_str) - (ptr - data_str))) + { + break; + } + + ptr += len; + } + + *ptr = '\0'; + + printf("Slave: Queuing %d bytes for sending to master: %s\n", + config->num_bytes, data_str); + + bytes_written = write(fd, config->tx_buffer, config->num_bytes); + if (bytes_written < 0) + { + fprintf(stderr, "Error: Failed to write to %s: %s\n", + SOURCE_FILE, strerror(errno)); + return -1; + } + + else if (bytes_written != config->num_bytes) + { + fprintf(stderr, "Error: Incomplete write. Expected %d, got %zd\n", + config->num_bytes, bytes_written); + return -1; + } + + return 0; +} + +/** + * @brief Executes the listen-only mode: waits for data from the master. + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure. + */ + +static int listen_mode(program_config_t *config, int fd) +{ + printf("Slave: Listen-only mode activated. Waiting for data\n" + " from master.\n"); + + return 0; +} + +/** + * @brief Executes the echo mode: continuously echoes received data to + * the master. + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure. + */ + +static int echo_mode_func(program_config_t *config, int fd) +{ + printf("Slave: Echo mode activated. Will echo received data until\n" + " timeout.\n"); - /* Print buffer in hexadecimal format */ + return 0; +} + +/** + * @brief Reads data from the SPI device with a specified timeout. + * Depending on the mode, it either exits after the first read or + * continues (echo mode). + * + * @param config Pointer to the program configuration structure. + * @param fd File descriptor for the SPI device. + * @return 0 on success, -1 on failure or timeout. + */ + +static int read_with_timeout(program_config_t *config, int fd) +{ + unsigned char buffer_rx[RX_BUFFER_SIZE]; + ssize_t bytes_read; + ssize_t bytes_written; + int select_ret; + + while (1) + { + fd_set read_fds; + struct timeval timeout; + + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + timeout.tv_sec = config->timeout_seconds; + timeout.tv_usec = 0; - printf("Slave: Read value in hex: "); - for (i = 0; i < bytes_read; ++i) + select_ret = select(fd + 1, &read_fds, + NULL, NULL, &timeout); + if (select_ret == -1) + { + fprintf(stderr, "Error: Select failed: %s\n", + strerror(errno)); + return -1; + } + else if (select_ret == 0) + { + if (config->mode == MODE_ECHO) + { + printf("Communication timeout after %d seconds. No more\n" + "data received from master.\n", + config->timeout_seconds); + } + else { - printf("%02x ", (unsigned char)buffer[i]); + printf("Communication timeout after %d seconds. No data\n" + "received from master.\n", + config->timeout_seconds); } - printf("\n"); + return -1; + } + else + { + bytes_read = read(fd, buffer_rx, RX_BUFFER_SIZE); + if (bytes_read < 0) + { + fprintf(stderr, "Error: Failed to read from %s: %s\n", + SOURCE_FILE, strerror(errno)); + return -1; + } - /* Write the same value back */ + else if (bytes_read == 0) + { + printf("No data received from master.\n"); + } - printf("Slave: Writing %d bytes back to %s\n", - bytes_read, SOURCE_FILE); - ssize_t bytes_written = write(fd, buffer, bytes_read); - if (bytes_written < 0) + else { - printf("Failed to write to %s: %s\n", - SOURCE_FILE, strerror(errno)); - close(fd); - return 0; + printf("Data received from master (%zd bytes): ", + bytes_read); + for (int i = 0; i < bytes_read; i++) + { + printf("%02X ", buffer_rx[i]); + } + + printf("\n"); + if (config->mode == MODE_ECHO) + { + bytes_written = write(fd, buffer_rx, + bytes_read); + if (bytes_written < 0) + { + fprintf(stderr, + "Error: Failed to write to %s: %s\n", + SOURCE_FILE, strerror(errno)); + return -1; + } + else if (bytes_written != bytes_read) + { + printf("Error: Incomplete write during echo. "); + fprintf(stderr, "Expected %zd, got %zd\n", + bytes_read, bytes_written); + return -1; + } + + printf("Echoed back %zd bytes to master.\n", + bytes_written); + } + + if (config->mode != MODE_ECHO) + { + break; + } } } + Review Comment: blank line complain :-P -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org