diff --git a/fw/atspi/ep0.c b/fw/atspi/ep0.c index f9f311e..55ea23e 100644 --- a/fw/atspi/ep0.c +++ b/fw/atspi/ep0.c @@ -29,6 +29,31 @@ #define error(...) +/* + * SDCC 2.8.0 had a number of code generation bugs that appeared in the big + * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the + * "size" variable to be written to memory. This work-around doesn't seem + * to be necessary with 2.9.0, but we keep it around, just in case. + * + * Unfortunately, the setup->bRequest garbling bug is still with us. Without + * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the + * value of setup->bRequest and then rejects all SETUP requests. + */ + +#define SDCC_FORCE_EVAL(type, value) \ + do { \ + static volatile type foo; \ + foo = value; \ + } while (0) + +#define SDCC_FORCE_UPDATE(type, var) \ + do { \ + volatile type foo; \ + foo = var; \ + var = foo; \ + } while (0) + + static const uint8_t id[] = { EP0ATSPI_MAJOR, EP0ATSPI_MINOR, HW_TYPE }; static __xdata uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQ */ static uint8_t size; @@ -73,8 +98,12 @@ static void do_buf_write(void *user) } +#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ + + static __bit my_setup(struct setup_request *setup) __reentrant { + unsigned tmp; uint8_t i; switch (setup->bmRequestType | setup->bRequest << 8) { @@ -84,22 +113,24 @@ static __bit my_setup(struct setup_request *setup) __reentrant return 0; usb_send(&ep0, id, setup->wLength, NULL, NULL); return 1; - case ATSPI_FROM_DEV(ATSPI_BUILD_NUMBER): - debug("ATSPI_BUILD_NUMBER\n"); - if (setup->wLength > 2) - return 0; - usb_send(&ep0, (void *) &build_number, setup->wLength, - NULL, NULL); - return 1; - case ATSPI_FROM_DEV(ATSPI_BUILD_DATE): - debug("ATSPI_BUILD_DATE\n"); - for (size = 0; build_date[size]; size++); - if (size > EP1_SIZE) - return 0; + case ATSPI_FROM_DEV(ATSPI_BUILD): + debug("ATSPI_BUILD\n"); + tmp = build_number; + for (i = BUILD_OFFSET-2; tmp; i--) { + buf[i] = (tmp % 10)+'0'; + tmp /= 10; + } + buf[i] = '#'; + buf[BUILD_OFFSET-1] = ' '; + for (size = 0; build_date[size]; size++) + buf[BUILD_OFFSET+size] = build_date[size]; + size += BUILD_OFFSET-i+1; + SDCC_FORCE_EVAL(uint8_t, setup->bRequest); if (size > setup->wLength) return 0; - usb_send(&ep0, build_date, size, NULL, NULL); + usb_send(&ep0, buf+i, size, NULL, NULL); return 1; + case ATSPI_TO_DEV(ATSPI_RESET): debug("ATSPI_RESET\n"); RSTSRC = SWRSF; @@ -180,6 +211,7 @@ static __bit my_setup(struct setup_request *setup) __reentrant nSS = 1; usb_send(&ep0, buf, size, NULL, NULL); return 1; +#endif default: error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", diff --git a/fw/include/atspi/ep0.h b/fw/include/atspi/ep0.h index a23d619..f8e037c 100644 --- a/fw/include/atspi/ep0.h +++ b/fw/include/atspi/ep0.h @@ -18,9 +18,8 @@ * Direction bRequest wValue wIndex wLength * * ->host ATSPI_ID - - 3 + * ->host ATSPI_BUILD - - #bytes * host-> ATSPI_RESET - - 0 - * ->host ATSPI_BUILD_NUMBER - - 2 - * ->host ATSPI_BUILD_DATE - - #bytes * * host-> ATSPI_RF_RESET - - * @@ -61,9 +60,8 @@ enum atspi_requests { ATSPI_ID = 0x00, + ATSPI_BUILD, ATSPI_RESET, - ATSPI_BUILD_NUMBER, - ATSPI_BUILD_DATE, ATSPI_RF_RESET = 0x10, ATSPI_REG_WRITE = 0x20, ATSPI_REG_READ, diff --git a/tools/atspi-id/Makefile b/tools/atspi-id/Makefile new file mode 100644 index 0000000..0afa6d8 --- /dev/null +++ b/tools/atspi-id/Makefile @@ -0,0 +1,21 @@ +# +# atspi/Makefile - Build the ATSPI identification utility +# +# Written 2010 by Werner Almesberger +# Copyright 2010 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. +# + + +F32XBASE = ../../../f32xbase + +MAIN = atspi-id +OBJS = $(F32XBASE)/lib/usb.o + +include $(F32XBASE)/lib/Makefile.common + +CFLAGS += -I$(F32XBASE)/include -I../../fw/include diff --git a/tools/atspi-id/atspi-id.c b/tools/atspi-id/atspi-id.c new file mode 100644 index 0000000..88b5fe6 --- /dev/null +++ b/tools/atspi-id/atspi-id.c @@ -0,0 +1,113 @@ +/* + * atspi-id/atspi-id.c - Identify a ben-wpan AF86RF230 board + * + * Written 2010 by Werner Almesberger + * Copyright 2010 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 "f32xbase/usb.h" +#include "atspi/ep0.h" +#include "atspi/usb-ids.h" + + +#define FROM_DEV ATSPI_FROM_DEV(0) + +#define BUF_SIZE 256 + + + +static int get_id(usb_dev_handle *dev, void *data, int size) +{ + int res; + + res = usb_control_msg(dev, FROM_DEV, ATSPI_ID, 0, 0, data, size, 1000); + if (res < 0) + fprintf(stderr, "ATSPI_ID: %s\n", usb_strerror()); + return res; +} + + +static int atspi_get_protocol(usb_dev_handle *dev, + uint8_t *major, uint8_t *minor, uint8_t *target) +{ + uint8_t ids[3]; + + if (get_id(dev, ids, 3) < 0) + return -1; + if (major) + *major = ids[0]; + if (minor) + *minor = ids[1]; + if (target) + *target = ids[2]; + + return 0; +} + + +static int atspi_get_build(usb_dev_handle *dev, char *buf, size_t size) +{ + int res; + + res = usb_control_msg(dev, FROM_DEV, ATSPI_BUILD, 0, 0, buf, size, + 1000); + if (res < 0) + fprintf(stderr, "ATSPI_BUILD: %s\n", usb_strerror()); + return res; +} + + +static void show_info(usb_dev_handle *dev) +{ + const struct usb_device *device = usb_device(dev); + uint8_t major, minor, target; + char buf[BUF_SIZE+1]; /* +1 for terminating \0 */ + int len; + + printf("%04x:%04x ", + device->descriptor.idVendor, device->descriptor.idProduct); + + if (atspi_get_protocol(dev, &major, &minor, &target) < 0) + exit(1); + printf("protocol %u.%u hw %u\n", major, minor, target); + + len = atspi_get_build(dev, buf, sizeof(buf)-1); + if (len < 0) + exit(1); + buf[len] = 0; + printf("%10s%s\n", "", buf); +} + + +static void usage(const char *name) +{ + fprintf(stderr, "%s\n", name); + exit(1); +} + + +int main(int argc, const char **argv) +{ + usb_dev_handle *dev; + + if (argc != 1) + usage(*argv); + dev = open_usb(USB_VENDOR, USB_PRODUCT); + if (!dev) { + fprintf(stderr, ":-(\n"); + return 1; + } + + show_info(dev); + + return 0; +}