1 /*!
2  * @file        usbd_msv_bot.c
3  *
4  * @brief       MSC BOT protocol core functions
5  *
6  * @version     V1.0.0
7  *
8  * @date        2021-12-25
9  *
10  * @attention
11  *
12  *  Copyright (C) 2020-2022 Geehy Semiconductor
13  *
14  *  You may not use this file except in compliance with the
15  *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16  *
17  *  The program is only for reference, which is distributed in the hope
18  *  that it will be useful and instructional for customers to develop
19  *  their software. Unless required by applicable law or agreed to in
20  *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21  *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23  *  and limitations under the License.
24  */
25 
26 /* Includes */
27 #include "usbd_msc_bot.h"
28 #include "usbd_core.h"
29 #include "usbd_storage_disk.h"
30 #include "usbd_msc_scsi.h"
31 
32 /** @addtogroup USB_Driver_Library USB Driver Library
33   @{
34 */
35 
36 /** @addtogroup Core_Device Core Device
37   @{
38 */
39 
40 /** @addtogroup Class
41   @{
42 */
43 
44 /** @addtogroup MSC_BOT
45   @{
46 */
47 
48 /** @defgroup MSC_BOT_Macros Macros
49   @{
50 */
51 
52 /**@} end of group MSC_BOT_Macros */
53 
54 /** @defgroup MSC_BOT_Enumerations Enumerations
55   @{
56 */
57 
58 /**@} end of group MSC_BOT_Enumerations */
59 
60 /** @defgroup MSC_BOT_Structures Structures
61   @{
62 */
63 
64 /**@} end of group MSC_BOT_Structures */
65 
66 /** @defgroup MSC_BOT_Variables Variables
67   @{
68 */
69 
70 BOT_Info_T g_BOTInfo;
71 
72 /**@} end of group MSC_BOT_Variables */
73 
74 /** @defgroup MSC_BOT_Functions Functions
75   @{
76 */
77 
78 static void USBD_MSC_BOT_DecodeCBW(void);
79 static void USBD_MSC_BOT_TxData(uint8_t* txBuf, uint16_t len);
80 static void USBD_MSC_BOT_Stall(void);
81 
82 /*!
83  * @brief       BOT Process Reset.
84  *
85  * @param       None
86  *
87  * @retval      None
88  */
USBD_MSC_BOT_Reset(void)89 void USBD_MSC_BOT_Reset(void)
90 {
91     g_BOTInfo.state = BOT_STATE_IDLE;
92     g_BOTInfo.status = BOT_STATUS_RECOVERY;
93 
94     USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW, MSC_BOT_CBW_LENGTH);
95 }
96 
97 /*!
98  * @brief       BOT Process initialization.
99  *
100  * @param       None
101  *
102  * @retval      None
103  */
USBD_MSC_BOT_Init(void)104 void USBD_MSC_BOT_Init(void)
105 {
106     g_BOTInfo.state = BOT_STATE_IDLE;
107     g_BOTInfo.status = BOT_STATUS_NORMAL;
108 
109     g_storageCallBack.Init(0);
110 
111     USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW, MSC_BOT_CBW_LENGTH);
112 }
113 
114 /*!
115  * @brief       Bulk OUT data handler.
116  *
117  * @param       ep : OUT endpoint
118  *
119  * @retval      None
120  */
USBD_MSC_BOT_OutData(uint8_t ep)121 void USBD_MSC_BOT_OutData(uint8_t ep)
122 {
123     if (g_BOTInfo.state == BOT_STATE_IDLE)
124     {
125         USBD_MSC_BOT_DecodeCBW();
126     }
127     else if (g_BOTInfo.state == BOT_STATE_DATA_OUT)
128     {
129         if (SCSI_CmdHandler(g_BOTInfo.CBW.bLUN, g_BOTInfo.CBW.CB) != SCSI_OK)
130         {
131             USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_FAIL);
132         }
133     }
134 }
135 
136 /*!
137  * @brief       Bulk IN data handler.
138  *
139  * @param       ep : IN endpoint
140  *
141  * @retval      None
142  */
USBD_MSC_BOT_InData(uint8_t ep)143 void USBD_MSC_BOT_InData(uint8_t ep)
144 {
145     if (g_BOTInfo.state == BOT_STATE_DATA_IN)
146     {
147         if (SCSI_CmdHandler(g_BOTInfo.CBW.bLUN, g_BOTInfo.CBW.CB) != SCSI_OK)
148         {
149             USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_FAIL);
150         }
151     }
152     else if ((g_BOTInfo.state == BOT_STATE_SEND_DATA) || \
153              (g_BOTInfo.state == BOT_STATE_LAST_DATA_IN))
154     {
155         USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_OK);
156     }
157 }
158 
159 /*!
160  * @brief       Decode CBW.
161  *
162  * @param       None
163  *
164  * @retval      None
165  */
USBD_MSC_BOT_DecodeCBW(void)166 static void USBD_MSC_BOT_DecodeCBW(void)
167 {
168     uint32_t xferCnt = g_usbDev.outBuf[MSC_OUT_EP & 0x7f].xferCnt;
169 
170     g_BOTInfo.CSW.dTag = g_BOTInfo.CBW.dTag;
171     g_BOTInfo.CSW.dDataResidue = g_BOTInfo.CBW.dDataXferLen;
172 
173     if ((xferCnt != MSC_BOT_CBW_LENGTH) || \
174             (g_BOTInfo.CBW.dSignature != MSC_BOT_CBW_SIGNATURE) || \
175             (g_BOTInfo.CBW.bLUN > 1) || (g_BOTInfo.CBW.bCBLen < 1) || \
176             (g_BOTInfo.CBW.bCBLen > 16))
177     {
178         SCSI_PutSenseCode(g_BOTInfo.CBW.bLUN, SCSI_SKEY_ILLEGAL_REQUEST,
179                           SCSI_ASC_INVALID_CDB, 0);
180 
181         g_BOTInfo.status = BOT_STATUS_ERROR;
182     }
183     else
184     {
185         if (SCSI_CmdHandler(g_BOTInfo.CBW.bLUN, g_BOTInfo.CBW.CB) != SCSI_OK)
186         {
187             USBD_MSC_BOT_Stall();
188         }
189         else if ((g_BOTInfo.state == BOT_STATE_IDLE) || \
190                  (g_BOTInfo.state == BOT_STATE_SEND_DATA))
191         {
192             if (g_BOTInfo.dataLen)
193             {
194                 USBD_MSC_BOT_TxData(g_BOTInfo.data, g_BOTInfo.dataLen);
195             }
196             else
197             {
198                 USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_OK);
199             }
200         }
201     }
202 }
203 
204 /*!
205  * @brief       MSC send data.
206  *
207  * @param       txBuf : buffer to send
208  *
209  * @param       len : buffer length
210  *
211  * @retval      None
212  */
USBD_MSC_BOT_TxData(uint8_t * txBuf,uint16_t len)213 static void USBD_MSC_BOT_TxData(uint8_t* txBuf, uint16_t len)
214 {
215     len = USB_MIN(len, g_BOTInfo.CBW.dDataXferLen);
216 
217     g_BOTInfo.CSW.dDataResidue -= len;
218     g_BOTInfo.CSW.bStatus = BOT_CSW_STATUS_CMD_OK;
219     g_BOTInfo.state = BOT_STATE_SEND_DATA;
220 
221     USBD_TxData(MSC_IN_EP & 0x7f, txBuf, len);
222 }
223 
224 /*!
225  * @brief       Send CSW.
226  *
227  * @param       cswStatus : status of CSW
228  *
229  * @retval      None
230  */
USBD_MSC_BOT_TxCSW(uint8_t cswStatus)231 void USBD_MSC_BOT_TxCSW(uint8_t cswStatus)
232 {
233     g_BOTInfo.CSW.dSignature = MSC_BOT_CSW_SIGNATURE;
234     g_BOTInfo.CSW.bStatus = cswStatus;
235     g_BOTInfo.state = BOT_STATE_IDLE;
236 
237     USBD_TxData(MSC_IN_EP & 0x7f, (uint8_t*)&g_BOTInfo.CSW,
238                 MSC_BOT_CSW_LENGTH);
239 
240     USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW,
241                 MSC_BOT_CBW_LENGTH);
242 }
243 
244 /*!
245  * @brief       handler clearFeature in standard request.
246  *
247  * @param       None
248  *
249  * @retval      None
250  */
USBD_MSV_BOT_ClearFeatureHandler(void)251 void USBD_MSV_BOT_ClearFeatureHandler(void)
252 {
253     if (g_BOTInfo.status == BOT_STATUS_ERROR)
254     {
255         USBD_SetEPTxStatus(MSC_IN_EP & 0x7f, USBD_EP_STATUS_NAK);
256         g_BOTInfo.status = BOT_STATUS_NORMAL;
257     }
258     else if (((g_usbDev.reqData.byte.wIndex[0] & 0x80) == 0x80) && \
259              g_BOTInfo.status != BOT_STATUS_RECOVERY)
260     {
261         USBD_MSC_BOT_TxCSW(BOT_CSW_STATUS_CMD_FAIL);
262     }
263 }
264 
265 /*!
266  * @brief       Stall MSC.
267  *
268  * @param       None
269  *
270  * @retval      None
271  */
USBD_MSC_BOT_Stall(void)272 static void USBD_MSC_BOT_Stall(void)
273 {
274     if ((g_BOTInfo.CBW.bmFlags == 0) && (g_BOTInfo.CBW.dDataXferLen != 0) && \
275             (g_BOTInfo.status == BOT_STATUS_NORMAL))
276     {
277         USBD_SetEPRxStatus(MSC_OUT_EP & 0x7f, USBD_EP_STATUS_STALL);
278     }
279 
280     USBD_SetEPTxStatus(MSC_IN_EP & 0x7f, USBD_EP_STATUS_STALL);
281 
282     if (g_BOTInfo.status == BOT_STATUS_ERROR)
283     {
284         USBD_RxData(MSC_OUT_EP & 0x7f, (uint8_t*)&g_BOTInfo.CBW, MSC_BOT_CBW_LENGTH);
285     }
286 }
287 
288 /**@} end of group MSC_BOT_Functions */
289 /**@} end of group MSC_BOT_ */
290 /**@} end of group Class */
291 /**@} end of group Core_Device */
292 /**@} end of group USB_Driver_Library */
293