/* * Copyright (c) 2015 Travis Geiselbrecht * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include /* a simple demo usb class device that reflects data written to * one endpoint to the other. */ #define LOCAL_TRACE 0 #define W(w) (w & 0xff), (w >> 8) #define W3(w) (w & 0xff), ((w >> 8) & 0xff), ((w >> 16) & 0xff) static status_t ep_cb_rx(ep_t endpoint, usbc_transfer_t *t); static status_t ep_cb_tx(ep_t endpoint, usbc_transfer_t *t); #define TRANSFER_SIZE 512 static void queue_rx(void) { static usbc_transfer_t transfer; static uint8_t buf[TRANSFER_SIZE]; transfer.callback = &ep_cb_rx; transfer.result = 0; transfer.buf = &buf; transfer.buflen = sizeof(buf); transfer.bufpos = 0; transfer.extra = 0; usbc_queue_rx(1, &transfer); } static void queue_tx(void) { static usbc_transfer_t transfer; static uint8_t buf[TRANSFER_SIZE]; for (uint i = 0; i < sizeof(buf); i++) { buf[i] = ~i; } transfer.callback = &ep_cb_tx; transfer.result = 0; transfer.buf = &buf; transfer.buflen = sizeof(buf); transfer.bufpos = 0; transfer.extra = 0; usbc_queue_tx(1, &transfer); } static status_t ep_cb_rx(ep_t endpoint, usbc_transfer_t *t) { #if LOCAL_TRACE LTRACEF("ep %u transfer %p\n", endpoint, t); usbc_dump_transfer(t); if (t->result >= 0) { hexdump8(t->buf, t->bufpos); } #endif if (t->result >= 0) queue_rx(); return NO_ERROR; } static status_t ep_cb_tx(ep_t endpoint, usbc_transfer_t *t) { #if LOCAL_TRACE LTRACEF("ep %u transfer %p\n", endpoint, t); usbc_dump_transfer(t); #endif if (t->result >= 0) queue_tx(); return NO_ERROR; } static status_t bulktest_usb_cb(void *cookie, usb_callback_op_t op, const union usb_callback_args *args) { LTRACEF("cookie %p, op %u, args %p\n", cookie, op, args); if (op == USB_CB_ONLINE) { usbc_setup_endpoint(1, USB_IN, 0x40, USB_BULK); usbc_setup_endpoint(1, USB_OUT, 0x40, USB_BULK); queue_rx(); queue_tx(); } return NO_ERROR; } status_t usb_class_bulktest_init(uint interface_num, ep_t epin, ep_t epout) { LTRACEF("epin %u, epout %u\n", epin, epout); /* build a descriptor for it */ uint8_t if_descriptor[] = { 0x09, /* length */ INTERFACE, /* type */ interface_num, /* 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 */ epin | 0x80, /* address: 1 IN */ 0x02, /* type: bulk */ W(64), /* max packet size: 64 */ 00, /* interval */ /* endpoint 1 OUT */ 0x07, /* length */ ENDPOINT, /* type */ epout, /* address: 1 OUT */ 0x02, /* type: bulk */ W(64), /* max packet size: 64 */ 00, /* interval */ }; usb_append_interface_lowspeed(if_descriptor, sizeof(if_descriptor)); usb_append_interface_highspeed(if_descriptor, sizeof(if_descriptor)); usb_register_callback(&bulktest_usb_cb, NULL); return NO_ERROR; }