Contiki 2.6

storage_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 storage.
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) 2004  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 usbstorage
00045  @{
00046 */
00047 
00048 //_____  I N C L U D E S ___________________________________________________
00049 
00050 
00051 
00052 #include "contiki.h"
00053 #include "usb_drv.h"
00054 #include "storage/storage_task.h"
00055 #include "usb_descriptors.h"
00056 #include "usb_standard_request.h"
00057 #include "usb_specific_request.h"
00058 #include "storage/scsi_decoder.h"
00059 #include "storage/ctrl_access.h"
00060 
00061 
00062 //_____ M A C R O S ________________________________________________________
00063 
00064 
00065 
00066 
00067 
00068 //_____ D E F I N I T I O N S ______________________________________________
00069 
00070 
00071 
00072 //_____ D E C L A R A T I O N S ____________________________________________
00073 
00074 
00075 
00076 extern  U8   usb_configuration_nb;
00077 
00078 
00079 static bit ms_data_direction;
00080 static  U8  dCBWTag[4];
00081 
00082 extern  U8  g_scsi_status;
00083 extern  U32 g_scsi_data_remaining;
00084 extern bit ms_multiple_drive;
00085 extern  U8  g_scsi_command[16];
00086 
00087 
00088 U8 usb_LUN;
00089 
00090 
00091 void usb_mass_storage_cbw (void);
00092 void usb_mass_storage_csw (void);
00093 
00094 #define Usb_set_ms_data_direction_in()  (ms_data_direction = 1)
00095 #define Usb_set_ms_data_direction_out() (ms_data_direction = 0)
00096 #define Is_usb_ms_data_direction_in()   (ms_data_direction == 1)
00097 
00098 static struct etimer et;
00099 
00100 PROCESS(storage_process, "Storage process");
00101 
00102 /**
00103  * \brief USB Mass Storage Class Process
00104  *
00105  *   This is the link between USB and the "good stuff". In this routine data
00106  *   is received and processed by USB Storage Class
00107  */
00108 PROCESS_THREAD(storage_process, ev, data_proc)
00109 {
00110    PROCESS_BEGIN();
00111 
00112    while(1) {
00113 
00114     
00115          if (usb_mode == mass_storage) {
00116 
00117                  if (Is_device_enumerated()) {
00118                  Usb_select_endpoint(MS_OUT_EP);
00119                  
00120                          if (Is_usb_receive_out()) {
00121                    usb_mass_storage_cbw();
00122                    usb_mass_storage_csw();
00123                  }
00124              }
00125 
00126         }
00127 
00128         if (usb_mode == mass_storage) {
00129                 etimer_set(&et, CLOCK_SECOND/250 + 1);
00130         } else {
00131                 etimer_set(&et, CLOCK_SECOND);
00132         }
00133 
00134         PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
00135 
00136   } //while(1)
00137 
00138   PROCESS_END();
00139 }
00140 
00141 
00142 
00143 
00144 //! @brief USB Command Block Wrapper (CBW) management
00145 //!
00146 //! This function decodes the CBW command and stores the SCSI command
00147 //!
00148 //! @warning Code:?? bytes (function code length)
00149 //!
00150 void usb_mass_storage_cbw (void)
00151 {
00152    bit cbw_error;
00153    uint8_t  c;
00154    uint8_t dummy;
00155 
00156    cbw_error = FALSE;
00157    Usb_select_endpoint(MS_OUT_EP);           //! check if dCBWSignature is correct
00158    if (0x55 != Usb_read_byte())
00159       { cbw_error = TRUE; } //! 'U'
00160    if (0x53 != Usb_read_byte())
00161       { cbw_error = TRUE; } //! 'S'
00162    if (0x42 != Usb_read_byte())
00163       { cbw_error = TRUE; } //! 'B'
00164    if (0x43 != Usb_read_byte())
00165       { cbw_error = TRUE; } //! 'C'
00166 
00167    dCBWTag[0] = Usb_read_byte();             //! Store CBW Tag to be repeated in CSW
00168    dCBWTag[1] = Usb_read_byte();
00169    dCBWTag[2] = Usb_read_byte();
00170    dCBWTag[3] = Usb_read_byte();
00171         
00172    LSB0(g_scsi_data_remaining) = Usb_read_byte();
00173    LSB1(g_scsi_data_remaining) = Usb_read_byte();
00174    LSB2(g_scsi_data_remaining) = Usb_read_byte();
00175    LSB3(g_scsi_data_remaining) = Usb_read_byte();
00176 
00177 
00178    if (Usb_read_byte() != 0x00)              //! if (bmCBWFlags.bit7 == 1) {direction = IN}
00179    {
00180       Usb_set_ms_data_direction_in();
00181       if (cbw_error)
00182       {
00183          Usb_ack_receive_out();
00184          Usb_select_endpoint(MS_IN_EP);
00185          Usb_enable_stall_handshake();
00186          return;
00187       }
00188    }
00189    else
00190    {
00191       Usb_set_ms_data_direction_out();
00192       if (cbw_error)
00193       {
00194          Usb_enable_stall_handshake();
00195          Usb_ack_receive_out();
00196          return;
00197       }
00198    }
00199 
00200    usb_LUN = Usb_read_byte();
00201 
00202    if (!ms_multiple_drive)
00203    {
00204       usb_LUN = get_cur_lun();
00205    }
00206 
00207    dummy      = Usb_read_byte();                //! dummy CBWCBLength read
00208 
00209 
00210    for (c=0; c<16; c++)                         // store scsi_command
00211    {
00212       g_scsi_command[c] = Usb_read_byte();
00213    }
00214 
00215    Usb_ack_receive_out();
00216 
00217    if (Is_usb_ms_data_direction_in())
00218    {
00219       Usb_select_endpoint(MS_IN_EP);
00220    }
00221 
00222    if (TRUE != scsi_decode_command())
00223    {
00224       if (g_scsi_data_remaining != 0)
00225       {
00226          Usb_enable_stall_handshake();
00227       }
00228    }
00229 }
00230 
00231 //! @brief USB Command Status Wrapper (CSW) management
00232 //!
00233 //! This function sends the status in relation with the last CBW
00234 //!
00235 void usb_mass_storage_csw (void)
00236 {
00237    Usb_select_endpoint(MS_IN_EP);
00238    while (Is_usb_endpoint_stall_requested())
00239    {
00240       Usb_select_endpoint(EP_CONTROL);
00241       if (Is_usb_receive_setup())       { usb_process_request(); }
00242       Usb_select_endpoint(MS_IN_EP);
00243    }
00244 
00245    Usb_select_endpoint(MS_OUT_EP);
00246    while (Is_usb_endpoint_stall_requested())
00247    {
00248       Usb_select_endpoint(EP_CONTROL);
00249       if (Is_usb_receive_setup())       { usb_process_request(); }
00250       Usb_select_endpoint(MS_OUT_EP);
00251    }
00252 
00253    Usb_select_endpoint(MS_IN_EP);
00254    while(!Is_usb_write_enabled());
00255                                                          //! write CSW Signature
00256    Usb_write_byte(0x55);                                 //! 'U'
00257    Usb_write_byte(0x53);                                 //! 'S'
00258    Usb_write_byte(0x42);                                 //! 'B'
00259    Usb_write_byte(0x53);                                 //! 'S'
00260                                                          //! write stored CBW Tag
00261    Usb_write_byte(dCBWTag[0]);
00262    Usb_write_byte(dCBWTag[1]);
00263    Usb_write_byte(dCBWTag[2]);
00264    Usb_write_byte(dCBWTag[3]);
00265                                                          //! write data residue value
00266    Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[3] );
00267    Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[2] );
00268    Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[1] );
00269    Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[0] );
00270 
00271    //! write command status
00272     Usb_write_byte(g_scsi_status);                        //! 0 -> PASS, 1 -> FAIL
00273     Usb_send_in();
00274 }
00275 
00276 /** @} */