From d460aec6700de247640affc3142d46c604b39ce0 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Fri, 2 Nov 2012 22:47:12 +0100 Subject: digital/ucoolib/ucoolib/hal/usb: add UsbStream --- digital/ucoolib/ucoolib/hal/usb/usb.stm32.cc | 159 +++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 digital/ucoolib/ucoolib/hal/usb/usb.stm32.cc (limited to 'digital/ucoolib/ucoolib/hal/usb/usb.stm32.cc') diff --git a/digital/ucoolib/ucoolib/hal/usb/usb.stm32.cc b/digital/ucoolib/ucoolib/hal/usb/usb.stm32.cc new file mode 100644 index 00000000..58435cd1 --- /dev/null +++ b/digital/ucoolib/ucoolib/hal/usb/usb.stm32.cc @@ -0,0 +1,159 @@ +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2012 Nicolas Schodet +// +// APBTeam: +// Web: http://apbteam.org/ +// Email: team AT apbteam DOT org +// +// 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. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} +#include "usb.stm32.hh" +#include + +#include +#include +#include +#include + +#include "usb_desc.stm32.h" + +extern "C" { + +void +otg_fs_isr () +{ + usbd_poll (); +} + +} + +namespace ucoo { + +UsbStreamControl *UsbStreamControl::instance_; + +const char *strings[] = { + "x", + NULL, + NULL, + NULL +}; + +UsbStreamControl::RxBuffer::RxBuffer (void) + : size (0), offset (0) +{ +} + +UsbStreamControl::UsbStreamControl (const char *vendor, const char *product) + : configured_ (false) +{ + //assert (!instance_); + instance_ = this; + strings[1] = vendor; + strings[2] = product; + rcc_peripheral_enable_clock (&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); + rcc_peripheral_enable_clock (&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); + gpio_mode_setup (GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, + GPIO9 | GPIO11 | GPIO12); + gpio_set_af (GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); + usbd_init (&otgfs_usb_driver, &usb_desc_dev, &usb_desc_config, strings); + usbd_register_set_config_callback (set_config); + nvic_enable_irq (NVIC_OTG_FS_IRQ); +} + +void +UsbStreamControl::set_config (uint16_t configured) +{ + instance_->configured_ = configured; + if (configured) + { + for (int i = 0; i < stream_nb_; i++) + { + usbd_ep_setup (0x01 + i, USB_ENDPOINT_ATTR_BULK, ep_size_, + rx_callback); + usbd_ep_setup (0x81 + i, USB_ENDPOINT_ATTR_BULK, ep_size_, NULL); + } + } +} + +void +UsbStreamControl::rx_callback (uint8_t ep) +{ + //assert (ep > 0 && ep <= stream_nb_); + int num = ep - 1; + RxBuffer &rb = instance_->rx_buffer_[num]; + //assert (rb.size == 0 && rb.offset == 0); + usbd_ep_nak_set (ep, 1); + rb.size = usbd_ep_read_packet (ep, rb.buf, ep_size_); +} + +UsbStream::UsbStream (UsbStreamControl &control, int num) + : control_ (control), num_ (num) +{ + //assert (num < UsbStreamControl::stream_nb_); +} + +int +UsbStream::read (char *buf, int count) +{ + UsbStreamControl::RxBuffer &rb = control_.rx_buffer_[num_]; + /* Wait for reception. */ + if (!rb.size && !block_) + return 0; + while (!rb.size) + barrier (); + /* Copy to provided buffer. */ + int len = std::min (count, rb.size - rb.offset); + buf = std::copy (rb.buf + rb.offset, rb.buf + rb.offset + len, buf); + rb.offset += len; + /* Reload buffer? */ + if (rb.offset == rb.size) + { + rb.offset = rb.size = 0; + barrier (); + usbd_ep_nak_set (num_ + 1, 0); + } + /* Done. */ + return len; +} + +int +UsbStream::write (const char *buf, int count) +{ + int left = count; + while (left) + { + if (control_.configured_) + { + int len = std::min (left, UsbStreamControl::ep_size_); + len = usbd_ep_write_packet (num_ + 0x81, buf, len); + buf += len; + left -= len; + } + if (!block_) + break; + } + return count - left; +} + +int +UsbStream::poll () +{ + UsbStreamControl::RxBuffer &rb = control_.rx_buffer_[num_]; + return rb.size - rb.offset; +} + +} // namespace ucoo -- cgit v1.2.3