diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 53f0e6ac2..a45fba737 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -30,31 +30,59 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +static scsi_inquiry_resp_t inquiry_resp; +static scsi_read_capacity10_resp_t capacity_resp; +uint32_t block_size; +uint32_t block_count; + +bool capacity_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + (void) dev_addr; + (void) cbw; + + if (csw->status != 0) + { + printf("Read Capacity (10) failed\r\n"); + return false; + } + + // Capacity response field: Block size and Last LBA are both Big-Endian + block_count = tu_ntohl(capacity_resp.last_lba) + 1; + block_size = tu_ntohl(capacity_resp.block_size); + + printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); + printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); + + return true; +} + +bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) +{ + if (csw->status != 0) + { + printf("Inquiry failed\r\n"); + return false; + } + + // Print out Vendor ID, Product ID and Rev + printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); + + // Read capacity of device + tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb); + + return true; +} //------------- IMPLEMENTATION -------------// void tuh_msc_mounted_cb(uint8_t dev_addr) { printf("A MassStorage device is mounted\r\n"); - //------------- Disk Information -------------// -#if 0 - // SCSI VendorID[8] & ProductID[16] from Inquiry Command - uint8_t const* p_vendor = tuh_msc_get_vendor_name(dev_addr); - uint8_t const* p_product = tuh_msc_get_product_name(dev_addr); + block_size = block_count = 0; - for(uint8_t i=0; i<8; i++) putchar(p_vendor[i]); - - putchar(' '); - for(uint8_t i=0; i<16; i++) putchar(p_product[i]); - putchar('\n'); -#endif - - uint32_t last_lba = 0; - uint32_t block_size = 0; - tuh_msc_get_capacity(dev_addr, &last_lba, &block_size); - printf("Disk Size: %ld MB\r\n", (last_lba+1)/ ((1024*1024)/block_size) ); - printf("LBA 0-0x%lX Block Size: %ld\r\n", last_lba, block_size); + uint8_t const lun = 0; + tuh_msc_scsi_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb); // // //------------- file system (only 1 LUN support) -------------// // uint8_t phy_disk = dev_addr-1; diff --git a/examples/obsolete/host/src/msc_host_app.c b/examples/obsolete/host/src/msc_host_app.c index 77747b536..8afb6ede8 100644 --- a/examples/obsolete/host/src/msc_host_app.c +++ b/examples/obsolete/host/src/msc_host_app.c @@ -64,7 +64,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr) putchar('\n'); uint32_t last_lba, block_size; - tuh_msc_get_capacity(dev_addr, &last_lba, &block_size); + tuh_msc_read_capacity(dev_addr, &last_lba, &block_size); printf("Disk Size: %d MB\n", (last_lba+1)/ ((1024*1024)/block_size) ); printf("LBA 0-0x%X Block Size: %d\n", last_lba, block_size); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index e8bed989c..7a46b6866 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -53,11 +53,7 @@ typedef struct uint8_t max_lun; - scsi_read_capacity10_resp_t capacity; - volatile bool is_initialized; - uint8_t vendor_id[8]; - uint8_t product_id[16]; uint8_t stage; void* buffer; @@ -75,6 +71,11 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_i //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) +{ + return msch_data[dev_addr-1].max_lun; +} + bool tuh_msc_is_mounted(uint8_t dev_addr) { return tuh_device_is_configured(dev_addr) && // is configured can be omitted @@ -87,19 +88,6 @@ bool tuh_msc_is_busy(uint8_t dev_addr) hcd_edpt_busy(dev_addr, msch_data[dev_addr-1].ep_in); } -bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) -{ - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - - if ( !p_msc->is_initialized ) return false; - TU_ASSERT(p_last_lba != NULL && p_block_size != NULL); - - (*p_last_lba) = p_msc->capacity.last_lba; - (*p_block_size) = p_msc->capacity.block_size; - - return true; -} - //--------------------------------------------------------------------+ // PUBLIC API: SCSI COMMAND //--------------------------------------------------------------------+ @@ -126,33 +114,46 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu return true; } -#if 0 -tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb) { - msch_interface_t* p_msch = &msch_data[dev_addr-1]; + msch_interface_t* p_msc = &msch_data[dev_addr-1]; + if ( !p_msc->is_initialized ) return false; - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - p_msch->cbw.total_bytes = sizeof(scsi_inquiry_resp_t); - p_msch->cbw.dir = TUSB_DIR_IN_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); + msc_cbw_t cbw = { 0 }; + + msc_cbw_add_signature(&cbw, lun); + cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read_capacity10_t); + cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; + + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); + + return true; +} + +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb) +{ + msc_cbw_t cbw = { 0 }; + + msc_cbw_add_signature(&cbw, lun); + cbw.total_bytes = sizeof(scsi_inquiry_resp_t); + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_inquiry_t); - //------------- SCSI command -------------// scsi_inquiry_t const cmd_inquiry = { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_resp_t) }; + memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); - memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); + TU_ASSERT(tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb)); - TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_data) ); - - return TUSB_ERROR_NONE; + return true; } -#endif -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb) { msc_cbw_t cbw = { 0 }; msc_cbw_add_signature(&cbw, lun); @@ -252,20 +253,12 @@ void msch_init(void) tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); } - void msch_close(uint8_t dev_addr) { tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback } -static bool get_csw(uint8_t dev_addr, msch_interface_t * p_msc) -{ - p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); - return true; -} - bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = &msch_data[dev_addr-1]; @@ -288,12 +281,15 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 }else { // Status stage - get_csw(dev_addr, p_msc); + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); } break; case MSC_STAGE_DATA: - get_csw(dev_addr, p_msc); + // Status stage + p_msc->stage = MSC_STAGE_STATUS; + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, sizeof(msc_csw_t))); break; case MSC_STAGE_STATUS: @@ -317,7 +313,6 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { @@ -331,9 +326,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) @@ -378,6 +371,7 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c // STALL means zero p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0; + p_msc->max_lun++; // MAX LUN is minus 1 by specs // MSCU Reset #if 0 // not really needed @@ -397,16 +391,6 @@ static bool open_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t c TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) ); #endif -#if 0 - //------------- SCSI Inquiry -------------// - TU_LOG2("SCSI Inquiry\r\n"); - tusbh_msc_inquiry(dev_addr, 0, msch_buffer); - TU_ASSERT( osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT) ); - - memcpy(p_msc->vendor_id , ((scsi_inquiry_resp_t*) msch_buffer)->vendor_id , 8); - memcpy(p_msc->product_id, ((scsi_inquiry_resp_t*) msch_buffer)->product_id, 16); -#endif - // TODO multiple LUN support TU_LOG2("SCSI Test Unit Ready\r\n"); tuh_msc_test_unit_ready(dev_addr, 0, open_test_unit_ready_complete); @@ -418,18 +402,11 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw { if (csw->status == 0) { - TU_LOG2("SCSI Read Capacity 10\r\n"); - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - msc_cbw_t new_cbw = { 0 }; - msc_cbw_add_signature(&new_cbw, cbw->lun); - new_cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t); - new_cbw.dir = TUSB_DIR_IN_MASK; - new_cbw.cmd_len = sizeof(scsi_read_capacity10_t); - new_cbw.command[0] = SCSI_CMD_READ_CAPACITY_10; - - TU_ASSERT(tuh_msc_scsi_command(dev_addr, &new_cbw, &p_msc->capacity, open_read_capacity10_complete)); + // Unit is ready, Enumeration is complete + p_msc->is_initialized = true; // open complete TODO remove + tuh_msc_mounted_cb(dev_addr); }else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries @@ -443,25 +420,9 @@ static bool open_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw static bool open_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) { + TU_ASSERT(csw->status == 0); TU_ASSERT(tuh_msc_test_unit_ready(dev_addr, cbw->lun, open_test_unit_ready_complete)); return true; } -static bool open_read_capacity10_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw) -{ - TU_ASSERT(csw->status == 0); - - msch_interface_t* p_msc = &msch_data[dev_addr-1]; - - // Note: Block size and last LBA are big-endian - p_msc->capacity.last_lba = tu_ntohl(p_msc->capacity.last_lba); - p_msc->capacity.block_size = tu_ntohl(p_msc->capacity.block_size); - - // Enumeration is complete - p_msc->is_initialized = true; // open complete TODO remove - tuh_msc_mounted_cb(dev_addr); - - return true; -} - #endif diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 03231d17f..63b4753b1 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -63,9 +63,11 @@ bool tuh_msc_is_mounted(uint8_t dev_addr); */ bool tuh_msc_is_busy(uint8_t dev_addr); +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr); + bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb); -bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_t len); +bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb); /** \brief Get SCSI Capacity of MassStorage device * \param[in] dev_addr device address @@ -77,7 +79,7 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, void* response, uint32_ * to re-send SCSI READ CAPACITY 10 command */ -bool tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb); #if 0 /** \brief Perform SCSI READ 10 command to read data from MassStorage device