/** * @brief SCSI_Read10 * Process Read10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ { /* case 10 : Ho <> Di */ if ((hmsc->cbw.bmFlags & 0x80) != 0x80) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } hmsc->scsi_blk_addr = (params[2] << 24) | \ (params[3] << 16) | \ (params[4] << 8) | \ params[5]; hmsc->scsi_blk_len = (params[7] << 8) | \ params[8]; if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0) { return -1; /* error */ } hmsc->bot_state = USBD_BOT_DATA_IN; hmsc->scsi_blk_addr *= hmsc->scsi_blk_size; hmsc->scsi_blk_len *= hmsc->scsi_blk_size; /* cases 4,5 : Hi <> Dn */ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } } hmsc->bot_data_length = MSC_MEDIA_PACKET; return SCSI_ProcessRead(pdev, lun); }
/** * @brief SCSI_TestUnitReady * Process SCSI Test Unit Ready Command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; /* case 9 : Hi > D0 */ if (hmsc->cbw.dDataLength != 0) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); hmsc->bot_state = USBD_BOT_NO_DATA; return -1; } hmsc->bot_data_length = 0; return 0; }
/** * @brief SCSI_Read10 * Process Read10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_Read10(uint8_t lun , uint8_t *params) { if(MSC_BOT_State == BOT_IDLE) /* Idle */ { /* case 10 : Ho <> Di */ if ((MSC_BOT_cbw.bmFlags & 0x80) != 0x80) { SCSI_SenseCode(MSC_BOT_cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } if(USBD_STORAGE_fops->IsReady(lun) !=0 ) { SCSI_SenseCode(lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } SCSI_blk_addr = (params[2] << 24) | \ (params[3] << 16) | \ (params[4] << 8) | \ params[5]; SCSI_blk_len = (params[7] << 8) | \ params[8]; if( SCSI_CheckAddressRange(lun, SCSI_blk_addr, SCSI_blk_len) < 0) { return -1; /* error */ } MSC_BOT_State = BOT_DATA_IN; SCSI_blk_addr *= SCSI_blk_size; SCSI_blk_len *= SCSI_blk_size; /* cases 4,5 : Hi <> Dn */ if (MSC_BOT_cbw.dDataLength != SCSI_blk_len) { SCSI_SenseCode(MSC_BOT_cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } } MSC_BOT_DataLen = MSC_MEDIA_PACKET; return SCSI_ProcessRead(lun); }
// Process SCSI WRITE10 command // input: // pdev - pointer to the USB device handle // lun - logical unit number // params - pointer to the buffer with command parameters static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; if (hmsc->bot_state == USBD_BOT_IDLE) { // case 8 : Hi <> Do if (hmsc->cbw.bmFlags & 0x80) { SCSI_SenseCode(pdev,hmsc->cbw.bLUN,ILLEGAL_REQUEST,INVALID_CDB); return -1; } // Check whether media is ready if (((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) != 0) { SCSI_SenseCode(pdev,lun,NOT_READY,MEDIUM_NOT_PRESENT); return -1; } // Check if media is write-protected if (((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) != 0) { SCSI_SenseCode(pdev,lun,NOT_READY,WRITE_PROTECTED); return -1; } hmsc->scsi_blk_addr = (params[2] << 24) | (params[3] << 16) | (params[4] << 8) | params[5]; hmsc->scsi_blk_len = (params[7] << 8) | params[8]; // Check if LBA address is in the right range if (SCSI_CheckAddressRange(pdev,lun,hmsc->scsi_blk_addr,hmsc->scsi_blk_len) < 0) return -1; hmsc->scsi_blk_addr *= hmsc->scsi_blk_size; hmsc->scsi_blk_len *= hmsc->scsi_blk_size; // cases 3,11,13 : Hn,Ho <> D0 if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len) { SCSI_SenseCode(pdev,hmsc->cbw.bLUN,ILLEGAL_REQUEST,INVALID_CDB); return -1; } // Prepare endpoint to receive first data packet hmsc->bot_state = USBD_BOT_DATA_OUT; USBD_LL_PrepareReceive(pdev,MSC_EPOUT_ADDR,hmsc->bot_data,MIN(hmsc->scsi_blk_len,MSC_MEDIA_PACKET)); } else { // Write Process ongoing return SCSI_ProcessWrite(pdev,lun); } return 0; }
/** * @brief SCSI_CheckAddressRange * Check address range * @param lun: Logical unit number * @param blk_offset: first block address * @param blk_nbr: number of block to be processed * @retval status */ static int8_t SCSI_CheckAddressRange (uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr) { if (USBD_STORAGE_fops->GetCapacity(lun, &SCSI_blk_nbr, &SCSI_blk_size) != 0) { SCSI_SenseCode(lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } if ((blk_offset + blk_nbr) > SCSI_blk_nbr ) { SCSI_SenseCode(lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); return -1; } return 0; }
// Process SCSI READ FORMAT CAPACITY command // input: // pdev - pointer to the USB device handle // lun - logical unit number // params - pointer to the buffer with command parameters static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; uint16_t blk_size; uint32_t blk_nbr; uint16_t i; for (i = 0; i < 12; i++) hmsc->bot_data[i] = 0; if (((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun,&blk_nbr,&blk_size) != 0) { SCSI_SenseCode(pdev,lun,NOT_READY,MEDIUM_NOT_PRESENT); return -1; } else { hmsc->bot_data[3] = 0x08; hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1) >> 24); hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1) >> 16); hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1) >> 8); hmsc->bot_data[7] = (uint8_t)( blk_nbr - 1); hmsc->bot_data[8] = 0x02; hmsc->bot_data[9] = (uint8_t)(blk_size >> 16); hmsc->bot_data[10] = (uint8_t)(blk_size >> 8); hmsc->bot_data[11] = (uint8_t)(blk_size); hmsc->bot_data_length = 12; return 0; } }
/** * @brief SCSI_ReadFormatCapacity * Process Read Format Capacity command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t *params) { uint32_t blk_size; uint32_t blk_nbr; uint16_t i; for(i=0 ; i < 12 ; i++) { MSC_BOT_Data[i] = 0; } if(USBD_STORAGE_fops->GetCapacity(lun, &blk_nbr, &blk_size) != 0) { SCSI_SenseCode(lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } else { MSC_BOT_Data[3] = 0x08; MSC_BOT_Data[4] = (uint8_t)((blk_nbr - 1) >> 24); MSC_BOT_Data[5] = (uint8_t)((blk_nbr - 1) >> 16); MSC_BOT_Data[6] = (uint8_t)((blk_nbr - 1) >> 8); MSC_BOT_Data[7] = (uint8_t)(blk_nbr - 1); MSC_BOT_Data[8] = 0x02; MSC_BOT_Data[9] = (uint8_t)(blk_size >> 16); MSC_BOT_Data[10] = (uint8_t)(blk_size >> 8); MSC_BOT_Data[11] = (uint8_t)(blk_size); MSC_BOT_DataLen = 12; return 0; } }
/** * @brief SCSI_ReadCapacity10 * Process Read Capacity 10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } else { hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 24); hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 16); hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1) >> 8); hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1); hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24); hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16); hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8); hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size); hmsc->bot_data_length = 8; return 0; } }
// Process a SCSI command // input: // pdev - pointer to the USB device handle // lun - logical unit number // params - pointer to the buffer with command parameters int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { switch (params[0]) { case SCSI_TEST_UNIT_READY: return SCSI_TestUnitReady(pdev,lun,params); case SCSI_REQUEST_SENSE: return SCSI_RequestSense(pdev,lun,params); case SCSI_INQUIRY: return SCSI_Inquiry(pdev,lun,params); case SCSI_START_STOP_UNIT: return SCSI_StartStopUnit(pdev,lun,params); case SCSI_ALLOW_MEDIUM_REMOVAL: return SCSI_StartStopUnit(pdev,lun,params); case SCSI_MODE_SENSE6: return SCSI_ModeSense6(pdev,lun,params); case SCSI_MODE_SENSE10: return SCSI_ModeSense10(pdev,lun,params); case SCSI_READ_FORMAT_CAPACITIES: return SCSI_ReadFormatCapacity(pdev,lun,params); case SCSI_READ_CAPACITY10: return SCSI_ReadCapacity10(pdev,lun,params); case SCSI_READ10: return SCSI_Read10(pdev,lun,params); case SCSI_WRITE10: return SCSI_Write10(pdev,lun,params); case SCSI_VERIFY10: return SCSI_Verify10(pdev,lun,params); default: SCSI_SenseCode(pdev,lun,ILLEGAL_REQUEST,INVALID_CDB); return -1; } }
static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; if ((params[1]& 0x02) == 0x02) { SCSI_SenseCode (pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); return -1; /* Error, Verify Mode Not supported*/ } hmsc->scsi_blk_addr_in_blks = (params[2] << 24) | (params[3] << 16) | (params[4] << 8) | params[5]; hmsc->scsi_blk_len = (params[7] << 8) | params[8]; if(SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr_in_blks, hmsc->scsi_blk_len) < 0) { return -1; /* error */ } hmsc->bot_data_length = 0; return 0; }
static int8_t SCSI_ProcessWrite (uint8_t lun) { uint32_t len; len = MIN(SCSI_blk_len , MSC_MEDIA_PACKET); if(USBD_STORAGE_fops->Write(lun , MSC_BOT_Data, SCSI_blk_addr / SCSI_blk_size, len / SCSI_blk_size) < 0) { SCSI_SenseCode(lun, HARDWARE_ERROR, WRITE_FAULT); return -1; } // SCSI_blk_addr += len; // SCSI_blk_len -= len; // // /* case 12 : Ho = Do */ // MSC_BOT_csw.dDataResidue -= len; // // if (SCSI_blk_len == 0) // { // MSC_BOT_SendCSW (cdev, CSW_CMD_PASSED); // } // else // { // /* Prapare EP to Receive next packet */ // DCD_EP_PrepareRx (cdev, // MSC_OUT_EP, // MSC_BOT_Data, // MIN (SCSI_blk_len, MSC_MEDIA_PACKET)); // } return 0; }
// Handle write process // input: // pdev - pointer to the USB device handle // lun - logical unit number static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; uint32_t len; len = MIN(hmsc->scsi_blk_len,MSC_MEDIA_PACKET); if (((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun,hmsc->bot_data,hmsc->scsi_blk_addr / hmsc->scsi_blk_size,len / hmsc->scsi_blk_size) < 0) { SCSI_SenseCode(pdev,lun,HARDWARE_ERROR,WRITE_FAULT); return -1; } hmsc->scsi_blk_addr += len; hmsc->scsi_blk_len -= len; // case 12 : Ho = Do hmsc->csw.dDataResidue -= len; if (hmsc->scsi_blk_len == 0) { MSC_BOT_SendCSW(pdev,USBD_CSW_CMD_PASSED); } else { // Prepare endpoint to receive next packet USBD_LL_PrepareReceive(pdev,MSC_EPOUT_ADDR,hmsc->bot_data,MIN(hmsc->scsi_blk_len,MSC_MEDIA_PACKET)); } return 0; }
/** * @brief SCSI_ProcessRead * Handle Read Process * @param lun: Logical unit number * @retval status */ static int8_t SCSI_ProcessRead (uint8_t lun) { uint32_t len; len = MIN(SCSI_blk_len , MSC_MEDIA_PACKET); if( USBD_STORAGE_fops->Read(lun , MSC_BOT_Data, SCSI_blk_addr / SCSI_blk_size, len / SCSI_blk_size) < 0) { SCSI_SenseCode(lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); return -1; } DCD_EP_Tx (cdev, MSC_IN_EP, MSC_BOT_Data, len); SCSI_blk_addr += len; SCSI_blk_len -= len; /* case 6 : Hi = Di */ MSC_BOT_csw.dDataResidue -= len; if (SCSI_blk_len == 0) { MSC_BOT_State = BOT_LAST_DATA_IN; } return 0; }
/** * @brief SCSI_ReadCapacity10 * Process Read Capacity 10 command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t *params) { if(USBD_STORAGE_fops->GetCapacity(lun, &SCSI_blk_nbr, &SCSI_blk_size) != 0) { SCSI_SenseCode(lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } else { MSC_BOT_Data[0] = (uint8_t)((SCSI_blk_nbr - 1) >> 24); MSC_BOT_Data[1] = (uint8_t)((SCSI_blk_nbr - 1) >> 16); MSC_BOT_Data[2] = (uint8_t)((SCSI_blk_nbr - 1) >> 8); MSC_BOT_Data[3] = (uint8_t)(SCSI_blk_nbr - 1); MSC_BOT_Data[4] = (uint8_t)(SCSI_blk_size >> 24); MSC_BOT_Data[5] = (uint8_t)(SCSI_blk_size >> 16); MSC_BOT_Data[6] = (uint8_t)(SCSI_blk_size >> 8); MSC_BOT_Data[7] = (uint8_t)(SCSI_blk_size); MSC_BOT_DataLen = 8; return 0; } }
/** * @brief SCSI_ProcessCmd * Process SCSI commands * @param pdev: device instance * @param lun: Logical unit number * @param params: Command parameters * @retval status */ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { /* if (params[0] != SCSI_READ10 && params[0] != SCSI_WRITE10) { printf("SCSI_ProcessCmd(lun=%d, params=%x, %x)\n", lun, params[0], params[1]); } */ switch (params[0]) { case SCSI_TEST_UNIT_READY: return SCSI_TestUnitReady(pdev, lun, params); case SCSI_REQUEST_SENSE: return SCSI_RequestSense (pdev, lun, params); case SCSI_INQUIRY: return SCSI_Inquiry(pdev, lun, params); case SCSI_START_STOP_UNIT: return SCSI_StartStopUnit(pdev, lun, params); case SCSI_ALLOW_MEDIUM_REMOVAL: return SCSI_AllowMediumRemoval(pdev, lun, params); case SCSI_MODE_SENSE6: return SCSI_ModeSense6 (pdev, lun, params); case SCSI_MODE_SENSE10: return SCSI_ModeSense10 (pdev, lun, params); case SCSI_SYNCHRONIZE_CACHE10: case SCSI_SYNCHRONIZE_CACHE16: return SCSI_SynchronizeCache(pdev, lun, params); case SCSI_READ_FORMAT_CAPACITIES: return SCSI_ReadFormatCapacity(pdev, lun, params); case SCSI_READ_CAPACITY10: return SCSI_ReadCapacity10(pdev, lun, params); case SCSI_READ10: return SCSI_Read10(pdev, lun, params); case SCSI_WRITE10: return SCSI_Write10(pdev, lun, params); case SCSI_VERIFY10: return SCSI_Verify10(pdev, lun, params); default: SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); return -1; } }
/** * @brief SCSI_CheckAddressRange * Check address range * @param lun: Logical unit number * @param blk_offset: first block address * @param blk_nbr: number of block to be processed * @retval status */ static int8_t SCSI_CheckAddressRange (uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr) { if ((blk_offset + blk_nbr) > SCSI_blk_nbr ) { SCSI_SenseCode(lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); return -1; } return 0; }
/** * @brief MSC_BOT_CBW_Decode * Decode the CBW command and set the BOT state machine accordingtly * @param pdev: device instance * @retval None */ static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev) { USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; hmsc->csw.dTag = hmsc->cbw.dTag; hmsc->csw.dDataResidue = hmsc->cbw.dDataLength; if ((USBD_LL_GetRxDataSize (pdev ,MSC_EPOUT_ADDR) != USBD_BOT_CBW_LENGTH) || (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE)|| (hmsc->cbw.bLUN > 1) || (hmsc->cbw.bCBLength < 1) || (hmsc->cbw.bCBLength > 16)) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); hmsc->bot_status = USBD_BOT_STATUS_ERROR; MSC_BOT_Abort(pdev); } else { if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0) { if(hmsc->bot_state == USBD_BOT_NO_DATA) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED); } else { MSC_BOT_Abort(pdev); } } /*Burst xfer handled internally*/ else if ((hmsc->bot_state != USBD_BOT_DATA_IN) && (hmsc->bot_state != USBD_BOT_DATA_OUT) && (hmsc->bot_state != USBD_BOT_LAST_DATA_IN)) { if (hmsc->bot_data_length > 0) { MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length); } else if (hmsc->bot_data_length == 0) { MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED); } } } }
/** * @brief SCSI_TestUnitReady * Process SCSI Test Unit Ready Command * @param lun: Logical unit number * @param params: Command parameters * @retval status */ static int8_t SCSI_TestUnitReady(uint8_t lun, uint8_t *params) { /* case 9 : Hi > D0 */ if (MSC_BOT_cbw.dDataLength != 0) { SCSI_SenseCode(MSC_BOT_cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } if(USBD_STORAGE_fops->IsReady(lun) !=0 ) { SCSI_SenseCode(lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } MSC_BOT_DataLen = 0; return 0; }
// Check address range // input: // pdev - pointer to the USB device handle // lun - logical unit number // blk_offset - first block address // blk_nbr - number of blocks to be processed static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr) { SCSI_SenseCode(pdev,lun,ILLEGAL_REQUEST,ADDRESS_OUT_OF_RANGE); return -1; } return 0; }
static int8_t SCSI_Verify10(uint8_t lun , uint8_t *params) { if ((params[1]& 0x02) == 0x02) { SCSI_SenseCode (lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); return -1; /* Error, Verify Mode Not supported*/ } if(SCSI_CheckAddressRange(lun, SCSI_blk_addr, SCSI_blk_len) < 0) { return -1; /* error */ } MSC_BOT_DataLen = 0; return 0; }
// Process SCSI VERIFY10 command // input: // pdev - pointer to the USB device handle // lun - logical unit number // params - pointer to the buffer with command parameters static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; if ((params[1]& 0x02) == 0x02) { SCSI_SenseCode(pdev,lun,ILLEGAL_REQUEST,INVALID_FIELED_IN_COMMAND); return -1; // Error, verify mode not supported } // Check address range if(SCSI_CheckAddressRange(pdev,lun,hmsc->scsi_blk_addr,hmsc->scsi_blk_len) < 0) return -1; hmsc->bot_data_length = 0; return 0; }
/** * @brief MSC_BOT_CBW_Decode * Decode the CBW command and set the BOT state machine accordingtly * @param pdev: device instance * @retval None */ static void MSC_BOT_CBW_Decode (USB_OTG_CORE_HANDLE *pdev) { MSC_BOT_csw.dTag = MSC_BOT_cbw.dTag; MSC_BOT_csw.dDataResidue = MSC_BOT_cbw.dDataLength; if ((USBD_GetRxCount (pdev ,MSC_OUT_EP) != BOT_CBW_LENGTH) || (MSC_BOT_cbw.dSignature != BOT_CBW_SIGNATURE)|| (MSC_BOT_cbw.bLUN > 1) || (MSC_BOT_cbw.bCBLength < 1) || (MSC_BOT_cbw.bCBLength > 16)) { SCSI_SenseCode(MSC_BOT_cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); MSC_BOT_Status = BOT_STATE_ERROR; MSC_BOT_Abort(pdev); } else { if(SCSI_ProcessCmd(pdev, MSC_BOT_cbw.bLUN, &MSC_BOT_cbw.CB[0]) < 0) { MSC_BOT_Abort(pdev); } /*Burst xfer handled internally*/ else if ((MSC_BOT_State != BOT_DATA_IN) && (MSC_BOT_State != BOT_DATA_OUT) && (MSC_BOT_State != BOT_LAST_DATA_IN)) { if (MSC_BOT_DataLen > 0) { MSC_BOT_SendData(pdev, MSC_BOT_Data, MSC_BOT_DataLen); } else if (MSC_BOT_DataLen == 0) { MSC_BOT_SendCSW (pdev, CSW_CMD_PASSED); } } } }
// Handle read process // input: // pdev - pointer to the USB device handle // lun - logical unit number static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun) { USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; uint32_t len; len = MIN(hmsc->scsi_blk_len,MSC_MEDIA_PACKET); if (((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun,hmsc->bot_data,hmsc->scsi_blk_addr / hmsc->scsi_blk_size,len / hmsc->scsi_blk_size) < 0) { SCSI_SenseCode(pdev,lun,HARDWARE_ERROR,UNRECOVERED_READ_ERROR); return -1; } USBD_LL_Transmit(pdev,MSC_EPIN_ADDR,hmsc->bot_data,len); hmsc->scsi_blk_addr += len; hmsc->scsi_blk_len -= len; // case 6 : Hi = Di hmsc->csw.dDataResidue -= len; if (hmsc->scsi_blk_len == 0) hmsc->bot_state = USBD_BOT_LAST_DATA_IN; return 0; }
static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ { /* case 8 : Hi <> Do */ if ((hmsc->cbw.bmFlags & 0x80) == 0x80) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } /* Check whether Media is ready */ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } /* Check If media is write-protected */ if(((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) !=0 ) { SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED); return -1; } hmsc->scsi_blk_addr_in_blks = (params[2] << 24) | \ (params[3] << 16) | \ (params[4] << 8) | \ params[5]; hmsc->scsi_blk_len = (params[7] << 8) | \ params[8]; /* check if LBA address is in the right range */ if(SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr_in_blks, hmsc->scsi_blk_len) < 0) { return -1; /* error */ } hmsc->scsi_blk_len *= hmsc->scsi_blk_size; /* cases 3,11,13 : Hn,Ho <> D0 */ if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len) { SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } /* Prepare EP to receive first data packet */ hmsc->bot_state = USBD_BOT_DATA_OUT; USBD_LL_PrepareReceive (pdev, MSC_OUT_EP, hmsc->bot_data, MIN (hmsc->scsi_blk_len, MSC_MEDIA_PACKET)); } else /* Write Process ongoing */ { return SCSI_ProcessWrite(pdev, lun); } return 0; }
static int8_t SCSI_Write10 (uint8_t lun , uint8_t *params) { if (MSC_BOT_State == BOT_IDLE) /* Idle */ { /* case 8 : Hi <> Do */ if ((MSC_BOT_cbw.bmFlags & 0x80) == 0x80) { SCSI_SenseCode(MSC_BOT_cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } /* Check whether Media is ready */ if(USBD_STORAGE_fops->IsReady(lun) !=0 ) { SCSI_SenseCode(lun, NOT_READY, MEDIUM_NOT_PRESENT); return -1; } /* Check If media is write-protected */ if(USBD_STORAGE_fops->IsWriteProtected(lun) !=0 ) { SCSI_SenseCode(lun, NOT_READY, WRITE_PROTECTED); return -1; } SCSI_blk_addr = (params[2] << 24) | \ (params[3] << 16) | \ (params[4] << 8) | \ params[5]; SCSI_blk_len = (params[7] << 8) | \ params[8]; /* check if LBA address is in the right range */ if(SCSI_CheckAddressRange(lun, SCSI_blk_addr, SCSI_blk_len) < 0) { return -1; /* error */ } SCSI_blk_addr *= SCSI_blk_size; SCSI_blk_len *= SCSI_blk_size; /* cases 3,11,13 : Hn,Ho <> D0 */ if (MSC_BOT_cbw.dDataLength != SCSI_blk_len) { SCSI_SenseCode(MSC_BOT_cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); return -1; } /* Prepare EP to receive first data packet */ MSC_BOT_State = BOT_DATA_OUT; DCD_EP_PrepareRx (cdev, MSC_OUT_EP, MSC_BOT_Data, MIN (SCSI_blk_len, MSC_MEDIA_PACKET)); } else /* Write Process ongoing */ { return SCSI_ProcessWrite(lun); } return 0; }