diff --git a/app/usbtest/descriptor.c b/app/usbtest/descriptor.c new file mode 100644 index 00000000..97ebab76 --- /dev/null +++ b/app/usbtest/descriptor.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define W(w) (w & 0xff), (w >> 8) +#define W3(w) (w & 0xff), ((w >> 8) & 0xff), ((w >> 16) & 0xff) + +/* top level device descriptor */ +static const uint8_t dev_descr[] = { + 0x12, /* descriptor length */ + DEVICE, /* Device Descriptor type */ + W(0x0200), /* USB Version */ + 0xff, /* class */ + 0xff, /* subclass */ + 0xff, /* protocol */ + 64, /* max packet size, ept0 */ + W(0x9999), /* vendor */ + W(0x9999), /* product */ + W(0x9999), /* release */ + 0x0, /* manufacturer string */ + 0x0, /* product string */ + 0x0, /* serialno string */ + 0x1, /* num configs */ +}; + +/* high/low speed device qualifier */ +static const uint8_t devqual_descr[] = { + 0x0a, /* len */ + DEVICE_QUALIFIER, /* Device Qualifier type */ + W(0x0200), /* USB version */ + 0x00, /* class */ + 0x00, /* subclass */ + 0x00, /* protocol */ + 64, /* max packet size, ept0 */ + 0x01, /* num configs */ + 0x00 /* reserved */ +}; + +static const uint8_t cfg_descr[] = { + 0x09, /* Length of Cfg Descr */ + CONFIGURATION, /* Type of Cfg Descr */ + W(0x09), /* Total Length (incl ifc, ept) */ + 0x00, /* # Interfaces */ + 0x01, /* Cfg Value */ + 0x00, /* Cfg String */ + 0xc0, /* Attributes -- self powered */ + 250, /* Power Consumption - 500mA */ +}; + +static const uchar langid[] = { 0x04, 0x03, 0x09, 0x04 }; + +static const uint8_t if_descriptor_lowspeed[] = { + 0x09, /* length */ + INTERFACE, /* type */ + 0x01, /* interface num */ + 0x00, /* alternates */ + 0x02, /* endpoint count */ + 0xff, /* interface class */ + 0xff, /* interface subclass */ + 0x00, /* interface protocol */ + 0x00, /* string index */ + + /* endpoint 1 IN */ + 0x07, /* length */ + ENDPOINT, /* type */ + 0x81, /* address: 1 IN */ + 0x02, /* type: bulk */ + W(64), /* max packet size: 64 */ + 00, /* interval */ + + /* endpoint 1 OUT */ + 0x07, /* length */ + ENDPOINT, /* type */ + 0x01, /* address: 1 OUT */ + 0x02, /* type: bulk */ + W(64), /* max packet size: 64 */ + 00, /* interval */ +}; + +static usb_config config = { + .lowspeed = { + .device = USB_DESC_STATIC(dev_descr), + .device_qual = USB_DESC_STATIC(devqual_descr), + .config = USB_DESC_STATIC(cfg_descr), + }, + .highspeed = { + .device = USB_DESC_STATIC(dev_descr), + .device_qual = USB_DESC_STATIC(devqual_descr), + .config = USB_DESC_STATIC(cfg_descr), + }, + + .langid = USB_DESC_STATIC(langid), +}; + +void usbtest_usb_setup(void) +{ + usb_setup(&config); + printf("appending interfaces\n"); + usb_append_interface_lowspeed(if_descriptor_lowspeed, sizeof(if_descriptor_lowspeed)); + usb_append_interface_highspeed(if_descriptor_lowspeed, sizeof(if_descriptor_lowspeed)); + usbc_setup_endpoint(1, USB_OUT, 64); + usbc_setup_endpoint(1, USB_IN, 64); +} + +// vim: set ts=4 sw=4 expandtab: diff --git a/app/usbtest/rules.mk b/app/usbtest/rules.mk new file mode 100644 index 00000000..6e531257 --- /dev/null +++ b/app/usbtest/rules.mk @@ -0,0 +1,15 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +#GLOBAL_INCLUDES += $(LOCAL_DIR)/include + +MODULE_DEPS += \ + dev/usb + +MODULE_SRCS += \ + $(LOCAL_DIR)/usbtest.c \ + $(LOCAL_DIR)/descriptor.c \ + +include make/module.mk + diff --git a/app/usbtest/usbtest.c b/app/usbtest/usbtest.c new file mode 100644 index 00000000..db2b2183 --- /dev/null +++ b/app/usbtest/usbtest.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOCAL_TRACE 1 + +extern void usbtest_usb_setup(void); + +static status_t rx_callback(ep_t endpoint, struct usbc_transfer *transfer); +static usbc_transfer_t rx; +static uint8_t rxbuf[4096]; +static volatile bool rxqueued; + +static status_t tx_callback(ep_t endpoint, struct usbc_transfer *transfer); +static usbc_transfer_t tx; +static uint8_t txbuf[4095]; +static volatile bool txqueued; + +static event_t testevent; + +/* RX */ +static void queue_rx_transfer(void) +{ + rx.callback = rx_callback; + rx.result = 0; + rx.buf = rxbuf; + rx.buflen = sizeof(rxbuf); + rx.bufpos = 0; + rx.extra = NULL; + + memset(rxbuf, 0x99, sizeof(rxbuf)); + + rxqueued = true; + usbc_queue_rx(1, &rx); +} + +static status_t rx_callback(ep_t endpoint, struct usbc_transfer *transfer) +{ + LTRACEF("ep %u, transfer %p\n", endpoint, transfer); + + rxqueued = false; + event_signal(&testevent, false); + + return NO_ERROR; +} + +/* TX */ +static void queue_tx_transfer(void) +{ + tx.callback = tx_callback; + tx.result = 0; + tx.buf = txbuf; + tx.buflen = sizeof(txbuf); + tx.bufpos = 0; + tx.extra = NULL; + + for (uint i = 0; i < sizeof(txbuf); i++) + txbuf[i] = i * 3; + + txqueued = true; + usbc_queue_tx(1, &tx); +} + +static status_t tx_callback(ep_t endpoint, struct usbc_transfer *transfer) +{ + LTRACEF("ep %u, transfer %p\n", endpoint, transfer); + + txqueued = false; + event_signal(&testevent, false); + + return NO_ERROR; +} + +static void usbtest_init(const struct app_descriptor *app) +{ + LTRACE_ENTRY; + event_init(&testevent, false, EVENT_FLAG_AUTOUNSIGNAL); + usbtest_usb_setup(); + LTRACE_EXIT; +} + +static void usbtest_entry(const struct app_descriptor *app, void *args) +{ + LTRACE_ENTRY; + + TRACEF("starting usb stack\n"); + usb_start(); + + // XXX get callback from stack + thread_sleep(2000); + + TRACEF("queuing transfers\n"); + queue_rx_transfer(); + queue_tx_transfer(); + + while (event_wait(&testevent) == NO_ERROR) { + if (!rxqueued) { + /* dump the state of the transfer */ + LTRACEF("rx transfer completed\n"); + usbc_dump_transfer(&rx); + hexdump8(rx.buf, MIN(128, rx.bufpos)); + + queue_rx_transfer(); + } + if (!txqueued) { + /* dump the state of the transfer */ + LTRACEF("tx transfer completed\n"); + usbc_dump_transfer(&tx); + + queue_tx_transfer(); + } + } + + LTRACE_EXIT; +} + +APP_START(usbtest) + .init = usbtest_init, + .entry = usbtest_entry, +APP_END + +