mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Poll for media change, reduce code, cache capacity and block size.
This commit is contained in:
parent
1d771c1501
commit
a7498b5aa2
2 changed files with 233 additions and 79 deletions
263
masstorage.cpp
263
masstorage.cpp
|
@ -25,6 +25,12 @@ qNextPollTime(0),
|
||||||
bPollEnable(false),
|
bPollEnable(false),
|
||||||
dCBWTag(0),
|
dCBWTag(0),
|
||||||
bLastUsbError(0) {
|
bLastUsbError(0) {
|
||||||
|
ClearAllEP();
|
||||||
|
if (pUsb)
|
||||||
|
pUsb->RegisterDeviceClass(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BulkOnly::ClearAllEP() {
|
||||||
for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
|
for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
|
||||||
epInfo[i].epAddr = 0;
|
epInfo[i].epAddr = 0;
|
||||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||||
|
@ -33,8 +39,18 @@ bLastUsbError(0) {
|
||||||
//if (!i)
|
//if (!i)
|
||||||
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
||||||
}
|
}
|
||||||
if (pUsb)
|
// clear all LUN data as well
|
||||||
pUsb->RegisterDeviceClass(this);
|
for (uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) LUNOk[i] = false;
|
||||||
|
bIface = 0;
|
||||||
|
bNumEP = 1;
|
||||||
|
|
||||||
|
bAddress = 0;
|
||||||
|
qNextPollTime = 0;
|
||||||
|
bPollEnable = false;
|
||||||
|
bLastUsbError = 0;
|
||||||
|
bMaxLUN = 0;
|
||||||
|
bTheLUN = 0;
|
||||||
|
dCBWTag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
|
@ -47,22 +63,13 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
EpInfo *oldep_ptr = NULL;
|
EpInfo *oldep_ptr = NULL;
|
||||||
uint8_t num_of_conf; // number of configurations
|
uint8_t num_of_conf; // number of configurations
|
||||||
|
|
||||||
for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
|
ClearAllEP();
|
||||||
epInfo[i].epAddr = 0;
|
|
||||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
|
||||||
epInfo[i].epAttribs = 0;
|
|
||||||
|
|
||||||
//if (!i)
|
|
||||||
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||||
|
|
||||||
|
|
||||||
if (bAddress)
|
if (bAddress)
|
||||||
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
||||||
|
|
||||||
USBTRACE("MS Init\r\n");
|
|
||||||
// Get pointer to pseudo device with address 0 assigned
|
// Get pointer to pseudo device with address 0 assigned
|
||||||
p = addrPool.GetUsbDevicePtr(0);
|
p = addrPool.GetUsbDevicePtr(0);
|
||||||
|
|
||||||
|
@ -152,6 +159,8 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
if (bNumEP < 3)
|
if (bNumEP < 3)
|
||||||
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
USBTRACE("MS Init\r\n");
|
||||||
|
delay(120);
|
||||||
// Assign epInfo to epinfo pointer
|
// Assign epInfo to epinfo pointer
|
||||||
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
|
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
|
||||||
|
|
||||||
|
@ -163,7 +172,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
if (rcode)
|
if (rcode)
|
||||||
goto FailSetConfDescr;
|
goto FailSetConfDescr;
|
||||||
|
|
||||||
delay(10000);
|
delay(120); // Delay a bit for slow firmware.
|
||||||
|
|
||||||
rcode = GetMaxLUN(&bMaxLUN);
|
rcode = GetMaxLUN(&bMaxLUN);
|
||||||
if (rcode)
|
if (rcode)
|
||||||
|
@ -171,43 +180,54 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
|
|
||||||
ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
|
ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
|
||||||
|
|
||||||
delay(10);
|
if (bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
|
||||||
|
ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
|
||||||
|
|
||||||
|
delay(20); // Delay a bit for slow firmware.
|
||||||
|
|
||||||
bTheLUN = bMaxLUN;
|
bTheLUN = bMaxLUN;
|
||||||
|
|
||||||
|
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
|
||||||
|
InquiryResponse response;
|
||||||
|
rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
|
||||||
|
if (rcode) {
|
||||||
|
ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
|
||||||
|
} else {
|
||||||
|
uint8_t buf[192];
|
||||||
|
rcode = ModeSense(lun, 0, 0x3f, 0, 192, buf);
|
||||||
|
|
||||||
|
// 0xfe is OK, pass and don't report it
|
||||||
|
if (rcode != 0xfe && rcode != 0x00) {
|
||||||
|
ErrorMessage<uint8_t > (PSTR("ModeSense"), rcode);
|
||||||
|
} else {
|
||||||
|
Notify(PSTR("ModeSense: OK\r\n\r\n"), 0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool good;
|
||||||
|
for (uint8_t i = 1; i == 0; i++) {
|
||||||
|
good = false;
|
||||||
|
CheckMedia();
|
||||||
|
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) good |= LUNOk[lun];
|
||||||
|
if (good) break;
|
||||||
|
delay(118); // 255 loops =~ 30 seconds to allow for spin up, as per SCSI spec.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CheckMedia(); // Check one last time.
|
||||||
|
|
||||||
|
#if 0
|
||||||
//if (bMaxLUN > 0)
|
//if (bMaxLUN > 0)
|
||||||
|
|
||||||
{
|
{
|
||||||
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
|
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
|
||||||
ErrorMessage<uint8_t > (PSTR("\r\nLUN"), lun);
|
ErrorMessage<uint8_t > (PSTR("\r\nLUN"), lun);
|
||||||
Notify(PSTR("--------\r\n"), 0x80);
|
Notify(PSTR("--------\r\n"), 0x80);
|
||||||
|
if (!LUNOk[lun]) {
|
||||||
uint8_t count = 0;
|
ErrorMessage<uint8_t > (PSTR("Skip no media on LUN"), lun);
|
||||||
|
continue;
|
||||||
MediaCTL(lun, 0x01);
|
|
||||||
|
|
||||||
rcode = 0;
|
|
||||||
InquiryResponse response;
|
|
||||||
rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
|
|
||||||
|
|
||||||
if (rcode)
|
|
||||||
ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
|
|
||||||
|
|
||||||
rcode = 0;
|
|
||||||
Capacity capacity;
|
|
||||||
rcode = ReadCapacity(lun, sizeof (Capacity), (uint8_t*) & capacity);
|
|
||||||
|
|
||||||
if (rcode)
|
|
||||||
ErrorMessage<uint8_t > (PSTR("ReadCapacity"), rcode);
|
|
||||||
else {
|
|
||||||
for (uint8_t i = 0; i<sizeof (Capacity); i++)
|
|
||||||
PrintHex<uint8_t > (capacity.data[i], 0x80);
|
|
||||||
Notify(PSTR("\r\n\r\n"), 0x80);
|
|
||||||
// Only 512/1024/2048/4096 are valid values!
|
|
||||||
uint32_t c = ((uint32_t)capacity.data[4] << 24) + ((uint32_t)capacity.data[5] << 16) + ((uint32_t)capacity.data[6] << 8) + (uint32_t)capacity.data[7];
|
|
||||||
if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
|
|
||||||
rcode = 255;
|
|
||||||
goto FailInvalidSectorSize;
|
|
||||||
}
|
}
|
||||||
|
uint8_t count = 0;
|
||||||
while (rcode = TestUnitReady(lun)) {
|
while (rcode = TestUnitReady(lun)) {
|
||||||
if (rcode == MASS_ERR_NO_MEDIA)
|
if (rcode == MASS_ERR_NO_MEDIA)
|
||||||
break;
|
break;
|
||||||
|
@ -224,12 +244,46 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
delay(100);
|
delay(100);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count == 0xff)
|
// There is no sense to try and read capacity if there is no media.
|
||||||
|
// This is here in the event the check to skip has a false positive.
|
||||||
|
if (count == 0xff || rcode == MASS_ERR_NO_MEDIA) {
|
||||||
|
LUNOk[lun] = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
MediaCTL(lun, 0x01);
|
||||||
|
|
||||||
|
*/
|
||||||
rcode = 0;
|
rcode = 0;
|
||||||
#if 0
|
Capacity capacity;
|
||||||
|
rcode = ReadCapacity(lun, sizeof (Capacity), (uint8_t*) & capacity);
|
||||||
|
|
||||||
|
if (rcode) {
|
||||||
|
ErrorMessage<uint8_t > (PSTR("ReadCapacity"), rcode);
|
||||||
|
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY FAIL ON LUN"), lun);
|
||||||
|
LUNOk[lun] = false;
|
||||||
|
} else {
|
||||||
|
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
|
||||||
|
for (uint8_t i = 0; i<sizeof (Capacity); i++)
|
||||||
|
PrintHex<uint8_t > (capacity.data[i], 0x80);
|
||||||
|
Notify(PSTR("\r\n\r\n"), 0x80);
|
||||||
|
// Only 512/1024/2048/4096 are valid values!
|
||||||
|
uint32_t c = ((uint32_t)capacity.data[4] << 24) + ((uint32_t)capacity.data[5] << 16) + ((uint32_t)capacity.data[6] << 8) + (uint32_t)capacity.data[7];
|
||||||
|
if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
|
||||||
|
//rcode = 255;
|
||||||
|
//goto FailInvalidSectorSize;
|
||||||
|
LUNOk[lun] = false;
|
||||||
|
} else {
|
||||||
|
// Store capacity information.
|
||||||
|
CurrentSectorSize[lun] = (uint16_t)(c & 0xFFFF);
|
||||||
|
CurrentCapacity[lun] = ((uint32_t)capacity.data[0] << 24) + ((uint32_t)capacity.data[1] << 16) + ((uint32_t)capacity.data[2] << 8) + (uint32_t)capacity.data[3];
|
||||||
|
if (CurrentCapacity[lun] == 0xffffffffLU || CurrentCapacity[lun] == 0x00LU) {
|
||||||
|
// Buggy firmware will report 0xffffffff for empty
|
||||||
|
LUNOk[lun] = false;
|
||||||
|
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
uint8_t buf[512];
|
uint8_t buf[512];
|
||||||
rcode = Read(lun, 0, 512, 1, buf);
|
rcode = Read(lun, 0, 512, 1, buf);
|
||||||
|
@ -256,7 +310,6 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
else
|
else
|
||||||
Notify(PSTR("ModeSense: OK\r\n\r\n"), 0x80);
|
Notify(PSTR("ModeSense: OK\r\n\r\n"), 0x80);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
Notify(PSTR("==========\r\n"), 0x80);
|
Notify(PSTR("==========\r\n"), 0x80);
|
||||||
}
|
}
|
||||||
|
@ -268,6 +321,8 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||||
//goto FailOnInit;
|
//goto FailOnInit;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#endif
|
||||||
rcode = OnInit();
|
rcode = OnInit();
|
||||||
|
|
||||||
if (rcode)
|
if (rcode)
|
||||||
|
@ -303,36 +358,53 @@ FailOnInit:
|
||||||
FailGetMaxLUN:
|
FailGetMaxLUN:
|
||||||
USBTRACE("GetMaxLUN:");
|
USBTRACE("GetMaxLUN:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
/*
|
||||||
FailInquiry:
|
FailInquiry:
|
||||||
USBTRACE("Inquiry:");
|
USBTRACE("Inquiry:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailReadCapacity:
|
FailReadCapacity:
|
||||||
USBTRACE("ReadCapacity:");
|
USBTRACE("ReadCapacity:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailInvalidSectorSize:
|
FailRead0:
|
||||||
USBTRACE("Sector Size is NOT VALID: ");
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
FailRead0:
|
|
||||||
USBTRACE("Read0:");
|
USBTRACE("Read0:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailModeSense0:
|
FailModeSense0:
|
||||||
USBTRACE("ModeSense0:");
|
USBTRACE("ModeSense0:");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
FailModeSense1:
|
FailModeSense1:
|
||||||
USBTRACE("ModeSense1:");
|
USBTRACE("ModeSense1:");
|
||||||
|
|
||||||
|
*/
|
||||||
|
FailInvalidSectorSize:
|
||||||
|
USBTRACE("Sector Size is NOT VALID: ");
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
NotifyFail(rcode);
|
NotifyFail(rcode);
|
||||||
Release();
|
Release();
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t BulkOnly::GetCapacity(uint8_t lun) {
|
||||||
|
if (LUNOk[lun])
|
||||||
|
return CurrentCapacity[lun];
|
||||||
|
return 0LU;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
|
||||||
|
if (LUNOk[lun])
|
||||||
|
return CurrentSectorSize[lun];
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BulkOnly::LUNIsGood(uint8_t lun) {
|
||||||
|
return LUNOk[lun];
|
||||||
|
}
|
||||||
|
|
||||||
void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
|
void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
|
||||||
ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
|
ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
|
||||||
ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
|
ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
|
||||||
|
@ -361,26 +433,71 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BulkOnly::Release() {
|
uint8_t BulkOnly::Release() {
|
||||||
|
ClearAllEP();
|
||||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||||
|
|
||||||
bIface = 0;
|
|
||||||
bNumEP = 1;
|
|
||||||
|
|
||||||
bAddress = 0;
|
|
||||||
qNextPollTime = 0;
|
|
||||||
bPollEnable = false;
|
|
||||||
bLastUsbError = 0;
|
|
||||||
bMaxLUN = 0;
|
|
||||||
bTheLUN = 0;
|
|
||||||
dCBWTag = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BulkOnly::CheckMedia() {
|
||||||
|
uint8_t rcode;
|
||||||
|
for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
|
||||||
|
bool wasOK = LUNOk[lun];
|
||||||
|
rcode = TestUnitReady(lun);
|
||||||
|
if (rcode) {
|
||||||
|
//printf("\r\n[[[[[[[[[[[[[[[[[ LUN %i TUR %2.2X\r\n", lun, rcode);
|
||||||
|
LUNOk[lun] = false;
|
||||||
|
} else {
|
||||||
|
LUNOk[lun] = true;
|
||||||
|
}
|
||||||
|
if (!wasOK && LUNOk[lun]) {
|
||||||
|
Capacity capacity;
|
||||||
|
rcode = ReadCapacity(lun, sizeof (Capacity), (uint8_t*) & capacity);
|
||||||
|
|
||||||
|
if (rcode) {
|
||||||
|
ErrorMessage<uint8_t > (PSTR("ReadCapacity"), rcode);
|
||||||
|
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY FAIL ON LUN"), lun);
|
||||||
|
LUNOk[lun] = false;
|
||||||
|
} else {
|
||||||
|
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
|
||||||
|
for (uint8_t i = 0; i<sizeof (Capacity); i++)
|
||||||
|
PrintHex<uint8_t > (capacity.data[i], 0x80);
|
||||||
|
Notify(PSTR("\r\n\r\n"), 0x80);
|
||||||
|
// Only 512/1024/2048/4096 are valid values!
|
||||||
|
uint32_t c = ((uint32_t)capacity.data[4] << 24) + ((uint32_t)capacity.data[5] << 16) + ((uint32_t)capacity.data[6] << 8) + (uint32_t)capacity.data[7];
|
||||||
|
if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
|
||||||
|
//rcode = 255;
|
||||||
|
//goto FailInvalidSectorSize;
|
||||||
|
LUNOk[lun] = false;
|
||||||
|
} else {
|
||||||
|
// Store capacity information.
|
||||||
|
CurrentSectorSize[lun] = (uint16_t)(c & 0xFFFF);
|
||||||
|
CurrentCapacity[lun] = ((uint32_t)capacity.data[0] << 24) + ((uint32_t)capacity.data[1] << 16) + ((uint32_t)capacity.data[2] << 8) + (uint32_t)capacity.data[3];
|
||||||
|
if (CurrentCapacity[lun] == 0xffffffffLU || CurrentCapacity[lun] == 0x00LU) {
|
||||||
|
// Buggy firmware will report 0xffffffff or 0 for no media
|
||||||
|
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
|
||||||
|
LUNOk[lun] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Scan for media change
|
||||||
|
// @Oleg -- should we scan ALL LUN, or just one at a time?
|
||||||
|
|
||||||
uint8_t BulkOnly::Poll() {
|
uint8_t BulkOnly::Poll() {
|
||||||
uint8_t rcode = 0;
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
if (!bPollEnable)
|
if (!bPollEnable)
|
||||||
return 0;
|
return 0;
|
||||||
|
// needs a poll interval of 1 second.
|
||||||
|
if (qNextPollTime <= millis()) {
|
||||||
|
CheckMedia();
|
||||||
|
qNextPollTime = millis() + 1000;
|
||||||
|
}
|
||||||
|
rcode = 0;
|
||||||
|
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
@ -487,6 +604,8 @@ uint8_t BulkOnly::ResetRecovery() {
|
||||||
return bLastUsbError;
|
return bLastUsbError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't test if OK
|
||||||
|
|
||||||
uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
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);
|
||||||
|
@ -509,6 +628,8 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
||||||
return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
|
return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't test if OK, only for use internally.
|
||||||
|
|
||||||
uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
|
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);
|
||||||
|
@ -535,7 +656,7 @@ uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
|
||||||
uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
||||||
Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
|
Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
|
||||||
Notify(PSTR("---------------\r\n"), 0x80);
|
Notify(PSTR("---------------\r\n"), 0x80);
|
||||||
|
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
|
||||||
CommandBlockWrapper cbw;
|
CommandBlockWrapper cbw;
|
||||||
|
|
||||||
SetCurLUN(lun);
|
SetCurLUN(lun);
|
||||||
|
@ -555,7 +676,10 @@ uint8_t BulkOnly::ReadCapacity(uint8_t lun, uint16_t bsize, uint8_t *buf) {
|
||||||
return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
|
return HandleSCSIError(Transaction(&cbw, bsize, buf, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't test if OK
|
||||||
|
|
||||||
uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
|
uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
|
||||||
|
// if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
|
||||||
SetCurLUN(lun);
|
SetCurLUN(lun);
|
||||||
if (!bAddress) // || !bPollEnable)
|
if (!bAddress) // || !bPollEnable)
|
||||||
return MASS_ERR_UNIT_NOT_READY;
|
return MASS_ERR_UNIT_NOT_READY;
|
||||||
|
@ -581,6 +705,8 @@ uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Media control: 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media */
|
/* Media control: 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media */
|
||||||
|
// don't test if OK
|
||||||
|
|
||||||
uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
|
uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
|
||||||
SetCurLUN(lun);
|
SetCurLUN(lun);
|
||||||
uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
|
uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
|
||||||
|
@ -606,6 +732,7 @@ uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
|
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
|
||||||
|
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
|
||||||
Notify(PSTR("\r\nRead\r\n"), 0x80);
|
Notify(PSTR("\r\nRead\r\n"), 0x80);
|
||||||
Notify(PSTR("---------\r\n"), 0x80);
|
Notify(PSTR("---------\r\n"), 0x80);
|
||||||
|
|
||||||
|
@ -633,6 +760,7 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
|
||||||
|
|
||||||
/* 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 0
|
#if 0
|
||||||
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);
|
||||||
|
@ -661,6 +789,7 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf) {
|
uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf) {
|
||||||
|
if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
|
||||||
Notify(PSTR("\r\nWrite\r\n"), 0x80);
|
Notify(PSTR("\r\nWrite\r\n"), 0x80);
|
||||||
Notify(PSTR("---------\r\n"), 0x80);
|
Notify(PSTR("---------\r\n"), 0x80);
|
||||||
|
|
||||||
|
@ -688,6 +817,8 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc
|
||||||
return HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0));
|
return HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't test if OK
|
||||||
|
|
||||||
uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *pbuf) {
|
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\rModeSense\r\n"), 0x80);
|
||||||
Notify(PSTR("------------\r\n"), 0x80);
|
Notify(PSTR("------------\r\n"), 0x80);
|
||||||
|
|
27
masstorage.h
27
masstorage.h
|
@ -3,6 +3,15 @@
|
||||||
|
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
|
||||||
|
//<RANT>
|
||||||
|
// @Oleg -- Perhaps we need a central 'config.h', many of these includes and
|
||||||
|
// defines could be handled there, allowing for easier config.
|
||||||
|
|
||||||
|
// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>>
|
||||||
|
// 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.
|
||||||
|
#define MASS_MAX_SUPPORTED_LUN 8
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "avrpins.h"
|
#include "avrpins.h"
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
@ -19,6 +28,9 @@
|
||||||
|
|
||||||
#include <confdescparser.h>
|
#include <confdescparser.h>
|
||||||
|
|
||||||
|
// </RANT>
|
||||||
|
|
||||||
|
|
||||||
#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
|
#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
|
||||||
|
|
||||||
#define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
#define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||||
|
@ -207,8 +219,10 @@ protected:
|
||||||
uint8_t bLastUsbError; // Last USB error
|
uint8_t bLastUsbError; // Last USB error
|
||||||
uint8_t bMaxLUN; // Max LUN
|
uint8_t bMaxLUN; // Max LUN
|
||||||
uint8_t bTheLUN; // Active LUN
|
uint8_t bTheLUN; // Active LUN
|
||||||
// TO-ADD:
|
uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors
|
||||||
// uint32_t CurrentCapacity; // use this to check for media changes.
|
uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits
|
||||||
|
bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
|
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
|
||||||
|
|
||||||
|
@ -225,6 +239,8 @@ protected:
|
||||||
public:
|
public:
|
||||||
BulkOnly(USB *p);
|
BulkOnly(USB *p);
|
||||||
|
|
||||||
|
// Some of these should NOT be public.
|
||||||
|
|
||||||
uint8_t GetLastUsbError() {
|
uint8_t GetLastUsbError() {
|
||||||
return bLastUsbError;
|
return bLastUsbError;
|
||||||
};
|
};
|
||||||
|
@ -252,6 +268,10 @@ public:
|
||||||
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);
|
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);
|
||||||
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
|
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
|
||||||
|
|
||||||
|
bool LUNIsGood(uint8_t lun);
|
||||||
|
uint32_t GetCapacity(uint8_t lun);
|
||||||
|
uint16_t GetSectorSize(uint8_t lun);
|
||||||
|
|
||||||
// USBDeviceConfig implementation
|
// USBDeviceConfig implementation
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
virtual uint8_t Release();
|
virtual uint8_t Release();
|
||||||
|
@ -270,6 +290,9 @@ protected:
|
||||||
virtual uint8_t OnInit() {
|
virtual uint8_t OnInit() {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
private:
|
||||||
|
void ClearAllEP();
|
||||||
|
void CheckMedia();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __MASSTORAGE_H__
|
#endif // __MASSTORAGE_H__
|
||||||
|
|
Loading…
Reference in a new issue