summaryrefslogtreecommitdiff
path: root/src/class/msc
diff options
context:
space:
mode:
Diffstat (limited to 'src/class/msc')
-rw-r--r--src/class/msc/msc_device.c97
-rw-r--r--src/class/msc/msc_device.h3
-rw-r--r--src/class/msc/msc_host.c44
3 files changed, 84 insertions, 60 deletions
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index 97837b114..00b0a1d06 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -26,11 +26,11 @@
#include "tusb_option.h"
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MSC)
+#if (CFG_TUD_ENABLED && CFG_TUD_MSC)
+#include "device/dcd.h" // for faking dcd_event_xfer_complete
#include "device/usbd.h"
#include "device/usbd_pvt.h"
-#include "device/dcd.h" // for faking dcd_event_xfer_complete
#include "msc_device.h"
@@ -209,7 +209,7 @@ TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
{ .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" },
{ .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" },
{ .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" },
- { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent Allow Medium Removal" },
+ { .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent/Allow Medium Removal" },
{ .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" },
{ .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" },
{ .key = SCSI_CMD_READ_FORMAT_CAPACITY , .data = "Read Format Capacity" },
@@ -239,6 +239,12 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u
return true;
}
+static inline void set_sense_medium_not_present(uint8_t lun)
+{
+ // default sense is NOT READY, MEDIUM NOT PRESENT
+ tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00);
+}
+
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
@@ -406,7 +412,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
return false;
}
- TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
+ TU_LOG(MSC_DEBUG, " SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
//TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2);
p_csw->signature = MSC_CSW_SIGNATURE;
@@ -457,7 +463,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
{
// Didn't check for case 9 (Ho > Dn), which requires examining scsi command first
// but it is OK to just receive data then responded with failed status
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) );
+ TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, (uint16_t) p_msc->total_len) );
}
}else
{
@@ -467,13 +473,13 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// Invoke user callback if not built-in
if ( (resplen < 0) && (p_msc->sense_key == 0) )
{
- resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len);
+ resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len);
}
if ( resplen < 0 )
{
// unsupported command
- TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n");
+ TU_LOG(MSC_DEBUG, " SCSI unsupported or failed command\r\n");
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}
else if (resplen == 0)
@@ -500,7 +506,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
{
// cannot return more than host expect
p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes);
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) );
+ TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) p_msc->total_len) );
}
}
}
@@ -508,7 +514,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
break;
case MSC_STAGE_DATA:
- TU_LOG(MSC_DEBUG, " SCSI Data\r\n");
+ TU_LOG(MSC_DEBUG, " SCSI Data [Lun%u]\r\n", p_cbw->lun);
//TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2);
if (SCSI_CMD_READ_10 == p_cbw->command[0])
@@ -535,7 +541,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// OUT transfer, invoke callback if needed
if ( !is_data_in(p_cbw->dir) )
{
- int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len);
+ int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, (uint16_t) p_msc->total_len);
if ( cb_result < 0 )
{
@@ -569,7 +575,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// Wait for the Status phase to complete
if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) )
{
- TU_LOG(MSC_DEBUG, " SCSI Status = %u\r\n", p_csw->status);
+ TU_LOG(MSC_DEBUG, " SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status);
// TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2);
// Invoke complete callback if defined
@@ -654,8 +660,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
// Failed status response
resplen = - 1;
- // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ // set default sense if not set by callback
+ if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
}
break;
@@ -670,8 +676,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
// Failed status response
resplen = - 1;
- // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ // set default sense if not set by callback
+ if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
}
}
break;
@@ -691,17 +697,17 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
{
resplen = -1;
- // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ // set default sense if not set by callback
+ if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
}else
{
scsi_read_capacity10_resp_t read_capa10;
- read_capa10.last_lba = tu_htonl(block_count-1);
+ read_capa10.last_lba = tu_htonl(block_count-1);
read_capa10.block_size = tu_htonl(block_size);
resplen = sizeof(read_capa10);
- memcpy(buffer, &read_capa10, resplen);
+ memcpy(buffer, &read_capa10, (size_t) resplen);
}
}
break;
@@ -727,15 +733,15 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
{
resplen = -1;
- // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ // set default sense if not set by callback
+ if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
}else
{
read_fmt_capa.block_num = tu_htonl(block_count);
read_fmt_capa.block_size_u16 = tu_htons(block_size);
resplen = sizeof(read_fmt_capa);
- memcpy(buffer, &read_fmt_capa, resplen);
+ memcpy(buffer, &read_fmt_capa, (size_t) resplen);
}
}
break;
@@ -747,6 +753,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
.is_removable = 1,
.version = 2,
.response_data_format = 2,
+ .additional_length = sizeof(scsi_inquiry_resp_t) - 5,
};
// vendor_id, product_id, product_rev is space padded string
@@ -757,7 +764,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev);
resplen = sizeof(inquiry_rsp);
- memcpy(buffer, &inquiry_rsp, resplen);
+ memcpy(buffer, &inquiry_rsp, (size_t) resplen);
}
break;
@@ -765,10 +772,10 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
{
scsi_mode_sense6_resp_t mode_resp =
{
- .data_len = 3,
- .medium_type = 0,
- .write_protected = false,
- .reserved = 0,
+ .data_len = 3,
+ .medium_type = 0,
+ .write_protected = false,
+ .reserved = 0,
.block_descriptor_len = 0 // no block descriptor are included
};
@@ -781,7 +788,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
mode_resp.write_protected = !writable;
resplen = sizeof(mode_resp);
- memcpy(buffer, &mode_resp, resplen);
+ memcpy(buffer, &mode_resp, (size_t) resplen);
}
break;
@@ -789,18 +796,23 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
{
scsi_sense_fixed_resp_t sense_rsp =
{
- .response_code = 0x70,
+ .response_code = 0x70, // current, fixed format
.valid = 1
};
- sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
-
- sense_rsp.sense_key = p_msc->sense_key;
+ sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
+ sense_rsp.sense_key = (uint8_t) (p_msc->sense_key & 0x0F);
sense_rsp.add_sense_code = p_msc->add_sense_code;
sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier;
resplen = sizeof(sense_rsp);
- memcpy(buffer, &sense_rsp, resplen);
+ memcpy(buffer, &sense_rsp, (size_t) resplen);
+
+ // request sense callback could overwrite the sense data
+ if (tud_msc_request_sense_cb)
+ {
+ resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t) bufsize);
+ }
// Clear sense data after copy
tud_msc_set_sense(lun, 0, 0, 0);
@@ -835,8 +847,8 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
// negative means error -> endpoint is stalled & status in CSW set to failed
TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n");
- // Sense = Flash not ready for access
- tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00);
+ // set sense
+ set_sense_medium_not_present(p_cbw->lun);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}
@@ -847,7 +859,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
}
else
{
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, nbytes), );
+ TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, (uint16_t) nbytes), );
}
}
@@ -871,7 +883,7 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
}
// remaining bytes capped at class buffer
- int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len);
+ uint16_t nbytes = (uint16_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len);
// Write10 callback will be called later when usb transfer complete
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), );
@@ -900,8 +912,8 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3
// update actual byte before failed
p_msc->xferred_len += xferred_bytes;
- // Sense = Flash not ready for access
- tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00);
+ // Set sense
+ set_sense_medium_not_present(p_cbw->lun);
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}else
@@ -909,14 +921,15 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3
// Application consume less than what we got (including zero)
if ( (uint32_t) nbytes < xferred_bytes )
{
+ uint32_t const left_over = xferred_bytes - (uint32_t) nbytes;
if ( nbytes > 0 )
{
- p_msc->xferred_len += nbytes;
- memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes);
+ p_msc->xferred_len += (uint16_t) nbytes;
+ memmove(_mscd_buf, _mscd_buf+nbytes, left_over);
}
// simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter
- dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false);
+ dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false);
}
else
{
diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h
index d32694340..5839b168d 100644
--- a/src/class/msc/msc_device.h
+++ b/src/class/msc/msc_device.h
@@ -131,6 +131,9 @@ TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void);
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject);
+// Invoked when received REQUEST_SENSE
+TU_ATTR_WEAK int32_t tud_msc_request_sense_cb(uint8_t lun, void* buffer, uint16_t bufsize);
+
// Invoked when Read10 command is complete
TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun);
diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c
index fa6519956..934f79ff7 100644
--- a/src/class/msc/msc_host.c
+++ b/src/class/msc/msc_host.c
@@ -26,7 +26,7 @@
#include "tusb_option.h"
-#if TUSB_OPT_HOST_ENABLED & CFG_TUH_MSC
+#if CFG_TUH_ENABLED && CFG_TUH_MSC
#include "host/usbh.h"
#include "host/usbh_classdriver.h"
@@ -325,19 +325,19 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
p_msc->stage = MSC_STAGE_DATA;
uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out;
- TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, cbw->total_bytes));
+ TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes));
}else
{
// 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)));
+ TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
}
break;
case MSC_STAGE_DATA:
// 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)));
+ TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
break;
case MSC_STAGE_STATUS:
@@ -358,18 +358,19 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
// MSC Enumeration
//--------------------------------------------------------------------+
-static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+static void config_get_maxlun_complete (tuh_xfer_t* xfer);
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_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 *desc_itf, uint16_t max_len)
{
+ (void) rhport;
TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);
// msc driver length is fixed
- uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
+ uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
TU_ASSERT(drv_len <= max_len);
msch_interface_t* p_msc = get_itf(dev_addr);
@@ -378,7 +379,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
for(uint32_t i=0; i<2; i++)
{
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));
+ TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc));
if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
{
@@ -405,7 +406,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
//------------- Get Max Lun -------------//
TU_LOG2("MSC Get Max Lun\r\n");
- tusb_control_request_t request =
+ tusb_control_request_t const request =
{
.bmRequestType_bit =
{
@@ -418,27 +419,34 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
.wIndex = itf_num,
.wLength = 1
};
- TU_ASSERT(tuh_control_xfer(dev_addr, &request, &p_msc->max_lun, config_get_maxlun_complete));
+
+ tuh_xfer_t xfer =
+ {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = &p_msc->max_lun,
+ .complete_cb = config_get_maxlun_complete,
+ .user_data = 0
+ };
+ TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
-static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
+static void config_get_maxlun_complete (tuh_xfer_t* xfer)
{
- (void) request;
-
- msch_interface_t* p_msc = get_itf(dev_addr);
+ uint8_t const daddr = xfer->daddr;
+ msch_interface_t* p_msc = get_itf(daddr);
// STALL means zero
- p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0;
+ p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0;
p_msc->max_lun++; // MAX LUN is minus 1 by specs
// TODO multiple LUN support
TU_LOG2("SCSI Test Unit Ready\r\n");
uint8_t const lun = 0;
- tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete);
-
- return true;
+ tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete);
}
static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
@@ -476,7 +484,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw
// Capacity response field: Block size and Last LBA are both Big-Endian
scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _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);
+ p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
// Mark enumeration is complete
p_msc->mounted = true;