/* * ${file_name} * * Created on: ${date} * Author: hathach */ /* * Software License Agreement (BSD License) * Copyright (c) 2013, hathach (tinyusb.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the tinyUSB stack. */ #include "cdc.h" #include "common/fifo.h" #if defined TUSB_CFG_DEVICE_CDC && defined TUSB_CFG_DEVICE static USBD_HANDLE_T g_hCdc; static CDC_LINE_CODING line_coding; static uint8_t qBuffer[2][CDC_BUFFER_SIZE]; /* TX and RX buffers */ static fifo_t ffTX, ffRX; void usb_cdc_recv_isr(void) ATTR_WEAK ATTR_ALIAS(usb_cdc_recv_isr_stub); /**************************************************************************/ /*! @brief Stub for the optional CDC receive ISR that can be used to perform some action when data arrives via USB CDC */ /**************************************************************************/ void usb_cdc_recv_isr_stub (void) { return; } /**************************************************************************/ /*! @brief Adds a single byte to the transmit buffer for USB CDC @param[in] c The byte to send @returns TRUE if the byte was successfully added to the TX buffer @note See example for tusb_cdc_getc */ /**************************************************************************/ bool tusb_cdc_putc (uint8_t c) { return fifo_write(&ffTX, c); } /**************************************************************************/ /*! @brief Reads a single byte from the USB CDC buffer @param[in] c Pointer to the location where the byte should be written @returns TRUE if a byte was read from the buffer @section EXAMPLE @code // Convert incoming characters to upper case and send back via CDC if (usb_isConfigured()) { uint8_t cdc_char; if( tusb_cdc_getc(&cdc_char) ) { switch (cdc_char) { default : cdc_char = toupper(cdc_char); tusb_cdc_putc(cdc_char); break; } } } @endcode */ /**************************************************************************/ bool tusb_cdc_getc(uint8_t *c) { ASSERT(c, false); // not empty pointer return fifo_read(&ffRX, c); } /**************************************************************************/ /*! @brief Writes the supplied buffer to the USB CDC device @param[in] buffer Pointer to the buffer that should be written via USB CDC @param[in] count The number of bytes to write @returns The actual number of bytes sent out via USB CDC @section EXAMPLE @code // Capture printf output (in Red Suite) and send it to USB CDC // (Note: With newlib this function should be renamed to _write) int __sys_write(int file, char *ptr, int len) { #ifdef CFG_PRINTF_USBCDC // Handle USB CDC output if (usb_isConfigured()) { int length = len; while(length > 0) { uint16_t transferredCount; transferredCount = tusb_cdc_send( (uint8_t*) ptr, length); ptr += transferredCount; length -= transferredCount; } } #endif return len; } @endcode */ /**************************************************************************/ uint16_t tusb_cdc_send(uint8_t* buffer, uint16_t count) { uint16_t i=0; ASSERT(buffer && count, 0); while (i < count && fifo_write(&ffTX, buffer[i]) ) { i++; } return i; } /**************************************************************************/ /*! @brief Reads the incoming CDC buffer up to a maximum number of bytes @param[in] buffer Pointer to the buffer where data should be written @param[in] max The maximum number of bytes to read @returns The actual number of bytes received */ /**************************************************************************/ uint16_t tusb_cdc_recv(uint8_t* buffer, uint16_t max) { ASSERT(buffer && max, 0); return fifo_read_n(&ffRX, buffer, max); } #if 0 // ROM driver bug: cannot hook this to CIC_GetRequest // Need this to implement GetLineCode & detect ErrorCode_t CDC_Control_GetRequest(USBD_HANDLE_T hUsb, USB_SETUP_PACKET *pSetup, uint8_t **pBuffer, uint16_t *length) { return LPC_OK; } #endif /**************************************************************************/ /*! @brief TODO Add description */ /**************************************************************************/ ErrorCode_t CDC_SetLineCoding(USBD_HANDLE_T hUsb, CDC_LINE_CODING *lineCoding) { ASSERT(lineCoding, ERR_FAILED); memcpy(&line_coding, lineCoding, sizeof(CDC_LINE_CODING)); return LPC_OK; } /**************************************************************************/ /*! @brief TODO Add description */ /**************************************************************************/ ErrorCode_t CDC_SendBreak(USBD_HANDLE_T hCDC, uint16_t mstime) { return LPC_OK; } /**************************************************************************/ /*! @brief Bulk Out handler for the USB ROM drivers (UART TX) */ /**************************************************************************/ ErrorCode_t CDC_BulkIn_Hdlr(USBD_HANDLE_T hUsb, void* data, uint32_t event) { if (USB_EVT_IN == event) { uint8_t buffer[CDC_DATA_EP_MAXPACKET_SIZE]; uint16_t count; count = fifo_read_n(&ffTX, buffer, CDC_DATA_EP_MAXPACKET_SIZE); USBD_API->hw->WriteEP(hUsb, CDC_DATA_EP_IN, buffer, count); // write data to EP } return LPC_OK; } /**************************************************************************/ /*! @brief Bulk Out handler for the USB ROM drivers (UART RX) */ /**************************************************************************/ ErrorCode_t CDC_BulkOut_Hdlr(USBD_HANDLE_T hUsb, void* data, uint32_t event) { if (USB_EVT_OUT == event) { uint16_t count, i; uint8_t buffer[CDC_DATA_EP_MAXPACKET_SIZE]; count = USBD_API->hw->ReadEP(hUsb, CDC_DATA_EP_OUT, buffer); for (i=0; icore->RegisterEpHandler (hUsb , ((CDC_DATA_EP_IN & 0x0F) << 1) +1 , CDC_BulkIn_Hdlr , NULL), TUSB_ERROR_FAILED ); ASSERT ( LPC_OK == USBD_API->core->RegisterEpHandler (hUsb , (CDC_DATA_EP_OUT & 0x0F) << 1 , CDC_BulkOut_Hdlr , NULL), TUSB_ERROR_FAILED ); ASSERT ( LPC_OK == USBD_API->cdc->init(hUsb, &cdc_param, &g_hCdc), TUSB_ERROR_FAILED); /* update memory variables */ *mem_base = cdc_param.mem_base; *mem_size = cdc_param.mem_size; return TUSB_ERROR_NONE; } /**************************************************************************/ /*! @brief TODO Add description */ /**************************************************************************/ tusb_error_t tusb_cdc_configured(USBD_HANDLE_T hUsb) { uint8_t dummy=0; USBD_API->hw->WriteEP(hUsb, CDC_DATA_EP_IN, &dummy, 1); // initial packet for IN endpoint, will not work if omitted // FIXME abstract to hal #if MCU == MCU_LPC11UXX fifo_init (&ffTX, qBuffer[0], CDC_BUFFER_SIZE, false, USB_IRQn); // TX is non-overwritable fifo_init (&ffRX, qBuffer[1], CDC_BUFFER_SIZE, true, USB_IRQn); // RX is overwritable #elif MCU == MCU_LPC13UXX fifo_init (&ffTX, qBuffer[0], CDC_BUFFER_SIZE, false, USB_IRQ_IRQn); // TX is non-overwritable fifo_init (&ffRX, qBuffer[1], CDC_BUFFER_SIZE, true, USB_IRQ_IRQn); // RX is overwritable #elif MCU == MCU_LPC43XX fifo_init (&ffTX, qBuffer[0], CDC_BUFFER_SIZE, false, USB0_IRQn); // TODO USB1 TX is non-overwritable fifo_init (&ffRX, qBuffer[1], CDC_BUFFER_SIZE, true, USB0_IRQn); // RX is overwritable #else #error No MCU defined // TODO asbtract MCU #endif return TUSB_ERROR_NONE; } #endif