mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Make SCSI structs and definitions complete. Change all CDB size 6 commands to format version2, version 3, soon.
This commit is contained in:
parent
643972ad51
commit
fee903bbac
2 changed files with 394 additions and 243 deletions
375
masstorage.cpp
375
masstorage.cpp
|
@ -54,6 +54,22 @@ boolean BulkOnly::WriteProtected(uint8_t lun) {
|
||||||
return WriteOk[lun];
|
return WriteOk[lun];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap and execute a SCSI CDB with length of 6
|
||||||
|
*
|
||||||
|
* @param cdb CDB to execute
|
||||||
|
* @param buf_size Size of expected transaction
|
||||||
|
* @param buf Buffer
|
||||||
|
* @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
|
||||||
|
// promote to 32bits.
|
||||||
|
CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
|
||||||
|
SetCurLUN(cdb->LUN);
|
||||||
|
return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock or Unlock the tray or door on device.
|
* Lock or Unlock the tray or door on device.
|
||||||
* Caution: Some devices with buggy firmware will lock up.
|
* Caution: Some devices with buggy firmware will lock up.
|
||||||
|
@ -65,24 +81,8 @@ boolean BulkOnly::WriteProtected(uint8_t lun) {
|
||||||
uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
|
uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
|
||||||
Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
|
Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
|
||||||
Notify(PSTR("---------\r\n"), 0x80);
|
Notify(PSTR("---------\r\n"), 0x80);
|
||||||
|
CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);
|
||||||
CommandBlockWrapper cbw;
|
return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN);
|
||||||
SetCurLUN(lun);
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
|
||||||
cbw.dCBWDataTransferLength = 0;
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 6;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_PREVENT_REMOVAL;
|
|
||||||
cbw.CBWCB[4] = lock;
|
|
||||||
|
|
||||||
return (HandleSCSIError(Transaction(&cbw, 0, NULL, 0)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,26 +96,17 @@ uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
|
||||||
uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
|
uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
|
||||||
Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
|
Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
|
||||||
Notify(PSTR("-----------------\r\n"), 0x80);
|
Notify(PSTR("-----------------\r\n"), 0x80);
|
||||||
SetCurLUN(lun);
|
//SetCurLUN(lun);
|
||||||
uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
|
uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
|
||||||
if (bAddress) {
|
if (bAddress) {
|
||||||
CommandBlockWrapper cbw;
|
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, 0, MASS_CMD_DIR_OUT, lun, 6, SCSI_CMD_START_STOP_UNIT);
|
||||||
|
//cbw.CBWCB[1] = lun << 5;
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
//cbw.CBWCB[4] = ctl & 0x03;
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
//rcode = HandleSCSIError(Transaction(&cbw, 0, NULL));
|
||||||
cbw.dCBWDataTransferLength = 0;
|
CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_OUT;
|
rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
|
||||||
cbw.bmCBWLUN = lun;
|
} else {
|
||||||
cbw.bmCBWCBLength = 6;
|
SetCurLUN(lun);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_START_STOP_UNIT;
|
|
||||||
cbw.CBWCB[1] = lun << 5;
|
|
||||||
cbw.CBWCB[4] = ctl & 0x03;
|
|
||||||
|
|
||||||
rcode = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
|
|
||||||
}
|
}
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
@ -142,28 +133,18 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
|
||||||
Notify(PSTR("\r\nblock size:\t"), 0x90);
|
Notify(PSTR("\r\nblock size:\t"), 0x90);
|
||||||
D_PrintHex<uint16_t > (bsize, 0x90);
|
D_PrintHex<uint16_t > (bsize, 0x90);
|
||||||
Notify(PSTR("\r\n---------\r\n"), 0x80);
|
Notify(PSTR("\r\n---------\r\n"), 0x80);
|
||||||
CommandBlockWrapper cbw;
|
CommandBlockWrapper cbw = CommandBlockWrapper(0, ((uint32_t)bsize * blocks), MASS_CMD_DIR_IN, lun, 10, SCSI_CMD_READ_10);
|
||||||
|
|
||||||
again:
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 10;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_READ_10;
|
|
||||||
cbw.CBWCB[1] = lun << 5;
|
cbw.CBWCB[1] = lun << 5;
|
||||||
cbw.CBWCB[2] = ((addr >> 24) & 0xff);
|
cbw.CBWCB[2] = ((addr >> 24) & 0xff);
|
||||||
cbw.CBWCB[3] = ((addr >> 16) & 0xff);
|
cbw.CBWCB[3] = ((addr >> 16) & 0xff);
|
||||||
cbw.CBWCB[4] = ((addr >> 8) & 0xff);
|
cbw.CBWCB[4] = ((addr >> 8) & 0xff);
|
||||||
cbw.CBWCB[5] = (addr & 0xff);
|
cbw.CBWCB[5] = (addr & 0xff);
|
||||||
cbw.CBWCB[8] = blocks;
|
cbw.CBWCB[8] = blocks;
|
||||||
|
|
||||||
|
again:
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
cbw.dCBWTag = ++dCBWTag;
|
||||||
SetCurLUN(lun);
|
SetCurLUN(lun);
|
||||||
uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
|
uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, buf));
|
||||||
if (er == MASS_ERR_STALL) {
|
if (er == MASS_ERR_STALL) {
|
||||||
MediaCTL(lun, 1);
|
MediaCTL(lun, 1);
|
||||||
delay(150);
|
delay(150);
|
||||||
|
@ -196,20 +177,7 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc
|
||||||
D_PrintHex<uint16_t > (bsize, 0x90);
|
D_PrintHex<uint16_t > (bsize, 0x90);
|
||||||
Notify(PSTR("\r\n---------\r\n"), 0x80);
|
Notify(PSTR("\r\n---------\r\n"), 0x80);
|
||||||
//MediaCTL(lun, 0x01);
|
//MediaCTL(lun, 0x01);
|
||||||
CommandBlockWrapper cbw;
|
CommandBlockWrapper cbw = CommandBlockWrapper(0, ((uint32_t)bsize * blocks), MASS_CMD_DIR_OUT, lun, 10, SCSI_CMD_WRITE_10);
|
||||||
|
|
||||||
again:
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
|
||||||
cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_OUT;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 10;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
|
|
||||||
cbw.CBWCB[1] = lun << 5;
|
cbw.CBWCB[1] = lun << 5;
|
||||||
cbw.CBWCB[2] = ((addr >> 24) & 0xff);
|
cbw.CBWCB[2] = ((addr >> 24) & 0xff);
|
||||||
cbw.CBWCB[3] = ((addr >> 16) & 0xff);
|
cbw.CBWCB[3] = ((addr >> 16) & 0xff);
|
||||||
|
@ -217,8 +185,10 @@ again:
|
||||||
cbw.CBWCB[5] = (addr & 0xff);
|
cbw.CBWCB[5] = (addr & 0xff);
|
||||||
cbw.CBWCB[8] = 1;
|
cbw.CBWCB[8] = 1;
|
||||||
|
|
||||||
|
again:
|
||||||
|
cbw.dCBWTag = ++dCBWTag;
|
||||||
SetCurLUN(lun);
|
SetCurLUN(lun);
|
||||||
uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0));
|
uint8_t er = HandleSCSIError(Transaction(&cbw, bsize, (void*)buf));
|
||||||
if (er == MASS_ERR_WRITE_STALL) {
|
if (er == MASS_ERR_WRITE_STALL) {
|
||||||
MediaCTL(lun, 1);
|
MediaCTL(lun, 1);
|
||||||
delay(150);
|
delay(150);
|
||||||
|
@ -243,7 +213,7 @@ bIface(0),
|
||||||
bNumEP(1),
|
bNumEP(1),
|
||||||
qNextPollTime(0),
|
qNextPollTime(0),
|
||||||
bPollEnable(false),
|
bPollEnable(false),
|
||||||
dCBWTag(0),
|
//dCBWTag(0),
|
||||||
bLastUsbError(0) {
|
bLastUsbError(0) {
|
||||||
ClearAllEP();
|
ClearAllEP();
|
||||||
dCBWTag = 0;
|
dCBWTag = 0;
|
||||||
|
@ -692,23 +662,15 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
||||||
Notify(PSTR("\r\nInquiry\r\n"), 0x80);
|
Notify(PSTR("\r\nInquiry\r\n"), 0x80);
|
||||||
Notify(PSTR("---------\r\n"), 0x80);
|
Notify(PSTR("---------\r\n"), 0x80);
|
||||||
|
|
||||||
CommandBlockWrapper cbw;
|
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, bsize, MASS_CMD_DIR_IN, lun, 6, SCSI_CMD_INQUIRY);
|
||||||
SetCurLUN(lun);
|
//SetCurLUN(lun);
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
//cbw.CBWCB[1] = lun << 5;
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
//cbw.CBWCB[4] = bsize;
|
||||||
cbw.dCBWDataTransferLength = bsize;
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 6;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
//uint8_t rc = HandleSCSIError(Transaction(&cbw, bsize, buf));
|
||||||
cbw.CBWCB[i] = 0;
|
CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);
|
||||||
|
uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
|
|
||||||
cbw.CBWCB[1] = lun << 5;
|
|
||||||
cbw.CBWCB[4] = bsize;
|
|
||||||
|
|
||||||
uint8_t rc = HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
|
|
||||||
#if 0
|
#if 0
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
printf("LUN %i `", lun);
|
printf("LUN %i `", lun);
|
||||||
|
@ -752,6 +714,54 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For driver use only.
|
||||||
|
*
|
||||||
|
* @param lun Logical Unit Number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
|
||||||
|
//SetCurLUN(lun);
|
||||||
|
if (!bAddress)
|
||||||
|
return MASS_ERR_UNIT_NOT_READY;
|
||||||
|
|
||||||
|
Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
|
||||||
|
Notify(PSTR("-----------------\r\n"), 0x80);
|
||||||
|
|
||||||
|
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, 0, MASS_CMD_DIR_OUT, lun, 6, SCSI_CMD_TEST_UNIT_READY);
|
||||||
|
//cbw.CBWCB[1] = lun;
|
||||||
|
//uint8_t rc = HandleSCSIError(Transaction(&cbw, 0, NULL));
|
||||||
|
//return (rc);
|
||||||
|
CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
|
||||||
|
return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For driver use only.
|
||||||
|
*
|
||||||
|
* @param lun Logical Unit Number
|
||||||
|
* @param pc
|
||||||
|
* @param page
|
||||||
|
* @param subpage
|
||||||
|
* @param len
|
||||||
|
* @param pbuf
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
|
||||||
|
Notify(PSTR("\r\rModeSense\r\n"), 0x80);
|
||||||
|
Notify(PSTR("------------\r\n"), 0x80);
|
||||||
|
|
||||||
|
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, ((uint32_t)len), MASS_CMD_DIR_IN, lun, 6, SCSI_CMD_MODE_SENSE_6);
|
||||||
|
//SetCurLUN(lun);
|
||||||
|
//cbw.CBWCB[2] = ((pc << 6) | page);
|
||||||
|
//cbw.CBWCB[3] = subpage;
|
||||||
|
//cbw.CBWCB[4] = len;
|
||||||
|
//return HandleSCSIError(Transaction(&cbw, 512, pbuf));
|
||||||
|
CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage) , len, 0);
|
||||||
|
return SCSITransaction6(&cdb, 512, pbuf, (uint8_t)MASS_CMD_DIR_IN);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For driver use only.
|
* For driver use only.
|
||||||
*
|
*
|
||||||
|
@ -764,87 +774,16 @@ uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
|
||||||
Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
|
Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
|
||||||
Notify(PSTR("----------------\r\n"), 0x80);
|
Notify(PSTR("----------------\r\n"), 0x80);
|
||||||
|
|
||||||
CommandBlockWrapper cbw;
|
|
||||||
|
//CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, size, MASS_CMD_DIR_IN, lun, 6, SCSI_CMD_REQUEST_SENSE);
|
||||||
|
//SetCurLUN(lun);
|
||||||
|
//cbw.CBWCB[1] = lun << 5;
|
||||||
|
//cbw.CBWCB[4] = size;
|
||||||
|
|
||||||
|
CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);
|
||||||
|
CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
|
||||||
SetCurLUN(lun);
|
SetCurLUN(lun);
|
||||||
|
return Transaction(&cbw, size, buf);
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
|
||||||
cbw.dCBWDataTransferLength = size;
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 6;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
|
|
||||||
cbw.CBWCB[1] = lun << 5;
|
|
||||||
cbw.CBWCB[4] = size;
|
|
||||||
|
|
||||||
return Transaction(&cbw, size, buf, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For driver use only.
|
|
||||||
*
|
|
||||||
* @param lun Logical Unit Number
|
|
||||||
* @param bsize
|
|
||||||
* @param buf
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
|
||||||
Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
|
|
||||||
Notify(PSTR("---------------\r\n"), 0x80);
|
|
||||||
CommandBlockWrapper cbw;
|
|
||||||
|
|
||||||
SetCurLUN(lun);
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
|
||||||
cbw.dCBWDataTransferLength = bsize;
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 10;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_READ_CAPACITY_10;
|
|
||||||
cbw.CBWCB[1] = lun << 5;
|
|
||||||
|
|
||||||
return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For driver use only.
|
|
||||||
*
|
|
||||||
* @param lun Logical Unit Number
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
|
|
||||||
SetCurLUN(lun);
|
|
||||||
if (!bAddress)
|
|
||||||
return MASS_ERR_UNIT_NOT_READY;
|
|
||||||
|
|
||||||
Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
|
|
||||||
Notify(PSTR("-----------------\r\n"), 0x80);
|
|
||||||
|
|
||||||
CommandBlockWrapper cbw;
|
|
||||||
uint8_t rc;
|
|
||||||
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
|
||||||
cbw.dCBWDataTransferLength = 0;
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_OUT;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 6;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_TEST_UNIT_READY;
|
|
||||||
cbw.CBWCB[1] = lun;
|
|
||||||
rc = HandleSCSIError(Transaction(&cbw, 0, NULL, 0));
|
|
||||||
return (rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -874,6 +813,25 @@ uint8_t BulkOnly::Page3F(uint8_t lun) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For driver use only.
|
||||||
|
*
|
||||||
|
* @param lun Logical Unit Number
|
||||||
|
* @param bsize
|
||||||
|
* @param buf
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
||||||
|
Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
|
||||||
|
Notify(PSTR("---------------\r\n"), 0x80);
|
||||||
|
CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, bsize, MASS_CMD_DIR_IN, lun, 10, SCSI_CMD_READ_CAPACITY_10);
|
||||||
|
|
||||||
|
SetCurLUN(lun);
|
||||||
|
cbw.CBWCB[1] = lun << 5;
|
||||||
|
|
||||||
|
return HandleSCSIError(Transaction(&cbw, bsize, buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1056,6 +1014,13 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
|
||||||
return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
|
return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WANT_PARSER
|
||||||
|
|
||||||
|
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
|
||||||
|
return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For driver use only.
|
* For driver use only.
|
||||||
*
|
*
|
||||||
|
@ -1065,16 +1030,24 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
|
||||||
* @param flags
|
* @param flags
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, uint8_t flags) {
|
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
|
||||||
|
#if WANT_PARSER
|
||||||
|
, uint8_t flags
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
|
uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
|
||||||
boolean write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
|
boolean write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
|
||||||
|
#if WANT_PARSER
|
||||||
|
|
||||||
boolean callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
|
boolean callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
|
||||||
|
#endif
|
||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
uint8_t usberr;
|
uint8_t usberr;
|
||||||
CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
|
CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
|
||||||
|
// Not needed any longer, the constructor ensures this now
|
||||||
// Fix reserved bits.
|
// Fix reserved bits.
|
||||||
pcbw->bmReserved1 = 0;
|
//pcbw->bmReserved1 = 0;
|
||||||
pcbw->bmReserved2 = 0;
|
//pcbw->bmReserved2 = 0;
|
||||||
ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
|
ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
|
||||||
|
|
||||||
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
|
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
|
||||||
|
@ -1086,13 +1059,18 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
|
||||||
} else {
|
} else {
|
||||||
if (bytes) {
|
if (bytes) {
|
||||||
if (!write) {
|
if (!write) {
|
||||||
|
#if WANT_PARSER
|
||||||
if (callback) {
|
if (callback) {
|
||||||
uint8_t rbuf[bytes];
|
uint8_t rbuf[bytes];
|
||||||
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
|
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
|
||||||
if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
|
if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
|
||||||
} else {
|
} else {
|
||||||
|
#endif
|
||||||
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
|
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
|
||||||
|
#if WANT_PARSER
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
ret = HandleUsbError(usberr, epDataInIndex);
|
ret = HandleUsbError(usberr, epDataInIndex);
|
||||||
} else {
|
} else {
|
||||||
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
|
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
|
||||||
|
@ -1104,7 +1082,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!ret || ret == MASS_ERR_WRITE_STALL || ret == MASS_ERR_STALL) {
|
|
||||||
{
|
{
|
||||||
bytes = sizeof (CommandStatusWrapper);
|
bytes = sizeof (CommandStatusWrapper);
|
||||||
int tries = 2;
|
int tries = 2;
|
||||||
|
@ -1112,7 +1089,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
|
||||||
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
|
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
|
||||||
if (!usberr) break;
|
if (!usberr) break;
|
||||||
ClearEpHalt(epDataInIndex);
|
ClearEpHalt(epDataInIndex);
|
||||||
//HandleUsbError(usberr, epDataInIndex);
|
|
||||||
if (tries) ResetRecovery();
|
if (tries) ResetRecovery();
|
||||||
}
|
}
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
@ -1120,7 +1096,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
|
||||||
Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
|
Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
|
||||||
} else {
|
} else {
|
||||||
// Throw away csw, IT IS NOT OF ANY USE.
|
// Throw away csw, IT IS NOT OF ANY USE.
|
||||||
//HandleUsbError(usberr, epDataInIndex);
|
|
||||||
ResetRecovery();
|
ResetRecovery();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1151,42 +1126,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For driver use only.
|
|
||||||
*
|
|
||||||
* @param lun Logical Unit Number
|
|
||||||
* @param pc
|
|
||||||
* @param page
|
|
||||||
* @param subpage
|
|
||||||
* @param len
|
|
||||||
* @param pbuf
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
|
|
||||||
Notify(PSTR("\r\rModeSense\r\n"), 0x80);
|
|
||||||
Notify(PSTR("------------\r\n"), 0x80);
|
|
||||||
|
|
||||||
CommandBlockWrapper cbw;
|
|
||||||
SetCurLUN(lun);
|
|
||||||
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
|
||||||
cbw.dCBWDataTransferLength = ((uint32_t)len);
|
|
||||||
cbw.bmCBWFlags = MASS_CMD_DIR_IN;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = 6;
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
|
||||||
cbw.CBWCB[i] = 0;
|
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_MODE_SENSE_6;
|
|
||||||
cbw.CBWCB[2] = ((pc << 6) | page);
|
|
||||||
cbw.CBWCB[3] = subpage;
|
|
||||||
cbw.CBWCB[4] = len;
|
|
||||||
|
|
||||||
return HandleSCSIError(Transaction(&cbw, 512, pbuf, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For driver use only.
|
* For driver use only.
|
||||||
*
|
*
|
||||||
|
@ -1325,11 +1264,11 @@ void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
|
||||||
/* We won't be needing this... */
|
/* We won't be needing this... */
|
||||||
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
|
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
|
||||||
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
|
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
|
||||||
#if 0
|
#if WANT_PARSER
|
||||||
Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
|
Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
|
||||||
Notify(PSTR("---------\r\n"), 0x80);
|
Notify(PSTR("---------\r\n"), 0x80);
|
||||||
|
|
||||||
CommandBlockWrapper cbw;
|
CommandBlockWrapper cbw = CommandBlockWrapper();
|
||||||
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
cbw.dCBWTag = ++dCBWTag;
|
||||||
|
@ -1338,8 +1277,8 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
|
||||||
cbw.bmCBWLUN = lun;
|
cbw.bmCBWLUN = lun;
|
||||||
cbw.bmCBWCBLength = 10;
|
cbw.bmCBWCBLength = 10;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 16; i++)
|
//for (uint8_t i = 0; i < 16; i++)
|
||||||
cbw.CBWCB[i] = 0;
|
// cbw.CBWCB[i] = 0;
|
||||||
|
|
||||||
cbw.CBWCB[0] = SCSI_CMD_READ_10;
|
cbw.CBWCB[0] = SCSI_CMD_READ_10;
|
||||||
cbw.CBWCB[8] = blocks;
|
cbw.CBWCB[8] = blocks;
|
||||||
|
@ -1351,25 +1290,3 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
|
||||||
return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
|
return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// TO-DO: Unify CBW creation as much as possible.
|
|
||||||
// Make and submit CBW.
|
|
||||||
// if stalled, delay retry
|
|
||||||
// exit on 100 retries, or anything except stall.
|
|
||||||
|
|
||||||
uint8_t SubmitCBW(uint8_t cmd, uint8_t cmdsz, uint8_t lun, uint16_t bsize, uint8_t *buf, uint8_t flags) {
|
|
||||||
CommandBlockWrapper cbw;
|
|
||||||
SetCurLUN(lun);
|
|
||||||
cbw.dCBWSignature = MASS_CBW_SIGNATURE;
|
|
||||||
cbw.dCBWTag = ++dCBWTag;
|
|
||||||
cbw.dCBWDataTransferLength = bsize;
|
|
||||||
cbw.bmCBWFlags = flags;
|
|
||||||
cbw.bmCBWLUN = lun;
|
|
||||||
cbw.bmCBWCBLength = cmdsz;
|
|
||||||
for (uint8_t i = 0; i < 16; i++) cbw.CBWCB[i] = 0;
|
|
||||||
cbw.CBWCB[0] = cmd;
|
|
||||||
cbw.CBWCB[1] = lun << 5;
|
|
||||||
cbw.CBWCB[4] = bsize;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
262
masstorage.h
262
masstorage.h
|
@ -9,7 +9,14 @@
|
||||||
// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>>
|
// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>>
|
||||||
// Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives.
|
// Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives.
|
||||||
// Each LUN needs ~13 bytes to be able to track the state of each unit.
|
// Each LUN needs ~13 bytes to be able to track the state of each unit.
|
||||||
|
#ifndef MASS_MAX_SUPPORTED_LUN
|
||||||
#define MASS_MAX_SUPPORTED_LUN 8
|
#define MASS_MAX_SUPPORTED_LUN 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Cruft removal, makes driver smaller, faster.
|
||||||
|
#ifndef WANT_PARSER
|
||||||
|
#define WANT_PARSER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "avrpins.h"
|
#include "avrpins.h"
|
||||||
|
@ -64,32 +71,98 @@
|
||||||
#define MASS_CBW_SIGNATURE 0x43425355
|
#define MASS_CBW_SIGNATURE 0x43425355
|
||||||
#define MASS_CSW_SIGNATURE 0x53425355
|
#define MASS_CSW_SIGNATURE 0x53425355
|
||||||
|
|
||||||
#define MASS_CMD_DIR_OUT (0 << 7)
|
#define MASS_CMD_DIR_OUT 0 // (0 << 7)
|
||||||
#define MASS_CMD_DIR_IN (1 << 7)
|
#define MASS_CMD_DIR_IN 0x80 //(1 << 7)
|
||||||
|
|
||||||
#define SCSI_CMD_INQUIRY 0x12
|
/*
|
||||||
#define SCSI_CMD_REPORT_LUNS 0xA0
|
* Reference documents from T10 (http://www.t10.org)
|
||||||
|
* SCSI Primary Commands - 3 (SPC-3)
|
||||||
|
* SCSI Block Commands - 2 (SBC-2)
|
||||||
|
* Multi-Media Commands - 5 (MMC-5)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Group 1 commands (CDB's here are should all be 6-bytes) */
|
||||||
|
#define SCSI_CMD_TEST_UNIT_READY 0x00
|
||||||
#define SCSI_CMD_REQUEST_SENSE 0x03
|
#define SCSI_CMD_REQUEST_SENSE 0x03
|
||||||
#define SCSI_CMD_FORMAT_UNIT 0x04
|
#define SCSI_CMD_FORMAT_UNIT 0x04
|
||||||
#define SCSI_CMD_READ_6 0x08
|
#define SCSI_CMD_READ_6 0x08
|
||||||
#define SCSI_CMD_READ_10 0x28
|
|
||||||
#define SCSI_CMD_READ_CAPACITY_10 0x25
|
|
||||||
#define SCSI_CMD_TEST_UNIT_READY 0x00
|
|
||||||
#define SCSI_CMD_WRITE_6 0x0A
|
#define SCSI_CMD_WRITE_6 0x0A
|
||||||
#define SCSI_CMD_WRITE_10 0x2A
|
#define SCSI_CMD_INQUIRY 0x12
|
||||||
|
#define SCSI_CMD_MODE_SELECT_6 0x15
|
||||||
#define SCSI_CMD_MODE_SENSE_6 0x1A
|
#define SCSI_CMD_MODE_SENSE_6 0x1A
|
||||||
#define SCSI_CMD_MODE_SENSE_10 0x5A
|
|
||||||
#define SCSI_CMD_START_STOP_UNIT 0x1B
|
#define SCSI_CMD_START_STOP_UNIT 0x1B
|
||||||
#define SCSI_CMD_PREVENT_REMOVAL 0x1E
|
#define SCSI_CMD_PREVENT_REMOVAL 0x1E
|
||||||
|
/* Group 2 Commands (CDB's here are 10-bytes) */
|
||||||
|
#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
|
||||||
|
#define SCSI_CMD_READ_CAPACITY_10 0x25
|
||||||
|
#define SCSI_CMD_READ_10 0x28
|
||||||
|
#define SCSI_CMD_WRITE_10 0x2A
|
||||||
|
#define SCSI_CMD_SEEK_10 0x2B
|
||||||
|
#define SCSI_CMD_ERASE_10 0x2C
|
||||||
|
#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2E
|
||||||
|
#define SCSI_CMD_VERIFY_10 0x2F
|
||||||
|
#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35
|
||||||
|
#define SCSI_CMD_WRITE_BUFFER 0x3B
|
||||||
|
#define SCSI_CMD_READ_BUFFER 0x3C
|
||||||
|
#define SCSI_CMD_READ_SUBCHANNEL 0x42
|
||||||
|
#define SCSI_CMD_READ_TOC 0x43
|
||||||
|
#define SCSI_CMD_READ_HEADER 0x44
|
||||||
|
#define SCSI_CMD_PLAY_AUDIO_10 0x45
|
||||||
|
#define SCSI_CMD_GET_CONFIGURATION 0x46
|
||||||
|
#define SCSI_CMD_PLAY_AUDIO_MSF 0x47
|
||||||
|
#define SCSI_CMD_PLAY_AUDIO_TI 0x48
|
||||||
|
#define SCSI_CMD_PLAY_TRACK_REL_10 0x49
|
||||||
|
#define SCSI_CMD_GET_EVENT_STATUS 0x4A
|
||||||
|
#define SCSI_CMD_PAUSE_RESUME 0x4B
|
||||||
|
#define SCSI_CMD_READ_DISC_INFORMATION 0x51
|
||||||
|
#define SCSI_CMD_READ_TRACK_INFORMATION 0x52
|
||||||
|
#define SCSI_CMD_RESERVE_TRACK 0x53
|
||||||
|
#define SCSI_CMD_SEND_OPC_INFORMATION 0x54
|
||||||
|
#define SCSI_CMD_MODE_SELECT_10 0x55
|
||||||
|
#define SCSI_CMD_REPAIR_TRACK 0x58
|
||||||
|
#define SCSI_CMD_MODE_SENSE_10 0x5A
|
||||||
|
#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5B
|
||||||
|
#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5C
|
||||||
|
#define SCSI_CMD_SEND_CUE_SHEET 0x5D
|
||||||
|
/* Group 5 Commands (CDB's here are 12-bytes) */
|
||||||
|
#define SCSI_CMD_REPORT_LUNS 0xA0
|
||||||
|
#define SCSI_CMD_BLANK 0xA1
|
||||||
|
#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2
|
||||||
|
#define SCSI_CMD_SEND_KEY 0xA3
|
||||||
|
#define SCSI_CMD_REPORT_KEY 0xA4
|
||||||
|
#define SCSI_CMD_PLAY_AUDIO_12 0xA5
|
||||||
|
#define SCSI_CMD_LOAD_UNLOAD 0xA6
|
||||||
|
#define SCSI_CMD_SET_READ_AHEAD 0xA7
|
||||||
|
#define SCSI_CMD_READ_12 0xA8
|
||||||
|
#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9
|
||||||
|
#define SCSI_CMD_WRITE_12 0xAA
|
||||||
|
#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xAB
|
||||||
|
#define SCSI_CMD_GET_PERFORMANCE 0xAC
|
||||||
|
#define SCSI_CMD_READ_DVD_STRUCTURE 0xAD
|
||||||
|
#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5
|
||||||
|
#define SCSI_CMD_SET_STREAMING 0xB6
|
||||||
|
#define SCSI_CMD_READ_MSF 0xB9
|
||||||
|
#define SCSI_CMD_SET_SPEED 0xBB
|
||||||
|
#define SCSI_CMD_MECHANISM_STATUS 0xBD
|
||||||
|
#define SCSI_CMD_READ_CD 0xBE
|
||||||
|
#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBF
|
||||||
|
/* Vendor-unique Commands, included for completeness */
|
||||||
|
#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4 /* SONY unique */
|
||||||
|
#define SCSI_CMD_PLAYBACK_CONTROL 0xC9 /* SONY unique */
|
||||||
|
#define SCSI_CMD_READ_CDDA 0xD8 /* Vendor unique */
|
||||||
|
#define SCSI_CMD_READ_CDXA 0xDB /* Vendor unique */
|
||||||
|
#define SCSI_CMD_READ_ALL_SUBCODES 0xDF /* Vendor unique */
|
||||||
|
|
||||||
|
/* SCSI error codes */
|
||||||
#define SCSI_S_NOT_READY 0x02
|
#define SCSI_S_NOT_READY 0x02
|
||||||
#define SCSI_S_MEDIUM_ERROR 0x03
|
#define SCSI_S_MEDIUM_ERROR 0x03
|
||||||
#define SCSI_S_ILLEGAL_REQUEST 0x05
|
#define SCSI_S_ILLEGAL_REQUEST 0x05
|
||||||
#define SCSI_S_UNIT_ATTENTION 0x06
|
#define SCSI_S_UNIT_ATTENTION 0x06
|
||||||
|
|
||||||
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
|
|
||||||
#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
|
#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
|
||||||
#define SCSI_ASC_MEDIA_CHANGED 0x28
|
#define SCSI_ASC_MEDIA_CHANGED 0x28
|
||||||
|
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
|
||||||
|
|
||||||
|
/* USB error codes */
|
||||||
#define MASS_ERR_SUCCESS 0x00
|
#define MASS_ERR_SUCCESS 0x00
|
||||||
#define MASS_ERR_PHASE_ERROR 0x02
|
#define MASS_ERR_PHASE_ERROR 0x02
|
||||||
#define MASS_ERR_UNIT_NOT_READY 0x03
|
#define MASS_ERR_UNIT_NOT_READY 0x03
|
||||||
|
@ -123,6 +196,116 @@ struct Capacity {
|
||||||
//uint32_t dwBlockLength;
|
//uint32_t dwBlockLength;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CDB6 {
|
||||||
|
uint8_t Opcode;
|
||||||
|
|
||||||
|
unsigned LBAMSB : 5;
|
||||||
|
unsigned LUN : 3;
|
||||||
|
|
||||||
|
uint8_t LBAHB;
|
||||||
|
uint8_t LBALB;
|
||||||
|
uint8_t AllocationLength;
|
||||||
|
uint8_t Control;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) :
|
||||||
|
Opcode(_Opcode), LUN(_LUN), LBAMSB((LBA >>16) & 0x1f), LBAHB((LBA >> 8) & 0xff), LBALB(LBA & 0xff),
|
||||||
|
AllocationLength(_AllocationLength), Control(_Control) {}
|
||||||
|
CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) :
|
||||||
|
Opcode(_Opcode), LUN(_LUN), LBAMSB(0), LBAHB(0), LBALB(0),
|
||||||
|
AllocationLength(_AllocationLength), Control(_Control) {}
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef CDB6 CDB6_t;
|
||||||
|
|
||||||
|
struct CDB10 {
|
||||||
|
uint8_t Opcode;
|
||||||
|
|
||||||
|
unsigned Service_Action : 5;
|
||||||
|
unsigned Misc : 3;
|
||||||
|
|
||||||
|
uint8_t LBA_L_M_MB;
|
||||||
|
uint8_t LBA_L_M_LB;
|
||||||
|
uint8_t LBA_L_L_MB;
|
||||||
|
uint8_t LBA_L_L_LB;
|
||||||
|
|
||||||
|
uint8_t Misc2;
|
||||||
|
|
||||||
|
uint8_t ALC_MB;
|
||||||
|
uint8_t ALC_LB;
|
||||||
|
|
||||||
|
uint8_t Control;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef CDB10 CDB10_t;
|
||||||
|
|
||||||
|
struct CDB12 {
|
||||||
|
uint8_t Opcode;
|
||||||
|
|
||||||
|
unsigned Service_Action : 5;
|
||||||
|
unsigned Misc : 3;
|
||||||
|
|
||||||
|
uint8_t LBA_L_M_LB;
|
||||||
|
uint8_t LBA_L_L_MB;
|
||||||
|
uint8_t LBA_L_L_LB;
|
||||||
|
|
||||||
|
uint8_t ALC_M_LB;
|
||||||
|
uint8_t ALC_L_MB;
|
||||||
|
uint8_t ALC_L_LB;
|
||||||
|
uint8_t Control;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef CDB12 CDB12_t;
|
||||||
|
|
||||||
|
struct CDB_LBA32_16 {
|
||||||
|
uint8_t Opcode;
|
||||||
|
|
||||||
|
unsigned Service_Action : 5;
|
||||||
|
unsigned Misc : 3;
|
||||||
|
|
||||||
|
uint8_t LBA_L_M_MB;
|
||||||
|
uint8_t LBA_L_M_LB;
|
||||||
|
uint8_t LBA_L_L_MB;
|
||||||
|
uint8_t LBA_L_L_LB;
|
||||||
|
|
||||||
|
uint8_t A_M_M_MB;
|
||||||
|
uint8_t A_M_M_LB;
|
||||||
|
uint8_t A_M_L_MB;
|
||||||
|
uint8_t A_M_L_LB;
|
||||||
|
|
||||||
|
uint8_t ALC_M_MB;
|
||||||
|
uint8_t ALC_M_LB;
|
||||||
|
uint8_t ALC_L_MB;
|
||||||
|
uint8_t ALC_L_LB;
|
||||||
|
|
||||||
|
uint8_t Misc2;
|
||||||
|
uint8_t Control;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CDB_LBA64_16 {
|
||||||
|
uint8_t Opcode;
|
||||||
|
uint8_t Misc;
|
||||||
|
|
||||||
|
uint8_t LBA_M_M_MB;
|
||||||
|
uint8_t LBA_M_M_LB;
|
||||||
|
uint8_t LBA_M_L_MB;
|
||||||
|
uint8_t LBA_M_L_LB;
|
||||||
|
|
||||||
|
uint8_t LBA_L_M_MB;
|
||||||
|
uint8_t LBA_L_M_LB;
|
||||||
|
uint8_t LBA_L_L_MB;
|
||||||
|
uint8_t LBA_L_L_LB;
|
||||||
|
|
||||||
|
uint8_t ALC_M_MB;
|
||||||
|
uint8_t ALC_M_LB;
|
||||||
|
uint8_t ALC_L_MB;
|
||||||
|
uint8_t ALC_L_LB;
|
||||||
|
|
||||||
|
uint8_t Misc2;
|
||||||
|
uint8_t Control;
|
||||||
|
};
|
||||||
|
|
||||||
struct InquiryResponse {
|
struct InquiryResponse {
|
||||||
uint8_t DeviceType : 5;
|
uint8_t DeviceType : 5;
|
||||||
uint8_t PeripheralQualifier : 3;
|
uint8_t PeripheralQualifier : 3;
|
||||||
|
@ -133,13 +316,29 @@ struct InquiryResponse {
|
||||||
uint8_t Version;
|
uint8_t Version;
|
||||||
|
|
||||||
unsigned ResponseDataFormat : 4;
|
unsigned ResponseDataFormat : 4;
|
||||||
unsigned Reserved2 : 1;
|
unsigned HISUP : 1;
|
||||||
unsigned NormACA : 1;
|
unsigned NormACA : 1;
|
||||||
unsigned TrmTsk : 1;
|
unsigned TrmTsk : 1;
|
||||||
unsigned AERC : 1;
|
unsigned AERC : 1;
|
||||||
|
|
||||||
uint8_t AdditionalLength;
|
uint8_t AdditionalLength;
|
||||||
uint8_t Reserved3[2];
|
//uint8_t Reserved3[2];
|
||||||
|
|
||||||
|
unsigned PROTECT : 1;
|
||||||
|
unsigned Res : 2;
|
||||||
|
unsigned ThreePC : 1;
|
||||||
|
unsigned TPGS : 2;
|
||||||
|
unsigned ACC : 1;
|
||||||
|
unsigned SCCS : 1;
|
||||||
|
|
||||||
|
unsigned ADDR16 : 1;
|
||||||
|
unsigned R1 : 1;
|
||||||
|
unsigned R2 : 1;
|
||||||
|
unsigned MCHNGR : 1;
|
||||||
|
unsigned MULTIP : 1;
|
||||||
|
unsigned VS : 1;
|
||||||
|
unsigned ENCSERV : 1;
|
||||||
|
unsigned BQUE : 1;
|
||||||
|
|
||||||
unsigned SoftReset : 1;
|
unsigned SoftReset : 1;
|
||||||
unsigned CmdQue : 1;
|
unsigned CmdQue : 1;
|
||||||
|
@ -160,6 +359,14 @@ struct CommandBlockWrapperBase {
|
||||||
uint32_t dCBWTag;
|
uint32_t dCBWTag;
|
||||||
uint32_t dCBWDataTransferLength;
|
uint32_t dCBWDataTransferLength;
|
||||||
uint8_t bmCBWFlags;
|
uint8_t bmCBWFlags;
|
||||||
|
public:
|
||||||
|
|
||||||
|
CommandBlockWrapperBase() {
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) :
|
||||||
|
dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) {
|
||||||
|
}
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct CommandBlockWrapper : public CommandBlockWrapperBase {
|
struct CommandBlockWrapper : public CommandBlockWrapperBase {
|
||||||
|
@ -175,6 +382,26 @@ struct CommandBlockWrapper : public CommandBlockWrapperBase {
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t CBWCB[16];
|
uint8_t CBWCB[16];
|
||||||
|
|
||||||
|
CommandBlockWrapper() : bmReserved1(0), bmReserved2(0) {
|
||||||
|
for(uint8_t i = 0; i < 16; i++) CBWCB[i] = 0;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Generic Wrap
|
||||||
|
CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) :
|
||||||
|
CommandBlockWrapperBase(tag, xflen, flgs),
|
||||||
|
bmReserved1(0), bmReserved2(0), bmCBWLUN(lu), bmCBWCBLength(cmdlen) {
|
||||||
|
for(uint8_t i = 1; i < cmdlen; i++) CBWCB[i] = 0;
|
||||||
|
CBWCB[0] = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap for CDB of 6
|
||||||
|
CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) :
|
||||||
|
CommandBlockWrapperBase(tag, xflen, dir),
|
||||||
|
bmReserved1(0), bmReserved2(0), bmCBWLUN(cdb->LUN), bmCBWCBLength(6) {
|
||||||
|
memcpy(CBWCB, cdb, 6);
|
||||||
|
}
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct CommandStatusWrapper {
|
struct CommandStatusWrapper {
|
||||||
|
@ -275,8 +502,12 @@ public:
|
||||||
|
|
||||||
// UsbConfigXtracter implementation
|
// UsbConfigXtracter implementation
|
||||||
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
virtual boolean DEVCLASSOK(uint8_t klass) { return (klass == USB_CLASS_MASS_STORAGE); }
|
|
||||||
|
|
||||||
|
virtual boolean DEVCLASSOK(uint8_t klass) {
|
||||||
|
return(klass == USB_CLASS_MASS_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
|
uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
|
||||||
|
@ -298,7 +529,10 @@ private:
|
||||||
bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);
|
bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);
|
||||||
|
|
||||||
uint8_t ClearEpHalt(uint8_t index);
|
uint8_t ClearEpHalt(uint8_t index);
|
||||||
|
#if WANT_PARSER
|
||||||
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
|
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
|
||||||
|
#endif
|
||||||
|
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf);
|
||||||
uint8_t HandleUsbError(uint8_t error, uint8_t index);
|
uint8_t HandleUsbError(uint8_t error, uint8_t index);
|
||||||
uint8_t HandleSCSIError(uint8_t status);
|
uint8_t HandleSCSIError(uint8_t status);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue