Contiki 2.6
|
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 /** @} */