Skip to content

Commit 3532c25

Browse files
tmon-nordiccarlescufi
authored andcommitted
usb: device_next: accept padded Mass Storage CDBs
Universal Serial Bus Mass Storage Specification For Bootability requires that device shall accept Bulk-Only-Transport bCBWCBLength of 12 for all commands documented in the specification. Allow padding for commands documented in Bootability specification, but leave others intact. This fixes Request Sense on Windows 11 which previously failed due to bCBWCBLength being 12 instead of 6. Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
1 parent ee17b17 commit 3532c25

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

subsys/usb/device_next/class/usbd_msc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,10 @@ static void msc_process_cbw(struct msc_bot_ctx *ctx)
304304
struct scsi_ctx *lun = &ctx->luns[ctx->cbw.bCBWLUN];
305305
bool cmd_is_data_read, cmd_is_data_write;
306306
size_t data_len;
307+
int cb_len;
307308

308-
data_len = scsi_cmd(lun, ctx->cbw.CBWCB, ctx->cbw.bCBWCBLength, ctx->scsi_buf);
309+
cb_len = scsi_usb_boot_cmd_len(ctx->cbw.CBWCB, ctx->cbw.bCBWCBLength);
310+
data_len = scsi_cmd(lun, ctx->cbw.CBWCB, cb_len, ctx->scsi_buf);
309311
ctx->scsi_bytes = data_len;
310312
ctx->scsi_offset = 0;
311313
cmd_is_data_read = scsi_cmd_is_data_read(lun);

subsys/usb/device_next/class/usbd_msc_scsi.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,29 @@ SCSI_CMD_HANDLER(MODE_SENSE_10)
806806
return good(ctx, length);
807807
}
808808

809+
int scsi_usb_boot_cmd_len(const uint8_t *cb, int len)
810+
{
811+
/* Universal Serial Bus Mass Storage Specification For Bootability
812+
* requires device to accept CBW padded to 12 bytes for commands
813+
* documented in Bootability specification. Windows 11 uses padding
814+
* for REQUEST SENSE command.
815+
*/
816+
if (len != 12) {
817+
return len;
818+
}
819+
820+
switch (cb[0]) {
821+
case TEST_UNIT_READY: return sizeof(SCSI_CMD_STRUCT(TEST_UNIT_READY));
822+
case REQUEST_SENSE: return sizeof(SCSI_CMD_STRUCT(REQUEST_SENSE));
823+
case INQUIRY: return sizeof(SCSI_CMD_STRUCT(INQUIRY));
824+
case READ_CAPACITY_10: return sizeof(SCSI_CMD_STRUCT(READ_CAPACITY_10));
825+
case READ_10: return sizeof(SCSI_CMD_STRUCT(READ_10));
826+
case WRITE_10: return sizeof(SCSI_CMD_STRUCT(WRITE_10));
827+
case MODE_SENSE_10: return sizeof(SCSI_CMD_STRUCT(MODE_SENSE_10));
828+
default: return len;
829+
}
830+
}
831+
809832
size_t scsi_cmd(struct scsi_ctx *ctx, const uint8_t *cb, int len,
810833
uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])
811834
{

subsys/usb/device_next/class/usbd_msc_scsi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct scsi_ctx {
8484
void scsi_init(struct scsi_ctx *ctx, const char *disk, const char *vendor,
8585
const char *product, const char *revision);
8686
void scsi_reset(struct scsi_ctx *ctx);
87+
int scsi_usb_boot_cmd_len(const uint8_t *cb, int len);
8788
size_t scsi_cmd(struct scsi_ctx *ctx, const uint8_t *cb, int len,
8889
uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE]);
8990

0 commit comments

Comments
 (0)