F1 and F3 HAL / LL libraries
[betaflight.git] / lib / main / STM32F1 / Middlewares / ST / STM32_USB_Host_Library / Class / MSC / Src / usbh_msc_scsi.c
blob40332e400543e7a3a9ce5b3bd6c4d0adda947fd0
1 /**
2 ******************************************************************************
3 * @file usbh_msc_scsi.c
4 * @author MCD Application Team
5 * @version V3.2.2
6 * @date 07-July-2015
7 * @brief This file implements the SCSI commands
8 ******************************************************************************
9 * @attention
11 * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
13 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
14 * You may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at:
17 * http://www.st.com/software_license_agreement_liberty_v2
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
25 ******************************************************************************
26 */
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbh_msc.h"
30 #include "usbh_msc_scsi.h"
31 #include "usbh_msc_bot.h"
34 /** @addtogroup USBH_LIB
35 * @{
38 /** @addtogroup USBH_CLASS
39 * @{
42 /** @addtogroup USBH_MSC_CLASS
43 * @{
46 /** @defgroup USBH_MSC_SCSI
47 * @brief This file includes the mass storage related functions
48 * @{
49 */
52 /** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
53 * @{
54 */
56 /**
57 * @}
58 */
60 /** @defgroup USBH_MSC_SCSI_Private_Defines
61 * @{
62 */
63 /**
64 * @}
65 */
67 /** @defgroup USBH_MSC_SCSI_Private_Macros
68 * @{
69 */
70 /**
71 * @}
72 */
75 /** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
76 * @{
77 */
78 /**
79 * @}
80 */
83 /** @defgroup USBH_MSC_SCSI_Exported_Variables
84 * @{
85 */
87 /**
88 * @}
89 */
92 /** @defgroup USBH_MSC_SCSI_Private_Functions
93 * @{
94 */
97 /**
98 * @brief USBH_MSC_SCSI_TestUnitReady
99 * Issue TestUnitReady command.
100 * @param phost: Host handle
101 * @param lun: Logical Unit Number
102 * @retval USBH Status
104 USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost,
105 uint8_t lun)
107 USBH_StatusTypeDef error = USBH_FAIL ;
108 MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
110 switch(MSC_Handle->hbot.cmd_state)
112 case BOT_CMD_SEND:
114 /*Prepare the CBW and relevent field*/
115 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY;
116 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
117 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
119 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
120 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_TEST_UNIT_READY;
122 MSC_Handle->hbot.state = BOT_SEND_CBW;
123 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
124 error = USBH_BUSY;
125 break;
127 case BOT_CMD_WAIT:
128 error = USBH_MSC_BOT_Process(phost, lun);
129 break;
131 default:
132 break;
135 return error;
139 * @brief USBH_MSC_SCSI_ReadCapacity
140 * Issue Read Capacity command.
141 * @param phost: Host handle
142 * @param lun: Logical Unit Number
143 * @param capacity: pointer to the capacity structure
144 * @retval USBH Status
146 USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost,
147 uint8_t lun,
148 SCSI_CapacityTypeDef *capacity)
150 USBH_StatusTypeDef error = USBH_BUSY ;
151 MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
153 switch(MSC_Handle->hbot.cmd_state)
155 case BOT_CMD_SEND:
157 /*Prepare the CBW and relevent field*/
158 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10;
159 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
160 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
162 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
163 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ_CAPACITY10;
165 MSC_Handle->hbot.state = BOT_SEND_CBW;
167 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
168 MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
169 error = USBH_BUSY;
170 break;
172 case BOT_CMD_WAIT:
174 error = USBH_MSC_BOT_Process(phost, lun);
176 if(error == USBH_OK)
178 /*assign the capacity*/
179 capacity->block_nbr = MSC_Handle->hbot.pbuf[3] | (MSC_Handle->hbot.pbuf[2] << 8) |\
180 (MSC_Handle->hbot.pbuf[1] << 16) | (MSC_Handle->hbot.pbuf[0] << 24);
182 /*assign the page length*/
183 capacity->block_size = MSC_Handle->hbot.pbuf[7] | (MSC_Handle->hbot.pbuf[6] << 8);
185 break;
187 default:
188 break;
191 return error;
195 * @brief USBH_MSC_SCSI_Inquiry
196 * Issue Inquiry command.
197 * @param phost: Host handle
198 * @param lun: Logical Unit Number
199 * @param capacity: pointer to the inquiry structure
200 * @retval USBH Status
202 USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost,
203 uint8_t lun,
204 SCSI_StdInquiryDataTypeDef *inquiry)
206 USBH_StatusTypeDef error = USBH_FAIL ;
207 MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
208 switch(MSC_Handle->hbot.cmd_state)
210 case BOT_CMD_SEND:
212 /*Prepare the CBW and relevent field*/
213 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY;
214 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
215 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
217 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH);
218 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_INQUIRY;
219 MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
220 MSC_Handle->hbot.cbw.field.CB[2] = 0;
221 MSC_Handle->hbot.cbw.field.CB[3] = 0;
222 MSC_Handle->hbot.cbw.field.CB[4] = 0x24;
223 MSC_Handle->hbot.cbw.field.CB[5] = 0;
225 MSC_Handle->hbot.state = BOT_SEND_CBW;
227 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
228 MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
229 error = USBH_BUSY;
230 break;
232 case BOT_CMD_WAIT:
234 error = USBH_MSC_BOT_Process(phost, lun);
236 if(error == USBH_OK)
238 USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef));
239 /*assign Inquiry Data */
240 inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1F;
241 inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5;
242 inquiry->RemovableMedia = (MSC_Handle->hbot.pbuf[1] & 0x80)== 0x80;
243 USBH_memcpy (inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8);
244 USBH_memcpy (inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16);
245 USBH_memcpy (inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4);
247 break;
249 default:
250 break;
253 return error;
257 * @brief USBH_MSC_SCSI_RequestSense
258 * Issue RequestSense command.
259 * @param phost: Host handle
260 * @param lun: Logical Unit Number
261 * @param capacity: pointer to the sense data structure
262 * @retval USBH Status
264 USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost,
265 uint8_t lun,
266 SCSI_SenseTypeDef *sense_data)
268 USBH_StatusTypeDef error = USBH_FAIL ;
269 MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
271 switch(MSC_Handle->hbot.cmd_state)
273 case BOT_CMD_SEND:
275 /*Prepare the CBW and relevent field*/
276 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE;
277 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
278 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
280 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
281 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_REQUEST_SENSE;
282 MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
283 MSC_Handle->hbot.cbw.field.CB[2] = 0;
284 MSC_Handle->hbot.cbw.field.CB[3] = 0;
285 MSC_Handle->hbot.cbw.field.CB[4] = DATA_LEN_REQUEST_SENSE;
286 MSC_Handle->hbot.cbw.field.CB[5] = 0;
288 MSC_Handle->hbot.state = BOT_SEND_CBW;
289 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
290 MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
291 error = USBH_BUSY;
292 break;
294 case BOT_CMD_WAIT:
296 error = USBH_MSC_BOT_Process(phost, lun);
298 if(error == USBH_OK)
300 sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0F;
301 sense_data->asc = MSC_Handle->hbot.pbuf[12];
302 sense_data->ascq = MSC_Handle->hbot.pbuf[13];
304 break;
306 default:
307 break;
310 return error;
314 * @brief USBH_MSC_SCSI_Write
315 * Issue write10 command.
316 * @param phost: Host handle
317 * @param lun: Logical Unit Number
318 * @param address: sector address
319 * @param pbuf: pointer to data
320 * @param length: number of sector to write
321 * @retval USBH Status
323 USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost,
324 uint8_t lun,
325 uint32_t address,
326 uint8_t *pbuf,
327 uint32_t length)
329 USBH_StatusTypeDef error = USBH_FAIL ;
331 MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
333 switch(MSC_Handle->hbot.cmd_state)
335 case BOT_CMD_SEND:
337 /*Prepare the CBW and relevent field*/
338 MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
339 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
340 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
342 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
343 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_WRITE10;
345 /*logical block address*/
346 MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
347 MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
348 MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
349 MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
352 /*Transfer length */
353 MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
354 MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
357 MSC_Handle->hbot.state = BOT_SEND_CBW;
358 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
359 MSC_Handle->hbot.pbuf = pbuf;
360 error = USBH_BUSY;
361 break;
363 case BOT_CMD_WAIT:
364 error = USBH_MSC_BOT_Process(phost, lun);
365 break;
367 default:
368 break;
371 return error;
375 * @brief USBH_MSC_SCSI_Read
376 * Issue Read10 command.
377 * @param phost: Host handle
378 * @param lun: Logical Unit Number
379 * @param address: sector address
380 * @param pbuf: pointer to data
381 * @param length: number of sector to read
382 * @retval USBH Status
384 USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost,
385 uint8_t lun,
386 uint32_t address,
387 uint8_t *pbuf,
388 uint32_t length)
390 USBH_StatusTypeDef error = USBH_FAIL ;
391 MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
393 switch(MSC_Handle->hbot.cmd_state)
395 case BOT_CMD_SEND:
397 /*Prepare the CBW and relevent field*/
398 MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
399 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
400 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
402 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
403 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ10;
405 /*logical block address*/
406 MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
407 MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
408 MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
409 MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
412 /*Transfer length */
413 MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
414 MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
417 MSC_Handle->hbot.state = BOT_SEND_CBW;
418 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
419 MSC_Handle->hbot.pbuf = pbuf;
420 error = USBH_BUSY;
421 break;
423 case BOT_CMD_WAIT:
424 error = USBH_MSC_BOT_Process(phost, lun);
425 break;
427 default:
428 break;
431 return error;
436 * @}
440 * @}
444 * @}
448 * @}
452 * @}
455 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/