2 ******************************************************************************
\r
3 * @file usbh_msc_scsi.c
\r
4 * @author MCD Application Team
\r
6 * @date 18-February-2014
\r
7 * @brief This file implements the SCSI commands
\r
8 ******************************************************************************
\r
11 * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
\r
13 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
\r
14 * You may not use this file except in compliance with the License.
\r
15 * You may obtain a copy of the License at:
\r
17 * http://www.st.com/software_license_agreement_liberty_v2
\r
19 * Unless required by applicable law or agreed to in writing, software
\r
20 * distributed under the License is distributed on an "AS IS" BASIS,
\r
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
22 * See the License for the specific language governing permissions and
\r
23 * limitations under the License.
\r
25 ******************************************************************************
\r
28 /* Includes ------------------------------------------------------------------*/
\r
29 #include "usbh_msc.h"
\r
30 #include "usbh_msc_scsi.h"
\r
31 #include "usbh_msc_bot.h"
\r
34 /** @addtogroup USBH_LIB
\r
38 /** @addtogroup USBH_CLASS
\r
42 /** @addtogroup USBH_MSC_CLASS
\r
46 /** @defgroup USBH_MSC_SCSI
\r
47 * @brief This file includes the mass storage related functions
\r
52 /** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
\r
60 /** @defgroup USBH_MSC_SCSI_Private_Defines
\r
67 /** @defgroup USBH_MSC_SCSI_Private_Macros
\r
75 /** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
\r
83 /** @defgroup USBH_MSC_SCSI_Exported_Variables
\r
92 /** @defgroup USBH_MSC_SCSI_Private_Functions
\r
98 * @brief USBH_MSC_SCSI_TestUnitReady
\r
99 * Issue TestUnitReady command.
\r
100 * @param phost: Host handle
\r
101 * @param lun: Logical Unit Number
\r
102 * @retval USBH Status
\r
104 USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost,
\r
107 USBH_StatusTypeDef error = USBH_FAIL ;
\r
108 MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
\r
110 switch(MSC_Handle->hbot.cmd_state)
\r
112 case BOT_CMD_SEND:
\r
114 /*Prepare the CBW and relevent field*/
\r
115 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY;
\r
116 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
\r
117 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
\r
119 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
\r
120 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_TEST_UNIT_READY;
\r
122 MSC_Handle->hbot.state = BOT_SEND_CBW;
\r
123 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
\r
124 error = USBH_BUSY;
\r
127 case BOT_CMD_WAIT:
\r
128 error = USBH_MSC_BOT_Process(phost, lun);
\r
139 * @brief USBH_MSC_SCSI_ReadCapacity
\r
140 * Issue Read Capacity command.
\r
141 * @param phost: Host handle
\r
142 * @param lun: Logical Unit Number
\r
143 * @param capacity: pointer to the capacity structure
\r
144 * @retval USBH Status
\r
146 USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost,
\r
148 SCSI_CapacityTypeDef *capacity)
\r
150 USBH_StatusTypeDef error = USBH_BUSY ;
\r
151 MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
\r
153 switch(MSC_Handle->hbot.cmd_state)
\r
155 case BOT_CMD_SEND:
\r
157 /*Prepare the CBW and relevent field*/
\r
158 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10;
\r
159 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
\r
160 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
\r
162 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
\r
163 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ_CAPACITY10;
\r
165 MSC_Handle->hbot.state = BOT_SEND_CBW;
\r
167 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
\r
168 MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
\r
169 error = USBH_BUSY;
\r
172 case BOT_CMD_WAIT:
\r
174 error = USBH_MSC_BOT_Process(phost, lun);
\r
176 if(error == USBH_OK)
\r
178 /*assign the capacity*/
\r
179 capacity->block_nbr = MSC_Handle->hbot.pbuf[3] | (MSC_Handle->hbot.pbuf[2] << 8) |\
\r
180 (MSC_Handle->hbot.pbuf[1] << 16) | (MSC_Handle->hbot.pbuf[0] << 24);
\r
182 /*assign the page length*/
\r
183 capacity->block_size = MSC_Handle->hbot.pbuf[7] | (MSC_Handle->hbot.pbuf[6] << 8);
\r
195 * @brief USBH_MSC_SCSI_Inquiry
\r
196 * Issue Inquiry command.
\r
197 * @param phost: Host handle
\r
198 * @param lun: Logical Unit Number
\r
199 * @param capacity: pointer to the inquiry structure
\r
200 * @retval USBH Status
\r
202 USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost,
\r
204 SCSI_StdInquiryDataTypeDef *inquiry)
\r
206 USBH_StatusTypeDef error = USBH_FAIL ;
\r
207 MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
\r
208 switch(MSC_Handle->hbot.cmd_state)
\r
210 case BOT_CMD_SEND:
\r
212 /*Prepare the CBW and relevent field*/
\r
213 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY;
\r
214 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
\r
215 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
\r
217 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH);
\r
218 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_INQUIRY;
\r
219 MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
\r
220 MSC_Handle->hbot.cbw.field.CB[2] = 0;
\r
221 MSC_Handle->hbot.cbw.field.CB[3] = 0;
\r
222 MSC_Handle->hbot.cbw.field.CB[4] = 0x24;
\r
223 MSC_Handle->hbot.cbw.field.CB[5] = 0;
\r
225 MSC_Handle->hbot.state = BOT_SEND_CBW;
\r
227 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
\r
228 MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
\r
229 error = USBH_BUSY;
\r
232 case BOT_CMD_WAIT:
\r
234 error = USBH_MSC_BOT_Process(phost, lun);
\r
236 if(error == USBH_OK)
\r
238 USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef));
\r
239 /*assign Inquiry Data */
\r
240 inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1F;
\r
241 inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5;
\r
242 inquiry->RemovableMedia = (MSC_Handle->hbot.pbuf[1] & 0x80)== 0x80;
\r
243 USBH_memcpy (inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8);
\r
244 USBH_memcpy (inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16);
\r
245 USBH_memcpy (inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4);
\r
257 * @brief USBH_MSC_SCSI_RequestSense
\r
258 * Issue RequestSense command.
\r
259 * @param phost: Host handle
\r
260 * @param lun: Logical Unit Number
\r
261 * @param capacity: pointer to the sense data structure
\r
262 * @retval USBH Status
\r
264 USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost,
\r
266 SCSI_SenseTypeDef *sense_data)
\r
268 USBH_StatusTypeDef error = USBH_FAIL ;
\r
269 MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
\r
271 switch(MSC_Handle->hbot.cmd_state)
\r
273 case BOT_CMD_SEND:
\r
275 /*Prepare the CBW and relevent field*/
\r
276 MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE;
\r
277 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
\r
278 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
\r
280 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
\r
281 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_REQUEST_SENSE;
\r
282 MSC_Handle->hbot.cbw.field.CB[1] = (lun << 5);
\r
283 MSC_Handle->hbot.cbw.field.CB[2] = 0;
\r
284 MSC_Handle->hbot.cbw.field.CB[3] = 0;
\r
285 MSC_Handle->hbot.cbw.field.CB[4] = DATA_LEN_REQUEST_SENSE;
\r
286 MSC_Handle->hbot.cbw.field.CB[5] = 0;
\r
288 MSC_Handle->hbot.state = BOT_SEND_CBW;
\r
289 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
\r
290 MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
\r
291 error = USBH_BUSY;
\r
294 case BOT_CMD_WAIT:
\r
296 error = USBH_MSC_BOT_Process(phost, lun);
\r
298 if(error == USBH_OK)
\r
300 sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0F;
\r
301 sense_data->asc = MSC_Handle->hbot.pbuf[12];
\r
302 sense_data->ascq = MSC_Handle->hbot.pbuf[13];
\r
314 * @brief USBH_MSC_SCSI_Write
\r
315 * Issue write10 command.
\r
316 * @param phost: Host handle
\r
317 * @param lun: Logical Unit Number
\r
318 * @param address: sector address
\r
319 * @param pbuf: pointer to data
\r
320 * @param length: number of sector to write
\r
321 * @retval USBH Status
\r
323 USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost,
\r
329 USBH_StatusTypeDef error = USBH_FAIL ;
\r
331 MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
\r
333 switch(MSC_Handle->hbot.cmd_state)
\r
335 case BOT_CMD_SEND:
\r
337 /*Prepare the CBW and relevent field*/
\r
338 MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
\r
339 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
\r
340 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
\r
342 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
\r
343 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_WRITE10;
\r
345 /*logical block address*/
\r
346 MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
\r
347 MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
\r
348 MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
\r
349 MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
\r
352 /*Tranfer length */
\r
353 MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
\r
354 MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
\r
357 MSC_Handle->hbot.state = BOT_SEND_CBW;
\r
358 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
\r
359 MSC_Handle->hbot.pbuf = pbuf;
\r
360 error = USBH_BUSY;
\r
363 case BOT_CMD_WAIT:
\r
364 error = USBH_MSC_BOT_Process(phost, lun);
\r
375 * @brief USBH_MSC_SCSI_Read
\r
376 * Issue Read10 command.
\r
377 * @param phost: Host handle
\r
378 * @param lun: Logical Unit Number
\r
379 * @param address: sector address
\r
380 * @param pbuf: pointer to data
\r
381 * @param length: number of sector to read
\r
382 * @retval USBH Status
\r
384 USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost,
\r
390 USBH_StatusTypeDef error = USBH_FAIL ;
\r
391 MSC_HandleTypeDef *MSC_Handle = phost->pActiveClass->pData;
\r
393 switch(MSC_Handle->hbot.cmd_state)
\r
395 case BOT_CMD_SEND:
\r
397 /*Prepare the CBW and relevent field*/
\r
398 MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
\r
399 MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
\r
400 MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
\r
402 USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
\r
403 MSC_Handle->hbot.cbw.field.CB[0] = OPCODE_READ10;
\r
405 /*logical block address*/
\r
406 MSC_Handle->hbot.cbw.field.CB[2] = (((uint8_t*)&address)[3]);
\r
407 MSC_Handle->hbot.cbw.field.CB[3] = (((uint8_t*)&address)[2]);
\r
408 MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]);
\r
409 MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]);
\r
412 /*Tranfer length */
\r
413 MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ;
\r
414 MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ;
\r
417 MSC_Handle->hbot.state = BOT_SEND_CBW;
\r
418 MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
\r
419 MSC_Handle->hbot.pbuf = pbuf;
\r
420 error = USBH_BUSY;
\r
423 case BOT_CMD_WAIT:
\r
424 error = USBH_MSC_BOT_Process(phost, lun);
\r
455 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\r