1 /******************************************************************************************************************************************
2 * 文件名称: usbh_msc_core.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_stdreq.h"
24 #include "usbh_msc_bot.h"
25 #include "usbh_msc_core.h"
26 #include "usbh_msc_scsi.h"
27 
28 
29 USBH_Class_cb_t USBH_MSC_cb =
30 {
31     USBH_MSC_Init,
32     USBH_MSC_DeInit,
33     USBH_MSC_Request,
34     USBH_MSC_Process,
35 };
36 
37 
38 volatile USBH_MSC_Info_t USBH_MSC_Info;
39 volatile USBH_BOTXfer_t  USBH_BOTXfer;
40 
41 
42 static uint8_t DataInBuffer[64];
43 
44 
45 /******************************************************************************************************************************************
46 * 函数名称: USBH_MSC_Init()
47 * 功能说明:
48 * 输    入: 无
49 * 输    出: 无
50 * 注意事项: 无
51 ******************************************************************************************************************************************/
USBH_MSC_Init(USBH_Info_t * phost)52 USBH_Status USBH_MSC_Init(USBH_Info_t *phost)
53 {
54     USB_EpDesc_t *pEpIn, *pEpOut;
55 
56     if((phost->Device.Intf_Desc[0].bInterfaceClass == USB_MSC_CLASS) && \
57        (phost->Device.Intf_Desc[0].bInterfaceProtocol == USB_MSC_BOT))
58     {
59         if(phost->Device.Ep_Desc[0][0].bEndpointAddress & USB_EP_IN)
60         {
61             pEpIn  = &phost->Device.Ep_Desc[0][0];
62             pEpOut = &phost->Device.Ep_Desc[0][1];
63         }
64         else
65         {
66             pEpIn  = &phost->Device.Ep_Desc[0][1];
67             pEpOut = &phost->Device.Ep_Desc[0][0];
68         }
69 
70         USBH_MSC_Info.InEp      = pEpIn->bEndpointAddress;
71         USBH_MSC_Info.InEpSize  = pEpIn->wMaxPacketSize;
72         USBH_MSC_Info.OutEp     = pEpOut->bEndpointAddress;
73         USBH_MSC_Info.OutEpSize = pEpOut->wMaxPacketSize;
74 
75         USBH_MSC_DeInit(phost);
76     }
77     else
78     {
79         if(phost->usr_cb->DeviceNotSupported)
80             phost->usr_cb->DeviceNotSupported();
81     }
82 
83     return USBH_OK ;
84 }
85 
86 
87 /******************************************************************************************************************************************
88 * 函数名称: USBH_MSC_DeInit()
89 * 功能说明:
90 * 输    入: 无
91 * 输    出: 无
92 * 注意事项: 无
93 ******************************************************************************************************************************************/
USBH_MSC_DeInit(USBH_Info_t * phost)94 void USBH_MSC_DeInit(USBH_Info_t *phost)
95 {
96     USBH_MSC_Info.Ready = 0;
97     USBH_MSC_Info.InEpDATAX  = 0;
98     USBH_MSC_Info.OutEpDATAX = 0;
99 
100     USBH_MSC_BOT_Init();
101 }
102 
103 
104 /******************************************************************************************************************************************
105 * 函数名称: USBH_MSC_Request()
106 * 功能说明:
107 * 输    入: 无
108 * 输    出: 无
109 * 注意事项: 无
110 ******************************************************************************************************************************************/
USBH_MSC_Request(USBH_Info_t * phost)111 USBH_Status USBH_MSC_Request(USBH_Info_t *phost)
112 {
113     USBH_BOTXfer.MSCState = USBH_MSC_GET_MAXLUN;
114 
115     return USBH_OK;
116 }
117 
118 
119 /******************************************************************************************************************************************
120 * 函数名称: USBH_MSC_Process()
121 * 功能说明:  MSC state machine handler
122 * 输    入: 无
123 * 输    出: 无
124 * 注意事项: 无
125 ******************************************************************************************************************************************/
USBH_MSC_Process(USBH_Info_t * phost)126 USBH_Status USBH_MSC_Process(USBH_Info_t *phost)
127 {
128     USBH_Status status = USBH_BUSY;
129 
130     uint8_t mscStatus;
131     uint8_t appStatus;
132 
133     switch(USBH_BOTXfer.MSCState)
134     {
135     case USBH_MSC_GET_MAXLUN:
136         status = USBH_MSC_getMaxLUN(phost);
137         if(status == USBH_OK)
138         {
139             USBH_MSC_Info.MaxLUN = DataInBuffer[0];
140 
141             USBH_BOTXfer.MSCState = USBH_MSC_TEST_UNIT_READY;
142         }
143         else if(status == USBH_NOT_SUPPORTED)
144         {
145             /* 清除 STALL 后,进入 USBH_MSC_TEST_UNIT_READY */
146             USBH_BOTXfer.MSCStateBkp = USBH_MSC_TEST_UNIT_READY;
147 
148             USBH_BOTXfer.MSCState = USBH_MSC_CLEAR_STALL;
149         }
150         break;
151 
152     case USBH_MSC_CLEAR_STALL:
153         status = USBH_ClrFeature(phost, USBH_MSC_Info.InEp);
154         if(status == USBH_OK)
155         {
156             USBH_MSC_Info.MaxLUN = 0;   // 不支持 GetMaxLUN 请求,假设只有一个逻辑单元
157 
158             USBH_BOTXfer.MSCState = USBH_BOTXfer.MSCStateBkp;
159         }
160         break;
161 
162     case USBH_MSC_TEST_UNIT_READY:
163         mscStatus = USBH_MSC_TestUnitReady();
164         if(mscStatus == USBH_MSC_OK)
165         {
166             USBH_BOTXfer.MSCState = USBH_MSC_READ_CAPACITY10;
167 
168             status = USBH_OK;
169         }
170         else
171         {
172             USBH_MSC_ErrorHandle(mscStatus);
173         }
174         break;
175 
176     case USBH_MSC_READ_CAPACITY10:
177         mscStatus = USBH_MSC_ReadCapacity10();
178         if(mscStatus == USBH_MSC_OK)
179         {
180             USBH_BOTXfer.MSCState = USBH_MSC_DEFAULT_APP;
181 
182             USBH_MSC_Info.Ready = 1;
183 
184             status = USBH_OK;
185         }
186         else
187         {
188             USBH_MSC_ErrorHandle(mscStatus);
189         }
190         break;
191 
192     case USBH_MSC_MODE_SENSE6:
193         /* Issue ModeSense6 SCSI command for detecting if device is write-protected */
194         mscStatus = USBH_MSC_ModeSense6();
195         if(mscStatus == USBH_MSC_OK)
196         {
197             USBH_BOTXfer.MSCState = USBH_MSC_DEFAULT_APP;
198 
199             status = USBH_OK;
200         }
201         else
202         {
203             USBH_MSC_ErrorHandle(mscStatus);
204         }
205         break;
206 
207     case USBH_MSC_DEFAULT_APP:
208         /* Process Application callback for MSC */
209         appStatus = phost->usr_cb->UserApplication();
210         if(appStatus == 1)
211         {
212             /* De-init requested from application layer */
213             status =  USBH_APPLY_DEINIT;
214         }
215         break;
216 
217     case USBH_MSC_BOT_TRANSFER:
218         USBH_MSC_BOT_Process(phost);
219         break;
220 
221     case USBH_MSC_UNRECOVERED_STATE:
222         status = USBH_UNRECOVERED_ERROR;
223         break;
224 
225     case USBH_MSC_REQUEST_SENSE:
226         /* Issue RequestSense SCSI command for retrieving error code */
227         mscStatus = USBH_MSC_RequestSense();
228         if(mscStatus == USBH_MSC_OK)
229         {
230             USBH_BOTXfer.MSCState = USBH_BOTXfer.MSCStateBkp;
231 
232             status = USBH_OK;
233         }
234         else
235         {
236             USBH_MSC_ErrorHandle(mscStatus);
237         }
238         break;
239 
240     default:
241         break;
242     }
243 
244     return status;
245 }
246 
247 
248 /******************************************************************************************************************************************
249 * 函数名称: USBH_MSC_getMaxLUN()
250 * 功能说明:
251 * 输    入: 无
252 * 输    出: 无
253 * 注意事项: 无
254 ******************************************************************************************************************************************/
USBH_MSC_getMaxLUN(USBH_Info_t * phost)255 USBH_Status USBH_MSC_getMaxLUN(USBH_Info_t *phost)
256 {
257     phost->Ctrl.setup.bRequestType = USB_REQ_D2H | USB_REQ_CLASS | USB_REQ_TO_INTERFACE;
258 
259     phost->Ctrl.setup.bRequest = 0xFE;
260     phost->Ctrl.setup.wValue = 0;
261     phost->Ctrl.setup.wIndex = 0;
262     phost->Ctrl.setup.wLength = 1;
263 
264     return USBH_CtrlTransfer(phost, DataInBuffer , 1);
265 }
266 
267 
268 /******************************************************************************************************************************************
269 * 函数名称: USBH_MSC_ErrorHandle()
270 * 功能说明:
271 * 输    入: 无
272 * 输    出: 无
273 * 注意事项: 无
274 ******************************************************************************************************************************************/
USBH_MSC_ErrorHandle(uint8_t status)275 void USBH_MSC_ErrorHandle(uint8_t status)
276 {
277     if(status == USBH_MSC_FAIL)
278     {
279         /* Try MSC level error recovery, Issue the request Sense to get Drive error reason  */
280         USBH_BOTXfer.MSCState = USBH_MSC_REQUEST_SENSE;
281     }
282     else if(status == USBH_MSC_PHASE_ERROR)
283     {
284         /* Phase error, Go to Unrecovered state */
285         USBH_BOTXfer.MSCState = USBH_MSC_UNRECOVERED_STATE;
286     }
287 }
288