Contiki 2.6

usb_drv.c

Go to the documentation of this file.
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 /** @} */