Contiki 2.6
|
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/ 00002 /*! \file usb_drv.c************************************************************ 00003 * 00004 * \brief 00005 * This file contains the USB driver routines. 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 /** 00044 \addtogroup usbdriver 00045 @{ 00046 */ 00047 00048 //_____ I N C L U D E S ____________________________________________________ 00049 00050 #include "config.h" 00051 #include "conf_usb.h" 00052 #include "usb_drv.h" 00053 #include <util/delay.h> 00054 00055 //_____ M A C R O S ________________________________________________________ 00056 00057 //_____ D E C L A R A T I O N ______________________________________________ 00058 00059 #if (USB_DEVICE_FEATURE==DISABLED && USB_HOST_FEATURE==DISABLED) 00060 #error at least one of USB_DEVICE_FEATURE or USB_HOST_FEATURE should be unabled 00061 #endif 00062 00063 #if (USB_DEVICE_FEATURE == ENABLED) 00064 00065 #define USB_ENDPOINT_WAIT_TIMEOUT 250 00066 00067 U8 usb_endpoint_wait_for_write_enabled() { 00068 #if USB_ENDPOINT_WAIT_TIMEOUT 00069 U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; 00070 while(timeout) { 00071 if(Is_usb_sof()) { 00072 Usb_ack_sof(); 00073 timeout--; 00074 } 00075 #else 00076 while(1) { 00077 #endif 00078 if(Is_usb_write_enabled()) 00079 return 0; 00080 if((!Is_usb_enabled()) || Is_usb_detached()) 00081 return 1; 00082 if(!Is_usb_endpoint_enabled()) 00083 return 2; 00084 if(Is_usb_endpoint_stall_requested()) 00085 return 3; 00086 } 00087 return 10; 00088 } 00089 00090 U8 usb_endpoint_wait_for_read_control_enabled() { 00091 #if USB_ENDPOINT_WAIT_TIMEOUT 00092 U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; 00093 while(timeout) { 00094 if(Is_usb_sof()) { 00095 Usb_ack_sof(); 00096 timeout--; 00097 } 00098 #else 00099 while(1) { 00100 #endif 00101 if(Is_usb_read_control_enabled()) 00102 return 0; 00103 if((!Is_usb_enabled()) || Is_usb_detached()) 00104 return 1; 00105 if(!Is_usb_endpoint_enabled()) 00106 return 2; 00107 if(Is_usb_endpoint_stall_requested()) 00108 return 3; 00109 } 00110 return 10; 00111 } 00112 00113 00114 U8 usb_endpoint_wait_for_IN_ready() { 00115 #if USB_ENDPOINT_WAIT_TIMEOUT 00116 U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; 00117 while(timeout) { 00118 if(Is_usb_sof()) { 00119 Usb_ack_sof(); 00120 timeout--; 00121 } 00122 #else 00123 while(1) { 00124 #endif 00125 if(Is_usb_in_ready()) 00126 return 0; 00127 if((!Is_usb_enabled()) || Is_usb_detached()) 00128 return 1; 00129 if(!Is_usb_endpoint_enabled()) 00130 return 2; 00131 if(Is_usb_endpoint_stall_requested()) 00132 return 3; 00133 } 00134 return 10; 00135 } 00136 00137 00138 U8 usb_endpoint_wait_for_receive_out() { 00139 #if USB_ENDPOINT_WAIT_TIMEOUT 00140 U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT; 00141 while(timeout) { 00142 if(Is_usb_sof()) { 00143 Usb_ack_sof(); 00144 timeout--; 00145 } 00146 #else 00147 while(1) { 00148 #endif 00149 if(Is_usb_receive_out()) 00150 return 0; 00151 if((!Is_usb_enabled()) || Is_usb_detached()) 00152 return 1; 00153 if(!Is_usb_endpoint_enabled()) 00154 return 2; 00155 if(Is_usb_endpoint_stall_requested()) 00156 return 3; 00157 } 00158 return 10; 00159 } 00160 00161 //! usb_configure_endpoint. 00162 //! 00163 //! This function configures an endpoint with the selected type. 00164 //! 00165 //! @param config0 00166 //! @param config1 00167 //! 00168 //! @return Is_endpoint_configured(). 00169 //! 00170 U8 usb_config_ep(U8 config0, U8 config1) 00171 { 00172 Usb_enable_endpoint(); 00173 UECFG0X = config0; 00174 UECFG1X = (UECFG1X & (1<<ALLOC)) | config1; 00175 Usb_allocate_memory(); 00176 return (Is_endpoint_configured()); 00177 } 00178 00179 //! usb_select_endpoint_interrupt. 00180 //! 00181 //! This function select the endpoint where an event occurs and returns the 00182 //! number of this endpoint. If no event occurs on the endpoints, this 00183 //! function returns 0. 00184 //! 00185 //! @return 0 endpoint number. 00186 //! 00187 U8 usb_select_enpoint_interrupt(void) 00188 { 00189 U8 interrupt_flags; 00190 U8 ep_num; 00191 00192 ep_num = 0; 00193 interrupt_flags = Usb_interrupt_flags(); 00194 00195 while(ep_num < MAX_EP_NB) 00196 { 00197 if (interrupt_flags & 1) 00198 { 00199 return (ep_num); 00200 } 00201 else 00202 { 00203 ep_num++; 00204 interrupt_flags = interrupt_flags >> 1; 00205 } 00206 } 00207 return 0; 00208 } 00209 00210 //! usb_send_packet. 00211 //! 00212 //! This function moves the data pointed by tbuf to the selected endpoint fifo 00213 //! and sends it through the USB. 00214 //! 00215 //! 00216 //! @param ep_num number of the addressed endpoint 00217 //! @param tbuf address of the first data to send 00218 //! @param data_length number of bytes to send 00219 //! 00220 //! @return remaining_length address of the next U8 to send. 00221 //! 00222 //! Example: 00223 //! usb_send_packet(3,&first_data,0x20); // send packet on the endpoint #3 00224 //! while(!(Usb_tx_complete)); // wait packet ACK'ed by the Host 00225 //! Usb_clear_tx_complete(); // acknowledge the transmit 00226 //! 00227 //! Note: 00228 //! tbuf is incremented of 'data_length'. 00229 //! 00230 U8 usb_send_packet(U8 ep_num, U8* tbuf, U8 data_length) 00231 { 00232 U8 remaining_length; 00233 00234 remaining_length = data_length; 00235 Usb_select_endpoint(ep_num); 00236 while(Is_usb_write_enabled() && (0 != remaining_length)) 00237 { 00238 Usb_write_byte(*tbuf); 00239 remaining_length--; 00240 tbuf++; 00241 } 00242 return remaining_length; 00243 } 00244 00245 //! usb_read_packet. 00246 //! 00247 //! This function moves the data stored in the selected endpoint fifo to 00248 //! the address specified by *rbuf. 00249 //! 00250 //! 00251 //! @param ep_num number of the addressed endpoint 00252 //! @param rbuf aaddress of the first data to write with the USB data 00253 //! @param data_length number of bytes to read 00254 //! 00255 //! @return remaining_length address of the next U8 to send. 00256 //! 00257 //! Example: 00258 //! while(!(Usb_rx_complete)); // wait new packet received 00259 //! usb_read_packet(4,&first_data,usb_get_nb_byte); // read packet from ep 4 00260 //! Usb_clear_rx(); // acknowledge the transmit 00261 //! 00262 //! Note: 00263 //! rbuf is incremented of 'data_length'. 00264 //! 00265 U8 usb_read_packet(U8 ep_num, U8* rbuf, U8 data_length) 00266 { 00267 U8 remaining_length; 00268 00269 remaining_length = data_length; 00270 Usb_select_endpoint(ep_num); 00271 00272 while(Is_usb_read_enabled() && (0 != remaining_length)) 00273 { 00274 *rbuf = Usb_read_byte(); 00275 remaining_length--; 00276 rbuf++; 00277 } 00278 return remaining_length; 00279 } 00280 00281 //! usb_halt_endpoint. 00282 //! 00283 //! This function sends a STALL handshake for the next Host request. A STALL 00284 //! handshake will be send for each next request untill a SETUP or a Clear Halt 00285 //! Feature occurs for this endpoint. 00286 //! 00287 //! @param ep_num number of the addressed endpoint 00288 //! 00289 void usb_halt_endpoint (U8 ep_num) 00290 { 00291 Usb_select_endpoint(ep_num); 00292 Usb_enable_stall_handshake(); 00293 } 00294 00295 //! usb_init_device. 00296 //! 00297 //! This function initializes the USB device controller and 00298 //! configures the Default Control Endpoint. 00299 //! 00300 //! @retval FALSE if not Is_usb_id_device() returns FALSE 00301 //! @return usb_configure_endpoint() status 00302 //! 00303 U8 usb_init_device (void) 00304 { 00305 U8 rv = FALSE; 00306 00307 Usb_select_device(); 00308 if(Is_usb_id_device()) 00309 { 00310 Usb_select_endpoint(EP_CONTROL); 00311 if(!Is_usb_endpoint_enabled()) 00312 { 00313 #if (USB_LOW_SPEED_DEVICE==DISABLE) 00314 rv = usb_configure_endpoint(EP_CONTROL, \ 00315 TYPE_CONTROL, \ 00316 DIRECTION_OUT, \ 00317 SIZE_64, \ 00318 ONE_BANK, \ 00319 NYET_DISABLED); 00320 #else 00321 rv = usb_configure_endpoint(EP_CONTROL, \ 00322 TYPE_CONTROL, \ 00323 DIRECTION_OUT, \ 00324 SIZE_8, \ 00325 ONE_BANK, \ 00326 NYET_DISABLED); 00327 #endif 00328 00329 } 00330 } 00331 return rv; 00332 } 00333 00334 #endif 00335 00336 //! --------------------------------------------------------- 00337 //! ------------------ HOST --------------------------------- 00338 //! --------------------------------------------------------- 00339 00340 #if (USB_HOST_FEATURE == ENABLED) 00341 00342 //! usb_configure_pipe. 00343 //! 00344 //! This function configures a pipe with the selected type. 00345 //! 00346 //! @param config0 00347 //! @param config1 00348 //! 00349 //! @return Is_endpoint_configured(). 00350 U8 host_config_pipe(U8 config0, U8 config1) 00351 { 00352 Host_enable_pipe(); 00353 UPCFG0X = config0; 00354 UPCFG1X = config1; 00355 Host_allocate_memory(); 00356 return (Is_pipe_configured()); 00357 } 00358 00359 //! host_determine_pipe_size. 00360 //! 00361 //! This function returns the size configuration register value according 00362 //! to the endpint size detected inthe device enumeration process. 00363 //! 00364 //! @retval SIZE_8 pipe size register value. 00365 //! @retval SIZE_16 pipe size register value. 00366 //! @retval SIZE_32 pipe size register value. 00367 //! @retval SIZE_64 pipe size register value. 00368 //! @retval SIZE_128 pipe size register value. 00369 //! @retval SIZE_256 pipe size register value. 00370 //! @retval SIZE_512 pipe size register value. 00371 //! @retval SIZE_1024 pipe size register value. 00372 //! 00373 U8 host_determine_pipe_size(U16 size) 00374 { 00375 if(size <= 8 ) {return (SIZE_8 );} 00376 else if(size <= 16 ) {return (SIZE_16 );} 00377 else if(size <= 32 ) {return (SIZE_32 );} 00378 else if(size <= 64 ) {return (SIZE_64 );} 00379 else if(size <= 128) {return (SIZE_128 );} 00380 else if(size <= 256) {return (SIZE_256 );} 00381 else if(size <= 512) {return (SIZE_512 );} 00382 else {return (SIZE_1024);} 00383 00384 } 00385 00386 //! host_disable_all_pipe. 00387 //! 00388 //! This function disable all pipes for the host controller 00389 //! Usefull to execute upon device disconnection. 00390 //! 00391 void host_disable_all_pipe(void) 00392 { 00393 U8 i; 00394 for (i=0;i<7;i++) 00395 { 00396 Host_reset_pipe(i); 00397 Host_select_pipe(i); 00398 Host_unallocate_memory(); 00399 Host_disable_pipe(); 00400 } 00401 } 00402 00403 //! @brief Returns the pipe number that generates a USB communication interrupt 00404 //! 00405 //! This function sould be called only when an interrupt has been detected. Otherwize 00406 //! the return value is incorect 00407 //! 00408 //! @retval MAX_EP_NB + 1 - pipe_number 00409 //! 00410 U8 usb_get_nb_pipe_interrupt(void) 00411 { 00412 U8 interrupt_flags; 00413 U8 i; 00414 00415 interrupt_flags = Host_get_pipe_interrupt(); 00416 for(i=0;i< MAX_EP_NB;i++) 00417 { 00418 if (interrupt_flags & (1<<i)) 00419 { 00420 return (i); 00421 } 00422 } 00423 // This return should never occurs .... 00424 return MAX_EP_NB+1; 00425 } 00426 00427 00428 #endif // USB_HOST_FEATURE == ENABLED 00429 00430 /** @} */