diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml index 7c3eac8c..b4fac982 100644 --- a/.github/workflows/cpp.yml +++ b/.github/workflows/cpp.yml @@ -35,7 +35,7 @@ jobs: run: make -j $(nproc) test - name: Run unit tests - run: (set -o pipefail && bin/fullspec/piscsi_test | tee piscsi_test_log.txt) + run: (set -o pipefail && bin/piscsi_test | tee piscsi_test_log.txt) - name: Upload logs uses: actions/upload-artifact@v3 diff --git a/cpp/.clang-format b/cpp/.clang-format deleted file mode 100644 index 7e73f97c..00000000 --- a/cpp/.clang-format +++ /dev/null @@ -1,12 +0,0 @@ -BasedOnStyle: Microsoft -IndentWidth: 4 -AlwaysBreakAfterReturnType: None -AllowShortFunctionsOnASingleLine: Empty -KeepEmptyLinesAtTheStartOfBlocks: false -BreakBeforeBraces: Linux -AlignEscapedNewlines: Left -AlignTrailingComments: True -AllowShortEnumsOnASingleLine: True -AlignConsecutiveAssignments: Consecutive -ColumnLimit: 120 -PointerAlignment: Left \ No newline at end of file diff --git a/cpp/.gitignore b/cpp/.gitignore index 4efdbaa3..6f970d2d 100644 --- a/cpp/.gitignore +++ b/cpp/.gitignore @@ -12,6 +12,3 @@ obj bin coverage generated -.project -.cproject -.settings diff --git a/cpp/.vscode/launch.json b/cpp/.vscode/launch.json deleted file mode 100644 index f3a2f763..00000000 --- a/cpp/.vscode/launch.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "rascsi (gdb) Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/bin/fullspec/rascsi", - "args": [], - "stopAtEntry": true, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "targetArchitecture": "arm", - "miDebuggerPath": "${workspaceFolder}/launch_sudo.sh", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - }, - { - "name": "rascsi_test (gdb) Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/bin/fullspec/rascsi_test", - "args": [], - "stopAtEntry": true, - "cwd": "${fileDirname}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "description": "Set Disassembly Flavor to Intel", - "text": "-gdb-set disassembly-flavor intel", - "ignoreFailures": true - } - ] - }, - ] -} \ No newline at end of file diff --git a/cpp/.vscode/tasks.json b/cpp/.vscode/tasks.json deleted file mode 100644 index 6105ee09..00000000 --- a/cpp/.vscode/tasks.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "shell", - "label": "g++ build active file", - "command": "make", - "args": ["all", "DEBUG=1", "-j4"], - "options": { - "cwd": "${workspaceFolder}/" - }, - "problemMatcher": ["$gcc"], - "group": { - "kind": "build", - "isDefault": true - } - } - ] - } diff --git a/cpp/Makefile b/cpp/Makefile index c5d0b83d..104a1585 100644 --- a/cpp/Makefile +++ b/cpp/Makefile @@ -60,8 +60,8 @@ COVERAGE_DIR = coverage COVERAGE_FILE = piscsi.dat OS_FILES = ../os_integration -OBJDIR := obj/$(shell echo $(CONNECT_TYPE) | tr '[:upper:]' '[:lower:]') -BINDIR := bin/$(shell echo $(CONNECT_TYPE) | tr '[:upper:]' '[:lower:]') +OBJDIR := obj +BINDIR := bin BIN_ALL = \ $(BINDIR)/$(PISCSI) \ diff --git a/cpp/controllers/scsi_controller.cpp b/cpp/controllers/scsi_controller.cpp index 09752595..773b06dd 100644 --- a/cpp/controllers/scsi_controller.cpp +++ b/cpp/controllers/scsi_controller.cpp @@ -865,6 +865,10 @@ bool ScsiController::XferOutBlockOriented(bool cont) LogTrace("Done with DaynaPort Set Multicast Address"); break; + case scsi_command::eCmdSetIfaceMode: + LogTrace("Done with setting DaynaPort MAC address (ignore)"); + break; + default: stringstream s; s << "Received an unexpected command ($" << setfill('0') << setw(2) << hex diff --git a/cpp/devices/device_factory.cpp b/cpp/devices/device_factory.cpp index f951d645..011a496b 100644 --- a/cpp/devices/device_factory.cpp +++ b/cpp/devices/device_factory.cpp @@ -7,7 +7,7 @@ // //--------------------------------------------------------------------------- -#include "shared/network_util.h" +#include "shared/piscsi_util.h" #include "scsihd.h" #include "scsihd_nec.h" #include "scsimo.h" @@ -20,39 +20,14 @@ using namespace std; using namespace piscsi_util; -using namespace network_util; - -DeviceFactory::DeviceFactory() -{ - sector_sizes[SCHD] = { 512, 1024, 2048, 4096 }; - sector_sizes[SCRM] = { 512, 1024, 2048, 4096 }; - sector_sizes[SCMO] = { 512, 1024, 2048, 4096 }; - sector_sizes[SCCD] = { 512, 2048}; - - extension_mapping["hd1"] = SCHD; - extension_mapping["hds"] = SCHD; - extension_mapping["hda"] = SCHD; - extension_mapping["hdn"] = SCHD; - extension_mapping["hdi"] = SCHD; - extension_mapping["nhd"] = SCHD; - extension_mapping["hdr"] = SCRM; - extension_mapping["mos"] = SCMO; - extension_mapping["iso"] = SCCD; - extension_mapping["is1"] = SCCD; - - device_mapping["bridge"] = SCBR; - device_mapping["daynaport"] = SCDP; - device_mapping["printer"] = SCLP; - device_mapping["services"] = SCHS; -} PbDeviceType DeviceFactory::GetTypeForFile(const string& filename) const { - if (const auto& it = extension_mapping.find(GetExtensionLowerCase(filename)); it != extension_mapping.end()) { + if (const auto& it = EXTENSION_MAPPING.find(GetExtensionLowerCase(filename)); it != EXTENSION_MAPPING.end()) { return it->second; } - if (const auto& it = device_mapping.find(filename); it != device_mapping.end()) { + if (const auto& it = DEVICE_MAPPING.find(filename); it != DEVICE_MAPPING.end()) { return it->second; } @@ -75,8 +50,7 @@ shared_ptr DeviceFactory::CreateDevice(PbDeviceType type, int lun if (const string ext = GetExtensionLowerCase(filename); ext == "hdn" || ext == "hdi" || ext == "nhd") { device = make_shared(lun); } else { - device = make_shared(lun, sector_sizes.find(type)->second, false, - ext == "hd1" ? scsi_level::scsi_1_ccs : scsi_level::scsi_2); + device = make_shared(lun, false, ext == "hd1" ? scsi_level::scsi_1_ccs : scsi_level::scsi_2); // Some Apple tools require a particular drive identification if (ext == "hda") { @@ -88,17 +62,17 @@ shared_ptr DeviceFactory::CreateDevice(PbDeviceType type, int lun } case SCRM: - device = make_shared(lun, sector_sizes.find(type)->second, true); + device = make_shared(lun, true, scsi_level::scsi_2); device->SetProduct("SCSI HD (REM.)"); break; case SCMO: - device = make_shared(lun, sector_sizes.find(type)->second); + device = make_shared(lun); device->SetProduct("SCSI MO"); break; case SCCD: - device = make_shared(lun, sector_sizes.find(type)->second, + device = make_shared(lun, GetExtensionLowerCase(filename) == "is1" ? scsi_level::scsi_1_ccs : scsi_level::scsi_2); device->SetProduct("SCSI CD-ROM"); break; @@ -135,15 +109,3 @@ shared_ptr DeviceFactory::CreateDevice(PbDeviceType type, int lun return device; } - -// TODO Move to respective device, which may require changes in the SCSI_HD/SCSIHD_NEC inheritance hierarchy -unordered_set DeviceFactory::GetSectorSizes(PbDeviceType type) const -{ - const auto& it = sector_sizes.find(type); - if (it != sector_sizes.end()) { - return it->second; - } - else { - return {}; - } -} diff --git a/cpp/devices/device_factory.h b/cpp/devices/device_factory.h index fef1c17d..7072980c 100644 --- a/cpp/devices/device_factory.h +++ b/cpp/devices/device_factory.h @@ -11,9 +11,7 @@ #pragma once -#include "shared/piscsi_util.h" #include -#include #include #include "generated/piscsi_interface.pb.h" @@ -27,19 +25,32 @@ class DeviceFactory public: - DeviceFactory(); + DeviceFactory() = default; ~DeviceFactory() = default; shared_ptr CreateDevice(PbDeviceType, int, const string&) const; PbDeviceType GetTypeForFile(const string&) const; - unordered_set GetSectorSizes(PbDeviceType type) const; - const auto& GetExtensionMapping() const { return extension_mapping; } + const auto& GetExtensionMapping() const { return EXTENSION_MAPPING; } private: - unordered_map> sector_sizes; + const inline static unordered_map> EXTENSION_MAPPING = { + { "hd1", SCHD }, + { "hds", SCHD }, + { "hda", SCHD }, + { "hdn", SCHD }, + { "hdi", SCHD }, + { "nhd", SCHD }, + { "hdr", SCRM }, + { "mos", SCMO }, + { "is1", SCCD }, + { "iso", SCCD } + }; - unordered_map> extension_mapping; - - unordered_map> device_mapping; + const inline static unordered_map> DEVICE_MAPPING = { + { "bridge", SCBR }, + { "daynaport", SCDP }, + { "printer", SCLP }, + { "services", SCHS } + }; }; diff --git a/cpp/devices/device_logger.cpp b/cpp/devices/device_logger.cpp index 65afb129..4d78364a 100644 --- a/cpp/devices/device_logger.cpp +++ b/cpp/devices/device_logger.cpp @@ -39,16 +39,14 @@ void DeviceLogger::Error(const string& message) const void DeviceLogger::Log(level::level_enum level, const string& message) const { - if (!message.empty() && - (log_device_id == -1 || - (log_device_id == id && (log_device_lun == -1 || log_device_lun == lun)))) { - if (lun == -1) { - log(level, "(ID " + to_string(id) + ") - " + message); - } - else { - log(level, "(ID:LUN " + to_string(id) + ":" + to_string(lun) + ") - " + message); - } - } + if ((log_device_id == -1 || log_device_id == id) && (lun == -1 || log_device_lun == -1 || log_device_lun == lun)) { + if (lun == -1) { + log(level, "(ID " + to_string(id) + ") - " + message); + } + else { + log(level, "(ID:LUN " + to_string(id) + ":" + to_string(lun) + ") - " + message); + } + } } void DeviceLogger::SetIdAndLun(int i, int l) diff --git a/cpp/devices/disk.cpp b/cpp/devices/disk.cpp index bc8b53d0..b771b881 100644 --- a/cpp/devices/disk.cpp +++ b/cpp/devices/disk.cpp @@ -695,12 +695,18 @@ uint32_t Disk::GetSectorSizeInBytes() const void Disk::SetSectorSizeInBytes(uint32_t size_in_bytes) { - if (DeviceFactory device_factory; !device_factory.GetSectorSizes(GetType()).contains(size_in_bytes)) { - throw io_exception("Invalid sector size of " + to_string(size_in_bytes) + " byte(s)"); + if (!GetSupportedSectorSizes().contains(size_in_bytes)) { + throw io_exception("Invalid sector size of " + to_string(size_in_bytes) + " byte(s)"); } + uint64_t current_blocks = GetBlockCount(); + uint32_t current_size_shift_count = size_shift_count; + uint64_t current_size = current_blocks << current_size_shift_count; size_shift_count = CalculateShiftCount(size_in_bytes); assert(size_shift_count); + if ((current_blocks > 0) && (current_size_shift_count > 0)) { + SetBlockCount(current_size >> size_shift_count); + } } uint32_t Disk::GetConfiguredSectorSize() const @@ -708,13 +714,13 @@ uint32_t Disk::GetConfiguredSectorSize() const return configured_sector_size; } -bool Disk::SetConfiguredSectorSize(const DeviceFactory& device_factory, uint32_t configured_size) +bool Disk::SetConfiguredSectorSize(uint32_t configured_size) { - if (!device_factory.GetSectorSizes(GetType()).contains(configured_size)) { + if (!supported_sector_sizes.contains(configured_size)) { return false; } - configured_sector_size = configured_size; + configured_sector_size = configured_size; return true; } diff --git a/cpp/devices/disk.h b/cpp/devices/disk.h index 7364ad08..a69a4662 100644 --- a/cpp/devices/disk.h +++ b/cpp/devices/disk.h @@ -16,7 +16,6 @@ #include "shared/scsi.h" #include "shared/piscsi_util.h" -#include "device_factory.h" #include "disk_track.h" #include "disk_cache.h" #include "interfaces/scsi_block_commands.h" @@ -35,8 +34,7 @@ class Disk : public StorageDevice, private ScsiBlockCommands unique_ptr cache; - // The supported configurable sector sizes, empty if not configurable - unordered_set sector_sizes; + unordered_set supported_sector_sizes; uint32_t configured_sector_size = 0; // Sector size shift count (9=512, 10=1024, 11=2048, 12=4096) @@ -50,7 +48,9 @@ class Disk : public StorageDevice, private ScsiBlockCommands public: - using StorageDevice::StorageDevice; + Disk(PbDeviceType type, int lun, const unordered_set& s) + : StorageDevice(type, lun), supported_sector_sizes(s) {} + ~Disk() override = default; bool Init(const param_map&) override; void CleanUp() override; @@ -64,8 +64,9 @@ public: virtual int Read(span , uint64_t); uint32_t GetSectorSizeInBytes() const; - bool IsSectorSizeConfigurable() const { return !sector_sizes.empty(); } - bool SetConfiguredSectorSize(const DeviceFactory&, uint32_t); + bool IsSectorSizeConfigurable() const { return supported_sector_sizes.size() > 1; } + const auto& GetSupportedSectorSizes() const { return supported_sector_sizes; } + bool SetConfiguredSectorSize(uint32_t); void FlushCache() override; vector GetStatistics() const override; @@ -111,7 +112,7 @@ protected: void SetUpCache(off_t, bool = false); void ResizeCache(const string&, bool); - + bool GetRawMode() const { return (cache?cache->GetRawMode():false); } void SetUpModePages(map>&, int, bool) const override; void AddErrorPage(map>&, bool) const; virtual void AddFormatPage(map>&, bool) const; @@ -119,7 +120,6 @@ protected: void AddCachePage(map>&, bool) const; unordered_set GetSectorSizes() const; - void SetSectorSizes(const unordered_set& sizes) { sector_sizes = sizes; } void SetSectorSizeInBytes(uint32_t); uint32_t GetSectorSizeShiftCount() const { return size_shift_count; } void SetSectorSizeShiftCount(uint32_t count) { size_shift_count = count; } diff --git a/cpp/devices/disk_cache.h b/cpp/devices/disk_cache.h index ec486edd..d25eb2f0 100644 --- a/cpp/devices/disk_cache.h +++ b/cpp/devices/disk_cache.h @@ -51,6 +51,7 @@ public: ~DiskCache() = default; void SetRawMode(bool b) { cd_raw = b; } // CD-ROM raw mode setting + bool GetRawMode() const { return cd_raw; } bool Save(); // Save and release all bool ReadSector(span, uint32_t); // Sector Read diff --git a/cpp/devices/mode_page_device.cpp b/cpp/devices/mode_page_device.cpp index 7335d5a3..bb64cc37 100644 --- a/cpp/devices/mode_page_device.cpp +++ b/cpp/devices/mode_page_device.cpp @@ -114,7 +114,7 @@ void ModePageDevice::ModeSense10() const EnterDataInPhase(); } -void ModePageDevice::ModeSelect(scsi_command, cdb_t, span, int) const +void ModePageDevice::ModeSelect(scsi_command, cdb_t, span, int) { // There is no default implementation of MODE SELECT throw scsi_exception(sense_key::illegal_request, asc::invalid_command_operation_code); diff --git a/cpp/devices/mode_page_device.h b/cpp/devices/mode_page_device.h index 4a487fb2..4b657ebe 100644 --- a/cpp/devices/mode_page_device.h +++ b/cpp/devices/mode_page_device.h @@ -23,7 +23,7 @@ public: bool Init(const param_map&) override; - virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) const; + virtual void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int); protected: diff --git a/cpp/devices/scsi_command_util.cpp b/cpp/devices/scsi_command_util.cpp index 20bb83f7..5c6068a7 100644 --- a/cpp/devices/scsi_command_util.cpp +++ b/cpp/devices/scsi_command_util.cpp @@ -40,7 +40,8 @@ string scsi_command_util::ModeSelect(scsi_command cmd, cdb_t cdb, span 0) { @@ -62,6 +63,10 @@ string scsi_command_util::ModeSelect(scsi_command cmd, cdb_t cdb, span& buf, uint64_t) // response->flags = e_no_more_data; // } int size = rx_packet_size; - if (size < 64) { - // A frame must have at least 64 bytes (see https://github.com/PiSCSI/piscsi/issues/619) - // Note that this work-around breaks the checksum. As currently there are no known drivers - // that care for the checksum, and the Daynaport driver for the Atari expects frames of - // 64 bytes it was decided to accept the broken checksum. If a driver should pop up that - // breaks because of this, the work-around has to be re-evaluated. - size = 64; + if (size < 128) { + // A frame must have at least 64 bytes for the Atari driver, see https://github.com/PiSCSI/piscsi/issues/619, + // but also works with 128 bytes. + // The NetBSD driver requires at least 128 bytes, see https://github.com/PiSCSI/piscsi/issues/1098. + // The Mac driver is also fine with 128 bytes. + // Note that this work-around breaks the checksum. As currently there are no known drivers + // that care for the checksum it was decided to accept the broken checksum. + // If a driver should pop up that breaks because of this, the work-around has to be re-evaluated. + size = 128; } SetInt16(buf, 0, size); SetInt32(buf, 2, tap.HasPendingPackets() ? 0x10 : 0x00); diff --git a/cpp/devices/scsi_daynaport.h b/cpp/devices/scsi_daynaport.h index 94f45551..6074e081 100644 --- a/cpp/devices/scsi_daynaport.h +++ b/cpp/devices/scsi_daynaport.h @@ -6,6 +6,7 @@ // Copyright (C) 2020 akuker // Copyright (C) 2014-2020 GIMONS // Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2023 Uwe Seimet // // Licensed under the BSD 3-Clause License. // See LICENSE file in the project root folder. diff --git a/cpp/devices/scsi_printer.cpp b/cpp/devices/scsi_printer.cpp index 393e053e..dcb9188b 100644 --- a/cpp/devices/scsi_printer.cpp +++ b/cpp/devices/scsi_printer.cpp @@ -197,7 +197,7 @@ bool SCSIPrinter::WriteByteSequence(span buf) out.write((const char *)buf.data(), buf.size()); const bool status = out.fail(); - if (!status) { + if (status) { ++print_error_count; } diff --git a/cpp/devices/scsicd.cpp b/cpp/devices/scsicd.cpp index 200c36c3..e1d356bd 100644 --- a/cpp/devices/scsicd.cpp +++ b/cpp/devices/scsicd.cpp @@ -21,11 +21,8 @@ using namespace scsi_defs; using namespace scsi_command_util; -SCSICD::SCSICD(int lun, const unordered_set& sector_sizes, scsi_defs::scsi_level level) - : Disk(SCCD, lun), scsi_level(level) +SCSICD::SCSICD(int lun, scsi_defs::scsi_level level) : Disk(SCCD, lun, { 512, 2048 }), scsi_level(level) { - SetSectorSizes(sector_sizes); - SetReadOnly(true); SetRemovable(true); SetLockable(true); @@ -168,6 +165,29 @@ vector SCSICD::InquiryInternal() const return HandleInquiry(device_type::cd_rom, scsi_level, true); } +void SCSICD::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) +{ + int sector_size = 1 << GetSectorSizeShiftCount(); + int wanted_sector_size; + // skip Block Descriptor + int offset = 4; + // evaluate Mode Parameter Block Descriptor, sector size + wanted_sector_size = scsi_command_util::GetInt16(buf, offset + 6); + if (wanted_sector_size != sector_size) { + LogDebug("Changing sector size from " + to_string(sector_size) + " to " + to_string(wanted_sector_size)); + SetSectorSizeInBytes(wanted_sector_size); + ClearTrack(); + CreateDataTrack(); + FlushCache(); + ResizeCache(GetFilename(), GetRawMode()); + } + + if (const string result = scsi_command_util::ModeSelect(cmd, cdb, buf, length, sector_size); + !result.empty()) { + LogWarn(result); + } +} + void SCSICD::SetUpModePages(map>& pages, int page, bool changeable) const { Disk::SetUpModePages(pages, page, changeable); diff --git a/cpp/devices/scsicd.h b/cpp/devices/scsicd.h index db2620de..cb1158dd 100644 --- a/cpp/devices/scsicd.h +++ b/cpp/devices/scsicd.h @@ -25,7 +25,7 @@ class SCSICD : public Disk, private ScsiMmcCommands { public: - SCSICD(int, const unordered_set&, scsi_defs::scsi_level = scsi_level::scsi_2); + SCSICD(int, scsi_defs::scsi_level = scsi_level::scsi_2); ~SCSICD() override = default; bool Init(const param_map&) override; @@ -34,6 +34,7 @@ public: vector InquiryInternal() const override; int Read(span, uint64_t) override; + void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) override; protected: diff --git a/cpp/devices/scsihd.cpp b/cpp/devices/scsihd.cpp index 316c7575..51384c6a 100644 --- a/cpp/devices/scsihd.cpp +++ b/cpp/devices/scsihd.cpp @@ -19,11 +19,9 @@ using namespace scsi_command_util; -SCSIHD::SCSIHD(int lun, const unordered_set& sector_sizes, bool removable, scsi_defs::scsi_level level) - : Disk(removable ? SCRM : SCHD, lun), scsi_level(level) +SCSIHD::SCSIHD(int lun, bool removable, scsi_defs::scsi_level level, const unordered_set& sector_sizes) + : Disk(removable ? SCRM : SCHD, lun, sector_sizes), scsi_level(level) { - SetSectorSizes(sector_sizes); - SetProtectable(true); SetRemovable(removable); SetLockable(removable); @@ -84,7 +82,7 @@ vector SCSIHD::InquiryInternal() const return HandleInquiry(device_type::direct_access, scsi_level, IsRemovable()); } -void SCSIHD::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) const +void SCSIHD::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) { if (const string result = scsi_command_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount()); !result.empty()) { diff --git a/cpp/devices/scsihd.h b/cpp/devices/scsihd.h index 8216ae2a..95ded11a 100644 --- a/cpp/devices/scsihd.h +++ b/cpp/devices/scsihd.h @@ -28,7 +28,7 @@ class SCSIHD : public Disk public: - SCSIHD(int, const unordered_set&, bool, scsi_defs::scsi_level = scsi_level::scsi_2); + SCSIHD(int, bool, scsi_defs::scsi_level, const unordered_set& = { 512, 1024, 2048, 4096 }); ~SCSIHD() override = default; void FinalizeSetup(off_t); @@ -37,7 +37,7 @@ public: // Commands vector InquiryInternal() const override; - void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) const override; + void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) override; void AddFormatPage(map>&, bool) const override; void AddVendorPage(map>&, int, bool) const override; diff --git a/cpp/devices/scsihd_nec.h b/cpp/devices/scsihd_nec.h index eec3c1be..4c2fabe2 100644 --- a/cpp/devices/scsihd_nec.h +++ b/cpp/devices/scsihd_nec.h @@ -33,7 +33,7 @@ class SCSIHD_NEC : public SCSIHD //NOSONAR The inheritance hierarchy depth is ac { public: - explicit SCSIHD_NEC(int lun) : SCSIHD(lun, { 512 }, false) {} + explicit SCSIHD_NEC(int lun) : SCSIHD(lun, false, scsi_level::scsi_1_ccs, { 512 }) {} ~SCSIHD_NEC() override = default; void Open() override; diff --git a/cpp/devices/scsimo.cpp b/cpp/devices/scsimo.cpp index 167064a1..ab2af6c4 100644 --- a/cpp/devices/scsimo.cpp +++ b/cpp/devices/scsimo.cpp @@ -19,10 +19,8 @@ using namespace scsi_command_util; -SCSIMO::SCSIMO(int lun, const unordered_set& sector_sizes) : Disk(SCMO, lun) +SCSIMO::SCSIMO(int lun) : Disk(SCMO, lun, { 512, 1024, 2048, 4096 }) { - SetSectorSizes(sector_sizes); - // 128 MB, 512 bytes per sector, 248826 sectors geometries[512 * 248826] = { 512, 248826 }; // 230 MB, 512 bytes per block, 446325 sectors @@ -90,7 +88,7 @@ void SCSIMO::AddOptionPage(map>& pages, bool) const // Do not report update blocks } -void SCSIMO::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) const +void SCSIMO::ModeSelect(scsi_command cmd, cdb_t cdb, span buf, int length) { if (const string result = scsi_command_util::ModeSelect(cmd, cdb, buf, length, 1 << GetSectorSizeShiftCount()); !result.empty()) { diff --git a/cpp/devices/scsimo.h b/cpp/devices/scsimo.h index 41735d3b..b41c193c 100644 --- a/cpp/devices/scsimo.h +++ b/cpp/devices/scsimo.h @@ -26,13 +26,13 @@ class SCSIMO : public Disk { public: - SCSIMO(int, const unordered_set&); + explicit SCSIMO(int); ~SCSIMO() override = default; void Open() override; vector InquiryInternal() const override; - void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) const override; + void ModeSelect(scsi_defs::scsi_command, cdb_t, span, int) override; protected: diff --git a/cpp/hal/bus.cpp b/cpp/hal/bus.cpp index ff2edd1b..b135342a 100644 --- a/cpp/hal/bus.cpp +++ b/cpp/hal/bus.cpp @@ -60,23 +60,28 @@ const char* BUS::GetPhaseStrRaw(phase_t current_phase) { return it != phase_str_mapping.end() ? it->second : "INVALID"; } -//--------------------------------------------------------------------------- +// Phase Table +// Reference Table 8: https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-06.html +// This determines the phase based upon the Msg, C/D and I/O signals. // -// Phase Table -// Reference Table 8: https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-06.html -// This determines the phase based upon the Msg, C/D and I/O signals. -// -//--------------------------------------------------------------------------- +// |MSG|C/D|I/O| Phase +// | 0 | 0 | 0 | DATA OUT +// | 0 | 0 | 1 | DATA IN +// | 0 | 1 | 0 | COMMAND +// | 0 | 1 | 1 | STATUS +// | 1 | 0 | 0 | RESERVED +// | 1 | 0 | 1 | RESERVED +// | 1 | 1 | 0 | MESSAGE OUT +// | 1 | 1 | 1 | MESSAGE IN const array BUS::phase_table = { - // | MSG|C/D|I/O | - phase_t::dataout, // | 0 | 0 | 0 | - phase_t::datain, // | 0 | 0 | 1 | - phase_t::command, // | 0 | 1 | 0 | - phase_t::status, // | 0 | 1 | 1 | - phase_t::reserved, // | 1 | 0 | 0 | - phase_t::reserved, // | 1 | 0 | 1 | - phase_t::msgout, // | 1 | 1 | 0 | - phase_t::msgin // | 1 | 1 | 1 | + phase_t::dataout, + phase_t::datain, + phase_t::command, + phase_t::status, + phase_t::reserved, + phase_t::reserved, + phase_t::msgout, + phase_t::msgin }; //--------------------------------------------------------------------------- diff --git a/cpp/hal/bus.h b/cpp/hal/bus.h index 23740fe2..506cebf3 100644 --- a/cpp/hal/bus.h +++ b/cpp/hal/bus.h @@ -54,7 +54,7 @@ const static int SCSI_DELAY_FAST_NEGATION_PERIOD_NS = 30; // The DaynaPort SCSI Link do a short delay in the middle of transfering // a packet. This is the number of uS that will be delayed between the // header and the actual data. -const static int SCSI_DELAY_SEND_DATA_DAYNAPORT_US = 100; +const static int SCSI_DELAY_SEND_DATA_DAYNAPORT_NS = 100'000; class bus_exception : public runtime_error @@ -68,8 +68,7 @@ class BUS : public PinControl // Operation modes definition enum class mode_e { TARGET = 0, - INITIATOR = 1, - MONITOR = 2, + INITIATOR = 1 }; static int GetCommandByteCount(uint8_t); @@ -86,7 +85,6 @@ class BUS : public PinControl // Get the string phase name, based upon the raw data static const char *GetPhaseStrRaw(phase_t current_phase); - virtual int GetMode(int pin) = 0; virtual uint32_t Acquire() = 0; virtual unique_ptr GetSample(uint64_t timestamp = 0) = 0; @@ -97,9 +95,6 @@ class BUS : public PinControl // SEL signal event polling virtual bool PollSelectEvent() = 0; - // Clear SEL signal event - virtual void ClearSelectEvent() = 0; - virtual bool GetSignal(int pin) const = 0; // Get SCSI input signal value virtual void SetSignal(int pin, bool ast) = 0; diff --git a/cpp/hal/data_sample.h b/cpp/hal/data_sample.h index c5a57e30..d7e794b0 100644 --- a/cpp/hal/data_sample.h +++ b/cpp/hal/data_sample.h @@ -31,7 +31,6 @@ class DataSample virtual bool GetREQ() const = 0; virtual bool GetACT() const = 0; virtual uint8_t GetDAT() const = 0; - virtual bool GetDP() const = 0; virtual uint32_t GetRawCapture() const = 0; diff --git a/cpp/hal/data_sample_raspberry.cpp b/cpp/hal/data_sample_raspberry.cpp deleted file mode 100644 index 9634a912..00000000 --- a/cpp/hal/data_sample_raspberry.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator PiSCSI -// for Raspberry Pi -// -// Copyright (C) 2022 akuker -// -// [ SCSI Bus Monitor ] -// -//--------------------------------------------------------------------------- - -#include "shared/scsi.h" -#include "data_sample.h" - diff --git a/cpp/hal/data_sample_raspberry.h b/cpp/hal/data_sample_raspberry.h index a0b5e1e7..ee7cbc0e 100644 --- a/cpp/hal/data_sample_raspberry.h +++ b/cpp/hal/data_sample_raspberry.h @@ -74,10 +74,6 @@ class DataSample_Raspberry final : public DataSample { return GetSignal(PIN_ACT); } - bool GetDP() const override - { - return GetSignal(PIN_DP); - } uint8_t GetDAT() const override { uint8_t ret_val = 0; @@ -106,4 +102,4 @@ class DataSample_Raspberry final : public DataSample private: uint32_t data = 0; -}; \ No newline at end of file +}; diff --git a/cpp/hal/gpiobus.cpp b/cpp/hal/gpiobus.cpp index 837fc6d7..f0dc9cf5 100644 --- a/cpp/hal/gpiobus.cpp +++ b/cpp/hal/gpiobus.cpp @@ -1,10 +1,11 @@ //--------------------------------------------------------------------------- // -// SCSI Target Emulator PiSCSI -// for Raspberry Pi +// SCSI Target Emulator PiSCSI +// for Raspberry Pi // -// Powered by XM6 TypeG Technology. -// Copyright (C) 2016-2020 GIMONS +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2020 GIMONS +// Copyright (C) 2023 Uwe Seimet // //--------------------------------------------------------------------------- @@ -14,10 +15,11 @@ #include #include #include -#include +#include #ifdef __linux__ #include #endif +#include using namespace std; @@ -276,9 +278,12 @@ int GPIOBUS::SendHandShake(uint8_t *buf, int count, int delay_after_bytes) if (actmode == mode_e::TARGET) { for (i = 0; i < count; i++) { if (i == delay_after_bytes) { - spdlog::trace("DELAYING for " + to_string(SCSI_DELAY_SEND_DATA_DAYNAPORT_US) + " us after " + + spdlog::trace("DELAYING for " + to_string(SCSI_DELAY_SEND_DATA_DAYNAPORT_NS) + " ns after " + to_string(delay_after_bytes) + " bytes"); - SysTimer::SleepUsec(SCSI_DELAY_SEND_DATA_DAYNAPORT_US); + EnableIRQ(); + const timespec ts = { .tv_sec = 0, .tv_nsec = SCSI_DELAY_SEND_DATA_DAYNAPORT_NS}; + nanosleep(&ts, nullptr); + DisableIRQ(); } // Set the DATA signals @@ -403,42 +408,23 @@ bool GPIOBUS::PollSelectEvent() #endif } -//--------------------------------------------------------------------------- -// -// Cancel SEL signal event -// -//--------------------------------------------------------------------------- -void GPIOBUS::ClearSelectEvent() -{ - GPIO_FUNCTION_TRACE -} - -//--------------------------------------------------------------------------- -// -// Wait for signal change -// -//--------------------------------------------------------------------------- bool GPIOBUS::WaitSignal(int pin, bool ast) { - // Get current time - const uint32_t now = SysTimer::GetTimerLow(); - - // Calculate timeout (3000ms) - const uint32_t timeout = 3000 * 1000; + const auto now = chrono::steady_clock::now(); + // Wait up to 3 s do { - // Immediately upon receiving a reset Acquire(); - if (GetRST()) { - return false; - } - // Check for the signal edge if (GetSignal(pin) == ast) { return true; } - } while ((SysTimer::GetTimerLow() - now) < timeout); - // We timed out waiting for the signal + // Abort on a reset + if (GetRST()) { + return false; + } + } while ((chrono::duration_cast(chrono::steady_clock::now() - now).count()) < 3); + return false; } diff --git a/cpp/hal/gpiobus.h b/cpp/hal/gpiobus.h index fe774115..0e9e8129 100644 --- a/cpp/hal/gpiobus.h +++ b/cpp/hal/gpiobus.h @@ -182,8 +182,6 @@ class GPIOBUS : public BUS // SEL signal event polling bool PollSelectEvent() override; - // Clear SEL signal event - void ClearSelectEvent() override; protected: virtual void MakeTable() = 0; diff --git a/cpp/hal/gpiobus_raspberry.cpp b/cpp/hal/gpiobus_raspberry.cpp index 5b6f77f7..03bb9640 100644 --- a/cpp/hal/gpiobus_raspberry.cpp +++ b/cpp/hal/gpiobus_raspberry.cpp @@ -410,32 +410,30 @@ void GPIOBUS_Raspberry::SetBSY(bool ast) // Set BSY signal SetSignal(PIN_BSY, ast); - if (actmode == mode_e::TARGET) { - if (ast) { - // Turn on ACTIVE signal - SetControl(PIN_ACT, ACT_ON); + if (ast) { + // Turn on ACTIVE signal + SetControl(PIN_ACT, ACT_ON); - // Set Target signal to output - SetControl(PIN_TAD, TAD_OUT); + // Set Target signal to output + SetControl(PIN_TAD, TAD_OUT); - SetMode(PIN_BSY, OUT); - SetMode(PIN_MSG, OUT); - SetMode(PIN_CD, OUT); - SetMode(PIN_REQ, OUT); - SetMode(PIN_IO, OUT); - } else { - // Turn off the ACTIVE signal - SetControl(PIN_ACT, ACT_OFF); + SetMode(PIN_BSY, OUT); + SetMode(PIN_MSG, OUT); + SetMode(PIN_CD, OUT); + SetMode(PIN_REQ, OUT); + SetMode(PIN_IO, OUT); + } else { + // Turn off the ACTIVE signal + SetControl(PIN_ACT, ACT_OFF); - // Set the target signal to input - SetControl(PIN_TAD, TAD_IN); + // Set the target signal to input + SetControl(PIN_TAD, TAD_IN); - SetMode(PIN_BSY, IN); - SetMode(PIN_MSG, IN); - SetMode(PIN_CD, IN); - SetMode(PIN_REQ, IN); - SetMode(PIN_IO, IN); - } + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); } } @@ -608,55 +606,33 @@ uint8_t GPIOBUS_Raspberry::GetDAT() return (uint8_t)data; } -//--------------------------------------------------------------------------- -// -// Set data signals -// -//--------------------------------------------------------------------------- void GPIOBUS_Raspberry::SetDAT(uint8_t dat) { - // Write to port + // Write to ports #if SIGNAL_CONTROL_MODE == 0 uint32_t fsel = gpfsel[0]; fsel &= tblDatMsk[0][dat]; fsel |= tblDatSet[0][dat]; - if (fsel != gpfsel[0]) { - gpfsel[0] = fsel; - gpio[GPIO_FSEL_0] = fsel; - } + gpfsel[0] = fsel; + gpio[GPIO_FSEL_0] = fsel; fsel = gpfsel[1]; fsel &= tblDatMsk[1][dat]; fsel |= tblDatSet[1][dat]; - if (fsel != gpfsel[1]) { - gpfsel[1] = fsel; - gpio[GPIO_FSEL_1] = fsel; - } + gpfsel[1] = fsel; + gpio[GPIO_FSEL_1] = fsel; fsel = gpfsel[2]; fsel &= tblDatMsk[2][dat]; fsel |= tblDatSet[2][dat]; - if (fsel != gpfsel[2]) { - gpfsel[2] = fsel; - gpio[GPIO_FSEL_2] = fsel; - } + gpfsel[2] = fsel; + gpio[GPIO_FSEL_2] = fsel; #else gpio[GPIO_CLR_0] = tblDatMsk[dat]; gpio[GPIO_SET_0] = tblDatSet[dat]; -#endif // SIGNAL_CONTROL_MODE +#endif } -bool GPIOBUS_Raspberry::GetDP() const -{ - return GetSignal(PIN_DP); -} - -//--------------------------------------------------------------------------- -// -// Create work table -// -//--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- // // Signal table diff --git a/cpp/hal/gpiobus_raspberry.h b/cpp/hal/gpiobus_raspberry.h index a79df0e5..9918fe21 100644 --- a/cpp/hal/gpiobus_raspberry.h +++ b/cpp/hal/gpiobus_raspberry.h @@ -137,8 +137,6 @@ class GPIOBUS_Raspberry : public GPIOBUS // Set REQ signal void SetREQ(bool ast) override; - bool GetDP() const override; - // Get DAT signal uint8_t GetDAT() override; // Set DAT signal @@ -174,12 +172,6 @@ class GPIOBUS_Raspberry : public GPIOBUS // Set Control Signal void SetMode(int pin, int mode) override; // Set SCSI I/O mode - int GetMode(int pin) override - { - // Not implemented (or needed for thist gpio bus type) - (void)pin; - return -1; - } bool GetSignal(int pin) const override; // Get SCSI input signal value void SetSignal(int pin, bool ast) override; diff --git a/cpp/hal/gpiobus_virtual.cpp b/cpp/hal/gpiobus_virtual.cpp index 136dae24..5648a871 100644 --- a/cpp/hal/gpiobus_virtual.cpp +++ b/cpp/hal/gpiobus_virtual.cpp @@ -372,11 +372,6 @@ void GPIOBUS_Virtual::SetREQ(bool ast) SetSignal(PIN_REQ, ast); } -bool GPIOBUS_Virtual::GetDP() const -{ - return GetSignal(PIN_DP); -} - //--------------------------------------------------------------------------- // // Get data signals diff --git a/cpp/hal/gpiobus_virtual.h b/cpp/hal/gpiobus_virtual.h index 85e00c79..991e3f85 100644 --- a/cpp/hal/gpiobus_virtual.h +++ b/cpp/hal/gpiobus_virtual.h @@ -97,8 +97,6 @@ class GPIOBUS_Virtual final : public GPIOBUS void SetREQ(bool ast) override; // Set REQ signal - bool GetDP() const override; - bool WaitREQ(bool ast) override { return WaitSignal(PIN_REQ, ast); @@ -120,12 +118,6 @@ class GPIOBUS_Virtual final : public GPIOBUS // Set Control Signal void SetMode(int pin, int mode) override; // Set SCSI I/O mode - int GetMode(int pin) override - { - // Not implemented (or needed for thist gpio bus type) - (void)pin; - return -1; - } bool GetSignal(int pin) const override; // Get SCSI input signal value void SetSignal(int pin, bool ast) override; diff --git a/cpp/hal/pin_control.h b/cpp/hal/pin_control.h index 902a5de7..d5690d89 100644 --- a/cpp/hal/pin_control.h +++ b/cpp/hal/pin_control.h @@ -52,9 +52,6 @@ class PinControl // Set ENB signal virtual void SetENB(bool ast) = 0; - // Get parity signal - virtual bool GetDP() const = 0; - // GPIO pin direction setting virtual void PinConfig(int pin, int mode) = 0; // GPIO pin pull up/down resistor setting @@ -65,4 +62,4 @@ class PinControl PinControl() = default; virtual ~PinControl() = default; -}; \ No newline at end of file +}; diff --git a/cpp/hal/sbc_version.cpp b/cpp/hal/sbc_version.cpp index caebbedf..cd334ad3 100644 --- a/cpp/hal/sbc_version.cpp +++ b/cpp/hal/sbc_version.cpp @@ -144,7 +144,7 @@ uint32_t SBC_Version::GetPeripheralAddress(void) return address; } -#elif defined __NetBSD__ +#elif defined __NetBSD__ && (!defined(__x86_64__) || defined(__X86__)) uint32_t SBC_Version::GetPeripheralAddress(void) { char buf[1024]; diff --git a/cpp/hal/systimer.cpp b/cpp/hal/systimer.cpp index c2b4e7b8..9073ed82 100644 --- a/cpp/hal/systimer.cpp +++ b/cpp/hal/systimer.cpp @@ -43,12 +43,6 @@ uint32_t SysTimer::GetTimerLow() return systimer_ptr->GetTimerLow(); } -// Get system timer high byte -uint32_t SysTimer::GetTimerHigh() -{ - return systimer_ptr->GetTimerHigh(); -} - // Sleep for N nanoseconds void SysTimer::SleepNsec(uint32_t nsec) { diff --git a/cpp/hal/systimer.h b/cpp/hal/systimer.h index 0479ec5c..b4c4822d 100644 --- a/cpp/hal/systimer.h +++ b/cpp/hal/systimer.h @@ -29,8 +29,6 @@ class PlatformSpecificTimer virtual void Init() = 0; // Get system timer low byte virtual uint32_t GetTimerLow() = 0; - // Get system timer high byte - virtual uint32_t GetTimerHigh() = 0; // Sleep for N nanoseconds virtual void SleepNsec(uint32_t nsec) = 0; // Sleep for N microseconds @@ -48,8 +46,6 @@ class SysTimer static void Init(); // Get system timer low byte static uint32_t GetTimerLow(); - // Get system timer high byte - static uint32_t GetTimerHigh(); // Sleep for N nanoseconds static void SleepNsec(uint32_t nsec); // Sleep for N microseconds @@ -57,7 +53,6 @@ class SysTimer private: static bool initialized; - static bool is_allwinnner; static bool is_raspberry; static std::unique_ptr systimer_ptr; diff --git a/cpp/hal/systimer_raspberry.cpp b/cpp/hal/systimer_raspberry.cpp index 8814ea02..76da6abf 100644 --- a/cpp/hal/systimer_raspberry.cpp +++ b/cpp/hal/systimer_raspberry.cpp @@ -92,16 +92,6 @@ uint32_t SysTimer_Raspberry::GetTimerLow() return systaddr[SYST_CLO]; } -//--------------------------------------------------------------------------- -// -// Get system timer high byte -// -//--------------------------------------------------------------------------- -uint32_t SysTimer_Raspberry::GetTimerHigh() -{ - return systaddr[SYST_CHI]; -} - //--------------------------------------------------------------------------- // // Sleep in nanoseconds diff --git a/cpp/hal/systimer_raspberry.h b/cpp/hal/systimer_raspberry.h index 809d8229..e5ba2197 100644 --- a/cpp/hal/systimer_raspberry.h +++ b/cpp/hal/systimer_raspberry.h @@ -32,8 +32,6 @@ class SysTimer_Raspberry : public PlatformSpecificTimer void Init() override; // Get system timer low byte uint32_t GetTimerLow() override; - // Get system timer high byte - uint32_t GetTimerHigh() override; // Sleep for N nanoseconds void SleepNsec(uint32_t nsec) override; // Sleep for N microseconds diff --git a/cpp/launch_sudo.sh b/cpp/launch_sudo.sh deleted file mode 100755 index 6ce283c1..00000000 --- a/cpp/launch_sudo.sh +++ /dev/null @@ -1,3 +0,0 @@ -# This is used for debugging. VisualStudio code will call this file when launching -# the debugger, instead of directly calling GDB. That way we can add the pkexec -sudo /usr/bin/gdb "$@" \ No newline at end of file diff --git a/cpp/piscsi/piscsi_core.cpp b/cpp/piscsi/piscsi_core.cpp index 553e2297..2b2f6385 100644 --- a/cpp/piscsi/piscsi_core.cpp +++ b/cpp/piscsi/piscsi_core.cpp @@ -17,11 +17,9 @@ #include "shared/piscsi_version.h" #include "controllers/scsi_controller.h" #include "devices/device_logger.h" -#include "devices/device_factory.h" #include "devices/storage_device.h" #include "hal/gpiobus_factory.h" #include "hal/gpiobus.h" -#include "hal/systimer.h" #include "piscsi/piscsi_core.h" #include #include @@ -30,6 +28,7 @@ #include #include #include +#include using namespace std; using namespace filesystem; @@ -685,21 +684,19 @@ bool Piscsi::ShutDown(AbstractController::piscsi_shutdown_mode shutdown_mode) bool Piscsi::IsNotBusy() const { // Wait until BSY is released as there is a possibility for the - // initiator to assert it while setting the ID (for up to 3 seconds) - if (bus->GetBSY()) { - const uint32_t now = SysTimer::GetTimerLow(); + // initiator to assert it while setting the ID (for up to 3 seconds) + if (bus->GetBSY()) { + const auto now = chrono::steady_clock::now(); + while ((chrono::duration_cast(chrono::steady_clock::now() - now).count()) < 3) { + bus->Acquire(); - // Wait for 3s - while ((SysTimer::GetTimerLow() - now) < 3'000'000) { - bus->Acquire(); + if (!bus->GetBSY()) { + return true; + } + } - if (!bus->GetBSY()) { - return true; - } - } + return false; + } - return false; - } - - return true; + return true; } diff --git a/cpp/piscsi/piscsi_core.h b/cpp/piscsi/piscsi_core.h index 1560851d..8d8b917f 100644 --- a/cpp/piscsi/piscsi_core.h +++ b/cpp/piscsi/piscsi_core.h @@ -67,7 +67,7 @@ private: PiscsiImage piscsi_image; - PiscsiResponse response; + [[no_unique_address]] PiscsiResponse response; PiscsiService service; diff --git a/cpp/piscsi/piscsi_executor.cpp b/cpp/piscsi/piscsi_executor.cpp index d930184e..319623eb 100644 --- a/cpp/piscsi/piscsi_executor.cpp +++ b/cpp/piscsi/piscsi_executor.cpp @@ -10,7 +10,6 @@ #include "shared/piscsi_util.h" #include "shared/protobuf_util.h" #include "shared/piscsi_exceptions.h" -#include "devices/device_factory.h" #include "devices/disk.h" #include "localizer.h" #include "command_context.h" @@ -530,7 +529,7 @@ bool PiscsiExecutor::SetSectorSize(const CommandContext& context, shared_ptr(device); if (disk != nullptr && disk->IsSectorSizeConfigurable()) { - if (!disk->SetConfiguredSectorSize(device_factory, size)) { + if (!disk->SetConfiguredSectorSize(size)) { return context.ReturnLocalizedError(LocalizationKey::ERROR_BLOCK_SIZE, to_string(size)); } } diff --git a/cpp/piscsi/piscsi_executor.h b/cpp/piscsi/piscsi_executor.h index bae4fe60..6c4ea1a9 100644 --- a/cpp/piscsi/piscsi_executor.h +++ b/cpp/piscsi/piscsi_executor.h @@ -11,6 +11,7 @@ #include "hal/bus.h" #include "controllers/controller_manager.h" +#include "devices/device_factory.h" #include class DeviceFactory; @@ -60,7 +61,7 @@ private: ControllerManager& controller_manager; - const DeviceFactory device_factory; + [[no_unique_address]] const DeviceFactory device_factory; unordered_set reserved_ids; }; diff --git a/cpp/piscsi/piscsi_response.cpp b/cpp/piscsi/piscsi_response.cpp index 28e7e1a2..1f4d2fe0 100644 --- a/cpp/piscsi/piscsi_response.cpp +++ b/cpp/piscsi/piscsi_response.cpp @@ -24,26 +24,29 @@ using namespace piscsi_util; using namespace network_util; using namespace protobuf_util; -void PiscsiResponse::GetDeviceProperties(const Device& device, PbDeviceProperties& properties) const +void PiscsiResponse::GetDeviceProperties(shared_ptr device, PbDeviceProperties& properties) const { properties.set_luns(ControllerManager::GetScsiLunMax()); - properties.set_read_only(device.IsReadOnly()); - properties.set_protectable(device.IsProtectable()); - properties.set_stoppable(device.IsStoppable()); - properties.set_removable(device.IsRemovable()); - properties.set_lockable(device.IsLockable()); - properties.set_supports_file(device.SupportsFile()); - properties.set_supports_params(device.SupportsParams()); + properties.set_read_only(device->IsReadOnly()); + properties.set_protectable(device->IsProtectable()); + properties.set_stoppable(device->IsStoppable()); + properties.set_removable(device->IsRemovable()); + properties.set_lockable(device->IsLockable()); + properties.set_supports_file(device->SupportsFile()); + properties.set_supports_params(device->SupportsParams()); - if (device.SupportsParams()) { - for (const auto& [key, value] : device.GetDefaultParams()) { + if (device->SupportsParams()) { + for (const auto& [key, value] : device->GetDefaultParams()) { auto& map = *properties.mutable_default_params(); map[key] = value; } } - for (const auto& block_size : device_factory.GetSectorSizes(device.GetType())) { - properties.add_block_sizes(block_size); + shared_ptr disk = dynamic_pointer_cast(device); + if (disk != nullptr && disk->IsSectorSizeConfigurable()) { + for (const auto& sector_size : disk->GetSupportedSectorSizes()) { + properties.add_block_sizes(sector_size); + } } } @@ -52,7 +55,7 @@ void PiscsiResponse::GetDeviceTypeProperties(PbDeviceTypesInfo& device_types_inf auto type_properties = device_types_info.add_properties(); type_properties->set_type(type); const auto device = device_factory.CreateDevice(type, 0, ""); - GetDeviceProperties(*device, *type_properties->mutable_properties()); + GetDeviceProperties(device, *type_properties->mutable_properties()); } void PiscsiResponse::GetDeviceTypesInfo(PbDeviceTypesInfo& device_types_info) const @@ -67,37 +70,37 @@ void PiscsiResponse::GetDeviceTypesInfo(PbDeviceTypesInfo& device_types_info) co } } -void PiscsiResponse::GetDevice(const Device& device, PbDevice& pb_device, const string& default_folder) const +void PiscsiResponse::GetDevice(shared_ptr device, PbDevice& pb_device, const string& default_folder) const { - pb_device.set_id(device.GetId()); - pb_device.set_unit(device.GetLun()); - pb_device.set_vendor(device.GetVendor()); - pb_device.set_product(device.GetProduct()); - pb_device.set_revision(device.GetRevision()); - pb_device.set_type(device.GetType()); + pb_device.set_id(device->GetId()); + pb_device.set_unit(device->GetLun()); + pb_device.set_vendor(device->GetVendor()); + pb_device.set_product(device->GetProduct()); + pb_device.set_revision(device->GetRevision()); + pb_device.set_type(device->GetType()); GetDeviceProperties(device, *pb_device.mutable_properties()); auto status = pb_device.mutable_status(); - status->set_protected_(device.IsProtected()); - status->set_stopped(device.IsStopped()); - status->set_removed(device.IsRemoved()); - status->set_locked(device.IsLocked()); + status->set_protected_(device->IsProtected()); + status->set_stopped(device->IsStopped()); + status->set_removed(device->IsRemoved()); + status->set_locked(device->IsLocked()); - if (device.SupportsParams()) { - for (const auto& [key, value] : device.GetParams()) { + if (device->SupportsParams()) { + for (const auto& [key, value] : device->GetParams()) { SetParam(pb_device, key, value); } } - if (const auto disk = dynamic_cast(&device); disk) { - pb_device.set_block_size(device.IsRemoved()? 0 : disk->GetSectorSizeInBytes()); - pb_device.set_block_count(device.IsRemoved() ? 0: disk->GetBlockCount()); + if (const auto disk = dynamic_pointer_cast(device); disk) { + pb_device.set_block_size(device->IsRemoved()? 0 : disk->GetSectorSizeInBytes()); + pb_device.set_block_count(device->IsRemoved() ? 0: disk->GetBlockCount()); } - const auto storage_device = dynamic_cast(&device); + const auto storage_device = dynamic_pointer_cast(device); if (storage_device != nullptr) { - GetImageFile(*pb_device.mutable_file(), default_folder, device.IsReady() ? storage_device->GetFilename() : ""); + GetImageFile(*pb_device.mutable_file(), default_folder, device->IsReady() ? storage_device->GetFilename() : ""); } } @@ -191,7 +194,7 @@ void PiscsiResponse::GetDevices(const unordered_set>& { for (const auto& device : devices) { PbDevice *pb_device = server_info.mutable_devices_info()->add_devices(); - GetDevice(*device, *pb_device, default_folder); + GetDevice(device, *pb_device, default_folder); } } @@ -218,7 +221,7 @@ void PiscsiResponse::GetDevicesInfo(const unordered_setGetId() == id && d->GetLun() == lun) { - GetDevice(*d, *devices_info->add_devices(), default_folder); + GetDevice(d, *devices_info->add_devices(), default_folder); break; } } diff --git a/cpp/piscsi/piscsi_response.h b/cpp/piscsi/piscsi_response.h index b095416f..a4ab0331 100644 --- a/cpp/piscsi/piscsi_response.h +++ b/cpp/piscsi/piscsi_response.h @@ -25,7 +25,7 @@ class PiscsiResponse { public: - PiscsiResponse() = default; + PiscsiResponse() { } ~PiscsiResponse() = default; bool GetImageFile(PbImageFile&, const string&, const string&) const; @@ -47,11 +47,10 @@ private: inline static const vector EMPTY_VECTOR; - // TODO Try to get rid of this field by having the device instead of the factory providing the device data - const DeviceFactory device_factory; + [[no_unique_address]] const DeviceFactory device_factory; - void GetDeviceProperties(const Device&, PbDeviceProperties&) const; - void GetDevice(const Device&, PbDevice&, const string&) const; + void GetDeviceProperties(shared_ptr, PbDeviceProperties&) const; + void GetDevice(shared_ptr, PbDevice&, const string&) const; void GetDeviceTypeProperties(PbDeviceTypesInfo&, PbDeviceType) const; void GetAvailableImages(PbImageFilesInfo&, const string&, const string&, const string&, int) const; void GetAvailableImages(PbServerInfo&, const string&, const string&, const string&, int) const; diff --git a/cpp/piscsi/piscsi_service.cpp b/cpp/piscsi/piscsi_service.cpp index 4f842def..90f60774 100644 --- a/cpp/piscsi/piscsi_service.cpp +++ b/cpp/piscsi/piscsi_service.cpp @@ -42,7 +42,8 @@ string PiscsiService::Init(const callback& cb, int port) server.sin_family = PF_INET; server.sin_port = htons((uint16_t)port); server.sin_addr.s_addr = INADDR_ANY; - if (bind(service_socket, reinterpret_cast(&server), sizeof(sockaddr_in)) < 0) { //NOSONAR bit_cast is not supported by the bullseye compiler + if (bind(service_socket, reinterpret_cast(&server), //NOSONAR bit_cast is not supported by the bullseye compiler + static_cast(sizeof(sockaddr_in))) < 0) { Stop(); return "Port " + to_string(port) + " is in use, is piscsi already running?"; } diff --git a/cpp/shared/piscsi_version.cpp b/cpp/shared/piscsi_version.cpp index 702a2d2b..cbc124d5 100644 --- a/cpp/shared/piscsi_version.cpp +++ b/cpp/shared/piscsi_version.cpp @@ -14,7 +14,7 @@ // The following should be updated for each release const int piscsi_major_version = 23; // Last two digits of year const int piscsi_minor_version = 11; // Month -const int piscsi_patch_version = 1; // Patch number - increment for each update +const int piscsi_patch_version = -1; // Patch number - increment for each update using namespace std; diff --git a/cpp/test/device_factory_test.cpp b/cpp/test/device_factory_test.cpp index 0c51c194..ce74398b 100644 --- a/cpp/test/device_factory_test.cpp +++ b/cpp/test/device_factory_test.cpp @@ -39,41 +39,6 @@ TEST(DeviceFactoryTest, GetTypeForFile) EXPECT_EQ(device_factory.GetTypeForFile("test.iso.suffix"), UNDEFINED); } -TEST(DeviceFactoryTest, GetSectorSizes) -{ - DeviceFactory device_factory; - - unordered_set sector_sizes = device_factory.GetSectorSizes(SCHD); - EXPECT_EQ(4, sector_sizes.size()); - - EXPECT_TRUE(sector_sizes.contains(512)); - EXPECT_TRUE(sector_sizes.contains(1024)); - EXPECT_TRUE(sector_sizes.contains(2048)); - EXPECT_TRUE(sector_sizes.contains(4096)); - - sector_sizes = device_factory.GetSectorSizes(SCRM); - EXPECT_EQ(4, sector_sizes.size()); - - EXPECT_TRUE(sector_sizes.contains(512)); - EXPECT_TRUE(sector_sizes.contains(1024)); - EXPECT_TRUE(sector_sizes.contains(2048)); - EXPECT_TRUE(sector_sizes.contains(4096)); - - sector_sizes = device_factory.GetSectorSizes(SCMO); - EXPECT_EQ(4, sector_sizes.size()); - - EXPECT_TRUE(sector_sizes.contains(512)); - EXPECT_TRUE(sector_sizes.contains(1024)); - EXPECT_TRUE(sector_sizes.contains(2048)); - EXPECT_TRUE(sector_sizes.contains(4096)); - - sector_sizes = device_factory.GetSectorSizes(SCCD); - EXPECT_EQ(2, sector_sizes.size()); - - EXPECT_TRUE(sector_sizes.contains(512)); - EXPECT_TRUE(sector_sizes.contains(2048)); -} - TEST(DeviceFactoryTest, GetExtensionMapping) { DeviceFactory device_factory; diff --git a/cpp/test/disk_test.cpp b/cpp/test/disk_test.cpp index b0206403..f7ad298f 100644 --- a/cpp/test/disk_test.cpp +++ b/cpp/test/disk_test.cpp @@ -774,14 +774,8 @@ TEST(DiskTest, SectorSize) { MockDisk disk; - unordered_set sizes = { 512, 1024 }; - disk.SetSectorSizes(sizes); EXPECT_TRUE(disk.IsSectorSizeConfigurable()); - sizes.clear(); - disk.SetSectorSizes(sizes); - EXPECT_FALSE(disk.IsSectorSizeConfigurable()); - disk.SetSectorSizeShiftCount(9); EXPECT_EQ(9, disk.GetSectorSizeShiftCount()); EXPECT_EQ(512, disk.GetSectorSizeInBytes()); @@ -815,13 +809,12 @@ TEST(DiskTest, SectorSize) TEST(DiskTest, ConfiguredSectorSize) { - DeviceFactory device_factory; - MockSCSIHD disk(0, {}, false); + MockSCSIHD disk(0, false); - EXPECT_TRUE(disk.SetConfiguredSectorSize(device_factory, 512)); + EXPECT_TRUE(disk.SetConfiguredSectorSize(512)); EXPECT_EQ(512, disk.GetConfiguredSectorSize()); - EXPECT_FALSE(disk.SetConfiguredSectorSize(device_factory, 1234)); + EXPECT_FALSE(disk.SetConfiguredSectorSize(1234)); EXPECT_EQ(512, disk.GetConfiguredSectorSize()); } diff --git a/cpp/test/gpiobus_raspberry_test.cpp b/cpp/test/gpiobus_raspberry_test.cpp index 5a94d670..03184557 100644 --- a/cpp/test/gpiobus_raspberry_test.cpp +++ b/cpp/test/gpiobus_raspberry_test.cpp @@ -219,16 +219,3 @@ TEST(GpiobusRaspberry, GetREQ) bus.Acquire(); EXPECT_EQ(false, bus.GetREQ()); } - -TEST(GpiobusRaspberry, GetDP) -{ - SetableGpiobusRaspberry bus; - - bus.TestSetGpios(0x00); - bus.TestSetGpioPin(PIN_DP, true); - bus.Acquire(); - EXPECT_EQ(true, bus.GetDP()); - bus.TestSetGpioPin(PIN_DP, false); - bus.Acquire(); - EXPECT_EQ(false, bus.GetDP()); -} diff --git a/cpp/test/mocks.h b/cpp/test/mocks.h index fcf45cd5..919afd8d 100644 --- a/cpp/test/mocks.h +++ b/cpp/test/mocks.h @@ -53,7 +53,6 @@ public: MOCK_METHOD(void, SetENB, (bool), (override)); MOCK_METHOD(uint8_t, GetDAT, (), (override)); MOCK_METHOD(void, SetDAT, (uint8_t), (override)); - MOCK_METHOD(bool, GetDP, (), (const override)); MOCK_METHOD(uint32_t, Acquire, (), (override)); MOCK_METHOD(int, CommandHandShake, (vector&), (override)); MOCK_METHOD(int, ReceiveHandShake, (uint8_t *, int), (override)); @@ -61,13 +60,11 @@ public: MOCK_METHOD(bool, GetSignal, (int), (const override)); MOCK_METHOD(void, SetSignal, (int, bool), (override)); MOCK_METHOD(bool, PollSelectEvent, (), (override)); - MOCK_METHOD(void, ClearSelectEvent, (), (override)); MOCK_METHOD(unique_ptr, GetSample, (uint64_t), (override)); MOCK_METHOD(void, PinConfig, (int, int), (override)); MOCK_METHOD(void, PullConfig, (int , int ), (override)); MOCK_METHOD(void, SetControl, (int , bool ), (override)); MOCK_METHOD(void, SetMode, (int , int ), (override)); - MOCK_METHOD(int, GetMode, (int ), (override)); MockBus() = default; ~MockBus() override = default; @@ -352,7 +349,7 @@ public: MOCK_METHOD(void, FlushCache, (), (override)); MOCK_METHOD(void, Open, (), (override)); - MockDisk() : Disk(SCHD, 0) {} + MockDisk() : Disk(SCHD, 0, { 512, 1024, 2048, 4096 }) {} ~MockDisk() override = default; }; @@ -363,10 +360,15 @@ class MockSCSIHD : public SCSIHD //NOSONAR Ignore inheritance hierarchy depth in FRIEND_TEST(ScsiHdTest, FinalizeSetup); FRIEND_TEST(ScsiHdTest, GetProductData); FRIEND_TEST(ScsiHdTest, SetUpModePages); - FRIEND_TEST(PiscsiExecutorTest, SetSectorSize); + FRIEND_TEST(ScsiHdTest, GetSectorSizes); FRIEND_TEST(ScsiHdTest, ModeSelect); + FRIEND_TEST(PiscsiExecutorTest, SetSectorSize); - using SCSIHD::SCSIHD; +public: + + MockSCSIHD(int lun, bool removable) : SCSIHD(lun, removable, scsi_level::scsi_2) {} + explicit MockSCSIHD(const unordered_set& sector_sizes) : SCSIHD(0, false, scsi_level::scsi_2, sector_sizes) {} + ~MockSCSIHD() override = default; }; class MockSCSIHD_NEC : public SCSIHD_NEC //NOSONAR Ignore inheritance hierarchy depth in unit tests @@ -382,8 +384,10 @@ class MockSCSIHD_NEC : public SCSIHD_NEC //NOSONAR Ignore inheritance hierarchy class MockSCSICD : public SCSICD //NOSONAR Ignore inheritance hierarchy depth in unit tests { + FRIEND_TEST(ScsiCdTest, GetSectorSizes); FRIEND_TEST(ScsiCdTest, SetUpModePages); FRIEND_TEST(ScsiCdTest, ReadToc); + FRIEND_TEST(ScsiCdTest, ModeSelect); using SCSICD::SCSICD; }; diff --git a/cpp/test/piscsi_executor_test.cpp b/cpp/test/piscsi_executor_test.cpp index d6557be4..06b218a1 100644 --- a/cpp/test/piscsi_executor_test.cpp +++ b/cpp/test/piscsi_executor_test.cpp @@ -252,8 +252,6 @@ TEST(PiscsiExecutorTest, Attach) TEST(PiscsiExecutorTest, Insert) { - DeviceFactory device_factory; - auto bus = make_shared(); ControllerManager controller_manager; auto [controller, device] = CreateDevice(SCHD); @@ -500,13 +498,17 @@ TEST(PiscsiExecutorTest, SetSectorSize) CommandContext context(command, "", ""); unordered_set sizes; - auto hd = make_shared(0, sizes, false); + auto hd = make_shared(sizes); EXPECT_FALSE(executor.SetSectorSize(context, hd, 512)); sizes.insert(512); - hd = make_shared(0, sizes, false); + hd = make_shared(sizes); EXPECT_TRUE(executor.SetSectorSize(context, hd, 0)); EXPECT_FALSE(executor.SetSectorSize(context, hd, 1)); + EXPECT_FALSE(executor.SetSectorSize(context, hd, 512)); + + sizes.insert(1024); + hd = make_shared(sizes); EXPECT_TRUE(executor.SetSectorSize(context, hd, 512)); } diff --git a/cpp/test/scsi_command_util_test.cpp b/cpp/test/scsi_command_util_test.cpp index 20afa389..7bf81550 100644 --- a/cpp/test/scsi_command_util_test.cpp +++ b/cpp/test/scsi_command_util_test.cpp @@ -46,6 +46,11 @@ TEST(ScsiCommandUtilTest, ModeSelect6) Property(&scsi_exception::get_asc, asc::invalid_field_in_parameter_list)))) << "Unsupported page 0 was not rejected"; + // Page 1 + buf[12] = 0x01; + EXPECT_NO_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512)) + << "Page 1 is supported"; + // Page 3 (Format Device Page) buf[12] = 0x03; EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512); }, @@ -62,7 +67,25 @@ TEST(ScsiCommandUtilTest, ModeSelect6) Property(&scsi_exception::get_asc, asc::invalid_field_in_parameter_list)))) << "Not enough command parameters"; - EXPECT_FALSE(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512).empty()); + // check length computation + buf[3] = 8; + buf[10] = 2; + buf[12] = 1; + buf[13] = 10; + buf[14] = 0x24; + buf[24] = 0; + EXPECT_NO_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 512)) + << "Multi-page length computation"; + + // check length computation + buf[3] = 8; + buf[10] = 12; + buf[12] = 0; + buf[13] = 0; + buf[14] = 0; + buf[24] = 0; + EXPECT_NO_THROW(ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, 12, 512)) + << "Empty ModeSelect6"; } TEST(ScsiCommandUtilTest, ModeSelect10) @@ -111,8 +134,6 @@ TEST(ScsiCommandUtilTest, ModeSelect10) Property(&scsi_exception::get_sense_key, sense_key::illegal_request), Property(&scsi_exception::get_asc, asc::invalid_field_in_parameter_list)))) << "Not enough command parameters"; - - EXPECT_FALSE(ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 512).empty()); } TEST(ScsiCommandUtilTest, EnrichFormatPage) diff --git a/cpp/test/scsicd_test.cpp b/cpp/test/scsicd_test.cpp index fa5d8743..4ebe3ce2 100644 --- a/cpp/test/scsicd_test.cpp +++ b/cpp/test/scsicd_test.cpp @@ -34,10 +34,21 @@ TEST(ScsiCdTest, Inquiry) TestInquiry::Inquiry(SCCD, device_type::cd_rom, scsi_level::scsi_1_ccs, "PiSCSI SCSI CD-ROM ", 0x1f, true, "file.is1"); } +TEST(ScsiCdTest, GetSectorSizes) +{ + MockSCSICD cd(0); + + const auto& sector_sizes = cd.GetSupportedSectorSizes(); + EXPECT_EQ(2, sector_sizes.size()); + + EXPECT_TRUE(sector_sizes.contains(512)); + EXPECT_TRUE(sector_sizes.contains(2048)); +} + TEST(ScsiCdTest, SetUpModePages) { map> pages; - MockSCSICD cd(0, {}); + MockSCSICD cd(0); // Non changeable cd.SetUpModePages(pages, 0x3f, false); @@ -51,10 +62,10 @@ TEST(ScsiCdTest, SetUpModePages) TEST(ScsiCdTest, Open) { - MockSCSICD cd_iso(0, {}); - MockSCSICD cd_cue(0, {}); - MockSCSICD cd_raw(0, {}); - MockSCSICD cd_physical(0, {}); + MockSCSICD cd_iso(0); + MockSCSICD cd_cue(0); + MockSCSICD cd_raw(0); + MockSCSICD cd_physical(0); EXPECT_THROW(cd_iso.Open(), io_exception) << "Missing filename"; @@ -111,8 +122,7 @@ TEST(ScsiCdTest, Open) TEST(ScsiCdTest, ReadToc) { auto controller = make_shared(); - const unordered_set sector_sizes; - auto cd = make_shared(0, sector_sizes); + auto cd = make_shared(0); EXPECT_TRUE(cd->Init({})); controller->AddDevice(cd); @@ -123,3 +133,26 @@ TEST(ScsiCdTest, ReadToc) // Further testing requires filesystem access } + +TEST(ScsiCdTest, ModeSelect) +{ + MockSCSICD cd(0); + vector cmd(6); + vector buf(255); + + cd.SetSectorSizeInBytes(2048); + + // PF + cmd[1] = 0x10; + // Length + buf[3] = 0x08; + // 2048 bytes per sector + buf[10] = 0x08; + // Page 3 (Device Format Page) + buf[12] = 0x01; + EXPECT_NO_THROW(cd.ModeSelect(scsi_command::eCmdModeSelect6, cmd, buf, 255)) << "MODE SELECT(6) with sector size 2048 is supported"; + + // 512 bytes per sector + buf[10] = 0x02; + EXPECT_NO_THROW(cd.ModeSelect(scsi_command::eCmdModeSelect6, cmd, buf, 255)) << "MODE SELECT(6) with sector size 512 is supported"; +} diff --git a/cpp/test/scsihd_test.cpp b/cpp/test/scsihd_test.cpp index 1cdacad0..693f450b 100644 --- a/cpp/test/scsihd_test.cpp +++ b/cpp/test/scsihd_test.cpp @@ -30,14 +30,14 @@ TEST(ScsiHdTest, Inquiry) TEST(ScsiHdTest, SupportsSaveParameters) { - MockSCSIHD hd(0, {}, false); + MockSCSIHD hd(0, false); EXPECT_TRUE(hd.SupportsSaveParameters()); } TEST(ScsiHdTest, FinalizeSetup) { - MockSCSIHD hd(0, {}, false); + MockSCSIHD hd(0, false); hd.SetSectorSizeInBytes(1024); EXPECT_THROW(hd.FinalizeSetup(0), io_exception) << "Device has 0 blocks"; @@ -45,9 +45,9 @@ TEST(ScsiHdTest, FinalizeSetup) TEST(ScsiHdTest, GetProductData) { - MockSCSIHD hd_kb(0, {}, false); - MockSCSIHD hd_mb(0, {}, false); - MockSCSIHD hd_gb(0, {}, false); + MockSCSIHD hd_kb(0, false); + MockSCSIHD hd_mb(0, false); + MockSCSIHD hd_gb(0, false); const path filename = CreateTempFile(1); hd_kb.SetFilename(string(filename)); @@ -73,10 +73,23 @@ TEST(ScsiHdTest, GetProductData) remove(filename); } +TEST(ScsiHdTest, GetSectorSizes) +{ + MockSCSIHD hd(0, false); + + const auto& sector_sizes = hd.GetSupportedSectorSizes(); + EXPECT_EQ(4, sector_sizes.size()); + + EXPECT_TRUE(sector_sizes.contains(512)); + EXPECT_TRUE(sector_sizes.contains(1024)); + EXPECT_TRUE(sector_sizes.contains(2048)); + EXPECT_TRUE(sector_sizes.contains(4096)); +} + TEST(ScsiHdTest, SetUpModePages) { map> pages; - MockSCSIHD hd(0, {}, false); + MockSCSIHD hd(0, false); // Non changeable hd.SetUpModePages(pages, 0x3f, false); @@ -90,7 +103,7 @@ TEST(ScsiHdTest, SetUpModePages) TEST(ScsiHdTest, ModeSelect) { - MockSCSIHD hd(0, { 512 }, false); + MockSCSIHD hd({ 512 }); vector cmd(10); vector buf(255); diff --git a/cpp/test/scsimo_test.cpp b/cpp/test/scsimo_test.cpp index 2422c479..d38ee4a4 100644 --- a/cpp/test/scsimo_test.cpp +++ b/cpp/test/scsimo_test.cpp @@ -28,15 +28,28 @@ TEST(ScsiMoTest, Inquiry) TEST(ScsiMoTest, SupportsSaveParameters) { map> pages; - MockSCSIMO mo(0, {}); + MockSCSIMO mo(0); EXPECT_TRUE(mo.SupportsSaveParameters()); } +TEST(ScsiMoTest, GetSectorSizes) +{ + MockSCSIMO mo(0); + + const auto& sector_sizes = mo.GetSupportedSectorSizes(); + EXPECT_EQ(4, sector_sizes.size()); + + EXPECT_TRUE(sector_sizes.contains(512)); + EXPECT_TRUE(sector_sizes.contains(1024)); + EXPECT_TRUE(sector_sizes.contains(2048)); + EXPECT_TRUE(sector_sizes.contains(4096)); +} + TEST(ScsiMoTest, SetUpModePages) { map> pages; - MockSCSIMO mo(0, {}); + MockSCSIMO mo(0); // Non changeable mo.SetUpModePages(pages, 0x3f, false); @@ -51,7 +64,7 @@ TEST(ScsiMoTest, SetUpModePages) TEST(ScsiMoTest, TestAddVendorPage) { map> pages; - MockSCSIMO mo(0, {}); + MockSCSIMO mo(0); mo.SetReady(true); mo.SetUpModePages(pages, 0x21, false); @@ -122,7 +135,7 @@ TEST(ScsiMoTest, TestAddVendorPage) TEST(ScsiMoTest, ModeSelect) { - MockSCSIMO mo(0, { 1024, 2048 }); + MockSCSIMO mo(0); vector cmd(10); vector buf(255); diff --git a/docker/README.md b/docker/README.md index 736ac6ef..df0f7e7b 100644 --- a/docker/README.md +++ b/docker/README.md @@ -40,10 +40,11 @@ The following environment variables are available when using Docker Compose: | `WEB_HTTP_PORT` | 8080 | | `WEB_HTTPS_PORT` | 8443 | | `WEB_LOG_LEVEL` | info | -| `BACKEND_HOST` | backend | -| `BACKEND_PORT` | 6868 | -| `BACKEND_PASSWORD` | *[None]* | -| `BACKEND_LOG_LEVEL` | debug | +| `BACKEND_HOST` | backend | +| `BACKEND_PORT` | 6868 | +| `BACKEND_PASSWORD` | *[None]* | +| `BACKEND_LOG_LEVEL` | debug | +| `RESET_VENV` | *[None]* | **Examples:** @@ -57,6 +58,12 @@ Start the web UI with the log level set to debug: WEB_LOG_LEVEL=debug docker compose up ``` +Force resetting & reinstalling Python web `venv` directory: + +``` +RESET_VENV=1 docker compose up +``` + ## Volumes When using Docker Compose the following volumes will be mounted automatically: diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile index 0326aa2b..e86a1c5d 100644 --- a/docker/backend/Dockerfile +++ b/docker/backend/Dockerfile @@ -18,7 +18,7 @@ FROM debian:bullseye-slim AS runner USER root WORKDIR /home/pi -COPY --from=build /home/pi/piscsi/cpp/bin/fullspec/* /usr/local/bin/ +COPY --from=build /home/pi/piscsi/cpp/bin/* /usr/local/bin/ COPY docker/backend/piscsi_wrapper.sh /usr/local/bin/piscsi_wrapper.sh RUN chmod +x /usr/local/bin/* RUN mkdir -p /home/pi/images diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index e3ea35a2..d18b8883 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -36,6 +36,7 @@ services: - "127.0.0.1:${WEB_HTTPS_PORT:-8443}:443" environment: - BACKEND_PASSWORD=${BACKEND_PASSWORD:-} + - RESET_VENV=${RESET_VENV:-} init: true command: [ "--backend-host=${BACKEND_HOST:-backend}", diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile index 1d74a423..7c9528d1 100644 --- a/docker/web/Dockerfile +++ b/docker/web/Dockerfile @@ -4,7 +4,7 @@ ARG OS_VERSION=bullseye FROM "debian:${OS_VERSION}-slim" RUN apt-get update \ - && apt-get install -y --no-install-recommends sudo systemd rsyslog procps man-db wget git \ + && apt-get install -y --no-install-recommends sudo systemd rsyslog procps man-db wget git gcc \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/easyinstall.sh b/easyinstall.sh index 21b1d5a7..04c78469 100755 --- a/easyinstall.sh +++ b/easyinstall.sh @@ -76,7 +76,7 @@ SECRET_FILE="$HOME/.config/piscsi/secret" FILE_SHARE_PATH="$HOME/shared_files" FILE_SHARE_NAME="Pi File Server" -APT_PACKAGES_COMMON="build-essential git protobuf-compiler bridge-utils ca-certificates" +APT_PACKAGES_COMMON="build-essential git protobuf-compiler bridge-utils ca-certificates rsyslog" APT_PACKAGES_BACKEND="libspdlog-dev libpcap-dev libprotobuf-dev protobuf-compiler libgmock-dev clang" APT_PACKAGES_PYTHON="python3 python3-dev python3-pip python3-venv python3-setuptools python3-wheel libev-dev libevdev2" APT_PACKAGES_WEB="nginx-light genisoimage man2html hfsutils dosfstools kpartx unzip unar disktype gettext" @@ -92,7 +92,7 @@ function initialChecks() { } # Only to be used for pi-gen automated install -function cacheSudo() { +function sudoCache() { echo "Caching sudo password" echo raspberry | sudo -v -S } @@ -948,8 +948,9 @@ function installSamba() { # Installs and configures Webmin function installWebmin() { WEBMIN_PATH="/usr/share/webmin" - WEBMIN_MODULE_CONFIG="/etc/webmin/netatalk2/config" - WEBMIN_MODULE_VERSION="1.0" + WEBMIN_NETATALK_MODULE_CONFIG="/etc/webmin/netatalk2/config" + WEBMIN_NETATALK_MODULE_VERSION="1.0" + WEBMIN_VSFTPD_MODULE_VERSION="2023-12-10" if [ -d "$WEBMIN_PATH" ]; then echo @@ -967,25 +968,30 @@ function installWebmin() { echo "Installing packages..." sudo apt-get install curl libcgi-session-perl --no-install-recommends --assume-yes /dev/null || true - wget -O netatalk2-wbm.tgz "https://github.com/Netatalk/netatalk-webmin/releases/download/netatalk2-$WEBMIN_MODULE_VERSION/netatalk2-wbm-$WEBMIN_MODULE_VERSION.tgz" /dev/null || true + wget -O vsftpd.wbm.tgz "https://github.com/rdmark/vsftpd-webmin/releases/download/$WEBMIN_VSFTPD_MODULE_VERSION/vsftpd-$WEBMIN_VSFTPD_MODULE_VERSION.wbm.gz" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/ctrlboard/requirements.txt b/python/ctrlboard/requirements.txt index be85c311..867dd60e 100644 --- a/python/ctrlboard/requirements.txt +++ b/python/ctrlboard/requirements.txt @@ -1,10 +1,10 @@ -#adafruit-circuitpython-busdevice==5.1.1 -#adafruit-circuitpython-framebuf==1.4.8 -#adafruit-circuitpython-ssd1306==2.12.3 -luma-oled==3.8.1 +luma.core==2.4.1 +luma.oled==3.8.1 Pillow==10.0.1 -RPi.GPIO==0.7.0 protobuf==3.19.5 -unidecode==1.3.2 +pyftdi==0.55.0 +pyserial==3.5 +pyusb==1.2.1 smbus==1.1.post2 - +smbus2==0.4.3 +Unidecode==1.3.2 diff --git a/python/ctrlboard/src/ctrlboard_event_handler/ctrlboard_menu_update_event_handler.py b/python/ctrlboard/src/ctrlboard_event_handler/ctrlboard_menu_update_event_handler.py index 768e996f..45e53ce5 100644 --- a/python/ctrlboard/src/ctrlboard_event_handler/ctrlboard_menu_update_event_handler.py +++ b/python/ctrlboard/src/ctrlboard_event_handler/ctrlboard_menu_update_event_handler.py @@ -106,8 +106,9 @@ class CtrlBoardMenuUpdateEventHandler(Observer): handler_function(info_object) except AttributeError: log = logging.getLogger(__name__) - log.error( - "Handler function not found or returned an error. Skipping.", + log.debug( + "Handler function [%s] not found or returned an error. Skipping.", + str(handler_function_name), ) # noinspection PyUnusedLocal @@ -194,7 +195,7 @@ class CtrlBoardMenuUpdateEventHandler(Observer): """Method handles the rotary button press in the profile selection menu for selecting a profile to load.""" if info_object is not None and "name" in info_object: - file_cmd = FileCmds(sock_cmd=self.sock_cmd, piscsi=self.piscsi_cmd) + file_cmd = FileCmds(piscsi=self.piscsi_cmd) result = file_cmd.read_config(file_name=info_object["name"]) if result["status"] is True: self._menu_controller.show_message("Profile loaded!") diff --git a/python/ctrlboard/src/ctrlboard_menu_builder.py b/python/ctrlboard/src/ctrlboard_menu_builder.py index 3f322131..afdcb7f9 100644 --- a/python/ctrlboard/src/ctrlboard_menu_builder.py +++ b/python/ctrlboard/src/ctrlboard_menu_builder.py @@ -28,12 +28,7 @@ class CtrlBoardMenuBuilder(MenuBuilder): def __init__(self, piscsi_cmd: PiscsiCmds): super().__init__() self._piscsi_client = piscsi_cmd - self.file_cmd = FileCmds( - sock_cmd=piscsi_cmd.sock_cmd, - piscsi=piscsi_cmd, - token=piscsi_cmd.token, - locale=piscsi_cmd.locale, - ) + self.file_cmd = FileCmds(piscsi=piscsi_cmd) def build(self, name: str, context_object=None) -> Menu: if name == CtrlBoardMenuBuilder.SCSI_ID_MENU: @@ -48,7 +43,7 @@ class CtrlBoardMenuBuilder(MenuBuilder): return self.create_device_info_menu(context_object) log = logging.getLogger(__name__) - log.error("Provided menu name cannot be built!") + log.debug("Provided menu name [%s] cannot be built!", name) return self.create_scsi_id_list_menu(context_object) @@ -142,7 +137,7 @@ class CtrlBoardMenuBuilder(MenuBuilder): def create_images_menu(self, context_object=None): """Creates a sub menu showing all the available images""" menu = Menu(CtrlBoardMenuBuilder.IMAGES_MENU) - images_info = self.piscsi_cmd.list_images() + images_info = self._piscsi_client.list_images() menu.add_entry("Return", {"context": self.IMAGES_MENU, "action": self.ACTION_RETURN}) images = images_info["files"] sorted_images = sorted(images, key=lambda d: d["name"]) diff --git a/python/ctrlboard/src/menu/cycler.py b/python/ctrlboard/src/menu/cycler.py index e3144af7..aa785084 100644 --- a/python/ctrlboard/src/menu/cycler.py +++ b/python/ctrlboard/src/menu/cycler.py @@ -23,7 +23,7 @@ class Cycler: self._menu_controller = menu_controller self.sock_cmd = sock_cmd self.piscsi_cmd = piscsi_cmd - self.file_cmd = FileCmds(sock_cmd=self.sock_cmd, piscsi=self.piscsi_cmd) + self.file_cmd = FileCmds(piscsi=self.piscsi_cmd) self.cycle_entries = self.populate_cycle_entries() self.return_string = return_string self.return_entry = return_entry diff --git a/python/ctrlboard/src/menu/menu_renderer.py b/python/ctrlboard/src/menu/menu_renderer.py index 380fe401..aec3edb4 100644 --- a/python/ctrlboard/src/menu/menu_renderer.py +++ b/python/ctrlboard/src/menu/menu_renderer.py @@ -30,7 +30,7 @@ class MenuRenderer(ABC): self.draw = ImageDraw.Draw(self.image) self.font = ImageFont.truetype(config.font_path, size=config.font_size) # just a sample text to work with the font height - _, self.font_height = self.font.getsize("ABCabc") + self.font_height = self.font.getbbox("ABCabc")[3] self.cursor_position = 0 self.frame_start_row = 0 self.render_timestamp = None @@ -153,7 +153,8 @@ class MenuRenderer(ABC): def draw_fullsceen_message(self, text: str): """Draws a fullscreen message, i.e., a full-screen message.""" - font_width, font_height = self.font.getsize(text) + font_width = self.font.getlength(text) + font_height = self.font.getbbox(text)[3] centered_width = (self.disp.width - font_width) / 2 centered_height = (self.disp.height - font_height) / 2 @@ -171,7 +172,7 @@ class MenuRenderer(ABC): def draw_mini_message(self, text: str): """Draws a fullscreen message, i.e., a message covering only the center portion of the screen. The remaining areas stay visible.""" - font_width, _ = self.font.getsize(text) + font_width = self.font.getlength(text) centered_width = (self.disp.width - font_width) / 2 centered_height = (self.disp.height - self.font_height) / 2 @@ -270,7 +271,7 @@ class MenuRenderer(ABC): def setup_horizontal_scrolling(self, text): """Configure horizontal scrolling based on the configured screen dimensions.""" - font_width, _ = self.font.getsize(text) + font_width = self.font.getlength(text) self._current_line_horizontal_overlap = font_width - self.disp.width def update(self): diff --git a/python/web/genisoimage_hfs_resource_fork_map.txt b/python/web/genisoimage_hfs_resource_fork_map.txt new file mode 100644 index 00000000..62a27454 --- /dev/null +++ b/python/web/genisoimage_hfs_resource_fork_map.txt @@ -0,0 +1,322 @@ +# This file is used by the genisoimage command-line tool when generating an iso of type HFS +# to derive the CREATOR and TYPE resource fork attributes of each file in the generated image. +# +# genisoimage will look up the file's extension in the 1st column below, and then use the +# 3rd and 4th columns to derive the CREATOR and TYPE. +# +# This file ends with a "catch-all" file extension of ".*" which will be used if the file extension +# was not found in this map. +# +# Note: genisoimage does not support custom CREATOR/TYPE per EACH file in the image, +# so the best alternative to use the "per file extension" approach here. +# +# The five columns below are: file extension, file translation, CREATOR, TYPE and Description. +# Lines starting with the '#' character are comment lines and are ignored. +# +# See more info at the genisoimage Linux man page: https://linux.die.net/man/1/genisoimage +# +# The mapping entries below are derived from +# https://github.com/Netatalk/netatalk/blob/branch-netatalk-2-3/config/AppleVolumes.system +# Few entries, e.g the one for ".img" were modified; few more (e.g. ".dc42") were added. +# +# EXTN XLate CREATOR TYPE Application - Description (mime type) +.1st Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme (application/text)" +.669 Raw 'SNPL' '6669' "PlayerPro - 669 MOD Music" +.8med Raw 'SCPL' 'STrk' "SoundApp - Amiga OctaMed music" +.8svx Raw 'SCPL' '8SVX' "SoundApp - Amiga 8-bit sound" +.aif Raw 'SCPL' 'AIFF' "SoundApp - AIFF Sound (audio/x-aiff)" +.aifc Raw 'SCPL' 'AIFC' "SoundApp - AIFF Sound Compressed (audio/x-aiff)" +.aiff Raw 'SCPL' 'AIFF' "SoundApp - AIFF Sound (audio/x-aiff)" +.al Raw 'SCPL' 'ALAW' "SoundApp - ALAW Sound" +.ani Raw 'GKON' 'ANIi' "GraphicConverter - Animated NeoChrome" +.apd Ascii 'ALD3' 'TEXT' "Aldus PageMaker - Aldus Printer Description" +.arc Raw 'SITx' 'mArc' "ArcMac - PC ARChive" +.arj Raw 'DArj' 'BINA' "DeArj - ARJ Archive" +.arr Raw 'GKON' 'ARR ' "GraphicConverter - Amber ARR image" +.art Raw 'GKON' 'ART ' "GraphicConverter - First Publisher" +.ascii Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.asc Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.asf Ascii 'Ms01' 'ASF_' "Netshow Player (video/x-ms-asf)" +.asm Ascii 'ttxt' 'TEXT' "SimpleText - Assembly Source" +.asx Ascii 'Ms01' 'ASX_' "Netshow Player (video/x-ms-asf)" +.a Ascii 'ttxt' 'TEXT' "SimpleText - Assembly Source" +.au Raw 'TVOD' 'ULAW' "QuickTime Player - Sun Sound (audio/basic)" +.avi Raw 'TVOD' 'VfW ' "QuickTime Player - AVI Movie (video/avi)" +.bar Raw 'S691' 'BARF' "SunTar - Unix BAR Archive" +.bas Ascii 'ttxt' 'TEXT' "SimpleText - BASIC Source" +.bat Ascii 'ttxt' 'TEXT' "SimpleText - MS-DOS Batch File" +.bga Raw 'ogle' 'BMPp' "PictureViewer - OS/2 Bitmap" +.bib Ascii 'ttxt' 'TEXT' "SimpleText - BibTex Bibliography" +.binary Raw 'hDmp' 'BINA' "HexEdit - Untyped Binary Data (application/octet-stream)" +.bin Raw 'SITx' 'SIT!' "StuffIt Expander - MacBinary (application/macbinary)" +.bld Raw 'GKON' 'BLD ' "GraphicConverter - BLD" +.bmp Raw 'ogle' 'BMPp' "PictureViewer - Windows Bitmap" +.boo Ascii 'ttxt' 'TEXT' "SimpleText - BOO encoded" +.bst Ascii 'ttxt' 'TEXT' "SimpleText - BibTex Style" +.bw Raw 'GKON' 'SGI ' "GraphicConverter - SGI Image" +.cel Raw 'GKON' 'CEL ' "GraphicConverter - KISS CEL" +.cgm Raw 'GKON' 'CGMm' "GraphicConverter - Computer Graphics Meta" +.class Raw 'CWIE' 'Clss' "CodeWarrior - Java Class File" +.clp Raw 'GKON' 'CLPp' "GraphicConverter - Windows Clipboard" +.cmd Ascii 'ttxt' 'TEXT' "SimpleText - OS/2 Batch File" +.com Raw 'SWIN' 'PCFA' "SoftWindows - MS-DOS Executable" +.cpp Ascii 'CWIE' 'TEXT' "CodeWarrior - C++ Source" +.cp Ascii 'CWIE' 'TEXT' "CodeWarrior - C++ Source" +.cpt Raw 'SITx' 'PACT' "StuffIt Expander - Compact Pro Archive" +.csv Ascii 'XCEL' 'TEXT' "Excel - Comma Separated Vars" +.ct Raw 'GKON' '..CT' "GraphicConverter - Scitex-CT" +.c Ascii 'CWIE' 'TEXT' "CodeWarrior - C Source" +.cur Raw 'GKON' 'CUR ' "GraphicConverter - Windows Cursor" +.cut Raw 'GKON' 'Halo' "GraphicConverter - Dr Halo Image" +.cvs Raw 'DAD2' 'drw2' "Canvas - Canvas Drawing" +.cwj Raw 'cwkj' 'CWSS' "ClarisWorks 4.0 - ClarisWorks Document" +.dat Raw 'GKON' 'TCLl' "GraphicConverter - TCL image" +.dbf Raw 'FOX+' 'COMP' "FoxBase+ - DBase Document" +.dc42 Raw 'dCpy' 'dImg' "DiskCopy - Floppy Disk image" +.dcx Raw 'GKON' 'DCXx' "GraphicConverter - Some PCX Images" +.dif Ascii 'XCEL' 'TEXT' "Excel - Data Interchange Format" +.diz Ascii 'R*Ch' 'TEXT' "BBEdit - BBS Descriptive Text" +.dl Raw 'AnVw' 'DL ' "MacAnim Viewer - DL Animation" +.dll Raw 'SWIN' 'PCFL' "SoftWindows - Windows DLL" +.doc Raw 'MSWD' 'WDBN' "Microsoft Word - Word Document (application/msword)" +.dot Raw 'MSWD' 'sDBN' "Microsoft Word - Word for Windows Template" +.dsk Raw 'dCpy' 'dImg' "Disk Copy - Apple DiskCopy Image" +.dvi Raw 'xdvi' 'ODVI' "xdvi - TeX DVI Document (application/x-dvi)" +.dwt Ascii 'DmWr' 'TEXT' "Dreamweaver - Dreamweaver Template" +.dxf Ascii 'SWVL' 'TEXT' "Swivel Pro - AutoCAD 3D Data" +.eps Raw 'vgrd' 'EPSF' "LaserWriter 8 - Postscript (application/postscript)" +.epsf Raw 'vgrd' 'EPSF' "LaserWriter 8 - Postscript (application/postscript)" +.etx Ascii 'ezVu' 'TEXT' "Easy View - SEText (text/x-setext)" +.evy Raw 'ENVY' 'EVYD' "Envoy - Envoy Document" +.exe Raw 'SWIN' 'PCFA' "SoftWindows - MS-DOS Executable" +.faq Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/x-usenet-faq)" +.fit Raw 'GKON' 'FITS' "GraphicConverter - Flexible Image Transport (image/x-fits)" +.fla Raw 'MFL2' 'SPA ' "Macromedia Flash - Flash source" +.flc Raw 'TVOD' 'FLI ' "QuickTime Player - FLIC Animation" +.fli Raw 'TVOD' 'FLI ' "QuickTime Player - FLI Animation" +.fm Raw 'FMPR' 'FMPR' "FileMaker Pro - FileMaker Pro Database" +.for Ascii 'MPS ' 'TEXT' "MPW Shell - Fortran Source" +.fts Raw 'GKON' 'FITS' "GraphicConverter - Flexible Image Transport" +.gem Raw 'GKON' 'GEM-' "GraphicConverter - GEM Metafile" +.gif Raw 'ogle' 'GIFf' "PictureViewer - GIF Picture (image/gif)" +.gl Raw 'AnVw' 'GL ' "MacAnim Viewer - GL Animation" +.grp Raw 'GKON' 'GRPp' "GraphicConverter - GRP Image" +.gz Raw 'SITx' 'SIT!' "StuffIt Expander - Gnu ZIP Archive (application/x-gzip)" +.hcom Raw 'SCPL' 'FSSD' "SoundApp - SoundEdit Sound ex SOX" +.hpgl Raw 'GKON' 'HPGL' "GraphicConverter - HP GL/2" +.hpp Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File" +.hp Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File" +.hqx Ascii 'SITx' 'TEXT' "StuffIt Expander - BinHex (application/mac-binhex40)" +.hr Raw 'GKON' 'TR80' "GraphicConverter - TSR-80 HR +.h Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File" +.html Ascii 'MOSS' 'TEXT' "Netscape Communicator - HyperText (text/html)" +.htm Ascii 'MOSS' 'TEXT' "Netscape Communicator - HyperText (text/html)" +.i3 Ascii 'R*ch' 'TEXT' "BBEdit - Modula 3 Interface" +.ic1 Raw 'GKON' 'IMAG' "GraphicConverter - Atari Image" +.ic2 Raw 'GKON' 'IMAG' "GraphicConverter - Atari Image" +.ic3 Raw 'GKON' 'IMAG' "GraphicConverter - Atari Image" +.icn Raw 'GKON' 'ICO ' "GraphicConverter - Windows Icon" +.ico Raw 'GKON' 'ICO ' "GraphicConverter - Windows Icon" +.ief Raw 'GKON' 'IEF ' "GraphicConverter - IEF image (image/ief)" +.iff Raw 'GKON' 'ILBM' "GraphicConverter - Amiga IFF Image" +.ilbm Raw 'GKON' 'ILBM' "GraphicConverter - Amiga ILBM Image" +.image Raw 'dCpy' 'dImg' "DiskCopy - Apple DiskCopy Image" +.img Raw 'dCpy' 'dImg' "DiskCopy - Apple DiskCopy Image" +.ini Ascii 'ttxt' 'TEXT' "SimpleText - Windows INI File" +.iso Raw 'ddsk' 'rodh' "Disk Copy - Apple ISO Image" +.iss Raw 'GKON' 'ISS ' "GraphicConverter - ISS" +.java Ascii 'CWIE' 'TEXT' "CodeWarrior - Java Source File" +.jfif Raw 'ogle' 'JFIF' "PictureViewer - JFIF Image" +.jif Raw 'GKON' 'JIFf' "GraphicConverter - JIF99a" +.jpeg Raw 'ogle' 'JPEG' "PictureViewer - JPEG Picture (image/jpeg)" +.jpe Raw 'ogle' 'JPEG' "PictureViewer - JPEG Picture (image/jpeg)" +.jpg Raw 'ogle' 'JPEG' "PictureViewer - JPEG Picture (image/jpeg)" +.latex Ascii 'OTEX' 'TEXT' "OzTex - Latex (application/x-latex)" +.lbm Raw 'GKON' 'ILBM' "GraphicConverter - Amiga IFF Image" +.lha Raw 'SITx' 'LHA ' "StuffIt Expander - LHArc Archive" +.lwf Raw 'GKON' 'lwfF' "GraphicConverter - LuraWave(LWF)" +.lzh Raw 'SITx' 'LHA ' "StuffIt Expander - LHArc Archive" +.m1a Raw 'TVOD' 'MPEG' "MoviePlayer - MPEG-1 audiostream (audio/x-mpeg)" +.m1s Raw 'TVOD' 'MPEG' "MoviePlayer - MPEG-1 systemstream" +.m1v Raw 'TVOD' 'M1V ' "MoviePlayer - MPEG-1 IPB videostream (video/mpeg)" +.m2 Ascii 'R*ch' 'TEXT' "BBEdit - Modula 2 Source" +.m2v Raw 'MPG2' 'MPG2' "MPEG2decoder - MPEG-2 IPB videostream" +.m3 Ascii 'R*ch' 'TEXT' "BBEdit - Modula 3 Source" +.mac Raw 'ogle' 'PICT' "PictureViewer - PICT Picture (image/x-pict)" +.mak Ascii 'R*ch' 'TEXT' "BBEdit - Makefile" +.mbm Raw 'GKON' 'MBM ' "GraphicConverter - PSION 5(MBM)" +.mcw Raw 'MSWD' 'WDBN' "Microsoft Word - Mac Word Document" +.med Raw 'SCPL' 'STrk' "SoundApp - Amiga MED Sound" +.me Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme" +.mf Ascii '*MF*' 'TEXT' "Metafont - Metafont" +.midi Raw 'TVOD' 'Midi' "MoviePlayer - MIDI Music" +.mid Raw 'TVOD' 'Midi' "MoviePlayer - MIDI Music" +.mif Ascii 'Fram' 'TEXT' "FrameMaker - FrameMaker MIF (application/x-framemaker)" +.mime Ascii 'SITx' 'TEXT' "StuffIt Expander - MIME Message (message/rfc822)" +.ml Ascii 'R*ch' 'TEXT' "BBEdit - ML Source" +.mod Raw 'SCPL' 'STrk' "SoundApp - MOD Music" +.mol Ascii 'RSML' 'TEXT' "RasMac - MDL Molfile" +.moov Raw 'TVOD' 'MooV' "MoviePlayer - QuickTime Movie (video/quicktime)" +.mov Raw 'TVOD' 'MooV' "MoviePlayer - QuickTime Movie (video/quicktime)" +.mp2 Raw 'TVOD' 'MPEG' "MoviePlayer - MPEG-1 audiostream (audio/x-mpeg)" +.mp3 Raw 'TVOD' 'MPG3' "MoviePlayer - MPEG-3 audiostream (audio/x-mpeg)" +.mpa Raw 'TVOD' 'MPEG' "MoviePlayer - MPEG-1 audiostream (audio/x-mpeg)" +.mpeg Raw 'TVOD' 'MPEG' "MoviePlayer - MPEG Movie of some sort (video/mpeg)" +.mpe Raw 'TVOD' 'MPEG' "MoviePlayer - MPEG Movie of some sort (video/mpeg)" +.mpg Raw 'TVOD' 'MPEG' "MoviePlayer - MPEG Movie of some sort (video/mpeg)" +.msp Raw 'GKON' 'MSPp' "GraphicConverter - Microsoft Paint" +.mtm Raw 'SNPL' 'MTM ' "PlayerPro - MultiMOD Music" +.mwii Raw 'MWII' 'MW2D' "MacWrite II - MacWrite Document (application/macwriteii)" +.mw Raw 'MWII' 'MW2D' "MacWrite II - MacWrite Document (application/macwriteii)" +.neo Raw 'GKON' 'NeoC' "GraphicConverter - Atari NeoChrome" +.nfo Ascii 'ttxt' 'TEXT' "SimpleText - Info Text (application/text)" +.ngg Raw 'GKON' 'NGGC' "GraphicConverter - Mobile Phone (Nokia) Format" +.nol Raw 'GKON' 'NOL ' "GraphicConverter - Phone (Nokia) Format" +.nst Raw 'SCPL' 'STrk' "SoundApp - MOD Music" +.obj Raw 'SWIN' 'PCFL' "SoftWindows - Object (DOS/Windows)" +.oda Raw 'ODA ' 'ODIF' "MacODA XTND Translator - ODA Document (application/oda)" +.okt Raw 'SCPL' 'OKTA' "SoundApp - Oktalyser MOD Music" +.out Raw 'hDmp' 'BINA' "HexEdit - Output File" +.ovl Raw 'SWIN' 'PCFL' "SoftWindows - Overlay (DOS/Windows)" +.pac Raw 'GKON' 'STAD' "GraphicConverter - Atari STAD Image" +.pal Raw '8BIM' '8BCT' "GraphicConverter - Color Table" +.pas Ascii 'CWIE' 'TEXT' "CodeWarrior - Pascal Source" +.pbm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Bitmap (image/x-portable-bitmap)" +.pc1 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pc2 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pc3 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pcs Raw 'GKON' 'PICS' "GraphicConverter - Animated PICTs" +.pct Raw 'ogle' 'PICT' "PictureViewer - PICT Picture (image/x-pict)" +.pcx Raw 'GKON' 'PCXx' "GraphicConverter - PC PaintBrush" +.pdb Ascii 'RSML' 'TEXT' "RasMac - Brookhaven PDB file" +.pdf Raw 'CARO' 'PDF ' "Acrobat Reader - Portable Document Format (application/pdf)" +.pdx Ascii 'ALD5' 'TEXT' "PageMaker - Printer Description" +.pf Raw 'SITx' 'CSIT' "StuffIt Expander - Private File" +.pgc Raw 'GKON' 'PGCF' "GraphicConverter - PGC/PGF Atari Portfolio PCG" +.pgm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Graymap (image/x-portable-graymap)" +.pi1 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pi2 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pi3 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pic Raw 'ogle' 'PICT' "PictureViewer - PICT Picture (image/x-pict)" +.pics Raw 'GKON' 'PICS' "GraphicConverter - PICS-PICT Sequence" +.pict Raw 'ogle' 'PICT' "PictureViewer - PICT Picture (image/x-macpict)" +.pit Raw 'SITx' 'PIT ' "StuffIt Expander - PackIt Archive" +.pkg Raw 'SITx' 'HBSF' "StuffIt Expander - AppleLink Package" +.pl Ascii 'McPL' 'TEXT' "MacPerl - Perl Source" +.plt Raw 'GKON' 'HPGL' "GraphicConverter - HP GL/2" +.pm3 Raw 'ALD3' 'ALB3' "PageMaker - PageMaker 3 Document" +.pm4 Raw 'ALD4' 'ALB4' "PageMaker - PageMaker 4 Document" +.pm5 Raw 'ALD5' 'ALB5' "PageMaker - PageMaker 5 Document" +.pm Raw 'GKON' 'PMpm' "GraphicConverter - Bitmap from xv" +.png Raw 'ogle' 'PNG ' "PictureViewer - Portable Network Graphic" +.pntg Raw 'ogle' 'PNTG' "PictureViewer - Macintosh Painting" +.ppd Ascii 'ALD5' 'TEXT' "PageMaker - Printer Description" +.ppm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Pixmap (image/x-portable-pixmap)" +.prn Ascii 'R*ch' 'TEXT' "BBEdit - Printer Output File" +.psd Raw '8BIM' '8BPS' "Photoshop - PhotoShop Document" +.ps Ascii 'vgrd' 'TEXT' "LaserWriter 8 - PostScript (application/postscript)" +.pt4 Raw 'ALD4' 'ALT4' "PageMaker - PageMaker 4 Template" +.pt5 Raw 'ALD5' 'ALT5' "PageMaker - PageMaker 5 Template" +.p Ascii 'CWIE' 'TEXT' "CodeWarrior - Pascal Source" +.pxr Raw '8BIM' 'PXR ' "Photoshop - Pixar Image" +.qdv Raw 'GKON' 'QDVf' "GraphicConverter - QDV image" +.qt Raw 'TVOD' 'MooV' "MoviePlayer - QuickTime Movie (video/quicktime)" +.qxd Raw 'XPR3' 'XDOC' "QuarkXpress - QuarkXpress Document" +.qxt Raw 'XPR3' 'XTMP' "QuarkXpress - QuarkXpress Template" +.raw Raw 'ddsk' 'rodh' "Disk Copy - Apple raw disk Image" +.readme Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme (application/text)" +.rgba Raw 'GKON' 'SGI ' "GraphicConverter - SGI Image (image/x-rgb)" +.rgb Raw 'GKON' 'SGI ' "GraphicConverter - SGI Image (image/x-rgb)" +.rib Ascii 'RINI' 'TEXT' "Renderman - Renderman 3D Data" +.rif Raw 'GKON' 'RIFF' "GraphicConverter - RIFF Graphic" +.rle Raw 'GKON' 'RLE ' "GraphicConverter - RLE image" +.rme Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme" +.rpl Raw 'REP!' 'FRL!' "Replica - Replica Document" +.rsc Raw 'RSED' 'rsrc' "ResEdit - Resource File" +.rsrc Raw 'RSED' 'rsrc' "ResEdit - Resource File" +.rtf Ascii 'MSWD' 'TEXT' "Microsoft Word - Rich Text Format (application/rtf)" +.rtx Ascii 'R*ch' 'TEXT' "BBEdit - Rich Text (text/richtext)" +.s3m Raw 'SNPL' 'S3M ' "PlayerPro - ScreamTracker 3 MOD" +.scc Raw 'GKON' 'MSX ' "GraphicConverter - MSX pitcure" +.scg Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.sci Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.scp Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.scr Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.scu Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.sea Raw '????' 'APPL' "Self Extracting Archive - Self-Extracting Archive" +.sf Raw 'SDHK' 'IRCM' "SoundHack - IRCAM Sound" +.sgi Raw 'ogle' 'SGI ' "PictureViewer - SGI Image" +.shar Ascii 'UnSh' 'TEXT' "UnShar - Unix Shell Archive (application/x-shar)" +.sha Ascii 'UnSh' 'TEXT' "UnShar - Unix Shell Archive (application/x-shar)" +.shp Raw 'GKON' 'SHPp' "GraphicConverter - Printmaster Icon Library" +.sithqx Ascii 'SITx' 'TEXT' "StuffIt Expander - BinHexed StuffIt Archive (application/mac-binhex40)" +.sit Raw 'SITx' 'SIT!' "StuffIt Expander - StuffIt 1.5.1 Archive (application/x-stuffit)" +.six Raw 'GKON' 'SIXE' "GraphicConverter - SIXEL image" +.slk Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet" +.snd Raw 'SCPL' 'BINA' "SoundApp - Sound of various types" +.spc Raw 'GKON' 'Spec' "GraphicConverter - Atari Spectrum 512" +.sr Raw 'GKON' 'SUNn' "GraphicConverter - Sun Raster Image" +.sty Ascii '*TEX' 'TEXT' "Textures - TeX Style" +.sun Raw 'GKON' 'SUNn' "GraphicConverter - Sun Raster Image" +.sup Raw 'GKON' 'SCRN' "GraphicConverter - StartupScreen" +.svx Raw 'SCPL' '8SVX' "SoundApp - Amiga IFF Sound" +.swf Raw 'SWF2' 'SWFL' "Macromedia Flash - Flash" +.syk Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet" +.sylk Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet" +.targa Raw 'GKON' 'TPIC' "GraphicConverter - Truevision Image" +.tar Raw 'SITx' 'TARF' "StuffIt Expander - Unix Tape ARchive (application/x-tar)" +.taz Raw 'SITx' 'ZIVU' "StuffIt Expander - Compressed Tape ARchive (application/x-compress)" +.texinfo Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document (application/x-texinfo)" +.texi Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document" +.tex Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document (application/x-tex)" +.text Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.tga Raw 'GKON' 'TPIC' "GraphicConverter - Truevision Image" +.tgz Raw 'SITx' 'Gzip' "StuffIt Expander - Gnu ZIPed Tape ARchive (application/x-gzip)" +.tiff Raw 'ogle' 'TIFF' "PictureViewer - TIFF Picture (image/tiff)" +.tif Raw 'ogle' 'TIFF' "PictureViewer - TIFF Picture (image/tiff)" +.tny Raw 'GKON' 'TINY' "GraphicConverter - Atari TINY Bitmap" +.tsv Ascii 'XCEL' 'TEXT' "Excel - Tab Separated Values (text/tab-separated-values)" +.tx8 Ascii 'ttxt' 'TEXT' "SimpleText - 8-bit ASCII Text" +.txt Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.ul Raw 'TVOD' 'ULAW' "MoviePlayer - Mu-Law Sound (audio/basic)" +.url Raw 'Arch' 'AURL' "Anarchie - URL Bookmark (message/external-body)" +.uue Ascii 'SITx' 'TEXT' "StuffIt Expander - UUEncode" +.uu Ascii 'SITx' 'TEXT' "StuffIt Expander - UUEncode" +.vff Raw 'GKON' 'VFFf' "GraphicConverter - DESR VFF Greyscale Image" +.vga Raw 'ogle' 'BMPp' "PictureViewer - OS/2 Bitmap" +.voc Raw 'SCPL' 'VOC ' "SoundApp - VOC Sound" +.vpb Raw 'GKON' 'VPB ' "GraphicConverter - VPB QUANTEL" +.w51 Raw 'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.1 Doc (application/wordperfect5.1)" +.wav Raw 'TVOD' 'WAVE' "MoviePlayer - Windows WAV Sound (audio/x-wav)" +.wbmp Raw 'GKON' 'WBMP' "GraphicConverter - WBMP" +.wk1 Raw 'XCEL' 'XLBN' "Excel - Lotus Spreadsheet r2.1" +.wks Raw 'XCEL' 'XLBN' "Excel - Lotus Spreadsheet r1.x" +.wmf Raw 'GKON' 'WMF ' "GraphicConverter - Windows Metafile" +.wp4 Raw 'WPC2' '.WP4' "WordPerfect - WordPerfect PC 4.2 Doc" +.wp5 Raw 'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.x Doc (application/wordperfect5.1)" +.wp6 Raw 'WPC2' '.WP6' "WordPerfect - WordPerfect PC 6.x Doc" +.wpg Raw 'GKON' 'WPGf' "GraphicConverter - WordPerfect Graphic" +.wpm Raw 'WPC2' 'WPD1' "WordPerfect - WordPerfect Mac" +.wp Raw 'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.x Doc (application/wordperfect5.1)" +.wri Raw 'MSWD' 'WDBN' "Microsoft Word - MS Write/Windows" +.wve Raw 'SCPL' 'BINA' "SoundApp - PSION sound" +.x10 Raw 'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)" +.x11 Raw 'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)" +.xbm Raw 'GKON' 'XBM ' "GraphicConverter - X-Windows Bitmap (image/x-xbm)" +.x-face Raw 'GKON' 'TEXT' "GraphicConverter - X-Face" +.xlc Raw 'XCEL' 'XLC ' "Excel - Excel Chart" +.xlm Raw 'XCEL' 'XLM ' "Excel - Excel Macro" +.xls Raw 'XCEL' 'XLS ' "Excel - Excel Spreadsheet" +.xlw Raw 'XCEL' 'XLW ' "Excel - Excel Workspace" +.xl Raw 'XCEL' 'XLS ' "Excel - Excel Spreadsheet" +.xm Raw 'SNPL' 'XM ' "PlayerPro - FastTracker MOD Music" +.xpm Raw 'GKON' 'XPM ' "GraphicConverter - X-Windows Pixmap (image/x-xpm)" +.xpm Raw 'GKON' 'XPM ' "GraphicConverter - X-Windows Pixmap (image/x-xpixmap)" +.xwd Raw 'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)" +.zip Raw 'SITx' 'ZIP ' "StuffIt Expander - PC ZIP Archive (application/zip)" +.zoo Raw 'Booz' 'Zoo ' "MacBooz - Zoo Archive" +.z Raw 'SITx' 'ZIVU' "StuffIt Expander - Unix Compress Archive (application/x-compress)" +# +# The default translation for anything not recognized: +# +* Ascii 'ttxt' 'TEXT' "SimpleText - Text file" diff --git a/python/web/src/static/themes/classic/style.css b/python/web/src/static/themes/classic/style.css index d77de45a..de672365 100644 --- a/python/web/src/static/themes/classic/style.css +++ b/python/web/src/static/themes/classic/style.css @@ -58,6 +58,15 @@ div.footer div.theme-change-hint { margin-bottom: 15px; } +div.login-status { + text-align: right; +} + +div.login-status a { + color: white; + text-decoration: underline; +} + div.logged-in { background-color: green; } diff --git a/python/web/src/static/themes/modern/icons/external-link.svg b/python/web/src/static/themes/modern/icons/external-link.svg new file mode 100644 index 00000000..6236df3e --- /dev/null +++ b/python/web/src/static/themes/modern/icons/external-link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python/web/src/static/themes/modern/style.css b/python/web/src/static/themes/modern/style.css index e057da98..4aa05505 100644 --- a/python/web/src/static/themes/modern/style.css +++ b/python/web/src/static/themes/modern/style.css @@ -282,18 +282,6 @@ div.header div.login-form-title { display: none; } -div.header div.authentication-disabled span.separator { - display: none; -} - -div.header div.authentication-disabled span.wiki-help-text { - display: block; -} - -div.header div.authentication-disabled a { - color: #fff; -} - @media (max-width: 900px) { div.header { flex-wrap: wrap; @@ -663,10 +651,11 @@ table#attached-devices td.actions { table#attached-devices td.parameters form { display: flex; + align-items: center; } table#attached-devices td.parameters form label { - display: none; + padding: 0 0.5rem 0 0; } table#attached-devices td.parameters form select { @@ -775,6 +764,11 @@ section#files p { margin-top: 1rem; } +section#files details.subdir { + padding-left: 1rem; + padding-right: 1rem; +} + section#files details.subdir summary.dirname { text-decoration: underline; font-family: monospace; @@ -864,7 +858,7 @@ section#upload a p { /* ------------------------------------------------------------------------------ - Index > Section: Attach peripheral devices + Index > Section: Attach devices ------------------------------------------------------------------------------ */ section#attach-devices table th:last-child, @@ -876,6 +870,10 @@ section#attach-devices form { display: block; } +section#attach-devices table form select.table-dropdown { + width: 16rem; +} + @media (max-width: 900px) { section#attach-devices table tr th:nth-child(2), section#attach-devices table tr td:nth-child(2) { @@ -971,6 +969,10 @@ section#services li.disabled { background: url("icons/cloud-off.svg") no-repeat left center; } +section#services li.extlink { + background: url("icons/external-link.svg") no-repeat left center; +} + /* ------------------------------------------------------------------------------ Drives page diff --git a/python/web/src/templates/admin.html b/python/web/src/templates/admin.html index c28d41a4..b3ec6e05 100644 --- a/python/web/src/templates/admin.html +++ b/python/web/src/templates/admin.html @@ -115,23 +115,25 @@
  • {{ _("If you want to add a service, run the easyinstall.sh script and choose the one to install.") }}
  • {{ _("In order to manage the services in the Web UI, you may install Webmin as well.") }}
  • +
  • {{ _("To browse the modern web, install a vintage web proxy such as Macproxy.", url="https://github.com/PiSCSI/piscsi/wiki/Vintage-Web-Proxy#macproxy") }} +
diff --git a/python/web/src/templates/base.html b/python/web/src/templates/base.html index 0c555f72..5f317a92 100644 --- a/python/web/src/templates/base.html +++ b/python/web/src/templates/base.html @@ -27,37 +27,31 @@
- {% if env["auth_active"] %} + {% if env["logged_in"] or not env["auth_active"] %} + {% else %} - + {% endif %}
diff --git a/python/web/src/templates/index.html b/python/web/src/templates/index.html index 01e4967b..c8f78b01 100644 --- a/python/web/src/templates/index.html +++ b/python/web/src/templates/index.html @@ -24,6 +24,7 @@ +{% if env["cfg_dir_exists"] %}

@@ -54,6 +55,13 @@

+{% else %} + +
+{{ _("Please create the PiSCSI configuration dir to use configurations:")}} {{ CFG_DIR }} +
+ +{% endif %} @@ -82,13 +90,12 @@ {% endif %} @@ -135,13 +149,6 @@
{{ device.device_name }} - {% if "No Media" in device.status %} + {% if "No Media" in device.status %}
+ - - - +
{% else %} {% if device.params %} @@ -120,7 +127,14 @@ {% endif %} {% endfor %} {% elif device.file %} - {{ device.file }} +
+ + {% if device.device_type in REMOVABLE_DEVICE_TYPES and "No Media" not in device.status %} + + + + {% endif %} +
{% endif %} {% endif %}
{% if device.id in scsi_ids["occupied_ids"] %} - {% if device.device_type in REMOVABLE_DEVICE_TYPES and "No Media" not in device.status %} -
- - - -
- {% endif %}
@@ -209,12 +216,8 @@ -{% if not files|length: %} -
- {{ _("The images directory is currently empty.") }} -
-{% else %} - +{% if env["image_dir_exists"] %} +{% if files|length %}
{% for subdir, group in formatted_image_files.items() %} @@ -309,7 +312,6 @@ {% else %} - + + + + + + {% for type in device_types.keys() %} + + + + + + {% endfor %} +
{{ _("Device") }}{{ _("Key") }}{{ _("Actions") }}
+ {% if device_types[type]["name"] == type %} + {% if type in REMOVABLE_DEVICE_TYPES %} +
{{ _("Unknown Removable Disk Drive") }}
+ {% elif type in DISK_DEVICE_TYPES %} +
{{ _("Unknown Fixed Disk Drive") }}
+ {% else %} +
{{ _("Unknown Device") }}
+ {% endif %} + {% else %} +
{{ device_types[type]["name"] }}
+ {% endif %} +
+
{{ type }}
+
+ + + {% for key, value in device_types[type]["params"] | dictsort %} + + {% if value.isnumeric() %} + + {% elif key == "interface" %} + + {% else %} + + {% endif %} + {% endfor %} + {% if type in DISK_DEVICE_TYPES %} + + + + + {% endif %} + + + + + + +

@@ -432,6 +596,69 @@
+
+
+ + {{ _("Create Empty Disk Image") }} + +
    +
  • {{ _("Please refer to wiki documentation to learn more about the supported image file types.", url="https://github.com/PiSCSI/piscsi/wiki/Supported-Device-Types#image-types") }}
  • +
  • {{ _("It is not recommended to use the Lido hard disk driver with the Macintosh Plus.") }}
  • +
+
+ +
+ + + + + + + + + + + +
+
+ +
+

{{ _("Create Disk Image With Properties") }}

+
+ +
+
@@ -507,166 +734,4 @@
-
-
- - {{ _("Create Empty Disk Image") }} - -
    -
  • {{ _("Please refer to wiki documentation to learn more about the supported image file types.", url="https://github.com/PiSCSI/piscsi/wiki/Supported-Device-Types#image-types") }}
  • -
  • {{ _("It is not recommended to use the Lido hard disk driver with the Macintosh Plus.") }}
  • -
-
- -
- - - - - - - - - - - -
-
- -
-

{{ _("Create Disk Image With Properties") }}

-
- -
- -
-
- - {{ _("Attach Peripheral Device") }} - -
    - - {% if bridge_configured %} -
  • {{ _("The piscsi_bridge network bridge is active and ready to be used by an emulated network adapter!") }}
  • - {% else %} -
  • {{ _("Please configure the piscsi_bridge network bridge before attaching an emulated network adapter!") }}
  • - {% endif %} -
  • {{ _("To browse the modern web, install a vintage web proxy such as Macproxy.", url="https://github.com/PiSCSI/piscsi/wiki/Vintage-Web-Proxy#macproxy") }}
  • - -
  • {{ _("Read more about supported device types on the wiki.", url="https://github.com/PiSCSI/piscsi/wiki/Supported-Device-Types") }} -
  • -
-
- - - - - - - {% for type in REMOVABLE_DEVICE_TYPES + PERIPHERAL_DEVICE_TYPES %} - - - - - - {% endfor %} -
{{ _("Device") }}{{ _("Key") }}{{ _("Parameters and Actions") }}
-
{{ device_types[type]["name"] }}
-
-
{{ type }}
-
-
- - {% for key, value in device_types[type]["params"] | dictsort %} - - {% if value.isnumeric() %} - - {% elif key == "interface" %} - - {% else %} - - {% endif %} - {% endfor %} - {% if type in REMOVABLE_DEVICE_TYPES %} - - - {% endif %} - - - - - -
-
-
- -
{% endblock content %} diff --git a/python/web/src/templates/upload.html b/python/web/src/templates/upload.html index 2a3b9b3e..823abfbb 100644 --- a/python/web/src/templates/upload.html +++ b/python/web/src/templates/upload.html @@ -41,8 +41,8 @@ @@ -78,6 +78,7 @@ b: "{{ _("B") }}" } } + Dropzone.discover()