/* Copyright 2016 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "registers.h" #include "timer.h" #include "usb_dwc_stream.h" #include "util.h" #include "console.h" #define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) /* * This function tries to shove new bytes from the USB host into the queue for * consumption elsewhere. It is invoked either by a HW interrupt (telling us we * have new bytes from the USB host), or by whoever is reading bytes out of the * other end of the queue (telling us that there's now more room in the queue * if we still have bytes to shove in there). */ int rx_stream_handler(struct usb_stream_config const *config) { int rx_count = rx_ep_pending(config->endpoint); /* If we have some, try to shove them into the queue */ if (rx_count) { size_t added = QUEUE_ADD_UNITS( config->producer.queue, config->rx_ram, rx_count); if (added != rx_count) { CPRINTF("rx_stream_handler: failed ep%d " "queue %d bytes, accepted %d\n", config->endpoint, rx_count, added); } } if (!rx_ep_is_active(config->endpoint)) usb_read_ep(config->endpoint, config->rx_size, config->rx_ram); return rx_count; } /* Try to send some bytes to the host */ int tx_stream_handler(struct usb_stream_config const *config) { size_t count; if (!*(config->is_reset)) return 0; if (!tx_ep_is_ready(config->endpoint)) return 0; count = QUEUE_REMOVE_UNITS(config->consumer.queue, config->tx_ram, config->tx_size); if (count) usb_write_ep(config->endpoint, count, config->tx_ram); return count; } /* Reset stream */ void usb_stream_event(struct usb_stream_config const *config, enum usb_ep_event evt) { if (evt != USB_EVENT_RESET) return; epN_reset(config->endpoint); *(config->is_reset) = 1; /* Flush any queued data */ hook_call_deferred(config->deferred_tx, 0); hook_call_deferred(config->deferred_rx, 0); } static void usb_read(struct producer const *producer, size_t count) { struct usb_stream_config const *config = DOWNCAST(producer, struct usb_stream_config, producer); hook_call_deferred(config->deferred_rx, 0); } static void usb_written(struct consumer const *consumer, size_t count) { struct usb_stream_config const *config = DOWNCAST(consumer, struct usb_stream_config, consumer); hook_call_deferred(config->deferred_tx, 0); } struct producer_ops const usb_stream_producer_ops = { .read = usb_read, }; struct consumer_ops const usb_stream_consumer_ops = { .written = usb_written, };