Nirvana Jay / Mbed 2 deprecated F7DISCO_Demo

Dependencies:   BSP_DISCO_F746NG_patch mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbh_msc_scsi.c Source File

usbh_msc_scsi.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    usbh_msc_scsi.c 
00004   * @author  MCD Application Team
00005   * @version V3.2.2
00006   * @date    07-July-2015
00007   * @brief   This file implements the SCSI commands
00008   ******************************************************************************
00009   * @attention
00010   *
00011   * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
00012   *
00013   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
00014   * You may not use this file except in compliance with the License.
00015   * You may obtain a copy of the License at:
00016   *
00017   *        http://www.st.com/software_license_agreement_liberty_v2
00018   *
00019   * Unless required by applicable law or agreed to in writing, software 
00020   * distributed under the License is distributed on an "AS IS" BASIS, 
00021   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00022   * See the License for the specific language governing permissions and
00023   * limitations under the License.
00024   *
00025   ******************************************************************************
00026   */ 
00027 
00028 /* Includes ------------------------------------------------------------------*/
00029 #include "usbh_msc.h"
00030 #include "usbh_msc_scsi.h"
00031 #include "usbh_msc_bot.h"
00032 
00033 
00034 /** @addtogroup USBH_LIB
00035   * @{
00036   */
00037 
00038 /** @addtogroup USBH_CLASS
00039   * @{
00040   */
00041 
00042 /** @addtogroup USBH_MSC_CLASS
00043   * @{
00044   */
00045   
00046 /** @defgroup USBH_MSC_SCSI 
00047   * @brief    This file includes the mass storage related functions
00048   * @{
00049   */ 
00050 
00051 
00052 /** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
00053   * @{
00054   */ 
00055 
00056 /**
00057   * @}
00058   */ 
00059 
00060 /** @defgroup USBH_MSC_SCSI_Private_Defines
00061   * @{
00062   */ 
00063 /**
00064   * @}
00065   */ 
00066 
00067 /** @defgroup USBH_MSC_SCSI_Private_Macros
00068   * @{
00069   */ 
00070 /**
00071   * @}
00072   */ 
00073 
00074 
00075 /** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
00076   * @{
00077   */ 
00078 /**
00079   * @}
00080   */ 
00081 
00082 
00083 /** @defgroup USBH_MSC_SCSI_Exported_Variables
00084   * @{
00085   */ 
00086 
00087 /**
00088   * @}
00089   */ 
00090 
00091 
00092 /** @defgroup USBH_MSC_SCSI_Private_Functions
00093   * @{
00094   */ 
00095 
00096 
00097 /**
00098   * @brief  USBH_MSC_SCSI_TestUnitReady 
00099   *         Issue TestUnitReady command.
00100   * @param  phost: Host handle
00101   * @param  lun: Logical Unit Number
00102   * @retval USBH Status
00103   */
00104 USBH_StatusTypeDef USBH_MSC_SCSI_TestUnitReady (USBH_HandleTypeDef *phost, 
00105                                                 uint8_t lun)
00106 {
00107   USBH_StatusTypeDef    error = USBH_FAIL ;
00108   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00109   
00110   switch(MSC_Handle->hbot.cmd_state)
00111   {
00112   case BOT_CMD_SEND:  
00113     
00114     /*Prepare the CBW and relevent field*/
00115     MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_MODE_TEST_UNIT_READY;     
00116     MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
00117     MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
00118     
00119     USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
00120     MSC_Handle->hbot.cbw.field.CB[0]  = OPCODE_TEST_UNIT_READY; 
00121     
00122     MSC_Handle->hbot.state = BOT_SEND_CBW;
00123     MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
00124     error = USBH_BUSY; 
00125     break;
00126     
00127   case BOT_CMD_WAIT: 
00128     error = USBH_MSC_BOT_Process(phost, lun);
00129     break;
00130     
00131   default:
00132     break;
00133   }
00134   
00135   return error;
00136 }
00137 
00138 /**
00139   * @brief  USBH_MSC_SCSI_ReadCapacity 
00140   *         Issue Read Capacity command.
00141   * @param  phost: Host handle
00142   * @param  lun: Logical Unit Number
00143   * @param  capacity: pointer to the capacity structure
00144   * @retval USBH Status
00145   */
00146 USBH_StatusTypeDef USBH_MSC_SCSI_ReadCapacity (USBH_HandleTypeDef *phost, 
00147                                                uint8_t lun,
00148                                                SCSI_CapacityTypeDef *capacity)
00149 {
00150   USBH_StatusTypeDef    error = USBH_BUSY ;
00151   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00152   
00153   switch(MSC_Handle->hbot.cmd_state)
00154   {
00155   case BOT_CMD_SEND:  
00156     
00157     /*Prepare the CBW and relevent field*/
00158     MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_READ_CAPACITY10;
00159     MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
00160     MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
00161     
00162     USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
00163     MSC_Handle->hbot.cbw.field.CB[0]  = OPCODE_READ_CAPACITY10; 
00164     
00165     MSC_Handle->hbot.state = BOT_SEND_CBW;
00166     
00167     MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
00168     MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
00169     error = USBH_BUSY; 
00170     break;
00171     
00172   case BOT_CMD_WAIT: 
00173     
00174     error = USBH_MSC_BOT_Process(phost, lun);
00175     
00176     if(error == USBH_OK)
00177     {
00178       /*assign the capacity*/
00179       capacity->block_nbr = MSC_Handle->hbot.pbuf[3] | (MSC_Handle->hbot.pbuf[2] << 8) |\
00180                            (MSC_Handle->hbot.pbuf[1] << 16) | (MSC_Handle->hbot.pbuf[0] << 24);
00181 
00182       /*assign the page length*/
00183       capacity->block_size = MSC_Handle->hbot.pbuf[7] | (MSC_Handle->hbot.pbuf[6] << 8); 
00184     }
00185     break;
00186     
00187   default:
00188     break;
00189   }
00190   
00191   return error;
00192 }
00193 
00194 /**
00195   * @brief  USBH_MSC_SCSI_Inquiry 
00196   *         Issue Inquiry command.
00197   * @param  phost: Host handle
00198   * @param  lun: Logical Unit Number
00199   * @param  capacity: pointer to the inquiry structure
00200   * @retval USBH Status
00201   */
00202 USBH_StatusTypeDef USBH_MSC_SCSI_Inquiry (USBH_HandleTypeDef *phost, 
00203                                                uint8_t lun, 
00204                                                SCSI_StdInquiryDataTypeDef *inquiry)
00205 {
00206   USBH_StatusTypeDef    error = USBH_FAIL ;
00207   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00208   switch(MSC_Handle->hbot.cmd_state)
00209   {
00210   case BOT_CMD_SEND:  
00211     
00212     /*Prepare the CBW and relevent field*/
00213     MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_INQUIRY;
00214     MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
00215     MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
00216     
00217     USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_LENGTH);
00218     MSC_Handle->hbot.cbw.field.CB[0]  = OPCODE_INQUIRY; 
00219     MSC_Handle->hbot.cbw.field.CB[1]  = (lun << 5);    
00220     MSC_Handle->hbot.cbw.field.CB[2]  = 0;    
00221     MSC_Handle->hbot.cbw.field.CB[3]  = 0;    
00222     MSC_Handle->hbot.cbw.field.CB[4]  = 0x24;    
00223     MSC_Handle->hbot.cbw.field.CB[5]  = 0;    
00224         
00225     MSC_Handle->hbot.state = BOT_SEND_CBW;
00226 
00227     MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
00228     MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
00229     error = USBH_BUSY; 
00230     break;
00231     
00232   case BOT_CMD_WAIT: 
00233     
00234     error = USBH_MSC_BOT_Process(phost, lun);
00235     
00236     if(error == USBH_OK)
00237     {
00238       USBH_memset(inquiry, 0, sizeof(SCSI_StdInquiryDataTypeDef));
00239       /*assign Inquiry Data */
00240       inquiry->DeviceType = MSC_Handle->hbot.pbuf[0] & 0x1F;
00241       inquiry->PeripheralQualifier = MSC_Handle->hbot.pbuf[0] >> 5;  
00242       inquiry->RemovableMedia = (MSC_Handle->hbot.pbuf[1] & 0x80)== 0x80;
00243       USBH_memcpy (inquiry->vendor_id, &MSC_Handle->hbot.pbuf[8], 8);
00244       USBH_memcpy (inquiry->product_id, &MSC_Handle->hbot.pbuf[16], 16);
00245       USBH_memcpy (inquiry->revision_id, &MSC_Handle->hbot.pbuf[32], 4);    
00246     }
00247     break;
00248     
00249   default:
00250     break;
00251   }
00252   
00253   return error;
00254 }
00255 
00256 /**
00257   * @brief  USBH_MSC_SCSI_RequestSense 
00258   *         Issue RequestSense command.
00259   * @param  phost: Host handle
00260   * @param  lun: Logical Unit Number
00261   * @param  capacity: pointer to the sense data structure
00262   * @retval USBH Status
00263   */
00264 USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost, 
00265                                                uint8_t lun, 
00266                                                SCSI_SenseTypeDef *sense_data)
00267 {
00268   USBH_StatusTypeDef    error = USBH_FAIL ;
00269   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00270   
00271   switch(MSC_Handle->hbot.cmd_state)
00272   {
00273   case BOT_CMD_SEND:  
00274     
00275     /*Prepare the CBW and relevent field*/
00276     MSC_Handle->hbot.cbw.field.DataTransferLength = DATA_LEN_REQUEST_SENSE;
00277     MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
00278     MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
00279     
00280     USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
00281     MSC_Handle->hbot.cbw.field.CB[0]  = OPCODE_REQUEST_SENSE; 
00282     MSC_Handle->hbot.cbw.field.CB[1]  = (lun << 5); 
00283     MSC_Handle->hbot.cbw.field.CB[2]  = 0; 
00284     MSC_Handle->hbot.cbw.field.CB[3]  = 0; 
00285     MSC_Handle->hbot.cbw.field.CB[4]  = DATA_LEN_REQUEST_SENSE;
00286     MSC_Handle->hbot.cbw.field.CB[5]  = 0;       
00287     
00288     MSC_Handle->hbot.state = BOT_SEND_CBW;
00289     MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
00290     MSC_Handle->hbot.pbuf = (uint8_t *)MSC_Handle->hbot.data;
00291     error = USBH_BUSY; 
00292     break;
00293     
00294   case BOT_CMD_WAIT: 
00295     
00296     error = USBH_MSC_BOT_Process(phost, lun);
00297     
00298     if(error == USBH_OK)
00299     {
00300       sense_data->key  = MSC_Handle->hbot.pbuf[2] & 0x0F;  
00301       sense_data->asc  = MSC_Handle->hbot.pbuf[12];
00302       sense_data->ascq = MSC_Handle->hbot.pbuf[13];
00303     }
00304     break;
00305     
00306   default:
00307     break;
00308   }
00309   
00310   return error;
00311 }
00312 
00313 /**
00314   * @brief  USBH_MSC_SCSI_Write 
00315   *         Issue write10 command.
00316   * @param  phost: Host handle
00317   * @param  lun: Logical Unit Number
00318   * @param  address: sector address
00319   * @param  pbuf: pointer to data
00320   * @param  length: number of sector to write
00321   * @retval USBH Status
00322   */
00323 USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost,
00324                                      uint8_t lun,
00325                                      uint32_t address,
00326                                      uint8_t *pbuf,
00327                                      uint32_t length)
00328 {
00329   USBH_StatusTypeDef    error = USBH_FAIL ;
00330 
00331   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00332   
00333   switch(MSC_Handle->hbot.cmd_state)
00334   {
00335   case BOT_CMD_SEND:  
00336     
00337     /*Prepare the CBW and relevent field*/
00338     MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
00339     MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT;
00340     MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
00341     
00342     USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
00343     MSC_Handle->hbot.cbw.field.CB[0]  = OPCODE_WRITE10; 
00344     
00345     /*logical block address*/
00346     MSC_Handle->hbot.cbw.field.CB[2]  = (((uint8_t*)&address)[3]);
00347     MSC_Handle->hbot.cbw.field.CB[3]  = (((uint8_t*)&address)[2]);
00348     MSC_Handle->hbot.cbw.field.CB[4]  = (((uint8_t*)&address)[1]);
00349     MSC_Handle->hbot.cbw.field.CB[5]  = (((uint8_t*)&address)[0]);
00350     
00351     
00352     /*Transfer length */
00353     MSC_Handle->hbot.cbw.field.CB[7]  = (((uint8_t *)&length)[1]) ; 
00354     MSC_Handle->hbot.cbw.field.CB[8]  = (((uint8_t *)&length)[0]) ; 
00355 
00356     
00357     MSC_Handle->hbot.state = BOT_SEND_CBW;
00358     MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
00359     MSC_Handle->hbot.pbuf = pbuf;
00360     error = USBH_BUSY; 
00361     break;
00362     
00363   case BOT_CMD_WAIT: 
00364     error = USBH_MSC_BOT_Process(phost, lun);
00365     break;
00366     
00367   default:
00368     break;
00369   }
00370   
00371   return error;
00372 }
00373 
00374 /**
00375   * @brief  USBH_MSC_SCSI_Read 
00376   *         Issue Read10 command.
00377   * @param  phost: Host handle
00378   * @param  lun: Logical Unit Number
00379   * @param  address: sector address
00380   * @param  pbuf: pointer to data
00381   * @param  length: number of sector to read
00382   * @retval USBH Status
00383   */
00384 USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost,
00385                                      uint8_t lun,
00386                                      uint32_t address,
00387                                      uint8_t *pbuf,
00388                                      uint32_t length)
00389 {
00390   USBH_StatusTypeDef    error = USBH_FAIL ;
00391   MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00392   
00393   switch(MSC_Handle->hbot.cmd_state)
00394   {
00395   case BOT_CMD_SEND:  
00396     
00397     /*Prepare the CBW and relevent field*/
00398     MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512;
00399     MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN;
00400     MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH;
00401     
00402     USBH_memset(MSC_Handle->hbot.cbw.field.CB, 0, CBW_CB_LENGTH);
00403     MSC_Handle->hbot.cbw.field.CB[0]  = OPCODE_READ10; 
00404     
00405     /*logical block address*/
00406     MSC_Handle->hbot.cbw.field.CB[2]  = (((uint8_t*)&address)[3]);
00407     MSC_Handle->hbot.cbw.field.CB[3]  = (((uint8_t*)&address)[2]);
00408     MSC_Handle->hbot.cbw.field.CB[4]  = (((uint8_t*)&address)[1]);
00409     MSC_Handle->hbot.cbw.field.CB[5]  = (((uint8_t*)&address)[0]);
00410     
00411     
00412     /*Transfer length */
00413     MSC_Handle->hbot.cbw.field.CB[7]  = (((uint8_t *)&length)[1]) ; 
00414     MSC_Handle->hbot.cbw.field.CB[8]  = (((uint8_t *)&length)[0]) ; 
00415 
00416     
00417     MSC_Handle->hbot.state = BOT_SEND_CBW;
00418     MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT;
00419     MSC_Handle->hbot.pbuf = pbuf;
00420     error = USBH_BUSY; 
00421     break;
00422     
00423   case BOT_CMD_WAIT: 
00424     error = USBH_MSC_BOT_Process(phost, lun);
00425     break;
00426     
00427   default:
00428     break;
00429   }
00430   
00431   return error;
00432 }
00433 
00434 
00435 /**
00436   * @}
00437   */ 
00438 
00439 /**
00440   * @}
00441   */ 
00442 
00443 /**
00444   * @}
00445   */
00446 
00447 /**
00448   * @}
00449   */ 
00450 
00451 /**
00452   * @}
00453   */
00454 
00455 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
00456 
00457 
00458