1 /******************************************************************************************************************************************
2 * 文件名称: usbh_msc_scsi.c
3 * 功能说明:
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0 2020年11月3日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include "SWM341.h"
22 #include "usbh_core.h"
23 #include "usbh_msc_bot.h"
24 #include "usbh_msc_core.h"
25 #include "usbh_msc_scsi.h"
26
27
28 #define OPCODE_TEST_UNIT_READY 0X00
29 #define OPCODE_READ_CAPACITY10 0x25
30 #define OPCODE_MODE_SENSE6 0x1A
31 #define OPCODE_READ10 0x28
32 #define OPCODE_WRITE10 0x2A
33 #define OPCODE_REQUEST_SENSE 0x03
34
35 #define DATLEN_READ_CAPACITY10 8 // Data Stage Length
36 #define DATLEN_MODE_SENSE6 63
37 #define DATLEN_REQUEST_SENSE 18
38
39
40 static uint8_t SCSI_Busy = 0;
41
42 static uint8_t DataInBuffer[64];
43
44
45 /******************************************************************************************************************************************
46 * 函数名称: USBH_MSC_TestUnitReady()
47 * 功能说明: Issues 'Test unit ready' command to the device.
48 * 输 入: 无
49 * 输 出: 无
50 * 注意事项: 无
51 ******************************************************************************************************************************************/
USBH_MSC_TestUnitReady(void)52 USBH_MSC_Status USBH_MSC_TestUnitReady(void)
53 {
54 USBH_MSC_Status status = USBH_MSC_BUSY;
55
56 if(!SCSI_Busy)
57 {
58 USBH_CBWData.CBWTransferLength = 0; // No Data Stage
59 USBH_CBWData.CBWCBLength = 6;
60 USBH_CBWData.CBWCB[0] = OPCODE_TEST_UNIT_READY;
61 for(uint8_t i = 1; i < 16; i++) USBH_CBWData.CBWCB[i] = 0;
62
63 USBH_BOTXfer.bCSWStatus = USBH_MSC_BUSY;
64 USBH_BOTXfer.BOTState = USBH_MSC_BOT_CBW;
65
66 USBH_BOTXfer.MSCStateBkp = USBH_BOTXfer.MSCState;
67 USBH_BOTXfer.MSCState = USBH_MSC_BOT_TRANSFER;
68
69 SCSI_Busy = 1;
70 }
71 else
72 {
73 if(USBH_BOTXfer.bCSWStatus != USBH_MSC_BUSY)
74 {
75 status = USBH_BOTXfer.bCSWStatus;
76
77 SCSI_Busy = 0;
78 }
79 }
80
81 return status;
82 }
83
84
85 /******************************************************************************************************************************************
86 * 函数名称: USBH_MSC_ReadCapacity10()
87 * 功能说明: Issue the read capacity command to the device.
88 * 输 入: 无
89 * 输 出: 无
90 * 注意事项: 无
91 ******************************************************************************************************************************************/
USBH_MSC_ReadCapacity10(void)92 USBH_MSC_Status USBH_MSC_ReadCapacity10(void)
93 {
94 USBH_MSC_Status status = USBH_MSC_BUSY;
95
96 if(!SCSI_Busy)
97 {
98 USBH_CBWData.CBWTransferLength = DATLEN_READ_CAPACITY10;
99 USBH_CBWData.CBWFlags = USB_REQ_D2H;
100 USBH_CBWData.CBWCBLength = 10;
101 USBH_CBWData.CBWCB[0] = OPCODE_READ_CAPACITY10;
102 for(uint8_t i = 1; i < 16; i++) USBH_CBWData.CBWCB[i] = 0;
103
104 USBH_BOTXfer.pDataBuffer = DataInBuffer;
105
106 USBH_BOTXfer.bCSWStatus = USBH_MSC_BUSY;
107 USBH_BOTXfer.BOTState = USBH_MSC_BOT_CBW;
108
109 USBH_BOTXfer.MSCStateBkp = USBH_BOTXfer.MSCState;
110 USBH_BOTXfer.MSCState = USBH_MSC_BOT_TRANSFER;
111
112 SCSI_Busy = 1;
113 }
114 else
115 {
116 if(USBH_BOTXfer.bCSWStatus != USBH_MSC_BUSY)
117 {
118 if(USBH_BOTXfer.bCSWStatus == USBH_MSC_OK)
119 {
120 /* assign the capacity */
121 ((uint8_t *)&USBH_MSC_Info.Capacity)[3] = DataInBuffer[0];
122 ((uint8_t *)&USBH_MSC_Info.Capacity)[2] = DataInBuffer[1];
123 ((uint8_t *)&USBH_MSC_Info.Capacity)[1] = DataInBuffer[2];
124 ((uint8_t *)&USBH_MSC_Info.Capacity)[0] = DataInBuffer[3];
125
126 /* assign the page length */
127 ((uint8_t *)&USBH_MSC_Info.PageSize)[1] = DataInBuffer[6];
128 ((uint8_t *)&USBH_MSC_Info.PageSize)[0] = DataInBuffer[7];
129 }
130
131 status = USBH_BOTXfer.bCSWStatus;
132
133 SCSI_Busy = 0;
134 }
135 }
136
137 return status;
138 }
139
140
141 /******************************************************************************************************************************************
142 * 函数名称: USBH_MSC_ModeSense6()
143 * 功能说明: Issue the Mode Sense6 Command to the device.
144 * Used for reading the WriteProtect Status of the Mass-Storage device.
145 * 输 入: 无
146 * 输 出: 无
147 * 注意事项: 无
148 ******************************************************************************************************************************************/
USBH_MSC_ModeSense6(void)149 USBH_MSC_Status USBH_MSC_ModeSense6(void)
150 {
151 USBH_MSC_Status status = USBH_MSC_BUSY;
152
153 if(!SCSI_Busy)
154 {
155 USBH_CBWData.CBWTransferLength = DATLEN_MODE_SENSE6;
156 USBH_CBWData.CBWFlags = USB_REQ_D2H;
157 USBH_CBWData.CBWCBLength = 10;
158 USBH_CBWData.CBWCB[0] = OPCODE_MODE_SENSE6;
159 USBH_CBWData.CBWCB[1] = 0x00;
160 USBH_CBWData.CBWCB[2] = 0x3F;
161 USBH_CBWData.CBWCB[3] = 0x00;
162 USBH_CBWData.CBWCB[4] = DATLEN_MODE_SENSE6;
163 for(uint8_t i = 5; i < 16; i++) USBH_CBWData.CBWCB[i] = 0;
164
165 USBH_BOTXfer.pDataBuffer = DataInBuffer;
166
167 USBH_BOTXfer.bCSWStatus = USBH_MSC_BUSY;
168 USBH_BOTXfer.BOTState = USBH_MSC_BOT_CBW;
169
170 USBH_BOTXfer.MSCStateBkp = USBH_BOTXfer.MSCState;
171 USBH_BOTXfer.MSCState = USBH_MSC_BOT_TRANSFER;
172
173 SCSI_Busy = 1;
174 }
175 else
176 {
177 if(USBH_BOTXfer.bCSWStatus != USBH_MSC_BUSY)
178 {
179 if(USBH_BOTXfer.bCSWStatus == USBH_MSC_OK)
180 {
181 /* Assign the Write Protect status */
182 if(DataInBuffer[2] & 0x80)
183 {
184 USBH_MSC_Info.WProtect = 1;
185 }
186 else
187 {
188 USBH_MSC_Info.WProtect = 0;
189 }
190 }
191
192 status = USBH_BOTXfer.bCSWStatus;
193
194 SCSI_Busy = 0;
195 }
196 }
197
198 return status;
199 }
200
201
202 /******************************************************************************************************************************************
203 * 函数名称: USBH_MSC_Read10()
204 * 功能说明: Issue the read command to the device.
205 * 输 入: 无
206 * 输 出: 无
207 * 注意事项: 无
208 ******************************************************************************************************************************************/
USBH_MSC_Read10(uint8_t * buffer,uint32_t address,uint32_t nbOfbytes)209 USBH_MSC_Status USBH_MSC_Read10(uint8_t *buffer, uint32_t address, uint32_t nbOfbytes)
210 {
211 USBH_MSC_Status status = USBH_MSC_BUSY;
212 uint16_t nbOfPages;
213
214 if(!SCSI_Busy)
215 {
216 USBH_CBWData.CBWTransferLength = nbOfbytes;
217 USBH_CBWData.CBWFlags = USB_REQ_D2H;
218 USBH_CBWData.CBWCBLength = 10;
219 USBH_CBWData.CBWCB[0] = OPCODE_READ10;
220 USBH_CBWData.CBWCB[1] = 0x00;
221 /*logical block address*/
222 USBH_CBWData.CBWCB[2] = ((uint8_t *)&address)[3];
223 USBH_CBWData.CBWCB[3] = ((uint8_t *)&address)[2];
224 USBH_CBWData.CBWCB[4] = ((uint8_t *)&address)[1];
225 USBH_CBWData.CBWCB[5] = ((uint8_t *)&address)[0];
226 USBH_CBWData.CBWCB[6] = 0x00;
227 /*Transfer length */
228 nbOfPages = nbOfbytes / USBH_MSC_Info.PageSize;
229 USBH_CBWData.CBWCB[7] = ((uint8_t *)&nbOfPages)[1];
230 USBH_CBWData.CBWCB[8] = ((uint8_t *)&nbOfPages)[0];
231 for(uint8_t i = 9; i < 16; i++) USBH_CBWData.CBWCB[i] = 0;
232
233 USBH_BOTXfer.pDataBuffer = buffer;
234
235 USBH_BOTXfer.bCSWStatus = USBH_MSC_BUSY;
236 USBH_BOTXfer.BOTState = USBH_MSC_BOT_CBW;
237
238 USBH_BOTXfer.MSCStateBkp = USBH_BOTXfer.MSCState;
239 USBH_BOTXfer.MSCState = USBH_MSC_BOT_TRANSFER;
240
241 SCSI_Busy = 1;
242 }
243 else
244 {
245 if(USBH_BOTXfer.bCSWStatus != USBH_MSC_BUSY)
246 {
247 status = USBH_BOTXfer.bCSWStatus;
248
249 SCSI_Busy = 0;
250 }
251 }
252
253 return status;
254 }
255
256
257 /******************************************************************************************************************************************
258 * 函数名称: USBH_MSC_Write10()
259 * 功能说明: Issue the write command to the device.
260 * 输 入: 无
261 * 输 出: 无
262 * 注意事项: 无
263 ******************************************************************************************************************************************/
USBH_MSC_Write10(uint8_t * buffer,uint32_t address,uint32_t nbOfbytes)264 USBH_MSC_Status USBH_MSC_Write10(uint8_t *buffer, uint32_t address, uint32_t nbOfbytes)
265 {
266 USBH_MSC_Status status = USBH_MSC_BUSY;
267 uint16_t nbOfPages;
268
269 if(!SCSI_Busy)
270 {
271 USBH_CBWData.CBWTransferLength = nbOfbytes;
272 USBH_CBWData.CBWFlags = USB_REQ_H2D;
273 USBH_CBWData.CBWCBLength = 10;
274 USBH_CBWData.CBWCB[0] = OPCODE_WRITE10;
275 USBH_CBWData.CBWCB[1] = 0x00;
276 /*logical block address*/
277 USBH_CBWData.CBWCB[2] = ((uint8_t *)&address)[3];
278 USBH_CBWData.CBWCB[3] = ((uint8_t *)&address)[2];
279 USBH_CBWData.CBWCB[4] = ((uint8_t *)&address)[1];
280 USBH_CBWData.CBWCB[5] = ((uint8_t *)&address)[0];
281 USBH_CBWData.CBWCB[6] = 0x00;
282 /*Transfer length */
283 nbOfPages = nbOfbytes / USBH_MSC_Info.PageSize;
284 USBH_CBWData.CBWCB[7] = ((uint8_t *)&nbOfPages)[1];
285 USBH_CBWData.CBWCB[8] = ((uint8_t *)&nbOfPages)[0];
286 for(uint8_t i = 9; i < 16; i++) USBH_CBWData.CBWCB[i] = 0;
287
288 USBH_BOTXfer.pDataBuffer = buffer;
289
290 USBH_BOTXfer.bCSWStatus = USBH_MSC_BUSY;
291 USBH_BOTXfer.BOTState = USBH_MSC_BOT_CBW;
292
293 USBH_BOTXfer.MSCStateBkp = USBH_BOTXfer.MSCState;
294 USBH_BOTXfer.MSCState = USBH_MSC_BOT_TRANSFER;
295
296 SCSI_Busy = 1;
297 }
298 else
299 {
300 if(USBH_BOTXfer.bCSWStatus != USBH_MSC_BUSY)
301 {
302 status = USBH_BOTXfer.bCSWStatus;
303
304 SCSI_Busy = 0;
305 }
306 }
307
308 return status;
309 }
310
311
312 /******************************************************************************************************************************************
313 * 函数名称: USBH_MSC_RequestSense()
314 * 功能说明: Issues the Request Sense command to the device.
315 * 输 入: 无
316 * 输 出: 无
317 * 注意事项: 无
318 ******************************************************************************************************************************************/
USBH_MSC_RequestSense(void)319 USBH_MSC_Status USBH_MSC_RequestSense(void)
320 {
321 USBH_MSC_Status status = USBH_MSC_BUSY;
322
323 if(!SCSI_Busy)
324 {
325 USBH_CBWData.CBWTransferLength = DATLEN_REQUEST_SENSE;
326 USBH_CBWData.CBWFlags = USB_REQ_D2H;
327 USBH_CBWData.CBWCBLength = 6;
328 USBH_CBWData.CBWCB[0] = OPCODE_REQUEST_SENSE;
329 USBH_CBWData.CBWCB[1] = 0x00;
330 USBH_CBWData.CBWCB[2] = 0x00;
331 USBH_CBWData.CBWCB[3] = 0x00;
332 USBH_CBWData.CBWCB[4] = DATLEN_REQUEST_SENSE;
333 for(uint8_t i = 5; i < 16; i++) USBH_CBWData.CBWCB[i] = 0;
334
335 USBH_BOTXfer.pDataBuffer = DataInBuffer;
336
337 USBH_BOTXfer.bCSWStatus = USBH_MSC_BUSY;
338 USBH_BOTXfer.BOTState = USBH_MSC_BOT_CBW;
339
340 USBH_BOTXfer.MSCState = USBH_MSC_BOT_TRANSFER;
341
342 SCSI_Busy = 1;
343 }
344 else
345 {
346 if(USBH_BOTXfer.bCSWStatus != USBH_MSC_BUSY)
347 {
348 if(USBH_BOTXfer.bCSWStatus == USBH_MSC_OK)
349 {
350 /* Assign Sense data*/
351 ((uint8_t *)&USBH_MSC_Info.SenseKey)[3] = DataInBuffer[0];
352 ((uint8_t *)&USBH_MSC_Info.SenseKey)[2] = DataInBuffer[1];
353 ((uint8_t *)&USBH_MSC_Info.SenseKey)[1] = DataInBuffer[2];
354 ((uint8_t *)&USBH_MSC_Info.SenseKey)[0] = DataInBuffer[3];
355
356 status = USBH_MSC_OK;
357 }
358
359 status = USBH_BOTXfer.bCSWStatus;
360
361 SCSI_Busy = 0;
362 }
363 }
364
365 return status;
366 }
367