2 ******************************************************************************
3 * @file usbh_msc_scsi.c
4 * @author MCD Application Team
7 * @brief This file implements the SCSI commands
8 ******************************************************************************
11 * <h2><center>© 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 ******************************************************************************
28 /* Includes ------------------------------------------------------------------*/
30 #include "usbh_msc_scsi.h"
31 #include "usbh_msc_bot.h"
34 /** @addtogroup USBH_LIB
38 /** @addtogroup USBH_CLASS
42 /** @addtogroup USBH_MSC_CLASS
46 /** @defgroup USBH_MSC_SCSI
47 * @brief This file includes the mass storage related functions
52 /** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
60 /** @defgroup USBH_MSC_SCSI_Private_Defines
67 /** @defgroup USBH_MSC_SCSI_Private_Macros
75 /** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
83 /** @defgroup USBH_MSC_SCSI_Exported_Variables
92 /** @defgroup USBH_MSC_SCSI_Private_Functions
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
,
107 USBH_StatusTypeDef error
= USBH_FAIL
;
108 MSC_HandleTypeDef
*MSC_Handle
= (MSC_HandleTypeDef
*) phost
->pActiveClass
->pData
;
110 switch(MSC_Handle
->hbot
.cmd_state
)
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
;
128 error
= USBH_MSC_BOT_Process(phost
, lun
);
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
,
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
)
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
;
174 error
= USBH_MSC_BOT_Process(phost
, lun
);
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);
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
,
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
)
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
;
234 error
= USBH_MSC_BOT_Process(phost
, lun
);
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);
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
,
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
)
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
;
296 error
= USBH_MSC_BOT_Process(phost
, lun
);
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];
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
,
329 USBH_StatusTypeDef error
= USBH_FAIL
;
331 MSC_HandleTypeDef
*MSC_Handle
= (MSC_HandleTypeDef
*) phost
->pActiveClass
->pData
;
333 switch(MSC_Handle
->hbot
.cmd_state
)
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]);
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
;
364 error
= USBH_MSC_BOT_Process(phost
, lun
);
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
,
390 USBH_StatusTypeDef error
= USBH_FAIL
;
391 MSC_HandleTypeDef
*MSC_Handle
= (MSC_HandleTypeDef
*) phost
->pActiveClass
->pData
;
393 switch(MSC_Handle
->hbot
.cmd_state
)
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]);
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
;
424 error
= USBH_MSC_BOT_Process(phost
, lun
);
455 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/