Files
AT32F415_Firmware_Library/middlewares/usbd_class/msc/msc_bot_scsi.c

826 lines
23 KiB
C
Raw Normal View History

2021-12-14 13:34:31 +08:00
/**
**************************************************************************
* @file msc_bot_scsi.c
* @brief usb mass storage bulk-only transport and scsi command
**************************************************************************
2025-11-27 18:19:48 +08:00
*
* Copyright (c) 2025, Artery Technology, All rights reserved.
2021-12-14 13:34:31 +08:00
*
2022-04-11 19:32:28 +08:00
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
2021-12-14 13:34:31 +08:00
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
#include "msc_bot_scsi.h"
#include "msc_diskio.h"
/** @addtogroup AT32F415_middlewares_usbd_class
* @{
*/
/** @defgroup USB_msc_bot_scsi
* @brief usb device class mass storage demo
* @{
2022-04-11 19:32:28 +08:00
*/
2021-12-14 13:34:31 +08:00
/** @defgroup USB_msc_bot_functions
* @{
*/
2022-01-21 15:54:53 +08:00
#if defined ( __ICCARM__ ) /* iar compiler */
#pragma data_alignment=4
#endif
ALIGNED_HEAD uint8_t page00_inquiry_data[] ALIGNED_TAIL = {
2023-08-08 19:30:55 +08:00
0x00,
0x00,
0x00,
0x00,
0x00,
2021-12-14 13:34:31 +08:00
};
2022-01-21 15:54:53 +08:00
#if defined ( __ICCARM__ ) /* iar compiler */
#pragma data_alignment=4
#endif
ALIGNED_HEAD sense_type sense_data ALIGNED_TAIL =
2021-12-14 13:34:31 +08:00
{
0x70,
0x00,
SENSE_KEY_ILLEGAL_REQUEST,
0x00000000,
0x0A,
0x00000000,
0x20,
0x00,
0x00000000
};
2022-01-21 15:54:53 +08:00
#if defined ( __ICCARM__ ) /* iar compiler */
#pragma data_alignment=4
#endif
2022-04-11 19:32:28 +08:00
ALIGNED_HEAD uint8_t mode_sense6_data[8] ALIGNED_TAIL =
2021-12-14 13:34:31 +08:00
{
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
2022-01-21 15:54:53 +08:00
#if defined ( __ICCARM__ ) /* iar compiler */
#pragma data_alignment=4
#endif
2022-04-11 19:32:28 +08:00
ALIGNED_HEAD uint8_t mode_sense10_data[8] ALIGNED_TAIL =
2021-12-14 13:34:31 +08:00
{
0x00,
0x06,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
/**
* @brief initialize bulk-only transport and scsi
* @param udev: to the structure of usbd_core_type
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_init(void *udev)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
pmsc->msc_state = MSC_STATE_MACHINE_IDLE;
pmsc->bot_status = MSC_BOT_STATE_IDLE;
pmsc->max_lun = MSC_SUPPORT_MAX_LUN - 1;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->csw_struct.dCSWSignature = CSW_DCSWSIGNATURE;
pmsc->csw_struct.dCSWDataResidue = 0;
pmsc->csw_struct.dCSWSignature = 0;
pmsc->csw_struct.dCSWTag = CSW_BCSWSTATUS_PASS;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
usbd_flush_tx_fifo(pudev, USBD_MSC_BULK_IN_EPT&0x7F);
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
/* set out endpoint to receive status */
2022-03-03 19:38:35 +08:00
usbd_ept_recv(pudev, USBD_MSC_BULK_OUT_EPT, (uint8_t *)&pmsc->cbw_struct, CBW_CMD_LENGTH);
2021-12-14 13:34:31 +08:00
}
/**
* @brief reset bulk-only transport and scsi
* @param udev: to the structure of usbd_core_type
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_reset(void *udev)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
pmsc->msc_state = MSC_STATE_MACHINE_IDLE;
pmsc->bot_status = MSC_BOT_STATE_RECOVERY;
pmsc->max_lun = MSC_SUPPORT_MAX_LUN - 1;
usbd_flush_tx_fifo(pudev, USBD_MSC_BULK_IN_EPT&0x7F);
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
/* set out endpoint to receive status */
2022-03-03 19:38:35 +08:00
usbd_ept_recv(pudev, USBD_MSC_BULK_OUT_EPT, (uint8_t *)&pmsc->cbw_struct, CBW_CMD_LENGTH);
2021-12-14 13:34:31 +08:00
}
/**
* @brief bulk-only transport data in handler
* @param udev: to the structure of usbd_core_type
* @param ept_num: endpoint number
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_datain_handler(void *udev, uint8_t ept_num)
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
switch(pmsc->msc_state)
2021-12-14 13:34:31 +08:00
{
case MSC_STATE_MACHINE_DATA_IN:
if(bot_scsi_cmd_process(udev) != USB_OK)
{
bot_scsi_send_csw(udev, CSW_BCSWSTATUS_FAILED);
}
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_STATE_MACHINE_LAST_DATA:
case MSC_STATE_MACHINE_SEND_DATA:
bot_scsi_send_csw(udev, CSW_BCSWSTATUS_PASS);
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
default:
break;
}
}
/**
* @brief bulk-only transport data out handler
* @param udev: to the structure of usbd_core_type
* @param ept_num: endpoint number
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_dataout_handler(void *udev, uint8_t ept_num)
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
switch(pmsc->msc_state)
2021-12-14 13:34:31 +08:00
{
case MSC_STATE_MACHINE_IDLE:
bot_cbw_decode(udev);
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_STATE_MACHINE_DATA_OUT:
if(bot_scsi_cmd_process(udev) != USB_OK)
{
bot_scsi_send_csw(udev, CSW_BCSWSTATUS_FAILED);
}
break;
}
}
/**
* @brief bulk-only cbw decode
* @param udev: to the structure of usbd_core_type
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_cbw_decode(void *udev)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->csw_struct.dCSWTag = pmsc->cbw_struct.dCBWTage;
pmsc->csw_struct.dCSWDataResidue = pmsc->cbw_struct.dCBWDataTransferLength;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
/* check param */
2022-03-03 19:38:35 +08:00
if((pmsc->cbw_struct.dCBWSignature != CBW_DCBWSIGNATURE) ||
2021-12-14 13:34:31 +08:00
(usbd_get_recv_len(pudev, USBD_MSC_BULK_OUT_EPT) != CBW_CMD_LENGTH)
2022-03-03 19:38:35 +08:00
|| (pmsc->cbw_struct.bCBWLUN > MSC_SUPPORT_MAX_LUN) ||
(pmsc->cbw_struct.bCBWCBLength < 1) || (pmsc->cbw_struct.bCBWCBLength > 16))
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND);
2022-03-03 19:38:35 +08:00
pmsc->bot_status = MSC_BOT_STATE_ERROR;
2021-12-14 13:34:31 +08:00
bot_scsi_stall(udev);
}
else
{
if(bot_scsi_cmd_process(udev) != USB_OK)
{
bot_scsi_stall(udev);
}
2022-03-03 19:38:35 +08:00
else if((pmsc->msc_state != MSC_STATE_MACHINE_DATA_IN) &&
(pmsc->msc_state != MSC_STATE_MACHINE_DATA_OUT) &&
(pmsc->msc_state != MSC_STATE_MACHINE_LAST_DATA))
2021-12-14 13:34:31 +08:00
{
2022-03-03 19:38:35 +08:00
if(pmsc->data_len == 0)
2021-12-14 13:34:31 +08:00
{
bot_scsi_send_csw(udev, CSW_BCSWSTATUS_PASS);
}
2022-03-03 19:38:35 +08:00
else if(pmsc->data_len > 0)
2021-12-14 13:34:31 +08:00
{
2022-03-03 19:38:35 +08:00
bot_scsi_send_data(udev, pmsc->data, pmsc->data_len);
2021-12-14 13:34:31 +08:00
}
}
}
}
/**
* @brief send bot data
* @param udev: to the structure of usbd_core_type
* @param buffer: data buffer
* @param len: data len
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_send_data(void *udev, uint8_t *buffer, uint32_t len)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
uint32_t data_len = MIN(len, pmsc->cbw_struct.dCBWDataTransferLength);
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->csw_struct.dCSWDataResidue -= data_len;
pmsc->csw_struct.bCSWStatus = CSW_BCSWSTATUS_PASS;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->msc_state = MSC_STATE_MACHINE_SEND_DATA;
2022-04-11 19:32:28 +08:00
usbd_ept_send(pudev, USBD_MSC_BULK_IN_EPT,
2021-12-14 13:34:31 +08:00
buffer, data_len);
}
/**
* @brief send command status
* @param udev: to the structure of usbd_core_type
* @param status: csw status
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_send_csw(void *udev, uint8_t status)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->csw_struct.bCSWStatus = status;
pmsc->csw_struct.dCSWSignature = CSW_DCSWSIGNATURE;
pmsc->msc_state = MSC_STATE_MACHINE_IDLE;
2022-04-11 19:32:28 +08:00
usbd_ept_send(pudev, USBD_MSC_BULK_IN_EPT,
2022-03-03 19:38:35 +08:00
(uint8_t *)&pmsc->csw_struct, CSW_CMD_LENGTH);
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
usbd_ept_recv(pudev, USBD_MSC_BULK_OUT_EPT,
2022-03-03 19:38:35 +08:00
(uint8_t *)&pmsc->cbw_struct, CBW_CMD_LENGTH);
2021-12-14 13:34:31 +08:00
}
/**
* @brief send scsi sense code
* @param udev: to the structure of usbd_core_type
* @param sense_key: sense key
* @param asc: asc
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_sense_code(void *udev, uint8_t sense_key, uint8_t asc)
{
sense_data.sense_key = sense_key;
sense_data.asc = asc;
}
/**
* @brief check address
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
* @param blk_offset: blk offset address
* @param blk_count: blk number
2022-04-11 19:32:28 +08:00
* @retval usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_check_address(void *udev, uint8_t lun, uint32_t blk_offset, uint32_t blk_count)
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
if((blk_offset + blk_count) > pmsc->blk_nbr[lun])
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE);
return USB_FAIL;
}
return USB_OK;
}
/**
* @brief bot endpoint stall
* @param udev: to the structure of usbd_core_type
2022-04-11 19:32:28 +08:00
* @retval none
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_stall(void *udev)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if((pmsc->cbw_struct.dCBWDataTransferLength != 0) &&
(pmsc->cbw_struct.bmCBWFlags == 0) &&
pmsc->bot_status == MSC_BOT_STATE_IDLE)
2021-12-14 13:34:31 +08:00
{
usbd_set_stall(pudev, USBD_MSC_BULK_OUT_EPT);
}
usbd_set_stall(pudev, USBD_MSC_BULK_IN_EPT);
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->bot_status == MSC_BOT_STATE_ERROR)
2021-12-14 13:34:31 +08:00
{
2022-04-11 19:32:28 +08:00
usbd_ept_recv(pudev, USBD_MSC_BULK_OUT_EPT,
2022-03-03 19:38:35 +08:00
(uint8_t *)&pmsc->cbw_struct, CBW_CMD_LENGTH);
2021-12-14 13:34:31 +08:00
}
}
/**
* @brief bulk-only transport scsi command test unit
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_test_unit(void *udev, uint8_t lun)
{
usb_sts_type status = USB_OK;
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->cbw_struct.dCBWDataTransferLength != 0)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND);
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->data_len = 0;
2021-12-14 13:34:31 +08:00
return status;
}
/**
* @brief bulk-only transport scsi command inquiry
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_inquiry(void *udev, uint8_t lun)
{
uint8_t *pdata;
uint32_t trans_len = 0;
usb_sts_type status = USB_OK;
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->cbw_struct.CBWCB[1] & 0x01)
2021-12-14 13:34:31 +08:00
{
pdata = page00_inquiry_data;
trans_len = 5;
}
else
{
pdata = get_inquiry(lun);
2022-03-03 19:38:35 +08:00
if(pmsc->cbw_struct.dCBWDataTransferLength < SCSI_INQUIRY_DATA_LENGTH)
2021-12-14 13:34:31 +08:00
{
2022-03-03 19:38:35 +08:00
trans_len = pmsc->cbw_struct.dCBWDataTransferLength;
2021-12-14 13:34:31 +08:00
}
else
{
trans_len = SCSI_INQUIRY_DATA_LENGTH;
}
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->data_len = trans_len;
2021-12-14 13:34:31 +08:00
while(trans_len)
{
trans_len --;
2022-03-03 19:38:35 +08:00
pmsc->data[trans_len] = pdata[trans_len];
2021-12-14 13:34:31 +08:00
}
return status;
}
/**
* @brief bulk-only transport scsi command start stop
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_start_stop(void *udev, uint8_t lun)
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
pmsc->data_len = 0;
2021-12-14 13:34:31 +08:00
return USB_OK;
}
/**
* @brief bulk-only transport scsi command meidum removal
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_allow_medium_removal(void *udev, uint8_t lun)
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
pmsc->data_len = 0;
2021-12-14 13:34:31 +08:00
return USB_OK;
}
/**
* @brief bulk-only transport scsi command mode sense6
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_mode_sense6(void *udev, uint8_t lun)
{
uint8_t data_len = 8;
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
pmsc->data_len = 8;
2021-12-14 13:34:31 +08:00
while(data_len)
{
data_len --;
2022-03-03 19:38:35 +08:00
pmsc->data[data_len] = mode_sense6_data[data_len];
2021-12-14 13:34:31 +08:00
};
return USB_OK;
}
/**
* @brief bulk-only transport scsi command mode sense10
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_mode_sense10(void *udev, uint8_t lun)
{
uint8_t data_len = 8;
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
pmsc->data_len = 8;
2021-12-14 13:34:31 +08:00
while(data_len)
{
data_len --;
2022-03-03 19:38:35 +08:00
pmsc->data[data_len] = mode_sense10_data[data_len];
2021-12-14 13:34:31 +08:00
};
return USB_OK;
}
/**
* @brief bulk-only transport scsi command capacity
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_capacity(void *udev, uint8_t lun)
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
uint8_t *pdata = pmsc->data;
msc_disk_capacity(lun, &pmsc->blk_nbr[lun], &pmsc->blk_size[lun]);
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pdata[0] = (uint8_t)((pmsc->blk_nbr[lun] - 1) >> 24);
pdata[1] = (uint8_t)((pmsc->blk_nbr[lun] - 1) >> 16);
pdata[2] = (uint8_t)((pmsc->blk_nbr[lun] - 1) >> 8);
pdata[3] = (uint8_t)((pmsc->blk_nbr[lun] - 1));
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pdata[4] = (uint8_t)((pmsc->blk_size[lun]) >> 24);
pdata[5] = (uint8_t)((pmsc->blk_size[lun]) >> 16);
pdata[6] = (uint8_t)((pmsc->blk_size[lun]) >> 8);
pdata[7] = (uint8_t)((pmsc->blk_size[lun]));
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->data_len = 8;
2021-12-14 13:34:31 +08:00
return USB_OK;
}
/**
* @brief bulk-only transport scsi command format capacity
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_format_capacity(void *udev, uint8_t lun)
2022-04-11 19:32:28 +08:00
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
uint8_t *pdata = pmsc->data;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
pdata[0] = 0;
pdata[1] = 0;
pdata[2] = 0;
pdata[3] = 0x08;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
msc_disk_capacity(lun, &pmsc->blk_nbr[lun], &pmsc->blk_size[lun]);
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pdata[4] = (uint8_t)((pmsc->blk_nbr[lun] - 1) >> 24);
pdata[5] = (uint8_t)((pmsc->blk_nbr[lun] - 1) >> 16);
pdata[6] = (uint8_t)((pmsc->blk_nbr[lun] - 1) >> 8);
pdata[7] = (uint8_t)((pmsc->blk_nbr[lun] - 1));
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
pdata[8] = 0x02;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pdata[9] = (uint8_t)((pmsc->blk_size[lun]) >> 16);
pdata[10] = (uint8_t)((pmsc->blk_size[lun]) >> 8);
pdata[11] = (uint8_t)((pmsc->blk_size[lun]));
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->data_len = 12;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
return USB_OK;
}
/**
* @brief bulk-only transport scsi command request sense
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_request_sense(void *udev, uint8_t lun)
{
uint32_t trans_len = 0x12;
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
uint8_t *pdata = pmsc->data;
2021-12-14 13:34:31 +08:00
uint8_t *sdata = (uint8_t *)&sense_data;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
while(trans_len)
{
trans_len --;
pdata[trans_len] = sdata[trans_len];
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->cbw_struct.dCBWDataTransferLength < REQ_SENSE_STANDARD_DATA_LEN)
2021-12-14 13:34:31 +08:00
{
2022-03-03 19:38:35 +08:00
pmsc->data_len = pmsc->cbw_struct.dCBWDataTransferLength;
2021-12-14 13:34:31 +08:00
}
else
{
2022-03-03 19:38:35 +08:00
pmsc->data_len = REQ_SENSE_STANDARD_DATA_LEN;
2021-12-14 13:34:31 +08:00
}
return USB_OK;
}
/**
* @brief bulk-only transport scsi command verify
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_verify(void *udev, uint8_t lun)
{
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
uint8_t *cmd = pmsc->cbw_struct.CBWCB;
if((pmsc->cbw_struct.CBWCB[1] & 0x02) == 0x02)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->blk_addr = cmd[2] << 24 | cmd[3] << 16 | cmd[4] << 8 | cmd[5];
pmsc->blk_len = cmd[7] << 8 | cmd[8];
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(bot_scsi_check_address(udev, lun, pmsc->blk_addr, pmsc->blk_len) != USB_OK)
2021-12-14 13:34:31 +08:00
{
return USB_FAIL;
}
2022-03-03 19:38:35 +08:00
pmsc->data_len = 0;
2021-12-14 13:34:31 +08:00
return USB_OK;
}
/**
* @brief bulk-only transport scsi command read10
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_read10(void *udev, uint8_t lun)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
uint8_t *cmd = pmsc->cbw_struct.CBWCB;
2021-12-14 13:34:31 +08:00
uint32_t len;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->msc_state == MSC_STATE_MACHINE_IDLE)
2021-12-14 13:34:31 +08:00
{
2022-03-03 19:38:35 +08:00
if((pmsc->cbw_struct.bmCBWFlags & 0x80) != 0x80)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND);
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->blk_addr = cmd[2] << 24 | cmd[3] << 16 | cmd[4] << 8 | cmd[5];
pmsc->blk_len = cmd[7] << 8 | cmd[8];
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(bot_scsi_check_address(udev, lun, pmsc->blk_addr, pmsc->blk_len) != USB_OK)
2021-12-14 13:34:31 +08:00
{
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->blk_addr *= pmsc->blk_size[lun];
pmsc->blk_len *= pmsc->blk_size[lun];
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->cbw_struct.dCBWDataTransferLength != pmsc->blk_len)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND);
return USB_FAIL;
}
2022-03-03 19:38:35 +08:00
pmsc->msc_state = MSC_STATE_MACHINE_DATA_IN;
2021-12-14 13:34:31 +08:00
}
2022-03-03 19:38:35 +08:00
pmsc->data_len = MSC_MAX_DATA_BUF_LEN;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
len = MIN(pmsc->blk_len, MSC_MAX_DATA_BUF_LEN);
if( msc_disk_read(lun, pmsc->blk_addr, pmsc->data, len) != USB_OK)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_HARDWARE_ERROR, MEDIUM_NOT_PRESENT);
return USB_FAIL;
}
2022-03-03 19:38:35 +08:00
usbd_ept_send(pudev, USBD_MSC_BULK_IN_EPT, pmsc->data, len);
pmsc->blk_addr += len;
pmsc->blk_len -= len;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->csw_struct.dCSWDataResidue -= len;
if(pmsc->blk_len == 0)
2021-12-14 13:34:31 +08:00
{
2022-03-03 19:38:35 +08:00
pmsc->msc_state = MSC_STATE_MACHINE_LAST_DATA;
2021-12-14 13:34:31 +08:00
}
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
return USB_OK;
}
/**
* @brief bulk-only transport scsi command write10
* @param udev: to the structure of usbd_core_type
* @param lun: logical units number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_write10(void *udev, uint8_t lun)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
uint8_t *cmd = pmsc->cbw_struct.CBWCB;
2021-12-14 13:34:31 +08:00
uint32_t len;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->msc_state == MSC_STATE_MACHINE_IDLE)
2021-12-14 13:34:31 +08:00
{
2022-03-03 19:38:35 +08:00
if((pmsc->cbw_struct.bmCBWFlags & 0x80) == 0x80)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND);
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->blk_addr = cmd[2] << 24 | cmd[3] << 16 | cmd[4] << 8 | cmd[5];
pmsc->blk_len = cmd[7] << 8 | cmd[8];
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(bot_scsi_check_address(udev, lun, pmsc->blk_addr, pmsc->blk_len) != USB_OK)
2021-12-14 13:34:31 +08:00
{
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->blk_addr *= pmsc->blk_size[lun];
pmsc->blk_len *= pmsc->blk_size[lun];
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->cbw_struct.dCBWDataTransferLength != pmsc->blk_len)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND);
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->msc_state = MSC_STATE_MACHINE_DATA_OUT;
len = MIN(pmsc->blk_len, MSC_MAX_DATA_BUF_LEN);
usbd_ept_recv(pudev, USBD_MSC_BULK_OUT_EPT, (uint8_t *)pmsc->data, len);
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
}
else
{
2022-03-03 19:38:35 +08:00
len = MIN(pmsc->blk_len, MSC_MAX_DATA_BUF_LEN);
if(msc_disk_write(lun, pmsc->blk_addr, pmsc->data, len) != USB_OK)
2021-12-14 13:34:31 +08:00
{
bot_scsi_sense_code(udev, SENSE_KEY_HARDWARE_ERROR, MEDIUM_NOT_PRESENT);
return USB_FAIL;
}
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->blk_addr += len;
pmsc->blk_len -= len;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
pmsc->csw_struct.dCSWDataResidue -= len;
2022-04-11 19:32:28 +08:00
2022-03-03 19:38:35 +08:00
if(pmsc->blk_len == 0)
2021-12-14 13:34:31 +08:00
{
bot_scsi_send_csw(udev, CSW_BCSWSTATUS_PASS);
}
else
{
2022-03-03 19:38:35 +08:00
len = MIN(pmsc->blk_len, MSC_MAX_DATA_BUF_LEN);
usbd_ept_recv(pudev, USBD_MSC_BULK_OUT_EPT, (uint8_t *)pmsc->data, len);
2021-12-14 13:34:31 +08:00
}
}
return USB_OK;
}
/**
* @brief clear feature
* @param udev: to the structure of usbd_core_type
* @param etp_num: endpoint number
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
void bot_scsi_clear_feature(void *udev, uint8_t ept_num)
{
usbd_core_type *pudev = (usbd_core_type *)udev;
2022-03-03 19:38:35 +08:00
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
if(pmsc->bot_status == MSC_BOT_STATE_ERROR)
2021-12-14 13:34:31 +08:00
{
usbd_set_stall(pudev, USBD_MSC_BULK_IN_EPT);
2022-03-03 19:38:35 +08:00
pmsc->bot_status = MSC_BOT_STATE_IDLE;
2021-12-14 13:34:31 +08:00
}
2022-03-03 19:38:35 +08:00
else if(((ept_num & 0x80) == 0x80) && (pmsc->bot_status != MSC_BOT_STATE_RECOVERY))
2021-12-14 13:34:31 +08:00
{
bot_scsi_send_csw(udev, CSW_BCSWSTATUS_FAILED);
}
}
/**
* @brief bulk-only transport scsi command process
* @param udev: to the structure of usbd_core_type
2022-04-11 19:32:28 +08:00
* @retval status of usb_sts_type
2021-12-14 13:34:31 +08:00
*/
usb_sts_type bot_scsi_cmd_process(void *udev)
{
usb_sts_type status = USB_FAIL;
2022-03-03 19:38:35 +08:00
usbd_core_type *pudev = (usbd_core_type *)udev;
msc_type *pmsc = (msc_type *)pudev->class_handler->pdata;
switch(pmsc->cbw_struct.CBWCB[0])
2021-12-14 13:34:31 +08:00
{
case MSC_CMD_INQUIRY:
2022-03-03 19:38:35 +08:00
status = bot_scsi_inquiry(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_START_STOP:
2022-03-03 19:38:35 +08:00
status = bot_scsi_start_stop(udev, pmsc->cbw_struct.bCBWLUN);
2022-04-11 19:32:28 +08:00
break;
2021-12-14 13:34:31 +08:00
case MSC_CMD_MODE_SENSE6:
2022-03-03 19:38:35 +08:00
status = bot_scsi_mode_sense6(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_MODE_SENSE10:
2022-03-03 19:38:35 +08:00
status = bot_scsi_mode_sense10(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_ALLOW_MEDIUM_REMOVAL:
2022-03-03 19:38:35 +08:00
status = bot_scsi_allow_medium_removal(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_READ_10:
2022-03-03 19:38:35 +08:00
status = bot_scsi_read10(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_READ_CAPACITY:
2022-03-03 19:38:35 +08:00
status = bot_scsi_capacity(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_REQUEST_SENSE:
2022-03-03 19:38:35 +08:00
status = bot_scsi_request_sense(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_TEST_UNIT:
2022-03-03 19:38:35 +08:00
status = bot_scsi_test_unit(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_VERIFY:
2022-03-03 19:38:35 +08:00
status = bot_scsi_verify(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_WRITE_10:
2022-03-03 19:38:35 +08:00
status = bot_scsi_write10(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
case MSC_CMD_READ_FORMAT_CAPACITY:
2022-03-03 19:38:35 +08:00
status = bot_scsi_format_capacity(udev, pmsc->cbw_struct.bCBWLUN);
2021-12-14 13:34:31 +08:00
break;
2022-04-11 19:32:28 +08:00
2021-12-14 13:34:31 +08:00
default:
bot_scsi_sense_code(udev, SENSE_KEY_ILLEGAL_REQUEST, INVALID_COMMAND);
status = USB_FAIL;
break;
}
return status;
}
/**
* @}
2022-04-11 19:32:28 +08:00
*/
2021-12-14 13:34:31 +08:00
/**
* @}
*/
/**
* @}
*/