X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fremote_bitbang.c;h=663795296f933df3f12b3fb3febbaf50877357d5;hb=ee56c502607760deb1b44b4ab06b1cb3a59029fe;hp=fc7ef6b8741692c5a7e3232872954a81b062e5ca;hpb=08d4411b59dd8bd0e7d8009003b71d23acbf6eee;p=openocd.git diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index fc7ef6b874..663795296f 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -29,47 +27,89 @@ #include #include "bitbang.h" -#ifndef UNIX_PATH_LEN -#define UNIX_PATH_LEN 108 -#endif - /* arbitrary limit on host name length: */ #define REMOTE_BITBANG_HOST_MAX 255 -#define REMOTE_BITBANG_RAISE_ERROR(expr ...) \ - do { \ - LOG_ERROR(expr); \ - LOG_ERROR("Terminating openocd."); \ - exit(-1); \ - } while (0) - static char *remote_bitbang_host; static char *remote_bitbang_port; -FILE *remote_bitbang_in; -FILE *remote_bitbang_out; +static FILE *remote_bitbang_file; +static int remote_bitbang_fd; + +/* Circular buffer. When start == end, the buffer is empty. */ +static char remote_bitbang_buf[64]; +static unsigned remote_bitbang_start; +static unsigned remote_bitbang_end; + +static int remote_bitbang_buf_full(void) +{ + return remote_bitbang_end == + ((remote_bitbang_start + sizeof(remote_bitbang_buf) - 1) % + sizeof(remote_bitbang_buf)); +} + +/* Read any incoming data, placing it into the buffer. */ +static int remote_bitbang_fill_buf(void) +{ + socket_nonblock(remote_bitbang_fd); + while (!remote_bitbang_buf_full()) { + unsigned contiguous_available_space; + if (remote_bitbang_end >= remote_bitbang_start) { + contiguous_available_space = sizeof(remote_bitbang_buf) - + remote_bitbang_end; + if (remote_bitbang_start == 0) + contiguous_available_space -= 1; + } else { + contiguous_available_space = remote_bitbang_start - + remote_bitbang_end - 1; + } + ssize_t count = read(remote_bitbang_fd, + remote_bitbang_buf + remote_bitbang_end, + contiguous_available_space); + if (count > 0) { + remote_bitbang_end += count; + if (remote_bitbang_end == sizeof(remote_bitbang_buf)) + remote_bitbang_end = 0; + } else if (count == 0) { + return ERROR_OK; + } else if (count < 0) { + if (errno == EAGAIN) { + return ERROR_OK; + } else { + LOG_ERROR("remote_bitbang_fill_buf: %s (%d)", + strerror(errno), errno); + return ERROR_FAIL; + } + } + } + + return ERROR_OK; +} -static void remote_bitbang_putc(int c) +static int remote_bitbang_putc(int c) { - if (EOF == fputc(c, remote_bitbang_out)) - REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno)); + if (EOF == fputc(c, remote_bitbang_file)) { + LOG_ERROR("remote_bitbang_putc: %s", strerror(errno)); + return ERROR_FAIL; + } + return ERROR_OK; } static int remote_bitbang_quit(void) { - if (EOF == fputc('Q', remote_bitbang_out)) { + if (EOF == fputc('Q', remote_bitbang_file)) { LOG_ERROR("fputs: %s", strerror(errno)); return ERROR_FAIL; } - if (EOF == fflush(remote_bitbang_out)) { + if (EOF == fflush(remote_bitbang_file)) { LOG_ERROR("fflush: %s", strerror(errno)); return ERROR_FAIL; } /* We only need to close one of the FILE*s, because they both use the same */ /* underlying file descriptor. */ - if (EOF == fclose(remote_bitbang_out)) { + if (EOF == fclose(remote_bitbang_file)) { LOG_ERROR("fclose: %s", strerror(errno)); return ERROR_FAIL; } @@ -81,55 +121,84 @@ static int remote_bitbang_quit(void) return ERROR_OK; } -/* Get the next read response. */ -static int remote_bitbang_rread(void) +static bb_value_t char_to_int(int c) { - if (EOF == fflush(remote_bitbang_out)) { - remote_bitbang_quit(); - REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno)); - } - - int c = fgetc(remote_bitbang_in); switch (c) { case '0': - return 0; + return BB_LOW; case '1': - return 1; + return BB_HIGH; default: remote_bitbang_quit(); - REMOTE_BITBANG_RAISE_ERROR( - "remote_bitbang: invalid read response: %c(%i)", c, c); + LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c); + return BB_ERROR; + } +} + +/* Get the next read response. */ +static bb_value_t remote_bitbang_rread(void) +{ + if (EOF == fflush(remote_bitbang_file)) { + remote_bitbang_quit(); + LOG_ERROR("fflush: %s", strerror(errno)); + return BB_ERROR; + } + + /* Enable blocking access. */ + socket_block(remote_bitbang_fd); + char c; + ssize_t count = read(remote_bitbang_fd, &c, 1); + if (count == 1) { + return char_to_int(c); + } else { + remote_bitbang_quit(); + LOG_ERROR("read: count=%d, error=%s", (int) count, strerror(errno)); + return BB_ERROR; } } -static int remote_bitbang_read(void) +static int remote_bitbang_sample(void) { - remote_bitbang_putc('R'); + if (remote_bitbang_fill_buf() != ERROR_OK) + return ERROR_FAIL; + assert(!remote_bitbang_buf_full()); + return remote_bitbang_putc('R'); +} + +static bb_value_t remote_bitbang_read_sample(void) +{ + if (remote_bitbang_start != remote_bitbang_end) { + int c = remote_bitbang_buf[remote_bitbang_start]; + remote_bitbang_start = + (remote_bitbang_start + 1) % sizeof(remote_bitbang_buf); + return char_to_int(c); + } return remote_bitbang_rread(); } -static void remote_bitbang_write(int tck, int tms, int tdi) +static int remote_bitbang_write(int tck, int tms, int tdi) { char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0)); - remote_bitbang_putc(c); + return remote_bitbang_putc(c); } -static void remote_bitbang_reset(int trst, int srst) +static int remote_bitbang_reset(int trst, int srst) { char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0)); - remote_bitbang_putc(c); + return remote_bitbang_putc(c); } -static void remote_bitbang_blink(int on) +static int remote_bitbang_blink(int on) { char c = on ? 'B' : 'b'; - remote_bitbang_putc(c); + return remote_bitbang_putc(c); } static struct bitbang_interface remote_bitbang_bitbang = { - .read = &remote_bitbang_read, + .buf_size = sizeof(remote_bitbang_buf) - 1, + .sample = &remote_bitbang_sample, + .read_sample = &remote_bitbang_read_sample, .write = &remote_bitbang_write, - .reset = &remote_bitbang_reset, .blink = &remote_bitbang_blink, }; @@ -137,7 +206,7 @@ static int remote_bitbang_init_tcp(void) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; struct addrinfo *result, *rp; - int fd; + int fd = 0; LOG_INFO("Connecting to %s:%s", remote_bitbang_host ? remote_bitbang_host : "localhost", @@ -192,8 +261,8 @@ static int remote_bitbang_init_unix(void) struct sockaddr_un addr; addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, remote_bitbang_host, UNIX_PATH_LEN); - addr.sun_path[UNIX_PATH_LEN-1] = '\0'; + strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path)); + addr.sun_path[sizeof(addr.sun_path)-1] = '\0'; if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { LOG_ERROR("connect: %s", strerror(errno)); @@ -205,29 +274,24 @@ static int remote_bitbang_init_unix(void) static int remote_bitbang_init(void) { - int fd; bitbang_interface = &remote_bitbang_bitbang; + remote_bitbang_start = 0; + remote_bitbang_end = 0; + LOG_INFO("Initializing remote_bitbang driver"); if (remote_bitbang_port == NULL) - fd = remote_bitbang_init_unix(); + remote_bitbang_fd = remote_bitbang_init_unix(); else - fd = remote_bitbang_init_tcp(); - - if (fd < 0) - return fd; + remote_bitbang_fd = remote_bitbang_init_tcp(); - remote_bitbang_in = fdopen(fd, "r"); - if (remote_bitbang_in == NULL) { - LOG_ERROR("fdopen: failed to open read stream"); - close(fd); - return ERROR_FAIL; - } + if (remote_bitbang_fd < 0) + return remote_bitbang_fd; - remote_bitbang_out = fdopen(fd, "w"); - if (remote_bitbang_out == NULL) { + remote_bitbang_file = fdopen(remote_bitbang_fd, "w+"); + if (remote_bitbang_file == NULL) { LOG_ERROR("fdopen: failed to open write stream"); - fclose(remote_bitbang_in); + close(remote_bitbang_fd); return ERROR_FAIL; } @@ -277,10 +341,18 @@ static const struct command_registration remote_bitbang_command_handlers[] = { COMMAND_REGISTRATION_DONE, }; -struct jtag_interface remote_bitbang_interface = { - .name = "remote_bitbang", +static struct jtag_interface remote_bitbang_interface = { .execute_queue = &bitbang_execute_queue, +}; + +struct adapter_driver remote_bitbang_adapter_driver = { + .name = "remote_bitbang", + .transports = jtag_only, .commands = remote_bitbang_command_handlers, + .init = &remote_bitbang_init, .quit = &remote_bitbang_quit, + .reset = &remote_bitbang_reset, + + .jtag_ops = &remote_bitbang_interface, };