Contiki 2.6

uart_usb_lib.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00002 /*! \file uart_usb_lib.c *********************************************************************
00003  *
00004  * \brief
00005  *      This file controls the UART USB functions.
00006  *
00007  * \addtogroup usbstick
00008  *
00009  * \author
00010  *      Atmel Corporation: http://www.atmel.com \n
00011  *      Support email: avr@atmel.com
00012  *
00013  ******************************************************************************/
00014 /* Copyright (c) 2008  ATMEL Corporation
00015    All rights reserved.
00016 
00017    Redistribution and use in source and binary forms, with or without
00018    modification, are permitted provided that the following conditions are met:
00019 
00020    * Redistributions of source code must retain the above copyright
00021      notice, this list of conditions and the following disclaimer.
00022    * Redistributions in binary form must reproduce the above copyright
00023      notice, this list of conditions and the following disclaimer in
00024      the documentation and/or other materials provided with the
00025      distribution.
00026    * Neither the name of the copyright holders nor the names of
00027      contributors may be used to endorse or promote products derived
00028      from this software without specific prior written permission.
00029 
00030   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00031   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00032   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00033   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00034   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00035   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00036   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00037   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00038   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00039   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00040   POSSIBILITY OF SUCH DAMAGE.
00041 */
00042 
00043 /*_____ I N C L U D E S ____________________________________________________*/
00044 
00045 #include "config.h"
00046 #include "usb_drv.h"
00047 #include "usb_descriptors.h"
00048 #include "serial/uart_usb_lib.h"
00049 #include "cdc_task.h"
00050 #include <stdio.h>
00051 
00052 /**
00053  \addtogroup cdctask
00054  @{
00055  */
00056 
00057 /*_____ M A C R O S ________________________________________________________*/
00058 
00059 #ifndef USB_CDC_ACM_HOOK_TX_START
00060 #define USB_CDC_ACM_HOOK_TX_START(char)
00061 #endif
00062 
00063 #ifndef USB_CDC_ACM_HOOK_TX_END
00064 #define USB_CDC_ACM_HOOK_TX_END(char)
00065 #endif
00066 
00067 #ifndef USB_CDC_ACM_HOOK_CLS_CHANGED
00068 #define USB_CDC_ACM_HOOK_CLS_CHANGED(state)
00069 #endif
00070 
00071 #ifndef USB_CDC_ACM_HOOK_CONFIGURED
00072 #define USB_CDC_ACM_HOOK_CONFIGURED()
00073 #endif
00074 
00075 #ifndef USB_CDC_ACM_CONF_LOCAL_ECHO
00076 #define USB_CDC_ACM_CONF_LOCAL_ECHO 0
00077 #endif
00078 
00079 /*_____ D E F I N I T I O N ________________________________________________*/
00080 
00081 Uchar tx_counter;
00082 Uchar rx_counter;
00083 S_line_coding   line_coding;
00084 
00085 /*_____ D E C L A R A T I O N ______________________________________________*/
00086 
00087 void uart_usb_configure_endpoints() {
00088         usb_configure_endpoint(
00089                 VCP_INT_EP,     
00090                 TYPE_INTERRUPT,   
00091                 DIRECTION_IN,  
00092                 SIZE_32,       
00093                 ONE_BANK,     
00094                 NYET_ENABLED
00095         );
00096 
00097         usb_configure_endpoint(
00098                 VCP_TX_EP,      
00099                 TYPE_BULK,     
00100                 DIRECTION_IN,  
00101                 SIZE_32,       
00102                 TWO_BANKS,     
00103                 NYET_ENABLED
00104         );
00105 
00106         usb_configure_endpoint(
00107                 VCP_RX_EP,      
00108                 TYPE_BULK,     
00109                 DIRECTION_OUT,  
00110                 SIZE_32,       
00111                 TWO_BANKS,     
00112                 NYET_ENABLED
00113         );
00114 
00115         Usb_reset_endpoint(VCP_INT_EP);
00116         Usb_reset_endpoint(VCP_TX_EP);
00117         Usb_reset_endpoint(VCP_RX_EP);
00118         
00119         USB_CDC_ACM_HOOK_CONFIGURED();
00120 }
00121 
00122 
00123 int usb_stdout_putchar(char c, FILE *stream)
00124 {
00125         // Preserve the currently selected endpoint
00126         uint8_t uenum = UENUM;
00127         
00128         // send to USB port
00129         // don't send anything if USB can't accept chars
00130         Usb_select_endpoint(VCP_TX_EP);
00131 
00132         if(usb_endpoint_wait_for_write_enabled()!=0)
00133                 return 0;
00134 
00135         if(c=='\n')
00136                 uart_usb_putchar('\r');
00137 
00138         if(c!='\r')
00139                 uart_usb_putchar(c);
00140 
00141         // Restore previously selected endpoint
00142         UENUM = uenum;
00143 
00144         return 0;
00145 }
00146 
00147 static FILE usb_stdout = FDEV_SETUP_STREAM(usb_stdout_putchar,
00148                                              NULL,
00149                                              _FDEV_SETUP_WRITE);
00150 
00151 /**
00152   * @brief Initializes the uart_usb library
00153   */
00154 void uart_usb_init(void)
00155 {
00156   tx_counter = 0;
00157   rx_counter = 0;
00158 }
00159 
00160 void uart_usb_set_stdout(void)
00161 {
00162   stdout = &usb_stdout;
00163 }
00164 
00165 
00166 static uint8_t uart_usb_control_line_state = 0;
00167 
00168 uint8_t uart_usb_get_control_line_state(void) {
00169         return uart_usb_control_line_state;
00170 }
00171 
00172 
00173 void uart_usb_set_control_line_state(uint8_t control_line_state)
00174 {
00175         uart_usb_control_line_state = control_line_state;
00176         USB_CDC_ACM_HOOK_CLS_CHANGED(control_line_state);
00177 }
00178 
00179 
00180 /**
00181   * @brief This function checks if the USB emission buffer is ready to accept at
00182   * at least 1 byte
00183   *
00184   * @retval TRUE if the firmware can write a new byte to transmit.
00185   * @retval FALSE otherwise
00186   */
00187 bit uart_usb_tx_ready(void)
00188 {
00189   Usb_select_endpoint(VCP_TX_EP);
00190   if (!Is_usb_write_enabled())
00191   {
00192     return FALSE;
00193   }
00194   return TRUE;
00195 }
00196 
00197 /**
00198   * @brief This function fills the USB transmit buffer with the new data. This buffer
00199   * is sent if complete. To flush this buffer before waiting full, launch
00200   * the uart_usb_flush() function.
00201   *
00202   * @param data_to_send Data to send
00203   *
00204   * @return data_to_send Data that was sent
00205   */
00206 int uart_usb_putchar(int data_to_send)
00207 {
00208         // Preserve the currently selected endpoint
00209         uint8_t uenum = UENUM;
00210 
00211         USB_CDC_ACM_HOOK_TX_START(data_to_send);
00212 
00213         Usb_select_endpoint(VCP_TX_EP);
00214 
00215         if(!uart_usb_tx_ready()) {
00216                 data_to_send=-1;
00217                 goto bail;
00218         }
00219 
00220         Usb_write_byte(data_to_send);
00221         tx_counter++;
00222 
00223         //If Endpoint full -> flush
00224         if(!Is_usb_write_enabled())
00225                 uart_usb_flush();
00226 
00227         USB_CDC_ACM_HOOK_TX_END(data_to_send);
00228 
00229 bail:
00230         // Restore previously selected endpoint
00231         UENUM = uenum;
00232 
00233         return data_to_send;
00234 }
00235 
00236 /** 
00237   * @brief This function checks if a character has been received on the USB bus.
00238   * 
00239   * @return bit (true if a byte is ready to be read)
00240   */
00241 bit uart_usb_test_hit(void)
00242 {
00243   if (!rx_counter)
00244   {
00245         // Preserve the currently selected endpoint
00246         uint8_t uenum = UENUM;
00247     Usb_select_endpoint(VCP_RX_EP);
00248     if (Is_usb_receive_out())
00249     {
00250       rx_counter = Usb_byte_counter();
00251       if (!rx_counter)
00252                 {
00253         Usb_ack_receive_out();
00254                 }
00255     }
00256         // Restore previously selected endpoint
00257         UENUM = uenum;
00258   }
00259   return (rx_counter!=0);
00260 }
00261 
00262 /** 
00263   * @brief This function reads one byte from the USB bus
00264   *
00265   * If one byte is present in the USB fifo, this byte is returned. If no data
00266   * is present in the USB fifo, this function waits for USB data.
00267   * 
00268   * @return U8 byte received
00269   */
00270 char uart_usb_getchar(void)
00271 {
00272   register Uchar data_rx;
00273 
00274   // Preserve the currently selected endpoint
00275   uint8_t uenum = UENUM;
00276   
00277   Usb_select_endpoint(VCP_RX_EP);
00278   if (!rx_counter) while (!uart_usb_test_hit());
00279   data_rx=Usb_read_byte();
00280   rx_counter--;
00281   if (!rx_counter) Usb_ack_receive_out();
00282   
00283 #if USB_CDC_ACM_CONF_LOCAL_ECHO
00284   //Local echo
00285   uart_usb_putchar(data_rx);
00286 #endif
00287   
00288   // Restore previously selected endpoint
00289   UENUM = uenum;
00290 
00291   return data_rx;
00292 }
00293 
00294 
00295 /**
00296   * @brief This function sends the data stored in the USB transmit buffer.
00297   * This function does nothing if there is no data in the buffer.
00298   */
00299 void uart_usb_flush (void)
00300 {
00301         // Preserve the currently selected endpoint
00302         uint8_t uenum = UENUM;
00303         
00304         Usb_select_endpoint(VCP_TX_EP);
00305         Usb_send_in();
00306         tx_counter = 0;
00307         usb_endpoint_wait_for_write_enabled();
00308 
00309         // Restore previously selected endpoint
00310         UENUM = uenum;
00311 }
00312 
00313 /** @} */