From c70a3c37ab71000c19427d37a05e5bcf4c09b2ee Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Fri, 22 Jul 2016 08:45:54 -0700 Subject: [PATCH] spi-hdlc-adapter: Bug fixes and updates (#274) Fixes issues with parsing command line arguments and also makes the reset pin behavior work properly. --- tools/spi-hdlc-adapter/spi-hdlc-adapter.c | 218 +++++++++++++++------- 1 file changed, 149 insertions(+), 69 deletions(-) diff --git a/tools/spi-hdlc-adapter/spi-hdlc-adapter.c b/tools/spi-hdlc-adapter/spi-hdlc-adapter.c index 27dcb8dda..fd6fa3a2b 100644 --- a/tools/spi-hdlc-adapter/spi-hdlc-adapter.c +++ b/tools/spi-hdlc-adapter/spi-hdlc-adapter.c @@ -59,7 +59,7 @@ /* ------------------------------------------------------------------------- */ /* MARK: Macros and Constants */ -#define SPI_HDLC_VERSION "0.0" +#define SPI_HDLC_VERSION "0.01" #define MAX_FRAME_SIZE 2048 #define HEADER_LEN 5 @@ -103,7 +103,7 @@ static const char* gResGpioDevPath = NULL; static int gVerbose = LOG_WARNING; static int gSpiDevFd = -1; -static int gResGpioDirFd = -1; +static int gResGpioValueFd = -1; static int gIntGpioValueFd = -1; static int gHDLCInputFd = -1; @@ -315,6 +315,8 @@ static int push_pull_spi() { // Device is off or in a bad state. gSpiTxFlowControl = true; + + syslog(LOG_DEBUG, "Discarded frame. (1)"); goto bail; } @@ -374,6 +376,8 @@ static int push_pull_spi() { // Device is off or in a bad state. gSpiTxFlowControl = true; + + syslog(LOG_DEBUG, "Discarded frame. (2)"); goto bail; } @@ -584,14 +588,23 @@ static int push_hdlc(void) if (ret < 0) { - perror("push_hdlc"); + if (errno == EAGAIN) + { + ret = 0; + } + else + { + perror("push_hdlc:write"); + syslog(LOG_ERR, "push_hdlc:write: errno=%d (%s)", errno, strerror(errno)); + } goto bail; } escaped_frame_sent += ret; // Reset state once we have sent the entire frame. - if (escaped_frame_len == escaped_frame_sent) { + if (escaped_frame_len == escaped_frame_sent) + { escaped_frame_len = escaped_frame_sent = 0; } @@ -610,7 +623,7 @@ static int pull_hdlc(void) if (!gSpiTxReady) { uint8_t byte; - while (read(gHDLCInputFd, &byte, 1) == 1) + while ((ret = read(gHDLCInputFd, &byte, 1)) == 1) { if (gSpiTxPayloadSize >= (MAX_FRAME_SIZE - HEADER_LEN)) { @@ -673,7 +686,22 @@ static int pull_hdlc(void) } } - return ret; + if (ret < 0) + { + if (errno == EAGAIN) + { + ret = 0; + } + else + { + perror("pull_hdlc:read"); + syslog(LOG_ERR, "pull_hdlc:read: errno=%d (%s)", errno, strerror(errno)); + } + } + + return ret < 0 + ? ret + : 0; } @@ -769,45 +797,77 @@ bail: static bool setup_res_gpio(const char* path) { + int setup_fd; int prev_errno = 0; char* dir_path = NULL; + char* value_path = NULL; int len; gResGpioDevPath = path; len = asprintf(&dir_path, "%s/direction", path); - if (len > 0) + if (len < 0) { - gResGpioDirFd = open(dir_path, O_WRONLY); - } - else - { - gResGpioDirFd = -1; + perror("asprintf"); + goto bail; } - prev_errno = errno; + len = asprintf(&value_path, "%s/value", path); - if (gResGpioDirFd >= 0) + if (len < 0) { - if (-1 == write(gResGpioDirFd, "high\n", 5)) + perror("asprintf"); + goto bail; + } + + setup_fd = open(dir_path, O_WRONLY); + + if (setup_fd >= 0) + { + if (-1 == write(setup_fd, "high\n", 5)) { - prev_errno = errno; - close(gResGpioDirFd); - gResGpioDirFd = -1; + perror("set_res_direction"); + goto bail; } } - if (gResGpioDirFd < 0) + gResGpioValueFd = open(value_path, O_WRONLY); + +bail: + + if (setup_fd >= 0) { - errno = prev_errno; - perror("Unable to open RES GPIO"); + close(setup_fd); } - free(dir_path); - errno = prev_errno; + if (dir_path) + { + free(dir_path); + } - return gResGpioDirFd >= 0; + if (value_path) + { + free(value_path); + } + + return gResGpioValueFd >= 0; +} + +static void trigger_reset(void) +{ + if (gResGpioValueFd >= 0) + { + lseek(gResGpioValueFd, 0, SEEK_SET); + write(gResGpioValueFd, "0\n", 2); + + usleep(10 * USEC_PER_MSEC); + + lseek(gResGpioValueFd, 0, SEEK_SET); + write(gResGpioValueFd, "1\n", 2); + + syslog(LOG_NOTICE, "Triggered hardware reset"); + } } static bool setup_int_gpio(const char* path) @@ -848,36 +908,35 @@ static bool setup_int_gpio(const char* path) setup_fd = open(dir_path, O_WRONLY); - if (setup_fd < 0) + if (setup_fd >= 0) { - perror("open"); - goto bail; + len = write(setup_fd, "in", 2); + if (len < 0) + { + perror("write"); + goto bail; + } + + close(setup_fd); + + setup_fd = -1; } - len = write(setup_fd, "in", 2); - - if (len < 0) - { - perror("write"); - goto bail; - } - - close(setup_fd); - setup_fd = open(edge_path, O_WRONLY); - if (setup_fd < 0) + if (setup_fd >= 0) { - perror("open"); - goto bail; - } + len = write(setup_fd, "falling", 7); - len = write(setup_fd, "falling", 7); + if (len < 0) + { + perror("write"); + goto bail; + } - if (len < 0) - { - perror("write"); - goto bail; + close(setup_fd); + + setup_fd = -1; } gIntGpioValueFd = open(value_path, O_RDONLY); @@ -959,6 +1018,7 @@ static void print_help(void) int main(int argc, char *argv[]) { int i = 0; + const char* prog = argv[0]; struct sigaction sigact; static fd_set read_set; static fd_set write_set; @@ -1010,24 +1070,16 @@ int main(int argc, char *argv[]) // ======================================================================== // ARGUMENT PARSING - openlog(basename(argv[0]), LOG_PERROR | LOG_PID | LOG_CONS, LOG_DAEMON); + openlog(basename(prog), LOG_PERROR | LOG_PID | LOG_CONS, LOG_DAEMON); - while (++i < argc) + setlogmask(setlogmask(0) & LOG_UPTO(gVerbose)); + + while (1) { - int c = getopt_long(argc, argv, "i:r:v:Vh?", options, &i); + int c = getopt_long(argc, argv, "i:r:v:Vh?", options, NULL); if (c == -1) { - if (gSpiDevPath != NULL) - { - fprintf(stderr, "%s: Unexpected argument \"%s\"\n", argv[0], optarg); - exit(EXIT_FAILURE); - } - - if (!setup_spi_dev(argv[i+1])) - { - syslog(LOG_ERR, "Unable to open SPI device \"%s\", %s", argv[i+1], strerror(errno)); - exit(EXIT_FAILURE); - } + break; } else { @@ -1094,9 +1146,29 @@ int main(int argc, char *argv[]) } } + argc -= optind; + argv += optind; + + if (argc >= 1) + { + if (!setup_spi_dev(argv[0])) + { + syslog(LOG_ERR, "%s: Unable to open SPI device \"%s\", %s", prog, argv[optind], strerror(errno)); + exit(EXIT_FAILURE); + } + argc--; + argv++; + } + + if (argc >= 1) + { + fprintf(stderr, "%s: Unexpected argument \"%s\"\n", prog, argv[0]); + exit(EXIT_FAILURE); + } + if (gSpiDevPath == NULL) { - fprintf(stderr, "%s: Missing SPI device path\n", argv[0]); + fprintf(stderr, "%s: Missing SPI device path\n", prog); exit(EXIT_FAILURE); } @@ -1166,6 +1238,13 @@ int main(int argc, char *argv[]) max_fd = gIntGpioValueFd; } + if (gIntGpioValueFd < 0) + { + syslog(LOG_WARNING, "Interrupt pin was not set, must poll SPI. Performance will suffer."); + } + + trigger_reset(); + // ======================================================================== // MAIN LOOP @@ -1187,7 +1266,6 @@ int main(int argc, char *argv[]) // We are being rate-limited by the NCP. timeout_ms = SPI_POLL_PERIOD_MSEC; syslog(LOG_INFO, "Rate limiting transactions"); - } else { @@ -1209,6 +1287,7 @@ int main(int argc, char *argv[]) // set the timeout to be 0. timeout_ms = 0; + syslog(LOG_DEBUG, "Interrupt."); } else { @@ -1232,10 +1311,9 @@ int main(int argc, char *argv[]) if (FD_ISSET(gHDLCInputFd, &read_set)) { // Read in the data. - gRet = pull_hdlc(); - - if (gRet) + if (pull_hdlc() < 0) { + gRet = EXIT_FAILURE; break; } } @@ -1244,10 +1322,9 @@ int main(int argc, char *argv[]) if (FD_ISSET(gHDLCOutputFd, &write_set)) { // Write out the data. - gRet = push_hdlc(); - - if (gRet) + if (push_hdlc() < 0) { + gRet = EXIT_FAILURE; break; } } @@ -1256,7 +1333,10 @@ int main(int argc, char *argv[]) // a packet or we have a packet to be sent. if ((gSpiRxPayloadSize == 0) || gSpiTxReady) { - gRet = push_pull_spi(); + if (push_pull_spi() < 0) + { + gRet = EXIT_FAILURE; + } } }