| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781 |
- /*!
- \file usbd_msc_scsi.c
- \brief USB SCSI layer functions
- \version 2020-08-01, V3.0.0, firmware for GD32F4xx
- \version 2022-03-09, V3.1.0, firmware for GD32F4xx
- \version 2022-06-30, V3.2.0, firmware for GD32F4xx
- */
- /*
- Copyright (c) 2022, GigaDevice Semiconductor Inc.
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holder nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- OF SUCH DAMAGE.
- */
- #include "usbd_enum.h"
- #include "usbd_msc_bbb.h"
- #include "usbd_msc_scsi.h"
- /* USB mass storage page 0 inquiry data */
- const uint8_t msc_page00_inquiry_data[] =
- {
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U,
- (INQUIRY_PAGE00_LENGTH - 4U),
- 0x80U,
- 0x83U,
- };
- /* USB mass storage sense 6 data */
- const uint8_t msc_mode_sense6_data[] =
- {
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U
- };
- /* USB mass storage sense 10 data */
- const uint8_t msc_mode_sense10_data[] =
- {
- 0x00U,
- 0x06U,
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U,
- 0x00U
- };
- /* local function prototypes ('static') */
- static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun);
- static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun);
- static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr);
- static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun);
- static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params);
- /*!
- \brief process SCSI commands
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- switch (params[0]) {
- case SCSI_TEST_UNIT_READY:
- return scsi_test_unit_ready (udev, lun, params);
- case SCSI_REQUEST_SENSE:
- return scsi_request_sense (udev, lun, params);
- case SCSI_INQUIRY:
- return scsi_inquiry (udev, lun, params);
- case SCSI_START_STOP_UNIT:
- return scsi_start_stop_unit (udev, lun, params);
- case SCSI_ALLOW_MEDIUM_REMOVAL:
- return scsi_allow_medium_removal (udev, lun, params);
- case SCSI_MODE_SENSE6:
- return scsi_mode_sense6 (udev, lun, params);
- case SCSI_MODE_SENSE10:
- return scsi_mode_sense10 (udev, lun, params);
- case SCSI_READ_FORMAT_CAPACITIES:
- return scsi_read_format_capacity (udev, lun, params);
- case SCSI_READ_CAPACITY10:
- return scsi_read_capacity10 (udev, lun, params);
- case SCSI_READ10:
- return scsi_read10 (udev, lun, params);
- case SCSI_WRITE10:
- return scsi_write10 (udev, lun, params);
- case SCSI_VERIFY10:
- return scsi_verify10 (udev, lun, params);
- case SCSI_FORMAT_UNIT:
- return scsi_format_cmd (udev, lun);
- case SCSI_READ_TOC_DATA:
- return scsi_toc_cmd_read (udev, lun, params);
- case SCSI_MODE_SELECT6:
- return scsi_mode_select6 (udev, lun, params);
- case SCSI_MODE_SELECT10:
- return scsi_mode_select10 (udev, lun, params);
- default:
- scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB);
- return -1;
- }
- }
- /*!
- \brief load the last error code in the error list
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] skey: sense key
- \param[in] asc: additional sense key
- \param[out] none
- \retval none
- */
- void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey;
- msc->scsi_sense[msc->scsi_sense_tail].ASC = asc;
- msc->scsi_sense_tail++;
- if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) {
- msc->scsi_sense_tail = 0U;
- }
- }
- /*!
- \brief process SCSI Test Unit Ready command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- /* case 9 : Hi > D0 */
- if (0U != msc->bbb_cbw.dCBWDataTransferLength) {
- scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB);
- return -1;
- }
- if (0 != usbd_mem_fops->mem_ready(lun)) {
- scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
- return -1;
- }
- msc->bbb_datalen = 0U;
- return 0;
- }
- /*!
- \brief process Inquiry command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->bbb_datalen = 0U;
- return 0;
- }
- /*!
- \brief process Inquiry command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->bbb_datalen = 0U;
- return 0;
- }
- /*!
- \brief process Inquiry command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- uint8_t *page = NULL;
- uint16_t len = 0U;
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- if (params[1] & 0x01U) {
- page = (uint8_t *)msc_page00_inquiry_data;
- len = INQUIRY_PAGE00_LENGTH;
- } else {
- page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun];
- len = (uint16_t)(page[4] + 5U);
- if (params[4] <= len) {
- len = params[4];
- }
- }
- msc->bbb_datalen = len;
- while (len) {
- len--;
- msc->bbb_data[len] = page[len];
- }
- return 0;
- }
- /*!
- \brief process Read Capacity 10 command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U;
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun];
- msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun];
- msc->bbb_data[0] = (uint8_t)(blk_num >> 24U);
- msc->bbb_data[1] = (uint8_t)(blk_num >> 16U);
- msc->bbb_data[2] = (uint8_t)(blk_num >> 8U);
- msc->bbb_data[3] = (uint8_t)(blk_num);
- msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U);
- msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U);
- msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U);
- msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]);
- msc->bbb_datalen = 8U;
- return 0;
- }
- /*!
- \brief process Read Format Capacity command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- uint16_t i = 0U;
- uint32_t blk_size = usbd_mem_fops->mem_block_size[lun];
- uint32_t blk_num = usbd_mem_fops->mem_block_len[lun];
- uint32_t blk_nbr = blk_num - 1U;
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- for (i = 0U; i < 12U; i++) {
- msc->bbb_data[i] = 0U;
- }
- msc->bbb_data[3] = 0x08U;
- msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U);
- msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U);
- msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U);
- msc->bbb_data[7] = (uint8_t)(blk_nbr);
- msc->bbb_data[8] = 0x02U;
- msc->bbb_data[9] = (uint8_t)(blk_size >> 16U);
- msc->bbb_data[10] = (uint8_t)(blk_size >> 8U);
- msc->bbb_data[11] = (uint8_t)(blk_size);
- msc->bbb_datalen = 12U;
- return 0;
- }
- /*!
- \brief process Mode Sense6 command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- uint16_t len = 8U;
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->bbb_datalen = len;
- while (len) {
- len--;
- msc->bbb_data[len] = msc_mode_sense6_data[len];
- }
- return 0;
- }
- /*!
- \brief process Mode Sense10 command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- uint16_t len = 8U;
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->bbb_datalen = len;
- while (len) {
- len--;
- msc->bbb_data[len] = msc_mode_sense10_data[len];
- }
- return 0;
- }
- /*!
- \brief process Request Sense command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- uint8_t i = 0U;
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) {
- msc->bbb_data[i] = 0U;
- }
- msc->bbb_data[0] = 0x70U;
- msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U;
- if ((msc->scsi_sense_head != msc->scsi_sense_tail)) {
- msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey;
- msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASC;
- msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASCQ;
- msc->scsi_sense_head++;
- if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) {
- msc->scsi_sense_head = 0U;
- }
- }
- msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]);
- return 0;
- }
- /*
- byte 5 (index 4) of start stop unit
- 7 6 5 4 3 2 1 0
- [ PWRCON ] R F E S
- S = start
- E = loadeject
- */
- #define STARTSTOPUNIT_START (1)
- #define STARTSTOPUNIT_LOADEJECT (2)
- /*!
- \brief process Start Stop Unit command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->bbb_datalen = 0U;
- /* not part of GDS class! make sure to bring this over if updating USB class */
- // if start = 0, load eject = 1, host is advising of media eject (usually a device removal too)
- if ((params[4] & STARTSTOPUNIT_LOADEJECT)) {
- if (!(params[4] & STARTSTOPUNIT_START))
- msc->scsi_disk_pop = 1U;
- }
- return 0;
- }
- /*!
- \brief process Allow Medium Removal command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- msc->bbb_datalen = 0U;
- return 0;
- }
- /*!
- \brief process Read10 command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- if (msc->bbb_state == BBB_IDLE) {
- /* direction is from device to host */
- if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) {
- scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB);
- return -1;
- }
- if (0 != usbd_mem_fops->mem_ready(lun)) {
- scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
- return -1;
- }
- msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \
- (params[4] << 8U) | params[5];
- msc->scsi_blk_len = (params[7] << 8U) | params[8];
- if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) {
- return -1; /* error */
- }
- msc->bbb_state = BBB_DATA_IN;
- msc->scsi_blk_addr *= msc->scsi_blk_size[lun];
- msc->scsi_blk_len *= msc->scsi_blk_size[lun];
- /* cases 4,5 : Hi <> Dn */
- if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) {
- scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB);
- return -1;
- }
- }
- msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE;
- return scsi_process_read (udev, lun);
- }
- /*!
- \brief process Write10 command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- if (BBB_IDLE == msc->bbb_state) {
- /* case 8 : Hi <> Do */
- if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) {
- scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB);
- return -1;
- }
- /* check whether media is ready */
- if (0 != usbd_mem_fops->mem_ready(lun)) {
- scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT);
- return -1;
- }
- /* check if media is write-protected */
- if (0 != usbd_mem_fops->mem_protected(lun)) {
- scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED);
- return -1;
- }
- msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \
- (params[4] << 8U) | params[5];
- msc->scsi_blk_len = (params[7] << 8U) | params[8];
- /* check if LBA address is in the right range */
- if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) {
- return -1; /* error */
- }
- msc->scsi_blk_addr *= msc->scsi_blk_size[lun];
- msc->scsi_blk_len *= msc->scsi_blk_size[lun];
- /* cases 3,11,13 : Hn,Ho <> D0 */
- if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) {
- scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB);
- return -1;
- }
- /* prepare endpoint to receive first data packet */
- msc->bbb_state = BBB_DATA_OUT;
- usbd_ep_recev (udev,
- MSC_OUT_EP,
- msc->bbb_data,
- USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE));
- } else { /* write process ongoing */
- return scsi_process_write (udev, lun);
- }
- return 0;
- }
- /*!
- \brief process Verify10 command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- if (0x02U == (params[1] & 0x02U)) {
- scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);
- return -1; /* error, verify mode not supported*/
- }
- if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) {
- return -1; /* error */
- }
- msc->bbb_datalen = 0U;
- return 0;
- }
- /*!
- \brief check address range
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] blk_offset: block offset
- \param[in] blk_nbr: number of block to be processed
- \param[out] none
- \retval status
- */
- static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) {
- scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE);
- return -1;
- }
- return 0;
- }
- /*!
- \brief handle read process
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[out] none
- \retval status
- */
- static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE);
- if (usbd_mem_fops->mem_read(lun,
- msc->bbb_data,
- msc->scsi_blk_addr,
- (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) {
- scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR);
- return -1;
- }
- usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len);
- msc->scsi_blk_addr += len;
- msc->scsi_blk_len -= len;
- /* case 6 : Hi = Di */
- msc->bbb_csw.dCSWDataResidue -= len;
- if (0U == msc->scsi_blk_len) {
- msc->bbb_state = BBB_LAST_DATA_IN;
- }
- return 0;
- }
- /*!
- \brief handle write process
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[out] none
- \retval status
- */
- static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun)
- {
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE);
- if (usbd_mem_fops->mem_write (lun,
- msc->bbb_data,
- msc->scsi_blk_addr,
- (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) {
- scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT);
- return -1;
- }
- msc->scsi_blk_addr += len;
- msc->scsi_blk_len -= len;
- /* case 12 : Ho = Do */
- msc->bbb_csw.dCSWDataResidue -= len;
- if (0U == msc->scsi_blk_len) {
- msc_bbb_csw_send (udev, CSW_CMD_PASSED);
- } else {
- /* prepare endpoint to receive next packet */
- usbd_ep_recev (udev,
- MSC_OUT_EP,
- msc->bbb_data,
- USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE));
- }
- return 0;
- }
- /*!
- \brief process Format Unit command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[out] none
- \retval status
- */
- static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun)
- {
- return 0;
- }
- /*!
- \brief process Read_Toc command
- \param[in] udev: pointer to USB device instance
- \param[in] lun: logical unit number
- \param[in] params: command parameters
- \param[out] none
- \retval status
- */
- static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params)
- {
- uint8_t* pPage;
- uint16_t len;
- usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE];
- pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN];
- len = (uint16_t)pPage[1] + 2U;
- msc->bbb_datalen = len;
- while (len) {
- len--;
- msc->bbb_data[len] = pPage[len];
- }
- return 0;
- }
|