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