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