Contiki 2.5
storage_task.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /*! \file usb_task.c *********************************************************************
3  *
4  * \brief
5  * This file manages the USB storage.
6  *
7  * \addtogroup usbstick
8  *
9  * \author
10  * Atmel Corporation: http://www.atmel.com \n
11  * Support email: avr@atmel.com
12  ******************************************************************************/
13 /*
14  Copyright (c) 2004 ATMEL Corporation
15  All rights reserved.
16 
17  Redistribution and use in source and binary forms, with or without
18  modification, are permitted provided that the following conditions are met:
19 
20  * Redistributions of source code must retain the above copyright
21  notice, this list of conditions and the following disclaimer.
22  * Redistributions in binary form must reproduce the above copyright
23  notice, this list of conditions and the following disclaimer in
24  the documentation and/or other materials provided with the
25  distribution.
26  * Neither the name of the copyright holders nor the names of
27  contributors may be used to endorse or promote products derived
28  from this software without specific prior written permission.
29 
30  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  POSSIBILITY OF SUCH DAMAGE.
41 */
42 
43 /**
44  \addtogroup usbstorage
45  @{
46 */
47 
48 //_____ I N C L U D E S ___________________________________________________
49 
50 
51 
52 #include "contiki.h"
53 #include "usb_drv.h"
54 #include "storage/storage_task.h"
55 #include "usb_descriptors.h"
56 #include "usb_standard_request.h"
57 #include "usb_specific_request.h"
58 #include "storage/scsi_decoder.h"
59 #include "storage/ctrl_access.h"
60 
61 
62 //_____ M A C R O S ________________________________________________________
63 
64 
65 
66 
67 
68 //_____ D E F I N I T I O N S ______________________________________________
69 
70 
71 
72 //_____ D E C L A R A T I O N S ____________________________________________
73 
74 
75 
76 extern U8 usb_configuration_nb;
77 
78 
79 static bit ms_data_direction;
80 static U8 dCBWTag[4];
81 
82 extern U8 g_scsi_status;
83 extern U32 g_scsi_data_remaining;
84 extern bit ms_multiple_drive;
85 extern U8 g_scsi_command[16];
86 
87 
88 U8 usb_LUN;
89 
90 
91 void usb_mass_storage_cbw (void);
92 void usb_mass_storage_csw (void);
93 
94 #define Usb_set_ms_data_direction_in() (ms_data_direction = 1)
95 #define Usb_set_ms_data_direction_out() (ms_data_direction = 0)
96 #define Is_usb_ms_data_direction_in() (ms_data_direction == 1)
97 
98 static struct etimer et;
99 
100 PROCESS(storage_process, "Storage process");
101 
102 /**
103  * \brief USB Mass Storage Class Process
104  *
105  * This is the link between USB and the "good stuff". In this routine data
106  * is received and processed by USB Storage Class
107  */
108 PROCESS_THREAD(storage_process, ev, data_proc)
109 {
110  PROCESS_BEGIN();
111 
112  while(1) {
113 
114 
115  if (usb_mode == mass_storage) {
116 
117  if (Is_device_enumerated()) {
118  Usb_select_endpoint(MS_OUT_EP);
119 
120  if (Is_usb_receive_out()) {
123  }
124  }
125 
126  }
127 
128  if (usb_mode == mass_storage) {
129  etimer_set(&et, CLOCK_SECOND/250 + 1);
130  } else {
131  etimer_set(&et, CLOCK_SECOND);
132  }
133 
135 
136  } //while(1)
137 
138  PROCESS_END();
139 }
140 
141 
142 
143 
144 //! @brief USB Command Block Wrapper (CBW) management
145 //!
146 //! This function decodes the CBW command and stores the SCSI command
147 //!
148 //! @warning Code:?? bytes (function code length)
149 //!
151 {
152  bit cbw_error;
153  uint8_t c;
154  uint8_t dummy;
155 
156  cbw_error = FALSE;
157  Usb_select_endpoint(MS_OUT_EP); //! check if dCBWSignature is correct
158  if (0x55 != Usb_read_byte())
159  { cbw_error = TRUE; } //! 'U'
160  if (0x53 != Usb_read_byte())
161  { cbw_error = TRUE; } //! 'S'
162  if (0x42 != Usb_read_byte())
163  { cbw_error = TRUE; } //! 'B'
164  if (0x43 != Usb_read_byte())
165  { cbw_error = TRUE; } //! 'C'
166 
167  dCBWTag[0] = Usb_read_byte(); //! Store CBW Tag to be repeated in CSW
168  dCBWTag[1] = Usb_read_byte();
169  dCBWTag[2] = Usb_read_byte();
170  dCBWTag[3] = Usb_read_byte();
171 
172  LSB0(g_scsi_data_remaining) = Usb_read_byte();
173  LSB1(g_scsi_data_remaining) = Usb_read_byte();
174  LSB2(g_scsi_data_remaining) = Usb_read_byte();
175  LSB3(g_scsi_data_remaining) = Usb_read_byte();
176 
177 
178  if (Usb_read_byte() != 0x00) //! if (bmCBWFlags.bit7 == 1) {direction = IN}
179  {
180  Usb_set_ms_data_direction_in();
181  if (cbw_error)
182  {
184  Usb_select_endpoint(MS_IN_EP);
186  return;
187  }
188  }
189  else
190  {
191  Usb_set_ms_data_direction_out();
192  if (cbw_error)
193  {
196  return;
197  }
198  }
199 
200  usb_LUN = Usb_read_byte();
201 
202  if (!ms_multiple_drive)
203  {
204  usb_LUN = get_cur_lun();
205  }
206 
207  dummy = Usb_read_byte(); //! dummy CBWCBLength read
208 
209 
210  for (c=0; c<16; c++) // store scsi_command
211  {
212  g_scsi_command[c] = Usb_read_byte();
213  }
214 
216 
217  if (Is_usb_ms_data_direction_in())
218  {
219  Usb_select_endpoint(MS_IN_EP);
220  }
221 
222  if (TRUE != scsi_decode_command())
223  {
224  if (g_scsi_data_remaining != 0)
225  {
227  }
228  }
229 }
230 
231 //! @brief USB Command Status Wrapper (CSW) management
232 //!
233 //! This function sends the status in relation with the last CBW
234 //!
236 {
237  Usb_select_endpoint(MS_IN_EP);
239  {
240  Usb_select_endpoint(EP_CONTROL);
242  Usb_select_endpoint(MS_IN_EP);
243  }
244 
245  Usb_select_endpoint(MS_OUT_EP);
247  {
248  Usb_select_endpoint(EP_CONTROL);
250  Usb_select_endpoint(MS_OUT_EP);
251  }
252 
253  Usb_select_endpoint(MS_IN_EP);
254  while(!Is_usb_write_enabled());
255  //! write CSW Signature
256  Usb_write_byte(0x55); //! 'U'
257  Usb_write_byte(0x53); //! 'S'
258  Usb_write_byte(0x42); //! 'B'
259  Usb_write_byte(0x53); //! 'S'
260  //! write stored CBW Tag
261  Usb_write_byte(dCBWTag[0]);
262  Usb_write_byte(dCBWTag[1]);
263  Usb_write_byte(dCBWTag[2]);
264  Usb_write_byte(dCBWTag[3]);
265  //! write data residue value
266  Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[3] );
267  Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[2] );
268  Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[1] );
269  Usb_write_byte( ((Byte*)&g_scsi_data_remaining)[0] );
270 
271  //! write command status
272  Usb_write_byte(g_scsi_status); //! 0 -> PASS, 1 -> FAIL
273  Usb_send_in();
274 }
275 
276 /** @} */