mirror of
https://github.com/hathach/tinyusb.git
synced 2025-05-09 15:21:21 +08:00
host msc: call read_capacity as part of enumeration
- add tuh_msc_get_block_count(), tuh_msc_get_block_size() - rename tuh_msc_mounted_cb/tuh_msc_unmounted_cb to tuh_msc_mount_cb/tuh_msc_unmount_cb to match device stack naming - change tuh_msc_is_busy() to tuh_msc_ready() - add CFG_TUH_MSC_MAXLUN (default to 4) to hold lun capacities - add host msc configured to for state check.
This commit is contained in:
parent
386a386345
commit
5108d76136
@ -31,31 +31,6 @@
|
|||||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
static scsi_inquiry_resp_t inquiry_resp;
|
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)
|
bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
|
||||||
{
|
{
|
||||||
@ -68,19 +43,21 @@ bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const
|
|||||||
// Print out Vendor ID, Product ID and Rev
|
// 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);
|
printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev);
|
||||||
|
|
||||||
// Read capacity of device
|
// Get capacity of device
|
||||||
tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb);
|
uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
|
||||||
|
uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
|
||||||
|
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------- IMPLEMENTATION -------------//
|
//------------- IMPLEMENTATION -------------//
|
||||||
void tuh_msc_mounted_cb(uint8_t dev_addr)
|
void tuh_msc_mount_cb(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
printf("A MassStorage device is mounted\r\n");
|
printf("A MassStorage device is mounted\r\n");
|
||||||
|
|
||||||
block_size = block_count = 0;
|
|
||||||
|
|
||||||
uint8_t const lun = 0;
|
uint8_t const lun = 0;
|
||||||
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
|
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
|
||||||
//
|
//
|
||||||
@ -110,7 +87,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr)
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void tuh_msc_unmounted_cb(uint8_t dev_addr)
|
void tuh_msc_unmount_cb(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
(void) dev_addr;
|
(void) dev_addr;
|
||||||
printf("A MassStorage device is unmounted\r\n");
|
printf("A MassStorage device is unmounted\r\n");
|
||||||
@ -133,11 +110,4 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr)
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
//void tuh_msc_scsi_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
|
|
||||||
//{
|
|
||||||
// (void) dev_addr;
|
|
||||||
// (void) cbw;
|
|
||||||
// (void) csw;
|
|
||||||
//}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,7 +48,7 @@ CFG_TUSB_MEM_SECTION static FATFS fatfs[CFG_TUSB_HOST_DEVICE_MAX];
|
|||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// tinyusb callbacks
|
// tinyusb callbacks
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
void tuh_msc_mounted_cb(uint8_t dev_addr)
|
void tuh_msc_mount_cb(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
puts("\na MassStorage device is mounted");
|
puts("\na MassStorage device is mounted");
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tuh_msc_unmounted_cb(uint8_t dev_addr)
|
void tuh_msc_unmount_cb(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
puts("\na MassStorage device is unmounted");
|
puts("\na MassStorage device is unmounted");
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ static DSTATUS disk_state[CFG_TUSB_HOST_DEVICE_MAX];
|
|||||||
static DRESULT wait_for_io_complete(uint8_t usb_addr)
|
static DRESULT wait_for_io_complete(uint8_t usb_addr)
|
||||||
{
|
{
|
||||||
// TODO with RTOS, this should use semaphore instead of blocking
|
// TODO with RTOS, this should use semaphore instead of blocking
|
||||||
while ( tuh_msc_is_busy(usb_addr) )
|
while ( !tuh_msc_ready(usb_addr) )
|
||||||
{
|
{
|
||||||
// TODO should have timeout here
|
// TODO should have timeout here
|
||||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||||
|
@ -53,8 +53,15 @@ typedef struct
|
|||||||
|
|
||||||
uint8_t max_lun;
|
uint8_t max_lun;
|
||||||
|
|
||||||
volatile bool mounted;
|
volatile bool configured; // Receive SET_CONFIGURE
|
||||||
|
volatile bool mounted; // Enumeration is complete
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t block_size;
|
||||||
|
uint32_t block_count;
|
||||||
|
} capacity[CFG_TUH_MSC_MAXLUN];
|
||||||
|
|
||||||
|
//------------- SCSI -------------//
|
||||||
uint8_t stage;
|
uint8_t stage;
|
||||||
void* buffer;
|
void* buffer;
|
||||||
tuh_msc_complete_cb_t complete_cb;
|
tuh_msc_complete_cb_t complete_cb;
|
||||||
@ -63,14 +70,15 @@ typedef struct
|
|||||||
msc_csw_t csw;
|
msc_csw_t csw;
|
||||||
}msch_interface_t;
|
}msch_interface_t;
|
||||||
|
|
||||||
CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX];
|
CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX];
|
||||||
|
|
||||||
// buffer used to read scsi information when mounted, largest response data currently is inquiry
|
// buffer used to read scsi information when mounted
|
||||||
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)];
|
// largest response data currently is inquiry TODO Inquiry is not part of enum anymore
|
||||||
|
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
|
||||||
|
|
||||||
static inline msch_interface_t* get_itf(uint8_t dev_addr)
|
static inline msch_interface_t* get_itf(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
return &msch_data[dev_addr-1];
|
return &_msch_itf[dev_addr-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
@ -82,18 +90,28 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr)
|
|||||||
return p_msc->max_lun;
|
return p_msc->max_lun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun)
|
||||||
|
{
|
||||||
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
|
return p_msc->capacity[lun].block_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun)
|
||||||
|
{
|
||||||
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
|
return p_msc->capacity[lun].block_size;
|
||||||
|
}
|
||||||
|
|
||||||
bool tuh_msc_mounted(uint8_t dev_addr)
|
bool tuh_msc_mounted(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
|
return p_msc->mounted;
|
||||||
// is configured can be omitted
|
|
||||||
return tuh_device_is_configured(dev_addr) && p_msc->mounted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tuh_msc_is_busy(uint8_t dev_addr)
|
bool tuh_msc_ready(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in);
|
return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
@ -110,7 +128,7 @@ static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun)
|
|||||||
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_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb)
|
||||||
{
|
{
|
||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
// TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command
|
TU_VERIFY(p_msc->configured);
|
||||||
|
|
||||||
// TODO claim endpoint
|
// TODO claim endpoint
|
||||||
|
|
||||||
@ -127,7 +145,7 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu
|
|||||||
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)
|
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_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
TU_VERIFY(p_msc->mounted);
|
TU_VERIFY(p_msc->configured);
|
||||||
|
|
||||||
msc_cbw_t cbw;
|
msc_cbw_t cbw;
|
||||||
cbw_init(&cbw, lun);
|
cbw_init(&cbw, lun);
|
||||||
@ -142,6 +160,9 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r
|
|||||||
|
|
||||||
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
|
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
|
||||||
{
|
{
|
||||||
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
|
TU_VERIFY(p_msc->mounted);
|
||||||
|
|
||||||
msc_cbw_t cbw;
|
msc_cbw_t cbw;
|
||||||
cbw_init(&cbw, lun);
|
cbw_init(&cbw, lun);
|
||||||
|
|
||||||
@ -161,10 +182,13 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons
|
|||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
|
TU_VERIFY(p_msc->configured);
|
||||||
|
|
||||||
msc_cbw_t cbw;
|
msc_cbw_t cbw;
|
||||||
cbw_init(&cbw, lun);
|
cbw_init(&cbw, lun);
|
||||||
|
|
||||||
cbw.total_bytes = 0; // Number of bytes
|
cbw.total_bytes = 0;
|
||||||
cbw.dir = TUSB_DIR_OUT;
|
cbw.dir = TUSB_DIR_OUT;
|
||||||
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
|
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
|
||||||
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
|
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
|
||||||
@ -201,11 +225,11 @@ bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba,
|
|||||||
msc_cbw_t cbw;
|
msc_cbw_t cbw;
|
||||||
cbw_init(&cbw, lun);
|
cbw_init(&cbw, lun);
|
||||||
|
|
||||||
cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10
|
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
|
||||||
cbw.dir = TUSB_DIR_IN_MASK;
|
cbw.dir = TUSB_DIR_IN_MASK;
|
||||||
cbw.cmd_len = sizeof(scsi_read10_t);
|
cbw.cmd_len = sizeof(scsi_read10_t);
|
||||||
|
|
||||||
scsi_read10_t cmd_read10 =
|
scsi_read10_t const cmd_read10 =
|
||||||
{
|
{
|
||||||
.cmd_code = SCSI_CMD_READ_10,
|
.cmd_code = SCSI_CMD_READ_10,
|
||||||
.lba = tu_htonl(lba),
|
.lba = tu_htonl(lba),
|
||||||
@ -225,11 +249,11 @@ bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_
|
|||||||
msc_cbw_t cbw;
|
msc_cbw_t cbw;
|
||||||
cbw_init(&cbw, lun);
|
cbw_init(&cbw, lun);
|
||||||
|
|
||||||
cbw.total_bytes = 512*block_count; // Number of bytes TODO get block size from READ CAPACITY 10
|
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
|
||||||
cbw.dir = TUSB_DIR_OUT;
|
cbw.dir = TUSB_DIR_OUT;
|
||||||
cbw.cmd_len = sizeof(scsi_write10_t);
|
cbw.cmd_len = sizeof(scsi_write10_t);
|
||||||
|
|
||||||
scsi_write10_t cmd_write10 =
|
scsi_write10_t const cmd_write10 =
|
||||||
{
|
{
|
||||||
.cmd_code = SCSI_CMD_WRITE_10,
|
.cmd_code = SCSI_CMD_WRITE_10,
|
||||||
.lba = tu_htonl(lba),
|
.lba = tu_htonl(lba),
|
||||||
@ -267,14 +291,14 @@ bool tuh_msc_reset(uint8_t dev_addr)
|
|||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
void msch_init(void)
|
void msch_init(void)
|
||||||
{
|
{
|
||||||
tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
|
tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void msch_close(uint8_t dev_addr)
|
void msch_close(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
tu_memclr(p_msc, sizeof(msch_interface_t));
|
tu_memclr(p_msc, sizeof(msch_interface_t));
|
||||||
tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback
|
tuh_msc_unmount_cb(dev_addr); // invoke Application Callback
|
||||||
}
|
}
|
||||||
|
|
||||||
bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
|
bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
|
||||||
@ -331,6 +355,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
|
|||||||
static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
|
static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
|
||||||
static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
|
static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
|
||||||
static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
|
static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
|
||||||
|
static bool config_read_capacity_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)
|
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
|
||||||
{
|
{
|
||||||
@ -369,6 +394,8 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
|
|||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
TU_ASSERT(p_msc->itf_num == itf_num);
|
TU_ASSERT(p_msc->itf_num == itf_num);
|
||||||
|
|
||||||
|
p_msc->configured = true;
|
||||||
|
|
||||||
//------------- Get Max Lun -------------//
|
//------------- Get Max Lun -------------//
|
||||||
TU_LOG2("MSC Get Max Lun\r\n");
|
TU_LOG2("MSC Get Max Lun\r\n");
|
||||||
tusb_control_request_t request =
|
tusb_control_request_t request =
|
||||||
@ -396,12 +423,13 @@ static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t
|
|||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
|
|
||||||
// STALL means zero
|
// STALL means zero
|
||||||
p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0;
|
p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0;
|
||||||
p_msc->max_lun++; // MAX LUN is minus 1 by specs
|
p_msc->max_lun++; // MAX LUN is minus 1 by specs
|
||||||
|
|
||||||
// TODO multiple LUN support
|
// TODO multiple LUN support
|
||||||
TU_LOG2("SCSI Test Unit Ready\r\n");
|
TU_LOG2("SCSI Test Unit Ready\r\n");
|
||||||
tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete);
|
uint8_t const lun = 0;
|
||||||
|
tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -410,19 +438,16 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
|
|||||||
{
|
{
|
||||||
if (csw->status == 0)
|
if (csw->status == 0)
|
||||||
{
|
{
|
||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
// Unit is ready, read its capacity
|
||||||
|
TU_LOG2("SCSI Read Capacity\r\n");
|
||||||
usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
|
tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete);
|
||||||
|
|
||||||
// Unit is ready, Enumeration is complete
|
|
||||||
p_msc->mounted = true;
|
|
||||||
tuh_msc_mounted_cb(dev_addr);
|
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
// Note: During enumeration, some device fails Test Unit Ready and require a few retries
|
// Note: During enumeration, some device fails Test Unit Ready and require a few retries
|
||||||
// with Request Sense to start working !!
|
// with Request Sense to start working !!
|
||||||
// TODO limit number of retries
|
// TODO limit number of retries
|
||||||
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete));
|
TU_LOG2("SCSI Request Sense\r\n");
|
||||||
|
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -435,4 +460,24 @@ static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool config_read_capacity_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 = get_itf(dev_addr);
|
||||||
|
|
||||||
|
// Capacity response field: Block size and Last LBA are both Big-Endian
|
||||||
|
scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer;
|
||||||
|
p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1;
|
||||||
|
p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
|
||||||
|
|
||||||
|
// Mark enumeration is complete
|
||||||
|
p_msc->mounted = true;
|
||||||
|
tuh_msc_mount_cb(dev_addr);
|
||||||
|
|
||||||
|
usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,6 +35,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Class Driver Configuration
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#ifndef CFG_TUH_MSC_MAXLUN
|
||||||
|
#define CFG_TUH_MSC_MAXLUN 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/** \addtogroup ClassDriver_MSC
|
/** \addtogroup ClassDriver_MSC
|
||||||
* @{
|
* @{
|
||||||
* \defgroup MSC_Host Host
|
* \defgroup MSC_Host Host
|
||||||
@ -51,12 +60,18 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms
|
|||||||
// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb()
|
// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb()
|
||||||
bool tuh_msc_mounted(uint8_t dev_addr);
|
bool tuh_msc_mounted(uint8_t dev_addr);
|
||||||
|
|
||||||
// Check if the interface is currently busy transferring data
|
// Check if the interface is currently ready or busy transferring data
|
||||||
bool tuh_msc_is_busy(uint8_t dev_addr);
|
bool tuh_msc_ready(uint8_t dev_addr);
|
||||||
|
|
||||||
// Get Max Lun
|
// Get Max Lun
|
||||||
uint8_t tuh_msc_get_maxlun(uint8_t dev_addr);
|
uint8_t tuh_msc_get_maxlun(uint8_t dev_addr);
|
||||||
|
|
||||||
|
// Get number of block
|
||||||
|
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun);
|
||||||
|
|
||||||
|
// Get block size in bytes
|
||||||
|
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun);
|
||||||
|
|
||||||
// Perform a full SCSI command (cbw, data, csw) in non-blocking manner.
|
// Perform a full SCSI command (cbw, data, csw) in non-blocking manner.
|
||||||
// Complete callback is invoked when SCSI op is complete.
|
// Complete callback is invoked when SCSI op is complete.
|
||||||
// return true if success, false if there is already pending operation.
|
// return true if success, false if there is already pending operation.
|
||||||
@ -74,10 +89,6 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_
|
|||||||
// Complete callback is invoked when SCSI op is complete.
|
// Complete callback is invoked when SCSI op is complete.
|
||||||
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb);
|
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb);
|
||||||
|
|
||||||
// Perform SCSI Read Capacity 10 command
|
|
||||||
// Complete callback is invoked when SCSI op is complete.
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer
|
// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer
|
||||||
// Complete callback is invoked when SCSI op is complete.
|
// Complete callback is invoked when SCSI op is complete.
|
||||||
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
|
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
|
||||||
@ -86,13 +97,19 @@ bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba,
|
|||||||
// Complete callback is invoked when SCSI op is complete.
|
// Complete callback is invoked when SCSI op is complete.
|
||||||
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
|
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
|
||||||
|
|
||||||
|
// Perform SCSI Read Capacity 10 command
|
||||||
|
// Complete callback is invoked when SCSI op is complete.
|
||||||
|
// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by
|
||||||
|
// simply call tuh_msc_get_block_count() and tuh_msc_get_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);
|
||||||
|
|
||||||
//------------- Application Callback -------------//
|
//------------- Application Callback -------------//
|
||||||
|
|
||||||
// Invoked when a device with MassStorage interface is mounted
|
// Invoked when a device with MassStorage interface is mounted
|
||||||
void tuh_msc_mounted_cb(uint8_t dev_addr);
|
void tuh_msc_mount_cb(uint8_t dev_addr);
|
||||||
|
|
||||||
// Invoked when a device with MassStorage interface is unmounted
|
// Invoked when a device with MassStorage interface is unmounted
|
||||||
void tuh_msc_unmounted_cb(uint8_t dev_addr);
|
void tuh_msc_unmount_cb(uint8_t dev_addr);
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Internal Class Driver API
|
// Internal Class Driver API
|
||||||
|
Loading…
x
Reference in New Issue
Block a user