From 0052195afbb71e6bc222efdefce04341b30046c8 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Thu, 8 Jun 2023 16:35:41 -0500 Subject: [PATCH 01/13] BlueSCSI Toolbox WIP --- lib/SCSI2SD/src/firmware/mode.c | 15 ++ lib/SCSI2SD/src/firmware/scsi.c | 4 + lib/minIni/minGlue.h | 7 +- lib/minIni/minIni.cpp | 2 +- lib/minIni/minIni_cache.cpp | 52 +++++ src/BlueSCSI_Toolbox.cpp | 400 ++++++++++++++++++++++++++++++++ src/BlueSCSI_Toolbox.h | 41 ++++ src/ImageBackingStore.cpp | 10 + src/ImageBackingStore.h | 3 + 9 files changed, 532 insertions(+), 2 deletions(-) create mode 100644 src/BlueSCSI_Toolbox.cpp create mode 100644 src/BlueSCSI_Toolbox.h diff --git a/lib/SCSI2SD/src/firmware/mode.c b/lib/SCSI2SD/src/firmware/mode.c index 3ccca2af..78c05bf6 100755 --- a/lib/SCSI2SD/src/firmware/mode.c +++ b/lib/SCSI2SD/src/firmware/mode.c @@ -246,6 +246,14 @@ static const uint8_t AppleVendorPage[] = 'A','P','P','L','E',' ','C','O','M','P','U','T','E','R',',',' ','I','N','C',' ',' ',' ' }; +static const uint8_t BlueSCSIVendorPage[] = +{ +0x31, // Page code +42, // Page length +'B','l','u','e','S','C','S','I',' ','i','s',' ','t','h','e',' ','B','E','S','T',' ', +'S','T','O','L','E','N',' ','F','R','O','M',' ','B','L','U','E','S','C','S','I',0x00 +}; + static void pageIn(int pc, int dataIdx, const uint8_t* pageData, int pageLen) { memcpy(&scsiDev.data[dataIdx], pageData, pageLen); @@ -525,6 +533,13 @@ static void doModeSense( idx += sizeof(AppleVendorPage); } + if (pageCode == 0x31 || pageCode == 0x3F) + { + pageFound = 1; + pageIn(pc, idx, BlueSCSIVendorPage, sizeof(BlueSCSIVendorPage)); + idx += sizeof(BlueSCSIVendorPage); + } + if (pageCode == 0x38) // Don't send unless requested { pageFound = 1; diff --git a/lib/SCSI2SD/src/firmware/scsi.c b/lib/SCSI2SD/src/firmware/scsi.c index 2e184fae..395d38f6 100755 --- a/lib/SCSI2SD/src/firmware/scsi.c +++ b/lib/SCSI2SD/src/firmware/scsi.c @@ -587,6 +587,10 @@ static void process_Command() { // Already handled. } + else if (scsiBlueSCSIToolboxCommand()) + { + // handled + } else if (scsiDiskCommand()) { // Already handled. diff --git a/lib/minIni/minGlue.h b/lib/minIni/minGlue.h index d27d2fba..330e8743 100644 --- a/lib/minIni/minGlue.h +++ b/lib/minIni/minGlue.h @@ -2,7 +2,7 @@ #include -#define INI_READONLY 1 +#define INI_OPENREWRITE 1 #define INI_FILETYPE FsFile #define INI_FILEPOS fspos_t @@ -11,3 +11,8 @@ bool ini_close(INI_FILETYPE *fp); bool ini_read(char *buffer, int size, INI_FILETYPE *fp); void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos); void ini_seek(INI_FILETYPE *fp, INI_FILEPOS *pos); + +bool ini_write(char *buffer, INI_FILETYPE *fp); +bool ini_openwrite(const char *filename, INI_FILETYPE *fp); +bool ini_openrewrite(const char *filename, INI_FILETYPE *fp); +void ini_rename(const char *new_name, const char *old_name); \ No newline at end of file diff --git a/lib/minIni/minIni.cpp b/lib/minIni/minIni.cpp index a80c5c76..ba1d0140 100644 --- a/lib/minIni/minIni.cpp +++ b/lib/minIni/minIni.cpp @@ -721,7 +721,7 @@ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const T ini_tell(&rfp, &tail); /* create new buffer (without writing it to file) */ writekey(LocalBuffer, Key, Value, NULL); - if (_tcslen(LocalBuffer) == (size_t)(tail - head)) { + if (_tcslen(LocalBuffer) == (size_t)(tail.position - head.position)) { /* length matches, close the file & re-open for read/write, then * write at the correct position */ diff --git a/lib/minIni/minIni_cache.cpp b/lib/minIni/minIni_cache.cpp index d549e4b3..6057c82d 100644 --- a/lib/minIni/minIni_cache.cpp +++ b/lib/minIni/minIni_cache.cpp @@ -71,6 +71,46 @@ bool ini_openread(const char *filename, INI_FILETYPE *fp) return fp->open(SD.vol(), filename, O_RDONLY); } +// Open .ini file either from cache or from SD card +bool ini_openwrite(const char *filename, INI_FILETYPE *fp) +{ +#if INI_CACHE_SIZE > 0 + if (g_ini_cache.valid && + (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0)) + { + fp->close(); + g_ini_cache.fp = fp; + g_ini_cache.current_pos.position = 0; + return true; + } +#endif + + return fp->open(SD.vol(), filename, O_WRONLY); +} + +// Open .ini file either from cache or from SD card +bool ini_openrewrite(const char *filename, INI_FILETYPE *fp) +{ +#if INI_CACHE_SIZE > 0 + if (g_ini_cache.valid && + (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0)) + { + fp->close(); + g_ini_cache.fp = fp; + g_ini_cache.current_pos.position = 0; + return true; + } +#endif + + return fp->open(SD.vol(), filename, O_RDWR); +} + +void ini_rename(const char * old_name, const char *new_name) +{ + SD.rename(old_name, new_name); + invalidate_ini_cache(); +} + // Close previously opened file bool ini_close(INI_FILETYPE *fp) { @@ -116,6 +156,18 @@ bool ini_read(char *buffer, int size, INI_FILETYPE *fp) } } +// Write to the card and invalidate the cache. +bool ini_write(char *buffer, INI_FILETYPE *fp) +{ + if(fp->write(buffer) > 0) + { + invalidate_ini_cache(); + return true; + } + else + return false; +} + // Get the position inside the file void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos) { diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp new file mode 100644 index 00000000..367b445b --- /dev/null +++ b/src/BlueSCSI_Toolbox.cpp @@ -0,0 +1,400 @@ +/** + * Copyright (C) 2023 Eric Helgeson + * + * This file is part of BlueSCSI + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +**/ +#include "BlueSCSI_Toolbox.h" +#include "BlueSCSI_disk.h" +#include "BlueSCSI_log.h" +#include +#include +extern "C" { +#include +#include +#include +} + + +static void doCountFiles(const char * dir_name) +{ + File dir; + File file; + char name[ MAX_MAC_PATH + 1]; + dir.open(dir_name); + dir.rewindDirectory(); + uint8_t file_count = 0; + while (file.openNext(&dir, O_RDONLY)) + { + if(file.getError() > 0) + { + file.close(); + break; + } + file.getName(name, 32 + 1); + file.close(); + // only count valid files. + if(name[0] != '.') + { + file_count = file_count + 1; + if(file_count > 100) { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = OPEN_RETRO_SCSI_TOO_MANY_FILES; + scsiDev.phase = STATUS; + dir.close(); + return; + } + } + } + scsiDev.data[0] = file_count; + scsiDev.dataLen = sizeof(file_count); + scsiDev.phase = DATA_IN; +} + +void onListFiles(const char * dir_name) { + File dir; + File file; + + memset(scsiDev.data, 0, 4096); + int ENTRY_SIZE = 40; + char name[MAX_MAC_PATH + 1]; + dir.open(dir_name); + dir.rewindDirectory(); + uint8_t index = 0; + byte file_entry[40] = {0}; + while (file.openNext(&dir, O_RDONLY)) + { + uint8_t isDir = file.isDirectory() ? 0x00 : 0x01; + file.getName(name, MAX_MAC_PATH + 1); + uint64_t size = file.fileSize(); + file.close(); + if(name[0] == '.') + continue; + file_entry[0] = index; + 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++]; + } + file_entry[35] = 0; //(size >> 32) & 0xff; + file_entry[36] = (size >> 24) & 0xff; + file_entry[37] = (size >> 16) & 0xff; + file_entry[38] = (size >> 8) & 0xff; + file_entry[39] = (size) & 0xff; + memcpy(&(scsiDev.data[ENTRY_SIZE * index]), file_entry, ENTRY_SIZE); + index = index + 1; + } + dir.close(); + + scsiDev.dataLen = 4096; + scsiDev.phase = DATA_IN; +} + +File get_file_from_index(uint8_t index, const char * dir_name) +{ + File dir; + FsFile file_test; + char name[MAX_MAC_PATH + 1]; + + 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, 32 + 1); + + if(name[0] == '.') + continue; + if (count == index) + { + dir.close(); + return file_test; + } + else + { + file_test.close(); + } + count++; + } + file_test.close(); + dir.close(); + return file_test; +} + +// Devices that are active on this SCSI device. +void onListDevices() +{ + for (int i = 0; i < NUM_SCSIID; i++) + { + const S2S_TargetCfg* cfg = s2s_getConfigById(i); + // id, type + if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED)) + { + scsiDev.data[i] = (int)cfg->deviceType; // 2 == cd + } + else + { + scsiDev.data[i] = 255; // not enabled target. + } + } + scsiDev.dataLen = 16; +} + +void onSetNextCD() +{ + char name[MAX_FILE_PATH]; + char full_path[MAX_FILE_PATH * 2]; + + uint8_t file_index = scsiDev.cdb[1]; + uint8_t cd_scsi_id = scsiDev.cdb[2]; + char section[6] = "SCSI0"; + char key[5] = "IMG0"; + section[4] = '0' + cd_scsi_id; + + image_config_t &img = *(image_config_t*)scsiDev.target->cfg; + debuglog("img.image_index: ", img.image_index); + int next_image_id = img.image_index + 1; + + if(img.image_index == 0) + { // have to check if we have a 0, if not set the current image to 0 so we can cycle back. + ini_gets(section, key, "", name, sizeof(name), CONFIGFILE); + if(strlen(name) == 0) + { + img.file.getName(name, MAX_FILE_PATH); + log("Nothing in IMG0, so put the current image in it: ", name); + ini_puts(section, key, name, CONFIGFILE); + } + else + { + log("Something in IMG0: ", name); + } + } + + debuglog("next_image_id: ", next_image_id); + if(next_image_id > 9) + next_image_id = 0; + + key[3] = '0' + next_image_id; + File next_cd = get_file_from_index(file_index, CD_IMG_DIR); + if(!next_cd.isFile()) + { + log("not a file?"); + next_cd.close(); + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + return; + } + next_cd.getName(name, sizeof(name)); + next_cd.close(); + snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", CD_IMG_DIR, name); + debuglog("full_path: ", full_path); + debuglog("key: ", key, " section: ", section); + // If file doesnt exist, ini_puts() will create it. + if(!ini_puts(section, key, full_path, CONFIGFILE)) + { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + return; + } +} + +File gFile; // global so we can keep it open while transfering. +void onGetFile10(void) { + uint8_t index = scsiDev.cdb[1]; + + uint32_t offset = ((uint32_t)scsiDev.cdb[2] << 24) | ((uint32_t)scsiDev.cdb[3] << 16) | ((uint32_t)scsiDev.cdb[4] << 8) | scsiDev.cdb[5]; + + if (offset == 0) // first time, open the file. + { + gFile = get_file_from_index(index, "/shared"); + if(!gFile.isDirectory() && !gFile.isReadable()) + { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + return; + } + } + + uint32_t file_total = gFile.size(); + memset(scsiDev.data, 0, 4096); + gFile.seekSet(offset * 4096); + int bytes_read = gFile.read(scsiDev.data, 4096); + if(offset * 4096 >= file_total) // transfer done, close. + { + gFile.close(); + } + scsiDev.dataLen = bytes_read; + scsiDev.phase = DATA_IN; +} + +/* + Prepares a file for receving. The file name is null terminated in the scsi data. +*/ +File receveFile; +void onSendFilePrep(void) +{ + char file_name[32+1]; + memset(file_name, '\0', 32+1); + scsiEnterPhase(DATA_OUT); + for (int i = 0; i < 32+1; ++i) + { + file_name[i] = scsiReadByte(); + } + SD.chdir("/shared"); + receveFile.open(file_name, FILE_WRITE); + SD.chdir("/"); + if(receveFile.isOpen() && receveFile.isWritable()) + { + receveFile.rewind(); + receveFile.sync(); + // do i need to manually set phase to status here? + return; + } else { + receveFile.close(); + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + } +} + +void onSendFileEnd(void) +{ + receveFile.sync(); + receveFile.close(); + scsiDev.phase = STATUS; +} + +void onSendFile10(void) +{ + if(!receveFile.isOpen() || !receveFile.isWritable()) + { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + } + + // Number of bytes sent this request, 1..512. + uint16_t bytes_sent = ((uint16_t)scsiDev.cdb[1] << 8) | scsiDev.cdb[2]; + // 512 byte offset of where to put these bytes. + uint32_t offset = ((uint32_t)scsiDev.cdb[3] << 16) | ((uint32_t)scsiDev.cdb[4] << 8) | scsiDev.cdb[5]; + uint16_t buf_size = 512; + uint8_t buf[512]; + + // Check if last block of file, and not the only bock in file. + if(bytes_sent < buf_size) + { + buf_size = bytes_sent; + } + + scsiEnterPhase(DATA_OUT); + scsiRead(buf, bytes_sent, NULL); + receveFile.seekCur(offset * 512); + receveFile.write(buf, buf_size); + if(receveFile.getWriteError()) + { + receveFile.clearWriteError(); + receveFile.close(); + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + } + //scsiDev.phase = STATUS; +} +void onToggleDebug() +{ + if(g_log_debug) + { + debuglog("Turning Debug logs off."); + } + else + { + log("Turning Debug logs on."); + } + g_log_debug = !g_log_debug; + scsiDev.phase = STATUS; +} + +extern "C" int scsiBlueSCSIToolboxCommand() +{ + int commandHandled = 1; + uint8_t command = scsiDev.cdb[0]; + + if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_FILES)) + { + doCountFiles("/shared"); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_LIST_FILES)) + { + // TODO: Allow user to set dir name via ini + onListFiles("/shared"); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_GET_FILE)) + { + onGetFile10(); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_PREP)) + { + onSendFilePrep(); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_10)) + { + onSendFile10(); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_END)) + { + onSendFileEnd(); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_TOGGLE_DEBUG)) + { + onToggleDebug(); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_LIST_CDS)) + { + onListFiles("/CDImages"); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_SET_NEXT_CD)) + { + onSetNextCD(); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_LIST_DEVICES)) + { + onListDevices(); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_CDS)) + { + // TODO: Allow user to set dir name via ini + doCountFiles("/CDImages"); + } + else + { + commandHandled = 0; + } + + return commandHandled; +} \ No newline at end of file diff --git a/src/BlueSCSI_Toolbox.h b/src/BlueSCSI_Toolbox.h new file mode 100644 index 00000000..4affaea4 --- /dev/null +++ b/src/BlueSCSI_Toolbox.h @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2023 Eric Helgeson + * + * This file is part of BlueSCSI + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +**/ + +#pragma once + +#include +#include +#include +#include "ImageBackingStore.h" +#define MAX_MAC_PATH 32 +#define CD_IMG_DIR "/CDImages" + + +#define BLUESCSI_TOOLBOX_COUNT_FILES 0xD2 +#define BLUESCSI_TOOLBOX_LIST_FILES 0xD0 +#define BLUESCSI_TOOLBOX_GET_FILE 0xD1 +#define BLUESCSI_TOOLBOX_SEND_FILE_PREP 0xD3 +#define BLUESCSI_TOOLBOX_SEND_FILE_10 0xD4 +#define BLUESCSI_TOOLBOX_SEND_FILE_END 0xD5 +#define BLUESCSI_TOOLBOX_TOGGLE_DEBUG 0xD6 +#define BLUESCSI_TOOLBOX_LIST_CDS 0xD7 +#define BLUESCSI_TOOLBOX_SET_NEXT_CD 0xD8 +#define BLUESCSI_TOOLBOX_LIST_DEVICES 0xD9 +#define BLUESCSI_TOOLBOX_COUNT_CDS 0xDA +#define OPEN_RETRO_SCSI_TOO_MANY_FILES 0x0001 \ No newline at end of file diff --git a/src/ImageBackingStore.cpp b/src/ImageBackingStore.cpp index 02095b16..4ac2041c 100644 --- a/src/ImageBackingStore.cpp +++ b/src/ImageBackingStore.cpp @@ -304,6 +304,16 @@ void ImageBackingStore::flush() } } +void ImageBackingStore::getName(char * name, size_t len) +{ + if(m_isrom) + name = (char*)"ROM:"; + else if(m_israw) + name = (char*)"RAW:"; + else + m_fsfile.getName(name, len); +} + uint64_t ImageBackingStore::position() { if (!m_israw && !m_isrom) diff --git a/src/ImageBackingStore.h b/src/ImageBackingStore.h index 6724c7cb..41572992 100644 --- a/src/ImageBackingStore.h +++ b/src/ImageBackingStore.h @@ -74,6 +74,9 @@ class ImageBackingStore // Flush any pending changes to filesystem void flush(); + // Get name of the fs_file + void getName(char *name, size_t len); + // Gets current position for following read/write operations // Result is only valid for regular files, not raw or flash access uint64_t position(); From 13901a66faad1cb9d8f9c35bdc638462e3603103 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Fri, 9 Jun 2023 15:51:38 -0500 Subject: [PATCH 02/13] Simplify CD Image swtiching --- src/BlueSCSI_Toolbox.cpp | 57 +++++----------------------------------- src/BlueSCSI_cdrom.cpp | 34 ++++++++++++++++++++++++ src/BlueSCSI_cdrom.h | 5 +++- src/BlueSCSI_disk.cpp | 2 +- 4 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index 367b445b..0bd4bfdc 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -18,6 +18,7 @@ **/ #include "BlueSCSI_Toolbox.h" #include "BlueSCSI_disk.h" +#include "BlueSCSI_cdrom.h" #include "BlueSCSI_log.h" #include #include @@ -46,7 +47,7 @@ static void doCountFiles(const char * dir_name) file.getName(name, 32 + 1); file.close(); // only count valid files. - if(name[0] != '.') + if(!scsiDiskFilenameValid(name)) { file_count = file_count + 1; if(file_count > 100) { @@ -81,7 +82,7 @@ void onListFiles(const char * dir_name) { file.getName(name, MAX_MAC_PATH + 1); uint64_t size = file.fileSize(); file.close(); - if(name[0] == '.') + if(!scsiDiskFilenameValid(name)) continue; file_entry[0] = index; file_entry[1] = isDir; @@ -120,9 +121,9 @@ File get_file_from_index(uint8_t index, const char * dir_name) file_test.close(); break; } - file_test.getName(name, 32 + 1); + file_test.getName(name, MAX_MAC_PATH + 1); - if(name[0] == '.') + if(!scsiDiskFilenameValid(name)) continue; if (count == index) { @@ -166,59 +167,13 @@ void onSetNextCD() uint8_t file_index = scsiDev.cdb[1]; uint8_t cd_scsi_id = scsiDev.cdb[2]; - char section[6] = "SCSI0"; - char key[5] = "IMG0"; - section[4] = '0' + cd_scsi_id; image_config_t &img = *(image_config_t*)scsiDev.target->cfg; - debuglog("img.image_index: ", img.image_index); - int next_image_id = img.image_index + 1; - - if(img.image_index == 0) - { // have to check if we have a 0, if not set the current image to 0 so we can cycle back. - ini_gets(section, key, "", name, sizeof(name), CONFIGFILE); - if(strlen(name) == 0) - { - img.file.getName(name, MAX_FILE_PATH); - log("Nothing in IMG0, so put the current image in it: ", name); - ini_puts(section, key, name, CONFIGFILE); - } - else - { - log("Something in IMG0: ", name); - } - } - - debuglog("next_image_id: ", next_image_id); - if(next_image_id > 9) - next_image_id = 0; - - key[3] = '0' + next_image_id; File next_cd = get_file_from_index(file_index, CD_IMG_DIR); - if(!next_cd.isFile()) - { - log("not a file?"); - next_cd.close(); - scsiDev.status = CHECK_CONDITION; - scsiDev.target->sense.code = ILLEGAL_REQUEST; - //SCSI_ASC_INVALID_FIELD_IN_CDB - scsiDev.phase = STATUS; - return; - } next_cd.getName(name, sizeof(name)); next_cd.close(); snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", CD_IMG_DIR, name); - debuglog("full_path: ", full_path); - debuglog("key: ", key, " section: ", section); - // If file doesnt exist, ini_puts() will create it. - if(!ini_puts(section, key, full_path, CONFIGFILE)) - { - scsiDev.status = CHECK_CONDITION; - scsiDev.target->sense.code = ILLEGAL_REQUEST; - //SCSI_ASC_INVALID_FIELD_IN_CDB - scsiDev.phase = STATUS; - return; - } + cdromSwitch(img, full_path); } File gFile; // global so we can keep it open while transfering. diff --git a/src/BlueSCSI_cdrom.cpp b/src/BlueSCSI_cdrom.cpp index 69c332f2..baa7e12d 100644 --- a/src/BlueSCSI_cdrom.cpp +++ b/src/BlueSCSI_cdrom.cpp @@ -1239,6 +1239,40 @@ bool cdromSwitchNextImage(image_config_t &img) return false; } +// Check if we have multiple CD-ROM images to cycle when drive is ejected. +bool cdromSwitch(image_config_t &img, const char* filename) +{ + // Check if we have a next image to load, so that drive is closed next time the host asks. + int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS; + +#ifdef ENABLE_AUDIO_OUTPUT + // if in progress for this device, terminate audio playback immediately (Annex C) + audio_stop(target_idx); + // Reset position tracking for the new image + audio_get_status_code(target_idx); // trash audio status code +#endif + + if (filename[0] != '\0') + { + log("Switching to next CD-ROM image for ", target_idx, ": ", filename); + img.file.close(); + bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048); + + if (status) + { + img.ejected = false; + img.cdrom_events = 2; // New media + return true; + } + } + else + { + log("Could not switch to CD-ROM image as provide filename was empty."); + } + + return false; +} + static void doGetEventStatusNotification(bool immed) { image_config_t &img = *(image_config_t*)scsiDev.target->cfg; diff --git a/src/BlueSCSI_cdrom.h b/src/BlueSCSI_cdrom.h index 95499152..1d14711b 100644 --- a/src/BlueSCSI_cdrom.h +++ b/src/BlueSCSI_cdrom.h @@ -31,4 +31,7 @@ bool cdromValidateCueSheet(image_config_t &img); // Audio playback status // boolean flag is true if just basic mechanism status (playback true/false) // is desired, or false if historical audio status codes should be returned -void cdromGetAudioPlaybackStatus(uint8_t *status, uint32_t *current_lba, bool current_only); \ No newline at end of file +void cdromGetAudioPlaybackStatus(uint8_t *status, uint32_t *current_lba, bool current_only); + +// switch to a given filename for the cd. +bool cdromSwitch(image_config_t &img, const char* filename); \ No newline at end of file diff --git a/src/BlueSCSI_disk.cpp b/src/BlueSCSI_disk.cpp index e59313f9..ad070b66 100644 --- a/src/BlueSCSI_disk.cpp +++ b/src/BlueSCSI_disk.cpp @@ -506,7 +506,7 @@ bool scsiDiskFilenameValid(const char* name) { if (strcasecmp(extension, ignore_exts[i]) == 0) { - // ignore these without log message + debuglog("-- Ignoring compressed file ", name); return false; } } From e8f7dc185dd3b4dc63a386c92bb420ea81c70954 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Fri, 9 Jun 2023 16:19:10 -0500 Subject: [PATCH 03/13] Dont stop audio playback if invalid filename --- src/BlueSCSI_cdrom.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/BlueSCSI_cdrom.cpp b/src/BlueSCSI_cdrom.cpp index baa7e12d..b0cf40f2 100644 --- a/src/BlueSCSI_cdrom.cpp +++ b/src/BlueSCSI_cdrom.cpp @@ -1216,16 +1216,15 @@ bool cdromSwitchNextImage(image_config_t &img) int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS; scsiDiskGetNextImageName(img, filename, sizeof(filename)); + if (filename[0] != '\0') + { #ifdef ENABLE_AUDIO_OUTPUT // if in progress for this device, terminate audio playback immediately (Annex C) audio_stop(target_idx); // Reset position tracking for the new image audio_get_status_code(target_idx); // trash audio status code #endif - - if (filename[0] != '\0') - { - log("Switching to next CD-ROM image for SCSI ID: ", target_idx, ": ", filename); + log("Switching to next CD-ROM image for ", target_idx, ": ", filename); img.file.close(); bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, getBlockSize(filename, target_idx, 2048)); @@ -1245,15 +1244,14 @@ bool cdromSwitch(image_config_t &img, const char* filename) // Check if we have a next image to load, so that drive is closed next time the host asks. int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS; -#ifdef ENABLE_AUDIO_OUTPUT - // if in progress for this device, terminate audio playback immediately (Annex C) - audio_stop(target_idx); - // Reset position tracking for the new image - audio_get_status_code(target_idx); // trash audio status code -#endif - if (filename[0] != '\0') { +#ifdef ENABLE_AUDIO_OUTPUT + // if in progress for this device, terminate audio playback immediately (Annex C) + audio_stop(target_idx); + // Reset position tracking for the new image + audio_get_status_code(target_idx); // trash audio status code +#endif log("Switching to next CD-ROM image for ", target_idx, ": ", filename); img.file.close(); bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048); From de182e26f9aa95b1b9ef58b7465358fb87a4c4cf Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Tue, 13 Jun 2023 10:49:09 -0500 Subject: [PATCH 04/13] Various fixes testing. --- src/BlueSCSI_Toolbox.cpp | 15 ++++++++------- src/BlueSCSI_disk.cpp | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index 0bd4bfdc..41c97f1f 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -44,10 +44,10 @@ static void doCountFiles(const char * dir_name) file.close(); break; } - file.getName(name, 32 + 1); + file.getName(name, MAX_MAC_PATH + 1); file.close(); // only count valid files. - if(!scsiDiskFilenameValid(name)) + if(scsiDiskFilenameValid(name)) { file_count = file_count + 1; if(file_count > 100) { @@ -124,7 +124,10 @@ File get_file_from_index(uint8_t index, const char * dir_name) file_test.getName(name, MAX_MAC_PATH + 1); if(!scsiDiskFilenameValid(name)) - continue; + { + file_test.close(); + continue; + } if (count == index) { dir.close(); @@ -147,17 +150,16 @@ void onListDevices() for (int i = 0; i < NUM_SCSIID; i++) { const S2S_TargetCfg* cfg = s2s_getConfigById(i); - // id, type if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED)) { scsiDev.data[i] = (int)cfg->deviceType; // 2 == cd } else { - scsiDev.data[i] = 255; // not enabled target. + scsiDev.data[i] = 0xFF; // not enabled target. } } - scsiDev.dataLen = 16; + scsiDev.dataLen = NUM_SCSIID; } void onSetNextCD() @@ -166,7 +168,6 @@ void onSetNextCD() char full_path[MAX_FILE_PATH * 2]; uint8_t file_index = scsiDev.cdb[1]; - uint8_t cd_scsi_id = scsiDev.cdb[2]; image_config_t &img = *(image_config_t*)scsiDev.target->cfg; File next_cd = get_file_from_index(file_index, CD_IMG_DIR); diff --git a/src/BlueSCSI_disk.cpp b/src/BlueSCSI_disk.cpp index ad070b66..9708be35 100644 --- a/src/BlueSCSI_disk.cpp +++ b/src/BlueSCSI_disk.cpp @@ -506,7 +506,7 @@ bool scsiDiskFilenameValid(const char* name) { if (strcasecmp(extension, ignore_exts[i]) == 0) { - debuglog("-- Ignoring compressed file ", name); + debuglog("-- Ignoring file ", name); return false; } } From 4522d1f3c08e234dd7615aa4a812b61de68fb6b4 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Fri, 11 Aug 2023 13:21:09 -0500 Subject: [PATCH 05/13] Fix Debug switching --- src/BlueSCSI_Toolbox.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index 41c97f1f..04df3441 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -284,16 +284,19 @@ void onSendFile10(void) } void onToggleDebug() { - if(g_log_debug) + if(scsiDev.cdb[1] == 0) // 0 == Set Debug, 1 == Get Debug State { - debuglog("Turning Debug logs off."); + g_log_debug = scsiDev.cdb[2]; + log("Set debug logs to: ", g_log_debug); + scsiDev.phase = STATUS; } else { - log("Turning Debug logs on."); + log("Debug currently set to: ", g_log_debug); + scsiDev.data[0] = g_log_debug ? 0x1 : 0x0; + scsiDev.dataLen = 1; + scsiDev.phase = DATA_IN; } - g_log_debug = !g_log_debug; - scsiDev.phase = STATUS; } extern "C" int scsiBlueSCSIToolboxCommand() From a8d7d58cead1381310320581714ba949ca04d30b Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Fri, 11 Aug 2023 15:15:42 -0500 Subject: [PATCH 06/13] cleanup some headers and warnings --- lib/SCSI2SD/src/firmware/bluescsi_toolbox.h | 25 +++++++++++++++++++++ lib/SCSI2SD/src/firmware/scsi.c | 1 + src/BlueSCSI_Toolbox.h | 4 ---- 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 lib/SCSI2SD/src/firmware/bluescsi_toolbox.h diff --git a/lib/SCSI2SD/src/firmware/bluescsi_toolbox.h b/lib/SCSI2SD/src/firmware/bluescsi_toolbox.h new file mode 100644 index 00000000..95877bd1 --- /dev/null +++ b/lib/SCSI2SD/src/firmware/bluescsi_toolbox.h @@ -0,0 +1,25 @@ +/** + * Copyright (C) 2023 Eric Helgeson + * + * This file is part of BlueSCSI + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +**/ + +#ifndef S2S_BLUESCSI_TOOLBOX_H +#define S2S_BLUESCSI_TOOLBOX_H + +int scsiBlueSCSIToolboxCommand(void); + +#endif diff --git a/lib/SCSI2SD/src/firmware/scsi.c b/lib/SCSI2SD/src/firmware/scsi.c index 395d38f6..e378a81d 100755 --- a/lib/SCSI2SD/src/firmware/scsi.c +++ b/lib/SCSI2SD/src/firmware/scsi.c @@ -30,6 +30,7 @@ #include "tape.h" #include "mo.h" #include "vendor.h" +#include "bluescsi_toolbox.h" #include diff --git a/src/BlueSCSI_Toolbox.h b/src/BlueSCSI_Toolbox.h index 4affaea4..ecacee31 100644 --- a/src/BlueSCSI_Toolbox.h +++ b/src/BlueSCSI_Toolbox.h @@ -19,10 +19,6 @@ #pragma once -#include -#include -#include -#include "ImageBackingStore.h" #define MAX_MAC_PATH 32 #define CD_IMG_DIR "/CDImages" From 5e2300355134ba38b0ceb179b8f9604b9875b27a Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Fri, 18 Aug 2023 13:30:13 -0500 Subject: [PATCH 07/13] Integrate Toolbox cd switcher with new CD[N] feature --- src/BlueSCSI_Toolbox.cpp | 21 +++++++++++++-------- src/BlueSCSI_Toolbox.h | 3 +-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index 04df3441..830ccb6d 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -162,18 +162,17 @@ void onListDevices() scsiDev.dataLen = NUM_SCSIID; } -void onSetNextCD() +void onSetNextCD(const char * img_dir) { char name[MAX_FILE_PATH]; char full_path[MAX_FILE_PATH * 2]; - uint8_t file_index = scsiDev.cdb[1]; image_config_t &img = *(image_config_t*)scsiDev.target->cfg; - File next_cd = get_file_from_index(file_index, CD_IMG_DIR); + File next_cd = get_file_from_index(file_index, img_dir); next_cd.getName(name, sizeof(name)); next_cd.close(); - snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", CD_IMG_DIR, name); + snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", img_dir, name); cdromSwitch(img, full_path); } @@ -302,6 +301,7 @@ void onToggleDebug() extern "C" int scsiBlueSCSIToolboxCommand() { int commandHandled = 1; + image_config_t &img = *(image_config_t*)scsiDev.target->cfg; uint8_t command = scsiDev.cdb[0]; if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_FILES)) @@ -335,11 +335,15 @@ extern "C" int scsiBlueSCSIToolboxCommand() } else if(unlikely(command == BLUESCSI_TOOLBOX_LIST_CDS)) { - onListFiles("/CDImages"); + char img_dir[4]; + snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS); + onListFiles(img_dir); } else if(unlikely(command == BLUESCSI_TOOLBOX_SET_NEXT_CD)) { - onSetNextCD(); + char img_dir[4]; + snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS); + onSetNextCD(img_dir); } else if(unlikely(command == BLUESCSI_TOOLBOX_LIST_DEVICES)) { @@ -347,8 +351,9 @@ extern "C" int scsiBlueSCSIToolboxCommand() } else if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_CDS)) { - // TODO: Allow user to set dir name via ini - doCountFiles("/CDImages"); + char img_dir[4]; + snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS); + doCountFiles(img_dir); } else { diff --git a/src/BlueSCSI_Toolbox.h b/src/BlueSCSI_Toolbox.h index ecacee31..a708f9da 100644 --- a/src/BlueSCSI_Toolbox.h +++ b/src/BlueSCSI_Toolbox.h @@ -20,8 +20,7 @@ #pragma once #define MAX_MAC_PATH 32 -#define CD_IMG_DIR "/CDImages" - +#define CD_IMG_DIR "CD%d" #define BLUESCSI_TOOLBOX_COUNT_FILES 0xD2 #define BLUESCSI_TOOLBOX_LIST_FILES 0xD0 From 18736bcb0b75c7202f9bfaa15ea7b1c4d9987a45 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Fri, 18 Aug 2023 13:40:59 -0500 Subject: [PATCH 08/13] toolbox: allow shared dir to be set by user. --- src/BlueSCSI_Toolbox.cpp | 28 ++++++++++++++++++---------- src/BlueSCSI_config.cpp | 5 +++++ src/BlueSCSI_config.h | 4 +++- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index 830ccb6d..c1e9f240 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -20,6 +20,7 @@ #include "BlueSCSI_disk.h" #include "BlueSCSI_cdrom.h" #include "BlueSCSI_log.h" +#include "BlueSCSI_config.h" #include #include extern "C" { @@ -177,14 +178,14 @@ void onSetNextCD(const char * img_dir) } File gFile; // global so we can keep it open while transfering. -void onGetFile10(void) { +void onGetFile10(char * dir_name) { uint8_t index = scsiDev.cdb[1]; uint32_t offset = ((uint32_t)scsiDev.cdb[2] << 24) | ((uint32_t)scsiDev.cdb[3] << 16) | ((uint32_t)scsiDev.cdb[4] << 8) | scsiDev.cdb[5]; if (offset == 0) // first time, open the file. { - gFile = get_file_from_index(index, "/shared"); + gFile = get_file_from_index(index, dir_name); if(!gFile.isDirectory() && !gFile.isReadable()) { scsiDev.status = CHECK_CONDITION; @@ -211,7 +212,7 @@ void onGetFile10(void) { Prepares a file for receving. The file name is null terminated in the scsi data. */ File receveFile; -void onSendFilePrep(void) +void onSendFilePrep(char * dir_name) { char file_name[32+1]; memset(file_name, '\0', 32+1); @@ -220,7 +221,7 @@ void onSendFilePrep(void) { file_name[i] = scsiReadByte(); } - SD.chdir("/shared"); + SD.chdir(dir_name); receveFile.open(file_name, FILE_WRITE); SD.chdir("/"); if(receveFile.isOpen() && receveFile.isWritable()) @@ -304,22 +305,29 @@ extern "C" int scsiBlueSCSIToolboxCommand() image_config_t &img = *(image_config_t*)scsiDev.target->cfg; uint8_t command = scsiDev.cdb[0]; - if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_FILES)) + if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_FILES)) { - doCountFiles("/shared"); + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + doCountFiles(img_dir); } else if (unlikely(command == BLUESCSI_TOOLBOX_LIST_FILES)) { - // TODO: Allow user to set dir name via ini - onListFiles("/shared"); + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + onListFiles(img_dir); } else if (unlikely(command == BLUESCSI_TOOLBOX_GET_FILE)) { - onGetFile10(); + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + onGetFile10(img_dir); } else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_PREP)) { - onSendFilePrep(); + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + onSendFilePrep(img_dir); } else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_10)) { diff --git a/src/BlueSCSI_config.cpp b/src/BlueSCSI_config.cpp index bb7207a7..5853c577 100644 --- a/src/BlueSCSI_config.cpp +++ b/src/BlueSCSI_config.cpp @@ -61,4 +61,9 @@ int getImg(int scsiId, int img_index, char* filename) int dirlen = ini_gets(section, key, "", filename, sizeof(filename), CONFIGFILE); return dirlen; +} + +int getToolBoxSharedDir(char * dir_name) +{ + return ini_gets("SCSI", "ToolBoxSharedDir", "/shared", dir_name, MAX_FILE_PATH, CONFIGFILE); } \ No newline at end of file diff --git a/src/BlueSCSI_config.h b/src/BlueSCSI_config.h index 01de02c2..d4b8f91c 100644 --- a/src/BlueSCSI_config.h +++ b/src/BlueSCSI_config.h @@ -84,4 +84,6 @@ int getBlockSize(char *filename, int scsiId, int default_size); int getImgDir(int scsiId, char* dirname); -int getImg(int scsiId, int img_index, char* filename); \ No newline at end of file +int getImg(int scsiId, int img_index, char* filename); + +int getToolBoxSharedDir(char * dir_name); \ No newline at end of file From bd6e3b6181756f72c9eee2a680f49b37d452fe30 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Sat, 19 Aug 2023 10:21:56 -0500 Subject: [PATCH 09/13] toolbox: only use one global. switch to FsFile --- src/BlueSCSI_Toolbox.cpp | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index c1e9f240..d9ad7e31 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -32,8 +32,8 @@ extern "C" { static void doCountFiles(const char * dir_name) { - File dir; - File file; + FsFile dir; + FsFile file; char name[ MAX_MAC_PATH + 1]; dir.open(dir_name); dir.rewindDirectory(); @@ -67,8 +67,8 @@ static void doCountFiles(const char * dir_name) } void onListFiles(const char * dir_name) { - File dir; - File file; + FsFile dir; + FsFile file; memset(scsiDev.data, 0, 4096); int ENTRY_SIZE = 40; @@ -106,9 +106,9 @@ void onListFiles(const char * dir_name) { scsiDev.phase = DATA_IN; } -File get_file_from_index(uint8_t index, const char * dir_name) +FsFile get_file_from_index(uint8_t index, const char * dir_name) { - File dir; + FsFile dir; FsFile file_test; char name[MAX_MAC_PATH + 1]; @@ -170,14 +170,14 @@ void onSetNextCD(const char * img_dir) uint8_t file_index = scsiDev.cdb[1]; image_config_t &img = *(image_config_t*)scsiDev.target->cfg; - File next_cd = get_file_from_index(file_index, img_dir); + FsFile next_cd = get_file_from_index(file_index, img_dir); next_cd.getName(name, sizeof(name)); next_cd.close(); snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", img_dir, name); cdromSwitch(img, full_path); } -File gFile; // global so we can keep it open while transfering. +FsFile gFile; // global so we can keep it open while transfering. void onGetFile10(char * dir_name) { uint8_t index = scsiDev.cdb[1]; @@ -211,7 +211,6 @@ void onGetFile10(char * dir_name) { /* Prepares a file for receving. The file name is null terminated in the scsi data. */ -File receveFile; void onSendFilePrep(char * dir_name) { char file_name[32+1]; @@ -222,16 +221,16 @@ void onSendFilePrep(char * dir_name) file_name[i] = scsiReadByte(); } SD.chdir(dir_name); - receveFile.open(file_name, FILE_WRITE); + gFile.open(file_name, FILE_WRITE); SD.chdir("/"); - if(receveFile.isOpen() && receveFile.isWritable()) + if(gFile.isOpen() && gFile.isWritable()) { - receveFile.rewind(); - receveFile.sync(); + gFile.rewind(); + gFile.sync(); // do i need to manually set phase to status here? return; } else { - receveFile.close(); + gFile.close(); scsiDev.status = CHECK_CONDITION; scsiDev.target->sense.code = ILLEGAL_REQUEST; //SCSI_ASC_INVALID_FIELD_IN_CDB @@ -241,14 +240,14 @@ void onSendFilePrep(char * dir_name) void onSendFileEnd(void) { - receveFile.sync(); - receveFile.close(); + gFile.sync(); + gFile.close(); scsiDev.phase = STATUS; } void onSendFile10(void) { - if(!receveFile.isOpen() || !receveFile.isWritable()) + if(!gFile.isOpen() || !gFile.isWritable()) { scsiDev.status = CHECK_CONDITION; scsiDev.target->sense.code = ILLEGAL_REQUEST; @@ -271,12 +270,12 @@ void onSendFile10(void) scsiEnterPhase(DATA_OUT); scsiRead(buf, bytes_sent, NULL); - receveFile.seekCur(offset * 512); - receveFile.write(buf, buf_size); - if(receveFile.getWriteError()) + gFile.seekCur(offset * 512); + gFile.write(buf, buf_size); + if(gFile.getWriteError()) { - receveFile.clearWriteError(); - receveFile.close(); + gFile.clearWriteError(); + gFile.close(); scsiDev.status = CHECK_CONDITION; scsiDev.target->sense.code = ILLEGAL_REQUEST; } From 1c094d58311ff646228e226306a61066cbb6ed66 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Sun, 8 Oct 2023 20:57:49 -0500 Subject: [PATCH 10/13] toolbox: use different logic for toolbox files --- src/BlueSCSI_Toolbox.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index d9ad7e31..cc15e7ef 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -29,6 +29,20 @@ extern "C" { #include } +bool toolboxFilenameValid(const char* name) +{ + if(name[0] == '.') + { + debuglog("toolbox: Ignoring hidden file ", name); + return false; + } + if(strlen(name) > MAX_MAC_PATH) + { + debuglog("toolbox: Ignoring filename over ", MAX_MAC_PATH, " in length: ", name, " - ", (int)strlen(name)); + return false; + } + return true; +} static void doCountFiles(const char * dir_name) { @@ -48,7 +62,7 @@ static void doCountFiles(const char * dir_name) file.getName(name, MAX_MAC_PATH + 1); file.close(); // only count valid files. - if(scsiDiskFilenameValid(name)) + if(toolboxFilenameValid(name)) { file_count = file_count + 1; if(file_count > 100) { @@ -83,7 +97,7 @@ void onListFiles(const char * dir_name) { file.getName(name, MAX_MAC_PATH + 1); uint64_t size = file.fileSize(); file.close(); - if(!scsiDiskFilenameValid(name)) + if(!toolboxFilenameValid(name)) continue; file_entry[0] = index; file_entry[1] = isDir; @@ -124,7 +138,7 @@ FsFile get_file_from_index(uint8_t index, const char * dir_name) } file_test.getName(name, MAX_MAC_PATH + 1); - if(!scsiDiskFilenameValid(name)) + if(!toolboxFilenameValid(name)) { file_test.close(); continue; From 96a552bab66d56afea7b7147e084fdaad0fa3740 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Sun, 8 Oct 2023 21:02:40 -0500 Subject: [PATCH 11/13] toolbox: Include BlueSCSI Toolbox commands in trace output --- src/BlueSCSI_log_trace.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/BlueSCSI_log_trace.cpp b/src/BlueSCSI_log_trace.cpp index 81a80e86..67df5da6 100644 --- a/src/BlueSCSI_log_trace.cpp +++ b/src/BlueSCSI_log_trace.cpp @@ -3,6 +3,7 @@ #include "BlueSCSI_log_trace.h" #include "BlueSCSI_log.h" #include +#include "BlueSCSI_Toolbox.h" extern "C" { #include @@ -78,6 +79,17 @@ static const char *getCommandName(uint8_t cmd) case 0xA8: return "Read12"; case 0xC0: return "OMTI-5204 DefineFlexibleDiskFormat"; case 0xC2: return "OMTI-5204 AssignDiskParameters"; + case BLUESCSI_TOOLBOX_COUNT_FILES: return "BLUESCSI_TOOLBOX_COUNT_FILES"; + case BLUESCSI_TOOLBOX_LIST_FILES: return "BLUESCSI_TOOLBOX_LIST_FILES"; + case BLUESCSI_TOOLBOX_GET_FILE: return "BLUESCSI_TOOLBOX_GET_FILE"; + case BLUESCSI_TOOLBOX_SEND_FILE_PREP: return "BLUESCSI_TOOLBOX_SEND_FILE_PREP"; + case BLUESCSI_TOOLBOX_SEND_FILE_10: return "BLUESCSI_TOOLBOX_SEND_FILE_10"; + case BLUESCSI_TOOLBOX_SEND_FILE_END: return "BLUESCSI_TOOLBOX_SEND_FILE_END"; + case BLUESCSI_TOOLBOX_TOGGLE_DEBUG: return "BLUESCSI_TOOLBOX_TOGGLE_DEBUG"; + case BLUESCSI_TOOLBOX_LIST_CDS: return "BLUESCSI_TOOLBOX_LIST_CDS"; + case BLUESCSI_TOOLBOX_SET_NEXT_CD: return "BLUESCSI_TOOLBOX_SET_NEXT_CD"; + case BLUESCSI_TOOLBOX_LIST_DEVICES: return "BLUESCSI_TOOLBOX_LIST_DEVICES"; + case BLUESCSI_TOOLBOX_COUNT_CDS: return "BLUESCSI_TOOLBOX_COUNT_CDS"; default: return "Unknown"; } } From 58a3c7134225beb21efa3bb8a8aee3752f6f8a74 Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Tue, 10 Oct 2023 08:24:41 -0500 Subject: [PATCH 12/13] toolbox: fix issues with long file names --- src/BlueSCSI_Toolbox.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index cc15e7ef..c08a1330 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -36,9 +36,9 @@ bool toolboxFilenameValid(const char* name) debuglog("toolbox: Ignoring hidden file ", name); return false; } - if(strlen(name) > MAX_MAC_PATH) + if(strlen(name) == 0) { - debuglog("toolbox: Ignoring filename over ", MAX_MAC_PATH, " in length: ", name, " - ", (int)strlen(name)); + debuglog("toolbox: Ignoring filename empty file name"); return false; } return true; @@ -48,7 +48,7 @@ static void doCountFiles(const char * dir_name) { FsFile dir; FsFile file; - char name[ MAX_MAC_PATH + 1]; + char name[MAX_FILE_PATH] = {0}; dir.open(dir_name); dir.rewindDirectory(); uint8_t file_count = 0; @@ -59,7 +59,7 @@ static void doCountFiles(const char * dir_name) file.close(); break; } - file.getName(name, MAX_MAC_PATH + 1); + file.getName(name, MAX_FILE_PATH); file.close(); // only count valid files. if(toolboxFilenameValid(name)) @@ -86,7 +86,7 @@ void onListFiles(const char * dir_name) { memset(scsiDev.data, 0, 4096); int ENTRY_SIZE = 40; - char name[MAX_MAC_PATH + 1]; + char name[MAX_FILE_PATH] = {0}; dir.open(dir_name); dir.rewindDirectory(); uint8_t index = 0; @@ -94,7 +94,9 @@ void onListFiles(const char * dir_name) { while (file.openNext(&dir, O_RDONLY)) { uint8_t isDir = file.isDirectory() ? 0x00 : 0x01; - file.getName(name, MAX_MAC_PATH + 1); + int len = file.getName(name, MAX_FILE_PATH); + if (len > MAX_MAC_PATH) + name[MAX_MAC_PATH] = 0x0; uint64_t size = file.fileSize(); file.close(); if(!toolboxFilenameValid(name)) @@ -124,7 +126,7 @@ FsFile get_file_from_index(uint8_t index, const char * dir_name) { FsFile dir; FsFile file_test; - char name[MAX_MAC_PATH + 1]; + char name[MAX_FILE_PATH] = {0}; dir.open(dir_name); dir.rewindDirectory(); // Back to the top @@ -136,7 +138,7 @@ FsFile get_file_from_index(uint8_t index, const char * dir_name) file_test.close(); break; } - file_test.getName(name, MAX_MAC_PATH + 1); + file_test.getName(name, MAX_FILE_PATH); if(!toolboxFilenameValid(name)) { @@ -179,8 +181,8 @@ void onListDevices() void onSetNextCD(const char * img_dir) { - char name[MAX_FILE_PATH]; - char full_path[MAX_FILE_PATH * 2]; + char name[MAX_FILE_PATH] = {0}; + char full_path[MAX_FILE_PATH * 2] = {0}; uint8_t file_index = scsiDev.cdb[1]; image_config_t &img = *(image_config_t*)scsiDev.target->cfg; From eec90b9ef328fe47a4a7188f38dce90f95c5a6ef Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Thu, 12 Oct 2023 17:08:25 -0500 Subject: [PATCH 13/13] toolbox: dont show .cue files in list --- src/BlueSCSI_Toolbox.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp index c08a1330..f5f64713 100644 --- a/src/BlueSCSI_Toolbox.cpp +++ b/src/BlueSCSI_Toolbox.cpp @@ -41,6 +41,13 @@ bool toolboxFilenameValid(const char* name) debuglog("toolbox: Ignoring filename empty file name"); return false; } + const char *extension = strrchr(name, '.'); + if (extension && strcasecmp(extension, ".cue") == 0) + { + debuglog("toolbox: Ignoring .cue ", name); + return false; + } + return true; }