usb_task.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00002 /*! \file usb_task.c *********************************************************************
00003  *
00004  * \brief
00005  *      This file manages the USB task either device/host or both.
00006  *
00007  *      The USB task selects the correct USB task (usb_device task or usb_host task
00008  *      to be executed depending on the current mode available.
00009  *
00010  *      According to USB_DEVICE_FEATURE and USB_HOST_FEATURE value (located in conf_usb.h file)
00011  *      The usb_task can be configured to support USB DEVICE mode or USB Host mode or both
00012  *      for a dual role device application.
00013  *
00014  *      This module also contains the general USB interrupt subroutine. This subroutine is used
00015  *      to detect asynchronous USB events.
00016  *
00017  *      Note:
00018  *        - The usb_task belongs to the scheduler, the usb_device_task and usb_host do not, they are called
00019  *          from the general usb_task
00020  *        - See conf_usb.h file for more details about the configuration of this module
00021  *
00022  * \addtogroup usbstick
00023  *
00024  * \author
00025  *      Atmel Corporation: http://www.atmel.com \n
00026  *      Support email: avr@atmel.com
00027  ******************************************************************************/
00028 /* Copyright (c) 2008  Colin O'Flynn
00029    Copyright (c) 2008  ATMEL Corporation
00030    All rights reserved.
00031 
00032    Redistribution and use in source and binary forms, with or without
00033    modification, are permitted provided that the following conditions are met:
00034 
00035    * Redistributions of source code must retain the above copyright
00036      notice, this list of conditions and the following disclaimer.
00037    * Redistributions in binary form must reproduce the above copyright
00038      notice, this list of conditions and the following disclaimer in
00039      the documentation and/or other materials provided with the
00040      distribution.
00041    * Neither the name of the copyright holders nor the names of
00042      contributors may be used to endorse or promote products derived
00043      from this software without specific prior written permission.
00044 
00045   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00046   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00047   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00048   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00049   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00050   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00051   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00052   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00053   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00054   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00055   POSSIBILITY OF SUCH DAMAGE.
00056 */
00057 
00058 /**
00059    \ingroup usbstick
00060    \defgroup usbtask USB Contiki Task
00061    @{
00062 */
00063 
00064 //_____  I N C L U D E S ___________________________________________________
00065 
00066 #include "contiki.h"
00067 #include "config.h"
00068 #include "conf_usb.h"
00069 #include "usb_drv.h"
00070 #include "usb_descriptors.h"
00071 #include "pll_drv.h"
00072 #include "usb_task.h"
00073 #include "rndis/rndis_protocol.h"
00074 #include "rndis/rndis_task.h"
00075 
00076 PROCESS(usb_process, "USB process");
00077 
00078 #ifndef  USE_USB_PADS_REGULATOR
00079    #error "USE_USB_PADS_REGULATOR" should be defined as ENABLE or DISABLE in conf_usb.h file
00080 #endif
00081 #include <avr/sleep.h>
00082 
00083 //_____ M A C R O S ________________________________________________________
00084 
00085 #ifndef LOG_STR_CODE
00086 #define LOG_STR_CODE(str)
00087 #else
00088 U8 code log_device_disconnect[]="Device Disconnected";
00089 U8 code log_id_change[]="Pin Id Change";
00090 #endif
00091 
00092 #define USB_EVENT 0x2F /* Contiki event number - I just made this one up?*/
00093 
00094 //_____ D E F I N I T I O N S ______________________________________________
00095 
00096 //!
00097 //! Public : U16 g_usb_event
00098 //! usb_connected is used to store USB events detected upon
00099 //! USB general interrupt subroutine
00100 //! Its value is managed by the following macros (See usb_task.h file)
00101 //! Usb_send_event(x)
00102 //! Usb_ack_event(x)
00103 //! Usb_clear_all_event()
00104 //! Is_usb_event(x)
00105 //! Is_not_usb_event(x)
00106 volatile uint16_t g_usb_event=0;
00107 
00108 
00109 //!
00110 //! Public : (bit) usb_connected
00111 //! usb_connected is set to TRUE when VBUS has been detected
00112 //! usb_connected is set to FALSE otherwise
00113 //! Used with USB_DEVICE_FEATURE == ENABLED only
00114 //!/
00115 bit   usb_connected;
00116 
00117 //!
00118 //! Public : (U8) usb_configuration_nb
00119 //! Store the number of the USB configuration used by the USB device
00120 //! when its value is different from zero, it means the device mode is enumerated
00121 //! Used with USB_DEVICE_FEATURE == ENABLED only
00122 //!/
00123 extern U8    usb_configuration_nb;
00124 
00125 
00126 //_____ D E C L A R A T I O N S ____________________________________________
00127 
00128 
00129 
00130 /**
00131  *   \brief Spare function to handle sleep mode.
00132  */
00133 extern void suspend_action(void)
00134 {
00135    Enable_interrupt();
00136    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
00137    sleep_mode();
00138 }
00139 
00140 /**
00141   *    \brief This function initializes the USB device controller
00142   *
00143   * This function enables the USB controller and init the USB interrupts.
00144   * The aim is to allow the USB connection detection in order to send
00145   * the appropriate USB event to the operating mode manager.
00146   * Start device function is executed once VBUS connection has been detected
00147   * either by the VBUS change interrupt either by the VBUS high level
00148   */
00149 void usb_start_device (void)
00150 {
00151    Pll_start_auto();
00152    Wait_pll_ready();
00153    Usb_unfreeze_clock();
00154    Usb_enable_vbus_interrupt();
00155    Usb_enable_reset_interrupt();
00156    usb_init_device();         // configure the USB controller EP0
00157    Usb_attach();
00158 }
00159 
00160 
00161 /**
00162   *  \brief USB Poll Handler
00163   *
00164   * This routine is repetively called, and deals with things such as new SETUP transfers
00165   * on the control endpoint
00166   */
00167 static void pollhandler(void) 
00168 {
00169         /* Check for setup packets */   
00170         Usb_select_endpoint(EP_CONTROL);
00171         if (Is_usb_receive_setup()) {
00172           usb_process_request();
00173         }
00174 
00175         /* The previous call might have requested we send
00176                 out something to the RNDIS interrupt endpoint */
00177         if (schedule_interrupt) {
00178                 Usb_select_endpoint(INT_EP);
00179 
00180                 //Linux is a bunch of lies, and won't read
00181                 //the interrupt endpoint. Hence if this isn't ready just exit
00182                 //while(!Is_usb_write_enabled());
00183 
00184                  if (Is_usb_write_enabled()) {
00185 
00186                         // Only valid interrupt is:
00187                         //   0x00000001 0x00000000
00188                         //
00189                         Usb_write_byte(0x01);
00190                         Usb_write_byte(0x00);
00191                         Usb_write_byte(0x00);
00192                         Usb_write_byte(0x00);
00193                         Usb_write_byte(0x00);
00194                         Usb_write_byte(0x00);
00195                         Usb_write_byte(0x00);
00196                         Usb_write_byte(0x00);
00197 
00198                         //Send back
00199                         Usb_send_in();
00200                         
00201                         schedule_interrupt = 0;
00202                 }
00203         }        
00204 
00205         /* Continue polling */
00206         process_poll(&usb_process);
00207 
00208 }
00209 /**
00210   *  \brief USB Process
00211   *
00212   * The actual USB process, deals with USB events such as resets, and being plugged in
00213   * or unplugged. A seperate polling routine is setup, which continously checks for 
00214   * things such as SETUP packets on the control interface. They must be responded to
00215   * very quickly, hence the need for a polling process.
00216   */
00217 PROCESS_THREAD(usb_process, ev, data_proc)
00218 {
00219 
00220 PROCESS_POLLHANDLER(pollhandler());
00221 
00222 PROCESS_BEGIN();
00223 
00224    
00225    /*** USB initilization ***/
00226 
00227    #if (USE_USB_PADS_REGULATOR==ENABLE)  // Otherwise assume USB PADs regulator is not used
00228    Usb_enable_regulator();
00229    #endif
00230 
00231    Usb_force_device_mode();
00232 
00233         /* Init USB controller */
00234    Enable_interrupt();
00235    Usb_disable();
00236    Usb_enable();
00237    Usb_select_device();
00238 #if (USB_LOW_SPEED_DEVICE==ENABLE)
00239    Usb_low_speed_mode();
00240 #endif
00241    Usb_enable_vbus_interrupt();
00242    Enable_interrupt();
00243 
00244    
00245    /* Ensure pollhandler is called to start it off */
00246    process_poll(&usb_process);
00247 
00248 
00249    /*** Begin actual USB process ***/
00250    while(1)
00251         {
00252 
00253   if (Is_usb_vbus_high()&& usb_connected==FALSE)
00254    {
00255       usb_connected = TRUE;
00256       usb_start_device();
00257       Usb_vbus_on_action();
00258    }
00259 
00260    if(Is_usb_event(EVT_USB_RESET))
00261    {
00262       Usb_ack_event(EVT_USB_RESET);
00263       Usb_reset_endpoint(0);
00264       usb_configuration_nb=0;
00265    }
00266 
00267 
00268         PROCESS_WAIT_EVENT_UNTIL(ev == USB_EVENT);
00269         }//while(1)
00270 
00271 PROCESS_END();
00272 
00273 }
00274 
00275 
00276 //! @brief USB general interrupt subroutine
00277 //!
00278 //! This function is called each time a USB interrupt occurs.
00279 //! The following USB DEVICE events are taken in charge:
00280 //! - VBus On / Off
00281 //! - Start Of Frame
00282 //! - Suspend
00283 //! - Wake-Up
00284 //! - Resume
00285 //! - Reset
00286 //! - Start of frame
00287 //!
00288 //! For each event, the user can launch an action by completing
00289 //! the associate define (See conf_usb.h file to add action upon events)
00290 //!
00291 //! Note: Only interrupts events that are enabled are processed
00292 //!
00293 
00294 ISR(USB_GEN_vect)
00295 { 
00296 
00297         process_post(&usb_process, USB_EVENT, NULL);
00298 
00299   //- VBUS state detection
00300    if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled())
00301    {
00302       Usb_ack_vbus_transition();
00303       if (Is_usb_vbus_high())
00304       {
00305          usb_connected = TRUE;
00306          Usb_vbus_on_action();
00307          Usb_send_event(EVT_USB_POWERED);
00308                         Usb_enable_reset_interrupt();
00309          usb_start_device();
00310                         Usb_attach();
00311       }
00312       else
00313       {
00314          Usb_vbus_off_action();
00315          usb_connected = FALSE;
00316          usb_configuration_nb = 0;
00317          Usb_send_event(EVT_USB_UNPOWERED);
00318       }
00319    }
00320   // - Device start of frame received
00321    if (Is_usb_sof() && Is_sof_interrupt_enabled())
00322    {
00323       Usb_ack_sof();
00324       Usb_sof_action();
00325    }
00326   // - Device Suspend event (no more USB activity detected)
00327    if (Is_usb_suspend() && Is_suspend_interrupt_enabled())
00328    {
00329       Usb_ack_suspend();
00330       Usb_enable_wake_up_interrupt();
00331       Usb_ack_wake_up();                 // clear wake up to detect next event
00332       Usb_freeze_clock();
00333       Usb_send_event(EVT_USB_SUSPEND);
00334       Usb_suspend_action();
00335    }
00336   // - Wake up event (USB activity detected): Used to resume
00337    if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled())
00338    {
00339       Usb_unfreeze_clock();
00340       Usb_ack_wake_up();
00341       Usb_disable_wake_up_interrupt();
00342       Usb_wake_up_action();
00343       Usb_send_event(EVT_USB_WAKE_UP);
00344    }
00345   // - Resume state bus detection
00346    if (Is_usb_resume() && Is_resume_interrupt_enabled())
00347    {
00348       Usb_disable_wake_up_interrupt();
00349       Usb_ack_resume();
00350       Usb_disable_resume_interrupt();
00351       Usb_resume_action();
00352       Usb_send_event(EVT_USB_RESUME);
00353    }
00354   // - USB bus reset detection
00355    if (Is_usb_reset()&& Is_reset_interrupt_enabled())
00356    {
00357       Usb_ack_reset();
00358       usb_init_device();
00359       Usb_reset_action();
00360       Usb_send_event(EVT_USB_RESET);
00361    }
00362 
00363 }
00364 
00365 /** @} */
00366 

Generated on Mon Apr 11 14:23:36 2011 for Contiki 2.5 by  doxygen 1.6.1