diff --git a/tools/atrf-proxy/atrf-proxy.c b/tools/atrf-proxy/atrf-proxy.c index b9bb7b8..be06382 100644 --- a/tools/atrf-proxy/atrf-proxy.c +++ b/tools/atrf-proxy/atrf-proxy.c @@ -55,18 +55,19 @@ static int get_num(struct netio *netio, int last, int *ret) } -static int cmd_more(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) +static int cmd_two(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) { int n, ret; + n = get_num(netio, 0, &ret); + if (n < 0) + return ret; + if (n > 255) + return netio_printf(netio, "-bad argument\n"); + if (!strcasecmp(cmd, "set")) { int val; - n = get_num(netio, 0, &ret); - if (n < 0) - return ret; - if (n > 255) - return netio_printf(netio, "-bad argument\n"); val = get_num(netio, 1, &ret); if (val < 0) return ret; @@ -77,28 +78,6 @@ static int cmd_more(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) return netio_printf(netio, "-I/O error\n"); return netio_printf(netio, "+\n"); } - - n = get_num(netio, 1, &ret); - if (n < 0) - return ret; - - if (!strcasecmp(cmd, "slp_tr")) { - if (n > 1) - return netio_printf(netio, "-bad argument\n"); - if (atrf_slp_tr(dsc, n) < 0) - return netio_printf(netio, "-I/O error\n"); - return netio_printf(netio, "+\n"); - } - if (!strcasecmp(cmd, "get")) { - uint8_t res; - - if (n > 255) - return netio_printf(netio, "-bad argument\n"); - res = atrf_reg_read(dsc, n); - if (atrf_error(dsc)) - return netio_printf(netio, "-I/O error\n"); - return netio_printf(netio, "+0x%02x\n", res); - } if (!strcasecmp(cmd, "write")) { uint8_t *tmp; ssize_t got; @@ -123,6 +102,47 @@ static int cmd_more(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) return netio_printf(netio, "-I/O error\n"); return netio_printf(netio, "+\n"); } + abort(); +} + + +static int cmd_more(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) +{ + int n, ret; + + if (!strcasecmp(cmd, "set")) + return cmd_two(dsc, netio, cmd); + if (!strcasecmp(cmd, "write")) + return cmd_two(dsc, netio, cmd); + + n = get_num(netio, 1, &ret); + if (n < 0) + return ret; + + if (!strcasecmp(cmd, "slp_tr")) { + if (n > 1) + return netio_printf(netio, "-bad argument\n"); + if (atrf_slp_tr(dsc, n) < 0) + return netio_printf(netio, "-I/O error\n"); + return netio_printf(netio, "+\n"); + } + if (!strcasecmp(cmd, "clkm")) { + if (n > 16) + return netio_printf(netio, "-bad argument\n"); + if (atrf_set_clkm(dsc, n) < 0) + return netio_printf(netio, "-error\n"); + return netio_printf(netio, "+\n"); + } + if (!strcasecmp(cmd, "get")) { + uint8_t res; + + if (n > 255) + return netio_printf(netio, "-bad argument\n"); + res = atrf_reg_read(dsc, n); + if (atrf_error(dsc)) + return netio_printf(netio, "-I/O error\n"); + return netio_printf(netio, "+0x%02x\n", res); + } return netio_printf(netio, "-unrecognized command\n"); } @@ -159,6 +179,8 @@ static int cmd_zero(struct atrf_dsc *dsc, struct netio *netio, const char *cmd) res = atrf_interrupt(dsc); if (res < 0) return netio_printf(netio, "-I/O error\n"); + if (!res) + usleep(100*1000); return netio_printf(netio, "+%d\n", res); } return netio_printf(netio, "-unrecognized command\n"); diff --git a/tools/lib/Makefile b/tools/lib/Makefile index 3b1fd7d..1c03d90 100644 --- a/tools/lib/Makefile +++ b/tools/lib/Makefile @@ -19,7 +19,7 @@ OBJS_host = atusb.o usbopen.o OBJS_ben_jlime = atben.o OBJS_ben_openwrt = atben.o -OBJS = atrf.o misctxrx.o cwtest.o netio.o $(OBJS_$(TARGET)) +OBJS = atrf.o atnet.o misctxrx.o cwtest.o netio.o $(OBJS_$(TARGET)) .PHONY: all clean spotless diff --git a/tools/lib/atnet.c b/tools/lib/atnet.c new file mode 100644 index 0000000..b857598 --- /dev/null +++ b/tools/lib/atnet.c @@ -0,0 +1,411 @@ +/* + * lib/atnet.c - Access functions library for network proxy + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netio.h" + +#include "driver.h" + + +#define DEFAULT_PORT "5440" + + +static char reply[1000]; + + +static int dialog_vsend(struct netio *netio, const char *fmt, va_list ap) +{ + va_list ap2; + char *buf; + int n; + + va_copy(ap2, ap); + n = vsnprintf(NULL, 0, fmt, ap2); + + buf = malloc(n+1); + if (!buf) { + perror("malloc"); + return -1; + } + + vsprintf(buf, fmt, ap); + + buf[n] = '\n'; + if (netio_write(netio, buf, n+1) < 0) + return -1; + return 0; +} + + +static int dialog_send(struct netio *netio, const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = dialog_vsend(netio, fmt, ap); + va_end(ap); + return res; +} + + +static int dialog_recv(struct netio *netio) +{ + int n; + + n = netio_read_until(netio, "\n", reply, sizeof(reply)-1, NULL); + if (n < 0) + return -1; + reply[n] = 0; + + return reply[0] == '+' ? 0 : -1; +} + + +static int dialog(struct netio *netio, const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = dialog_vsend(netio, fmt, ap); + va_end(ap); + if (res < 0) + return res; + + return dialog_recv(netio); +} + + +/* ----- error handling ---------------------------------------------------- */ + + +static int error; + + +static int atnet_error(void *dsc) +{ + return error; +} + + +static int atnet_clear_error(void *dsc) +{ + int ret; + + ret = error; + error = 0; + return ret; +} + + +/* ----- open/close -------------------------------------------------------- */ + + +static void *atnet_open(const char *arg) +{ + char *host = NULL, *comma; + const char *port = DEFAULT_PORT; + struct addrinfo *addrs; + const struct addrinfo *addr; + static struct addrinfo hint = { .ai_socktype = SOCK_STREAM }; + int res, s; + struct netio *netio; + + if (arg) { + host = strdup(arg); + if (!host) { + perror("strdup"); + return NULL; + } + comma = strchr(host, ','); + if (comma) { + *comma = 0; + port = comma+1; + } + } + res = getaddrinfo(arg && *host ? host : NULL, port, &hint, &addrs); + if (res < 0) { + fprintf(stderr, "%s: %s\n", arg, gai_strerror(res)); + free(host); + return NULL; + } + free(host); + + for (addr = addrs; addr; addr = addr->ai_next) { + s = socket(addr->ai_family, addr->ai_socktype, + addr->ai_protocol); + if (s < 0) + continue; + if (connect(s, addr->ai_addr, addr->ai_addrlen) >= 0) + break; + close(s); + } + if (!addr) { + perror(arg); + freeaddrinfo(addrs); + return NULL; + } + + freeaddrinfo(addrs); + + netio = netio_open(s); + if (!netio) + return NULL; + + if (dialog_recv(netio) < 0) { + netio_close(netio); + return NULL; + } + + error = 0; + return netio; +} + + +static void atnet_close(void *dsc) +{ + struct netio *netio = dsc; + + netio_close(netio); +} + + +/* ----- device mode ------------------------------------------------------- */ + + +static void atnet_reset(void *dsc) +{ + struct netio *netio = dsc; + + if (error) + return; + if (dialog(netio, "RESET") < 0) + error = 1; +} + + +static void atnet_reset_rf(void *dsc) +{ + struct netio *netio = dsc; + + if (error) + return; + if (dialog(netio, "RESET_RF") < 0) + error = 1; +} + + +static void atnet_test_mode(void *dsc) +{ + struct netio *netio = dsc; + + if (error) + return; + if (dialog(netio, "TEST") < 0) + error = 1; +} + + +static void atnet_slp_tr(void *dsc, int on) +{ + struct netio *netio = dsc; + + if (error) + return; + if (dialog(netio, "SLP_TR %d", on) < 0) + error = 1; +} + + +/* ----- register access --------------------------------------------------- */ + + +static void atnet_reg_write(void *dsc, uint8_t reg, uint8_t value) +{ + struct netio *netio = dsc; + + if (error) + return; + if (dialog(netio, "SET 0x%02x 0x%02x", reg, value) < 0) + error = 1; +} + + +static uint8_t atnet_reg_read(void *dsc, uint8_t reg) +{ + struct netio *netio = dsc; + unsigned long value; + char *end; + + if (error) + return; + if (dialog(netio, "GET 0x%02x", reg) < 0) { + error = 1; + return 0; + } + value = strtoul(reply+1, &end, 0); + if (*end || value > 255) { + fprintf(stderr, "invalid response \"%s\"\n", reply); + error = 1; + return 0; + } + return value; +} + + +/* ----- frame buffer access ----------------------------------------------- */ + + +static void atnet_buf_write(void *dsc, const void *buf, int size) +{ + struct netio *netio = dsc; + char tmp[20]; + int n; + + if (error) + return; + + n = snprintf(tmp, sizeof(tmp), "WRITE %d ", size); + assert(n < sizeof(tmp)); + if (netio_write(netio, tmp, n) < 0) { + error = 1; + return; + } + + if (netio_write(netio, buf, size) < 0) { + error = 1; + return; + } + + if (netio_write(netio, "\n", 1) < 0) { + error = 1; + return; + } + + if (dialog_recv(netio) < 0) + error = 1; +} + + +static int atnet_buf_read(void *dsc, void *buf, int size) +{ + struct netio *netio = dsc; + uint8_t tmp[200]; + int n, got = 0; + unsigned long len = 0; + char *end; + + if (error) + return -1; + + if (dialog_send(netio, "READ") < 0) + goto fail; + + n = netio_read_until(netio, " ", tmp, sizeof(tmp)-1, NULL); + if (*tmp == '-') { + tmp[n] = 0; + fprintf(stderr, "%s\n", tmp+1); + goto fail; + } + if (*tmp != '+' || n < 3) /* +0 */ + goto invalid; + len = strtoul(tmp+1, &end, 0); + if (*end != ' ') + goto invalid; + if (len > size) { + fprintf(stderr, "buffer overflow\n"); + goto fail; + } + + got = netio_read(netio, buf, len); + if (got < 0) + goto fail; + + if (netio_getc(netio, tmp) < 0) + goto fail; + if (*tmp == '\n') + return len; + +invalid: + fprintf(stderr, "invalid reponse\n"); +fail: + error = 1; + return -1; +} + + +/* ----- RF interrupt ------------------------------------------------------ */ + + +static int atnet_interrupt(void *dsc) +{ + struct netio *netio = dsc; + unsigned long value; + char *end; + + if (error) + return -1; + if (dialog(netio, "POLL") < 0) { + error = 1; + return -1; + } + value = strtoul(reply+1, &end, 0); + if (*end || value > 1) { + fprintf(stderr, "invalid response \"%s\"\n", reply); + error = 1; + return -1; + } + return value; +} + + +/* ----- CLKM handling ----------------------------------------------------- */ + + +static int atnet_set_clkm(void *dsc, int mhz) +{ + struct netio *netio = dsc; + + return dialog(netio, "CLKM %d", mhz); +} + + +/* ----- driver interface -------------------------------------------------- */ + + +struct atrf_driver atnet_driver = { + .name = "net", + .open = atnet_open, + .close = atnet_close, + .error = atnet_error, + .clear_error = atnet_clear_error, + .reset = atnet_reset, + .reset_rf = atnet_reset_rf, + .test_mode = atnet_test_mode, + .slp_tr = atnet_slp_tr, + .set_clkm = atnet_set_clkm, + .reg_write = atnet_reg_write, + .reg_read = atnet_reg_read, + .buf_write = atnet_buf_write, + .buf_read = atnet_buf_read, + .interrupt = atnet_interrupt, +}; diff --git a/tools/lib/atrf.c b/tools/lib/atrf.c index 4c83db4..1cf4160 100644 --- a/tools/lib/atrf.c +++ b/tools/lib/atrf.c @@ -28,6 +28,18 @@ struct atrf_dsc { }; +static const struct atrf_driver *drivers[] = { +#ifdef HAVE_BEN + &atben_driver, +#endif +#ifdef HAVE_USB + &atusb_driver, +#endif + &atnet_driver, + NULL +}; + + void *atrf_usb_handle(struct atrf_dsc *dsc) { #ifdef HAVE_USB @@ -92,17 +104,6 @@ static enum atrf_chip_id identify(struct atrf_dsc *dsc) } -const static struct atrf_driver *drivers[] = { -#ifdef HAVE_BEN - &atben_driver, -#endif -#ifdef HAVE_USB - &atusb_driver, -#endif - NULL -}; - - const char *atrf_default_driver_name(void) { return drivers[0] ? drivers[0]->name : "none"; diff --git a/tools/lib/atusb.c b/tools/lib/atusb.c index 510c848..e64316d 100644 --- a/tools/lib/atusb.c +++ b/tools/lib/atusb.c @@ -224,6 +224,7 @@ static int atusb_interrupt(void *dsc) if (res < 0) { fprintf(stderr, "ATUSB_POLL_INT: %d\n", res); error = 1; + return -1; } return buf; diff --git a/tools/lib/driver.h b/tools/lib/driver.h index f562f0d..95879c0 100644 --- a/tools/lib/driver.h +++ b/tools/lib/driver.h @@ -38,6 +38,7 @@ struct atrf_driver { extern struct atrf_driver atusb_driver; extern struct atrf_driver atben_driver; +extern struct atrf_driver atnet_driver; int atrf_set_clkm_generic(