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 /** @} */