29#if (CFG_TUD_ENABLED && CFG_TUD_MSC)
38#ifndef CFG_TUD_MSC_LOG_LEVEL
39 #define CFG_TUD_MSC_LOG_LEVEL CFG_TUD_LOG_LEVEL
42#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_MSC_LOG_LEVEL, __VA_ARGS__)
78CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t
_mscd_buf[CFG_TUD_MSC_EP_BUFSIZE];
89TU_ATTR_ALWAYS_INLINE
static inline bool is_data_in(uint8_t dir)
141 return tu_ntohl(lba);
147 return tu_ntohs(block_count);
156 if (block_count == 0)
return 0;
158 return (uint16_t) (cbw->
total_bytes / block_count);
170 TU_LOG_DRV(
" SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n");
180 TU_LOG_DRV(
" SCSI case 10 (Ho <> Di)\r\n");
185 TU_LOG_DRV(
" SCSI case 8 (Hi <> Do)\r\n");
188 else if ( 0 == block_count )
190 TU_LOG_DRV(
" SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n");
195 TU_LOG_DRV(
" Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n");
206#if CFG_TUSB_DEBUG >= CFG_TUD_MSC_LOG_LEVEL
234bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier)
280 TU_ASSERT(max_len >= drv_len, 0);
331 if ( ep_addr == p_msc->
ep_in )
336 TU_ASSERT(
send_csw(rhport, p_msc) );
339 else if ( ep_addr == p_msc->
ep_out )
362 TU_LOG_DRV(
" MSC BOT Reset\r\n");
373 TU_LOG_DRV(
" MSC Get Max Lun\r\n");
387 default:
return false;
401 switch (p_msc->
stage)
406 if(ep_addr != p_msc->
ep_out)
return true;
410 TU_LOG_DRV(
" SCSI CBW is not valid\r\n");
467 TU_LOG_DRV(
" SCSI reject non READ10/WRITE10 with large data\r\n");
481 if ( (resplen < 0) && (p_msc->
sense_key == 0) )
489 TU_LOG_DRV(
" SCSI unsupported or failed command\r\n");
492 else if (resplen == 0)
524 TU_LOG_DRV(
" SCSI Data [Lun%u]\r\n", p_cbw->
lun);
556 TU_LOG_DRV(
" SCSI unsupported command\r\n");
583 if( (ep_addr == p_msc->
ep_in) && (xferred_bytes ==
sizeof(
msc_csw_t)) )
585 TU_LOG_DRV(
" SCSI Status [Lun%u] = %u\r\n", p_cbw->
lun, p_csw->
status);
610 TU_LOG1(
" Warning expect SCSI Status but received unknown data\r\n");
629 TU_ASSERT(
send_csw(rhport, p_msc) );
633 #if TU_CHECK_MCU(OPT_MCU_CXD56)
661 switch ( scsi_cmd[0] )
712 uint32_t block_count;
714 uint16_t block_size_u16;
717 block_size = (uint32_t) block_size_u16;
721 if (block_count == 0 || block_size == 0)
731 read_capa10.
last_lba = tu_htonl(block_count-1);
732 read_capa10.
block_size = tu_htonl(block_size);
734 resplen =
sizeof(read_capa10);
746 .descriptor_type = 2,
750 uint32_t block_count;
757 if (block_count == 0 || block_size == 0)
765 read_fmt_capa.
block_num = tu_htonl(block_count);
768 resplen =
sizeof(read_fmt_capa);
780 .response_data_format = 2,
791 resplen =
sizeof(inquiry_rsp);
802 .write_protected =
false,
804 .block_descriptor_len = 0
807 bool writable =
true;
815 resplen =
sizeof(mode_resp);
833 resplen =
sizeof(sense_rsp);
847 default: resplen = -1;
break;
873 TU_LOG_DRV(
" tud_msc_read10_cb() return -1\r\n");
880 else if ( nbytes == 0 )
894 bool writable =
true;
935 TU_LOG_DRV(
" tud_msc_write10_cb() return -1\r\n");
947 if ( (uint32_t) nbytes < xferred_bytes )
949 uint32_t
const left_over = xferred_bytes - (uint32_t) nbytes;
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
@ MSC_PROTOCOL_BOT
Bulk-Only Transport.
struct TU_ATTR_PACKED scsi_inquiry_resp_t
SCSI Inquiry Response Data.
@ SCSI_SENSE_ILLEGAL_REQUEST
Indicates an illegal parameter in the command descriptor block or in the additional parameters.
@ SCSI_SENSE_NOT_READY
Indicates the logical unit addressed cannot be accessed.
@ SCSI_SENSE_DATA_PROTECT
Indicates that a command that reads or writes the medium was attempted on a block that is protected f...
@ MSC_CBW_SIGNATURE
Constant value of 43425355h (little endian)
@ MSC_CSW_SIGNATURE
Constant value of 53425355h (little endian)
@ MSC_CSW_STATUS_FAILED
MSC_CSW_STATUS_FAILED.
@ MSC_CSW_STATUS_PHASE_ERROR
MSC_CSW_STATUS_PHASE_ERROR.
@ MSC_CSW_STATUS_PASSED
MSC_CSW_STATUS_PASSED.
struct TU_ATTR_PACKED scsi_sense_fixed_resp_t
@ SCSI_CMD_TEST_UNIT_READY
The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/wri...
@ SCSI_CMD_READ_FORMAT_CAPACITY
The command allows the Host to request a list of the possible format capacities for an installed writ...
@ SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL
@ SCSI_CMD_REQUEST_SENSE
The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used t...
@ SCSI_CMD_WRITE_10
The WRITE (10) command requests that the device server transfer the specified logical block(s) from t...
@ SCSI_CMD_MODE_SELECT_6
provides a means for the application client to specify medium, logical unit, or peripheral device par...
@ SCSI_CMD_READ_CAPACITY_10
The SCSI Read Capacity command is used to obtain data capacity information from a target device.
@ SCSI_CMD_START_STOP_UNIT
@ SCSI_CMD_READ_10
The READ (10) command requests that the device server read the specified logical block(s) and transfe...
@ SCSI_CMD_MODE_SENSE_6
provides a means for a device server to report parameters to an application client....
@ SCSI_CMD_INQUIRY
The SCSI Inquiry command is used to obtain basic information from a target device.
@ MSC_REQ_RESET
This request is used to reset the mass storage device and its associated interface....
@ MSC_REQ_GET_MAX_LUN
The Get Max LUN device request is used to determine the number of logical units supported by the devi...
static uint16_t rdwr10_get_blocksize(msc_cbw_t const *cbw)
static void proc_read10_cmd(uint8_t rhport, mscd_interface_t *p_msc)
bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
static uint16_t rdwr10_get_blockcount(msc_cbw_t const *cbw)
static TU_ATTR_ALWAYS_INLINE bool is_data_in(uint8_t dir)
static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t *buffer, uint32_t bufsize)
void mscd_reset(uint8_t rhport)
static bool prepare_cbw(uint8_t rhport, mscd_interface_t *p_msc)
uint8_t rdwr10_validate_cmd(msc_cbw_t const *cbw)
bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier)
static void proc_bot_reset(mscd_interface_t *p_msc)
TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[]
uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
static void set_sense_medium_not_present(uint8_t lun)
static uint32_t rdwr10_get_lba(uint8_t const command[])
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static mscd_interface_t _mscd_itf
static bool send_csw(uint8_t rhport, mscd_interface_t *p_msc)
TU_ATTR_UNUSED tu_static tu_lookup_table_t const _msc_scsi_cmd_table
static void proc_write10_cmd(uint8_t rhport, mscd_interface_t *p_msc)
CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE]
static void fail_scsi_op(uint8_t rhport, mscd_interface_t *p_msc, uint8_t status)
static void proc_write10_new_data(uint8_t rhport, mscd_interface_t *p_msc, uint32_t xferred_bytes)
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize)
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize)
TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun)
TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun)
TU_ATTR_WEAK int32_t tud_msc_request_sense_cb(uint8_t lun, void *buffer, uint16_t bufsize)
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize)
TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun)
TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void)
bool tud_msc_test_unit_ready_cb(uint8_t lun)
void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size)
TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16])
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
TU_ATTR_WEAK bool tud_msc_prevent_allow_medium_removal_cb(uint8_t lun, uint8_t prohibit_removal, uint8_t control)
AUDIO Channel Cluster Descriptor (4.1)
uint32_t tag
Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTa...
uint8_t product_rev[4]
4 bytes of ASCII data defined by the vendor.
uint8_t status
indicates the success or failure of the command. Values from msc_csw_status_t
uint8_t lun
The device Logical Unit Number (LUN) to which the command block is being sent. For devices that suppo...
uint8_t dir
Bit 7 of this field define transfer direction - 0 : Data-Out from host to the device....
uint8_t add_sense_qualifier
uint32_t signature
Signature that helps identify this data packet as a CBW. The signature field shall contain the value ...
uint8_t product_id[16]
16 bytes of ASCII data defined by the vendor.
uint32_t block_num
must be 8*n, length in bytes of formattable capacity descriptor followed it.
uint8_t vendor_id[8]
8 bytes of ASCII data identifying the vendor of the product.
struct TU_ATTR_PACKED::@15::TU_ATTR_PACKED bmRequestType_bit
uint32_t data_residue
For Data-Out the device shall report in the dCSWDataResidue the difference between the amount of data...
uint8_t command[16]
The command block to be executed by the device. The device shall interpret the first cmd_len bytes in...
uint8_t bInterfaceClass
Class code (assigned by the USB-IF).
uint8_t response_code
70h - current errors, Fixed Format 71h - deferred errors, Fixed Format
uint8_t bInterfaceSubClass
Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bInterfaceCla...
uint8_t bRequest
Request type audio_cs_req_t.
uint32_t total_bytes
The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as...
uint8_t bInterfaceProtocol
Protocol code (assigned by the USB). These codes are qualified by the value of the bInterfaceClass ...
uint8_t bInterfaceNumber
Number of this interface. Zero-based value identifying the index in the array of concurrent interface...
CFG_TUSB_MEM_ALIGN msc_csw_t csw
uint8_t add_sense_qualifier
CFG_TUSB_MEM_ALIGN msc_cbw_t cbw
SCSI Read Capacity 10 Response Data.
uint32_t last_lba
The last Logical Block Address of the device.
uint32_t block_size
Block size in bytes.
static TU_ATTR_ALWAYS_INLINE uint8_t tu_u16_low(uint16_t ui16)
static TU_ATTR_ALWAYS_INLINE uint32_t tu_min32(uint32_t x, uint32_t y)
static TU_ATTR_ALWAYS_INLINE uint32_t tu_unaligned_read32(const void *mem)
static TU_ATTR_ALWAYS_INLINE uint16_t tu_unaligned_read16(const void *mem)
static TU_ATTR_ALWAYS_INLINE int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count)
static TU_ATTR_ALWAYS_INLINE bool tu_bit_test(uint32_t value, uint8_t pos)
static const char * tu_lookup_find(tu_lookup_table_t const *p_table, uint32_t key)
struct TU_ATTR_PACKED tusb_desc_interface_t
USB Interface Descriptor.
static TU_ATTR_ALWAYS_INLINE uint8_t const * tu_desc_next(void const *desc)
@ TUSB_REQ_FEATURE_EDPT_HALT
void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const *p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t *ep_out, uint8_t *ep_in)
bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr)
bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const *request, void *buffer, uint16_t len)
bool tud_control_status(uint8_t rhport, tusb_control_request_t const *request)
static TU_ATTR_ALWAYS_INLINE bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr)
CFG_TUH_MEM_ALIGN tusb_control_request_t request