|
@@ -30,12 +30,16 @@ extern "C" {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+const uint8_t MAX_FILE_LISTING_FILES = 100;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
extern "C" int8_t scsiToolboxEnabled()
|
|
extern "C" int8_t scsiToolboxEnabled()
|
|
|
{
|
|
{
|
|
|
static int8_t enabled = -1;
|
|
static int8_t enabled = -1;
|
|
|
if (enabled == -1)
|
|
if (enabled == -1)
|
|
|
{
|
|
{
|
|
|
enabled = ini_getbool("SCSI", "EnableToolbox", 0, CONFIGFILE);
|
|
enabled = ini_getbool("SCSI", "EnableToolbox", 0, CONFIGFILE);
|
|
|
|
|
+ logmsg("Toolbox enabled = ", enabled);
|
|
|
}
|
|
}
|
|
|
return enabled == 1;
|
|
return enabled == 1;
|
|
|
}
|
|
}
|
|
@@ -71,15 +75,19 @@ static void doCountFiles(const char * dir_name, bool isCD = false)
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
bool isDir = file.isDirectory();
|
|
bool isDir = file.isDirectory();
|
|
|
- file.getName(name, MAX_FILE_PATH);
|
|
|
|
|
|
|
+ size_t len = file.getName(name, MAX_FILE_PATH);
|
|
|
file.close();
|
|
file.close();
|
|
|
if (isCD && isDir)
|
|
if (isCD && isDir)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
+ // truncate filename the same way listing does, before validating name
|
|
|
|
|
+ if (len > MAX_MAC_PATH)
|
|
|
|
|
+ name[MAX_MAC_PATH] = 0x0;
|
|
|
|
|
+ dbgmsg("TOOLBOX COUNT FILES: truncated filename is '", name, "'");
|
|
|
// only count valid files.
|
|
// only count valid files.
|
|
|
if(toolboxFilenameValid(name, isCD))
|
|
if(toolboxFilenameValid(name, isCD))
|
|
|
{
|
|
{
|
|
|
file_count = file_count + 1;
|
|
file_count = file_count + 1;
|
|
|
- if(file_count > 100) {
|
|
|
|
|
|
|
+ if(file_count > MAX_FILE_LISTING_FILES) {
|
|
|
scsiDev.status = CHECK_CONDITION;
|
|
scsiDev.status = CHECK_CONDITION;
|
|
|
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
|
scsiDev.target->sense.code = ILLEGAL_REQUEST;
|
|
|
scsiDev.target->sense.asc = OPEN_RETRO_SCSI_TOO_MANY_FILES;
|
|
scsiDev.target->sense.asc = OPEN_RETRO_SCSI_TOO_MANY_FILES;
|
|
@@ -97,107 +105,121 @@ static void doCountFiles(const char * dir_name, bool isCD = false)
|
|
|
static void onListFiles(const char * dir_name, bool isCD = false) {
|
|
static void onListFiles(const char * dir_name, bool isCD = false) {
|
|
|
FsFile dir;
|
|
FsFile dir;
|
|
|
FsFile file;
|
|
FsFile file;
|
|
|
|
|
+ const size_t ENTRY_SIZE = 40;
|
|
|
|
|
|
|
|
- memset(scsiDev.data, 0, 4096);
|
|
|
|
|
- int ENTRY_SIZE = 40;
|
|
|
|
|
|
|
+ memset(scsiDev.data, 0, ENTRY_SIZE * (MAX_FILE_LISTING_FILES + 1));
|
|
|
char name[MAX_FILE_PATH] = {0};
|
|
char name[MAX_FILE_PATH] = {0};
|
|
|
|
|
+ uint8_t index = 0;
|
|
|
|
|
+ uint8_t file_entry[ENTRY_SIZE] = {0};
|
|
|
|
|
+
|
|
|
dir.open(dir_name);
|
|
dir.open(dir_name);
|
|
|
dir.rewindDirectory();
|
|
dir.rewindDirectory();
|
|
|
- uint8_t index = 0;
|
|
|
|
|
- uint8_t file_entry[40] = {0};
|
|
|
|
|
while (file.openNext(&dir, O_RDONLY))
|
|
while (file.openNext(&dir, O_RDONLY))
|
|
|
{
|
|
{
|
|
|
|
|
+ memset(name, 0, sizeof(name));
|
|
|
|
|
+ // get base information
|
|
|
uint8_t isDir = file.isDirectory() ? 0x00 : 0x01;
|
|
uint8_t isDir = file.isDirectory() ? 0x00 : 0x01;
|
|
|
- int len = file.getName(name, MAX_FILE_PATH);
|
|
|
|
|
- if (len > MAX_MAC_PATH)
|
|
|
|
|
- name[MAX_MAC_PATH] = 0x0;
|
|
|
|
|
|
|
+ size_t len = file.getName(name, MAX_FILE_PATH);
|
|
|
uint64_t size = file.fileSize();
|
|
uint64_t size = file.fileSize();
|
|
|
file.close();
|
|
file.close();
|
|
|
|
|
+ // truncate filename to fit in destination buffer
|
|
|
|
|
+ if (len > MAX_MAC_PATH)
|
|
|
|
|
+ name[MAX_MAC_PATH] = 0x0;
|
|
|
|
|
+ dbgmsg("TOOLBOX LIST FILES: truncated filename is '", name, "'");
|
|
|
|
|
+ // validate file is allowed for this listing
|
|
|
if (!toolboxFilenameValid(name, isCD))
|
|
if (!toolboxFilenameValid(name, isCD))
|
|
|
continue;
|
|
continue;
|
|
|
if (isCD && isDir == 0x00)
|
|
if (isCD && isDir == 0x00)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
+ // fill output buffer
|
|
|
file_entry[0] = index;
|
|
file_entry[0] = index;
|
|
|
file_entry[1] = isDir;
|
|
file_entry[1] = isDir;
|
|
|
- int c = 0; // Index of char in name[]
|
|
|
|
|
-
|
|
|
|
|
- for(int i = 2; i < (MAX_MAC_PATH + 1 + 2); i++) { // bytes 2 - 34
|
|
|
|
|
- file_entry[i] = name[c++];
|
|
|
|
|
|
|
+ for(int i = 0; i < MAX_MAC_PATH + 1 ; i++) {
|
|
|
|
|
+ file_entry[i + 2] = name[i]; // bytes 2 - 34
|
|
|
}
|
|
}
|
|
|
file_entry[35] = 0; //(size >> 32) & 0xff;
|
|
file_entry[35] = 0; //(size >> 32) & 0xff;
|
|
|
file_entry[36] = (size >> 24) & 0xff;
|
|
file_entry[36] = (size >> 24) & 0xff;
|
|
|
file_entry[37] = (size >> 16) & 0xff;
|
|
file_entry[37] = (size >> 16) & 0xff;
|
|
|
file_entry[38] = (size >> 8) & 0xff;
|
|
file_entry[38] = (size >> 8) & 0xff;
|
|
|
file_entry[39] = (size) & 0xff;
|
|
file_entry[39] = (size) & 0xff;
|
|
|
|
|
+ // send to SCSI output buffer
|
|
|
memcpy(&(scsiDev.data[ENTRY_SIZE * index]), file_entry, ENTRY_SIZE);
|
|
memcpy(&(scsiDev.data[ENTRY_SIZE * index]), file_entry, ENTRY_SIZE);
|
|
|
|
|
+ // increment index
|
|
|
index = index + 1;
|
|
index = index + 1;
|
|
|
|
|
+ if (index >= MAX_FILE_LISTING_FILES) break;
|
|
|
}
|
|
}
|
|
|
dir.close();
|
|
dir.close();
|
|
|
|
|
|
|
|
- scsiDev.dataLen = 4096;
|
|
|
|
|
|
|
+ scsiDev.dataLen = ENTRY_SIZE * index;
|
|
|
scsiDev.phase = DATA_IN;
|
|
scsiDev.phase = DATA_IN;
|
|
|
|
|
+ dbgmsg("TOOLBOX LIST FILES: returning ", index, " files for size ", scsiDev.dataLen);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static FsFile get_file_from_index(uint8_t index, const char * dir_name, bool isCD = false)
|
|
static FsFile get_file_from_index(uint8_t index, const char * dir_name, bool isCD = false)
|
|
|
{
|
|
{
|
|
|
- FsFile dir;
|
|
|
|
|
- FsFile file_test;
|
|
|
|
|
- char name[MAX_FILE_PATH] = {0};
|
|
|
|
|
|
|
+ FsFile dir;
|
|
|
|
|
+ FsFile file_test;
|
|
|
|
|
+ char name[MAX_FILE_PATH] = {0};
|
|
|
|
|
|
|
|
- dir.open(dir_name);
|
|
|
|
|
- dir.rewindDirectory(); // Back to the top
|
|
|
|
|
- int count = 0;
|
|
|
|
|
- while (file_test.openNext(&dir, O_RDONLY))
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- // If error there is no next file to open.
|
|
|
|
|
- if(file_test.getError() > 0) {
|
|
|
|
|
- file_test.close();
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- file_test.getName(name, MAX_FILE_PATH);
|
|
|
|
|
- if (isCD && file_test.isDirectory())
|
|
|
|
|
- {
|
|
|
|
|
- file_test.close();
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- if(!toolboxFilenameValid(name, isCD))
|
|
|
|
|
- {
|
|
|
|
|
- file_test.close();
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- if (count == index)
|
|
|
|
|
- {
|
|
|
|
|
- dir.close();
|
|
|
|
|
- return file_test;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
|
|
+ dir.open(dir_name);
|
|
|
|
|
+ dir.rewindDirectory(); // Back to the top
|
|
|
|
|
+ int count = 0;
|
|
|
|
|
+ while (file_test.openNext(&dir, O_RDONLY))
|
|
|
{
|
|
{
|
|
|
- file_test.close();
|
|
|
|
|
|
|
+ // If error there is no next file to open.
|
|
|
|
|
+ if(file_test.getError() > 0) {
|
|
|
|
|
+ file_test.close();
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ // no directories in CD image listing
|
|
|
|
|
+ if (isCD && file_test.isDirectory())
|
|
|
|
|
+ {
|
|
|
|
|
+ file_test.close();
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ // truncate filename the same way listing does, before validating name
|
|
|
|
|
+ size_t len = file_test.getName(name, MAX_FILE_PATH);
|
|
|
|
|
+ if (len > MAX_MAC_PATH)
|
|
|
|
|
+ name[MAX_MAC_PATH] = 0x0;
|
|
|
|
|
+ // validate filename
|
|
|
|
|
+ if(!toolboxFilenameValid(name, isCD))
|
|
|
|
|
+ {
|
|
|
|
|
+ file_test.close();
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ // found file?
|
|
|
|
|
+ if (count == index)
|
|
|
|
|
+ {
|
|
|
|
|
+ dir.close();
|
|
|
|
|
+ return file_test;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ file_test.close();
|
|
|
|
|
+ }
|
|
|
|
|
+ count++;
|
|
|
}
|
|
}
|
|
|
- count++;
|
|
|
|
|
- }
|
|
|
|
|
- file_test.close();
|
|
|
|
|
- dir.close();
|
|
|
|
|
- return file_test;
|
|
|
|
|
|
|
+ file_test.close();
|
|
|
|
|
+ dir.close();
|
|
|
|
|
+ return file_test;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Devices that are active on this SCSI device.
|
|
// Devices that are active on this SCSI device.
|
|
|
static void onListDevices()
|
|
static void onListDevices()
|
|
|
{
|
|
{
|
|
|
- for (int i = 0; i < NUM_SCSIID; i++)
|
|
|
|
|
- {
|
|
|
|
|
- const S2S_TargetCfg* cfg = s2s_getConfigById(i);
|
|
|
|
|
- if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
|
|
|
|
|
- {
|
|
|
|
|
- scsiDev.data[i] = (int)cfg->deviceType; // 2 == cd
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
|
|
+ for (int i = 0; i < NUM_SCSIID; i++)
|
|
|
{
|
|
{
|
|
|
- scsiDev.data[i] = 0xFF; // not enabled target.
|
|
|
|
|
|
|
+ const S2S_TargetCfg* cfg = s2s_getConfigById(i);
|
|
|
|
|
+ if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
|
|
|
|
|
+ {
|
|
|
|
|
+ scsiDev.data[i] = (int)cfg->deviceType; // 2 == cd
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ scsiDev.data[i] = 0xFF; // not enabled target.
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- scsiDev.dataLen = NUM_SCSIID;
|
|
|
|
|
|
|
+ scsiDev.dataLen = NUM_SCSIID;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void onSetNextCD(const char * img_dir)
|
|
static void onSetNextCD(const char * img_dir)
|
|
@@ -348,58 +370,69 @@ extern "C" int scsiToolboxCommand()
|
|
|
if (unlikely(command == TOOLBOX_COUNT_FILES))
|
|
if (unlikely(command == TOOLBOX_COUNT_FILES))
|
|
|
{
|
|
{
|
|
|
char img_dir[MAX_FILE_PATH];
|
|
char img_dir[MAX_FILE_PATH];
|
|
|
|
|
+ dbgmsg("TOOLBOX_COUNT_FILES");
|
|
|
getToolBoxSharedDir(img_dir);
|
|
getToolBoxSharedDir(img_dir);
|
|
|
doCountFiles(img_dir);
|
|
doCountFiles(img_dir);
|
|
|
}
|
|
}
|
|
|
else if (unlikely(command == TOOLBOX_LIST_FILES))
|
|
else if (unlikely(command == TOOLBOX_LIST_FILES))
|
|
|
{
|
|
{
|
|
|
char img_dir[MAX_FILE_PATH];
|
|
char img_dir[MAX_FILE_PATH];
|
|
|
|
|
+ dbgmsg("TOOLBOX_LIST_FILES");
|
|
|
getToolBoxSharedDir(img_dir);
|
|
getToolBoxSharedDir(img_dir);
|
|
|
onListFiles(img_dir);
|
|
onListFiles(img_dir);
|
|
|
}
|
|
}
|
|
|
else if (unlikely(command == TOOLBOX_GET_FILE))
|
|
else if (unlikely(command == TOOLBOX_GET_FILE))
|
|
|
{
|
|
{
|
|
|
char img_dir[MAX_FILE_PATH];
|
|
char img_dir[MAX_FILE_PATH];
|
|
|
|
|
+ dbgmsg("TOOLBOX_GET_FILE");
|
|
|
getToolBoxSharedDir(img_dir);
|
|
getToolBoxSharedDir(img_dir);
|
|
|
onGetFile10(img_dir);
|
|
onGetFile10(img_dir);
|
|
|
}
|
|
}
|
|
|
else if (unlikely(command == TOOLBOX_SEND_FILE_PREP))
|
|
else if (unlikely(command == TOOLBOX_SEND_FILE_PREP))
|
|
|
{
|
|
{
|
|
|
char img_dir[MAX_FILE_PATH];
|
|
char img_dir[MAX_FILE_PATH];
|
|
|
|
|
+ dbgmsg("TOOLBOX_SEND_FILE_PREP");
|
|
|
getToolBoxSharedDir(img_dir);
|
|
getToolBoxSharedDir(img_dir);
|
|
|
onSendFilePrep(img_dir);
|
|
onSendFilePrep(img_dir);
|
|
|
}
|
|
}
|
|
|
else if (unlikely(command == TOOLBOX_SEND_FILE_10))
|
|
else if (unlikely(command == TOOLBOX_SEND_FILE_10))
|
|
|
{
|
|
{
|
|
|
|
|
+ dbgmsg("TOOLBOX_SEND_FILE_10");
|
|
|
onSendFile10();
|
|
onSendFile10();
|
|
|
}
|
|
}
|
|
|
else if (unlikely(command == TOOLBOX_SEND_FILE_END))
|
|
else if (unlikely(command == TOOLBOX_SEND_FILE_END))
|
|
|
{
|
|
{
|
|
|
|
|
+ dbgmsg("TOOLBOX_SEND_FILE_END");
|
|
|
onSendFileEnd();
|
|
onSendFileEnd();
|
|
|
}
|
|
}
|
|
|
else if(unlikely(command == TOOLBOX_TOGGLE_DEBUG))
|
|
else if(unlikely(command == TOOLBOX_TOGGLE_DEBUG))
|
|
|
{
|
|
{
|
|
|
|
|
+ dbgmsg("TOOLBOX_TOGGLE_DEBUG");
|
|
|
onToggleDebug();
|
|
onToggleDebug();
|
|
|
}
|
|
}
|
|
|
else if(unlikely(command == TOOLBOX_LIST_CDS))
|
|
else if(unlikely(command == TOOLBOX_LIST_CDS))
|
|
|
{
|
|
{
|
|
|
char img_dir[4];
|
|
char img_dir[4];
|
|
|
|
|
+ dbgmsg("TOOLBOX_LIST_CDS");
|
|
|
snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS);
|
|
snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS);
|
|
|
onListFiles(img_dir, true);
|
|
onListFiles(img_dir, true);
|
|
|
}
|
|
}
|
|
|
else if(unlikely(command == TOOLBOX_SET_NEXT_CD))
|
|
else if(unlikely(command == TOOLBOX_SET_NEXT_CD))
|
|
|
{
|
|
{
|
|
|
char img_dir[4];
|
|
char img_dir[4];
|
|
|
|
|
+ dbgmsg("TOOLBOX_SET_NEXT_CD");
|
|
|
snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS);
|
|
snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS);
|
|
|
onSetNextCD(img_dir);
|
|
onSetNextCD(img_dir);
|
|
|
}
|
|
}
|
|
|
else if(unlikely(command == TOOLBOX_LIST_DEVICES))
|
|
else if(unlikely(command == TOOLBOX_LIST_DEVICES))
|
|
|
{
|
|
{
|
|
|
|
|
+ dbgmsg("TOOLBOX_LIST_DEVICES");
|
|
|
onListDevices();
|
|
onListDevices();
|
|
|
}
|
|
}
|
|
|
else if (unlikely(command == TOOLBOX_COUNT_CDS))
|
|
else if (unlikely(command == TOOLBOX_COUNT_CDS))
|
|
|
{
|
|
{
|
|
|
char img_dir[4];
|
|
char img_dir[4];
|
|
|
|
|
+ dbgmsg("TOOLBOX_COUNT_CDS");
|
|
|
snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS);
|
|
snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS);
|
|
|
doCountFiles(img_dir, true);
|
|
doCountFiles(img_dir, true);
|
|
|
}
|
|
}
|