From ec21e4ba4756379934fc24635438040f66d2ab7c Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Tue, 8 Feb 2011 23:53:25 -0300 Subject: [PATCH] atusb/fw2: support device -> host side of the ATUSB EP0 protocol - ep0.c: the ATUSB EP0 protocol engine - Makefile (OBJS): added ep0.o - atusb.c (main): initialize the EP0 protocol - spi.h: whitespace cleanup usb/patches/support-vendor-requests.patch: - usb/ctrl.c (ctrl_handler): also pass vendor-specific requests to the class handler - class/CDC/cdc.c (cdc_req_handler): reject vendor requests --- atusb/fw2/Makefile | 2 +- atusb/fw2/atusb.c | 2 + atusb/fw2/ep0.c | 241 ++++++++++++++++++ atusb/fw2/spi.h | 1 + atusb/fw2/usb/patches/series | 1 + .../usb/patches/support-vendor-requests.patch | 37 +++ 6 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 atusb/fw2/ep0.c create mode 100644 atusb/fw2/usb/patches/support-vendor-requests.patch diff --git a/atusb/fw2/Makefile b/atusb/fw2/Makefile index e6fc479..e806409 100644 --- a/atusb/fw2/Makefile +++ b/atusb/fw2/Makefile @@ -16,7 +16,7 @@ USB_OBJS = $(FreakUSB)/usb/usb.o $(FreakUSB)/usb/ctrl.o \ $(FreakUSB)/usb/usb_buf.o \ $(FreakUSB)/hw/at90usbxx2/ep.o $(FreakUSB)/hw/at90usbxx2/hw.o \ $(FreakUSB)/hw/at90usbxx2/isr.o -OBJS = atusb.o spi.o descr.o $(USB_OBJS) +OBJS = atusb.o spi.o descr.o ep0.o $(USB_OBJS) CFLAGS += -I../fw/include \ -I$(FreakUSB)/usb -I$(FreakUSB)/hw/at90usbxx2 \ diff --git a/atusb/fw2/atusb.c b/atusb/fw2/atusb.c index c2b85c7..bc1cd88 100644 --- a/atusb/fw2/atusb.c +++ b/atusb/fw2/atusb.c @@ -13,6 +13,7 @@ void reset_rf(void); +void ep0_init(void); void reset_rf(void) @@ -68,6 +69,7 @@ int main(void) CLR(LED); usb_init(); + ep0_init(); hw_init(); while (1) diff --git a/atusb/fw2/ep0.c b/atusb/fw2/ep0.c new file mode 100644 index 0000000..625a550 --- /dev/null +++ b/atusb/fw2/ep0.c @@ -0,0 +1,241 @@ +/* + * atspi/ep0.c - EP0 extension protocol + * + * Written 2008-2010 by Werner Almesberger + * Copyright 2008-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 +//#ifndef NULL +//#define NULL 0 +//#endif + +//#include "regs.h" +//#include "uart.h" +//#include "usb.h" + +#include "freakusb.h" + +#include "at86rf230.h" +#include "atusb/ep0.h" +//#include "version.h" +#include "io.h" +#include "spi.h" + + +#define HW_TYPE 2 /* @@@ needs more work */ +static const char *build_date = "today"; +static unsigned build_number = 42; + +extern void reset_rf(void); + + +#define debug(...) +#define error(...) + + +static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE }; +static uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */ +static uint8_t size; + + +static void do_buf_write(void *user) +{ + uint8_t i; + + spi_begin(); + for (i = 0; i != size; i++) + spi_send(buf[i]); + spi_end(); +} + + +static void do_usb_send(const uint8_t *data, int len) +{ + int i; + + for (i = 0; i++ != len; data++) { + usb_buf_write(EP_CTRL, *data); + if (!(i % MAX_BUF_SZ)) + ep_write(EP_CTRL); + } + ep_write(EP_CTRL); +} + + +#define usb_send(ep, buf, len, arg1, arg2) do_usb_send(buf, len) +#define usb_recv(ep, buf, len, fn, arg) /* later */ + + +#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ + + +/* keep things a similar to the original as possible for now */ +#define setup_request req_t +#define setup req +#define bmRequestType type +#define bRequest req +#define wValue val +#define wLength len +#define wIndex idx +#define __reentrant + + +static int my_setup(struct setup_request *setup) __reentrant +{ + unsigned tmp; + uint8_t i; + + switch (setup->bmRequestType | setup->bRequest << 8) { + case ATUSB_FROM_DEV(ATUSB_ID): + debug("ATUSB_ID\n"); + if (setup->wLength > 3) + return 0; + usb_send(&ep0, id, setup->wLength, NULL, NULL); + return 1; + case ATUSB_FROM_DEV(ATUSB_BUILD): + debug("ATUSB_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; + if (size > setup->wLength) + return 0; + usb_send(&ep0, buf+i, size, NULL, NULL); + return 1; + +#ifdef NOTYET + case ATUSB_TO_DEV(ATUSB_RESET): + debug("ATUSB_RESET\n"); + RSTSRC = SWRSF; + while (1); +#endif + + case ATUSB_TO_DEV(ATUSB_RF_RESET): + debug("ATUSB_RF_RESET\n"); + reset_rf(); + return 1; + +#ifdef NOTYET + case ATUSB_FROM_DEV(ATUSB_POLL_INT): + debug("ATUSB_POLL_INT\n"); + if (setup->wLength < 1) + return 0; + *buf = IRQ_RF; + usb_send(&ep0, buf, 1, NULL, NULL); + return 1; +#endif + + case ATUSB_TO_DEV(ATUSB_REG_WRITE): + debug("ATUSB_REG_WRITE\n"); + spi_begin(); + spi_send(AT86RF230_REG_WRITE | setup->wIndex); + spi_send(setup->wValue); + spi_end(); + return 1; + case ATUSB_FROM_DEV(ATUSB_REG_READ): + debug("ATUSB_REG_READ\n"); + spi_begin(); + spi_send(AT86RF230_REG_READ | setup->wIndex); + *buf = spi_recv(); + spi_end(); + usb_send(&ep0, buf, 1, NULL, NULL); + return 1; + + case ATUSB_TO_DEV(ATUSB_BUF_WRITE): + debug("ATUSB_BUF_WRITE\n"); + if (setup->wLength < 1) + return 0; + if (setup->wLength > MAX_PSDU) + return 0; + buf[0] = AT86RF230_BUF_WRITE; + buf[1] = setup->wLength; + size = setup->wLength+2; + usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); + return 1; + case ATUSB_FROM_DEV(ATUSB_BUF_READ): + debug("ATUSB_BUF_READ\n"); + if (setup->wLength < 2) /* PHR+LQI */ + return 0; + if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */ + return 0; + spi_begin(); + spi_send(AT86RF230_BUF_READ); + size = spi_recv(); + if (size >= setup->wLength) + size = setup->wLength-1; + for (i = 0; i != size+1; i++) + buf[i] = spi_recv(); + spi_end(); + usb_send(&ep0, buf, size+1, NULL, NULL); + return 1; + + case ATUSB_TO_DEV(ATUSB_SRAM_WRITE): + debug("ATUSB_SRAM_WRITE\n"); + if (setup->wIndex > SRAM_SIZE) + return 0; + if (setup->wIndex+setup->wLength > SRAM_SIZE) + return 0; + buf[0] = AT86RF230_SRAM_WRITE; + buf[1] = setup->wIndex; + size = setup->wLength+2; + usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); + return 1; + case ATUSB_TO_DEV(ATUSB_SRAM_READ): + debug("ATUSB_SRAM_READ\n"); + if (setup->wIndex > SRAM_SIZE) + return 0; + if (setup->wIndex+setup->wLength > SRAM_SIZE) + return 0; + spi_begin(); + spi_send(AT86RF230_SRAM_READ); + spi_send(setup->wIndex); + for (i = 0; i != size; i++) + buf[i] = spi_recv(); + spi_end(); + usb_send(&ep0, buf, size, NULL, NULL); + return 1; + + default: + error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", + setup->bmRequestType, setup->bRequest); + return 0; + } +} + + +static void class_init(void) +{ +} + + +static void req_handler(req_t *req) +{ + if (!my_setup(req)) + ep_set_stall(EP_CTRL); +} + + +static void rx_handler(void) +{ +} + + +void ep0_init(void) +{ + usb_reg_class_drvr(class_init, req_handler, rx_handler); +} diff --git a/atusb/fw2/spi.h b/atusb/fw2/spi.h index 69c5983..5c514da 100644 --- a/atusb/fw2/spi.h +++ b/atusb/fw2/spi.h @@ -3,6 +3,7 @@ #include + void spi_begin(void); uint8_t spi_io(uint8_t v); void spi_end(void); diff --git a/atusb/fw2/usb/patches/series b/atusb/fw2/usb/patches/series index 46b5888..a5c2d6d 100644 --- a/atusb/fw2/usb/patches/series +++ b/atusb/fw2/usb/patches/series @@ -2,3 +2,4 @@ cleanup.patch no-cdc.patch no-vbus-detect.patch correct-array-size.patch +support-vendor-requests.patch diff --git a/atusb/fw2/usb/patches/support-vendor-requests.patch b/atusb/fw2/usb/patches/support-vendor-requests.patch new file mode 100644 index 0000000..28403c0 --- /dev/null +++ b/atusb/fw2/usb/patches/support-vendor-requests.patch @@ -0,0 +1,37 @@ +Index: fw4/class/CDC/cdc.c +=================================================================== +--- fw4.orig/class/CDC/cdc.c 2011-02-08 17:11:11.000000000 -0300 ++++ fw4/class/CDC/cdc.c 2011-02-08 17:12:30.000000000 -0300 +@@ -76,7 +76,10 @@ + { + U8 i; + usb_pcb_t *pcb = usb_pcb_get(); +- ++ ++ if (req->type & TYPE_CLASS) ++ goto reject; ++ + switch (req->req) + { + case GET_LINE_CODING: +@@ -127,6 +130,7 @@ + break; + + default: ++ reject: + ep_set_stall(EP_CTRL); + break; + } +Index: fw4/usb/ctrl.c +=================================================================== +--- fw4.orig/usb/ctrl.c 2011-02-08 17:09:02.000000000 -0300 ++++ fw4/usb/ctrl.c 2011-02-08 17:12:51.000000000 -0300 +@@ -277,7 +277,7 @@ + reqp = (req_t *)req; + + // decode the standard request +- if (!(reqp->type & TYPE_CLASS)) ++ if (!(reqp->type & (TYPE_CLASS | TYPE_VENDOR))) + { + // this is a standard request + switch (reqp->req)