Skip to content

Commit fcca8bb

Browse files
authored
Merge pull request hathach#1327 from hathach/msc-request-sense
Add msc request sense callback
2 parents de4932d + 46f4f7f commit fcca8bb

File tree

6 files changed

+43
-58
lines changed

6 files changed

+43
-58
lines changed

examples/device/cdc_msc/src/msc_disk.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
243243

244244
switch (scsi_cmd[0])
245245
{
246-
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
247-
// Host is about to read/write etc ... better not to disconnect disk
248-
resplen = 0;
249-
break;
250-
251246
default:
252247
// Set Sense = Invalid Command Operation
253248
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);

examples/device/cdc_msc_freertos/src/msc_disk.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
221221

222222
switch (scsi_cmd[0])
223223
{
224-
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
225-
// Host is about to read/write etc ... better not to disconnect disk
226-
resplen = 0;
227-
break;
228-
229224
default:
230225
// Set Sense = Invalid Command Operation
231226
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);

examples/device/dynamic_configuration/src/msc_disk.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
221221

222222
switch (scsi_cmd[0])
223223
{
224-
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
225-
// Host is about to read/write etc ... better not to disconnect disk
226-
resplen = 0;
227-
break;
228-
229224
default:
230225
// Set Sense = Invalid Command Operation
231226
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);

examples/device/msc_dual_lun/src/msc_disk_dual.c

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
#if CFG_TUD_MSC
3030

31+
// When button is pressed, LUN1 will be set to not ready to simulate
32+
// medium not present (e.g SD card removed)
33+
3134
// Some MCU doesn't have enough 8KB SRAM to store the whole disk
3235
// We will use Flash as read-only disk with board that has
3336
// CFG_EXAMPLE_MSC_READONLY defined
@@ -227,7 +230,7 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16
227230
// return true allowing host to read/write this LUN e.g SD card inserted
228231
bool tud_msc_test_unit_ready_cb(uint8_t lun)
229232
{
230-
(void) lun;
233+
if ( lun == 1 && board_button_read() ) return false;
231234

232235
return true; // RAM disk is always ready
233236
}
@@ -320,23 +323,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
320323

321324
switch (scsi_cmd[0])
322325
{
323-
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
324-
// Host is about to read/write etc ... better not to disconnect disk
325-
resplen = 0;
326-
break;
327-
328-
case SCSI_CMD_START_STOP_UNIT:
329-
// Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power
330-
/* scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd;
331-
// Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well
332-
// Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage
333-
start_stop->start;
334-
start_stop->load_eject;
335-
*/
336-
resplen = 0;
337-
break;
338-
339-
340326
default:
341327
// Set Sense = Invalid Command Operation
342328
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);

src/class/msc/msc_device.c

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
209209
{ .key = SCSI_CMD_MODE_SELECT_6 , .data = "Mode_Select 6" },
210210
{ .key = SCSI_CMD_MODE_SENSE_6 , .data = "Mode_Sense 6" },
211211
{ .key = SCSI_CMD_START_STOP_UNIT , .data = "Start Stop Unit" },
212-
{ .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent Allow Medium Removal" },
212+
{ .key = SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL , .data = "Prevent/Allow Medium Removal" },
213213
{ .key = SCSI_CMD_READ_CAPACITY_10 , .data = "Read Capacity10" },
214214
{ .key = SCSI_CMD_REQUEST_SENSE , .data = "Request Sense" },
215215
{ .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
239239
return true;
240240
}
241241

242+
static inline void set_sense_medium_not_present(uint8_t lun)
243+
{
244+
// default sense is NOT READY, MEDIUM NOT PRESENT
245+
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00);
246+
}
247+
242248
//--------------------------------------------------------------------+
243249
// USBD Driver API
244250
//--------------------------------------------------------------------+
@@ -406,7 +412,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
406412
return false;
407413
}
408414

409-
TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
415+
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]));
410416
//TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2);
411417

412418
p_csw->signature = MSC_CSW_SIGNATURE;
@@ -473,7 +479,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
473479
if ( resplen < 0 )
474480
{
475481
// unsupported command
476-
TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n");
482+
TU_LOG(MSC_DEBUG, " SCSI unsupported or failed command\r\n");
477483
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
478484
}
479485
else if (resplen == 0)
@@ -508,7 +514,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
508514
break;
509515

510516
case MSC_STAGE_DATA:
511-
TU_LOG(MSC_DEBUG, " SCSI Data\r\n");
517+
TU_LOG(MSC_DEBUG, " SCSI Data [Lun%u]\r\n", p_cbw->lun);
512518
//TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2);
513519

514520
if (SCSI_CMD_READ_10 == p_cbw->command[0])
@@ -569,7 +575,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
569575
// Wait for the Status phase to complete
570576
if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) )
571577
{
572-
TU_LOG(MSC_DEBUG, " SCSI Status = %u\r\n", p_csw->status);
578+
TU_LOG(MSC_DEBUG, " SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status);
573579
// TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2);
574580

575581
// 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_
654660
// Failed status response
655661
resplen = - 1;
656662

657-
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
658-
if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
663+
// set default sense if not set by callback
664+
if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
659665
}
660666
break;
661667

@@ -670,8 +676,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
670676
// Failed status response
671677
resplen = - 1;
672678

673-
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
674-
if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
679+
// set default sense if not set by callback
680+
if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
675681
}
676682
}
677683
break;
@@ -691,13 +697,13 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
691697
{
692698
resplen = -1;
693699

694-
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
695-
if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
700+
// set default sense if not set by callback
701+
if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
696702
}else
697703
{
698704
scsi_read_capacity10_resp_t read_capa10;
699705

700-
read_capa10.last_lba = tu_htonl(block_count-1);
706+
read_capa10.last_lba = tu_htonl(block_count-1);
701707
read_capa10.block_size = tu_htonl(block_size);
702708

703709
resplen = sizeof(read_capa10);
@@ -727,8 +733,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
727733
{
728734
resplen = -1;
729735

730-
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
731-
if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
736+
// set default sense if not set by callback
737+
if ( p_msc->sense_key == 0 ) set_sense_medium_not_present(lun);
732738
}else
733739
{
734740
read_fmt_capa.block_num = tu_htonl(block_count);
@@ -765,10 +771,10 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
765771
{
766772
scsi_mode_sense6_resp_t mode_resp =
767773
{
768-
.data_len = 3,
769-
.medium_type = 0,
770-
.write_protected = false,
771-
.reserved = 0,
774+
.data_len = 3,
775+
.medium_type = 0,
776+
.write_protected = false,
777+
.reserved = 0,
772778
.block_descriptor_len = 0 // no block descriptor are included
773779
};
774780

@@ -789,19 +795,24 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
789795
{
790796
scsi_sense_fixed_resp_t sense_rsp =
791797
{
792-
.response_code = 0x70,
798+
.response_code = 0x70, // current, fixed format
793799
.valid = 1
794800
};
795801

796-
sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
797-
802+
sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
798803
sense_rsp.sense_key = p_msc->sense_key;
799804
sense_rsp.add_sense_code = p_msc->add_sense_code;
800805
sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier;
801806

802807
resplen = sizeof(sense_rsp);
803808
memcpy(buffer, &sense_rsp, resplen);
804809

810+
// request sense callback could overwrite the sense data
811+
if (tud_msc_request_sense_cb)
812+
{
813+
resplen = tud_msc_request_sense_cb(lun, buffer, bufsize);
814+
}
815+
805816
// Clear sense data after copy
806817
tud_msc_set_sense(lun, 0, 0, 0);
807818
}
@@ -835,8 +846,8 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
835846
// negative means error -> endpoint is stalled & status in CSW set to failed
836847
TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n");
837848

838-
// Sense = Flash not ready for access
839-
tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00);
849+
// set sense
850+
set_sense_medium_not_present(p_cbw->lun);
840851

841852
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
842853
}
@@ -900,8 +911,8 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3
900911
// update actual byte before failed
901912
p_msc->xferred_len += xferred_bytes;
902913

903-
// Sense = Flash not ready for access
904-
tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00);
914+
// Set sense
915+
set_sense_medium_not_present(p_cbw->lun);
905916

906917
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
907918
}else

src/class/msc/msc_device.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ TU_ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void);
131131
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
132132
TU_ATTR_WEAK bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject);
133133

134+
// Invoked when received REQUEST_SENSE
135+
TU_ATTR_WEAK int32_t tud_msc_request_sense_cb(uint8_t lun, void* buffer, uint16_t bufsize);
136+
134137
// Invoked when Read10 command is complete
135138
TU_ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun);
136139

0 commit comments

Comments
 (0)