From 1cf635be024332ddc6958ef3dedfe4c6302244c3 Mon Sep 17 00:00:00 2001 From: akuker Date: Sun, 16 Aug 2020 16:20:29 -0500 Subject: [PATCH] Additional changes.... command interface works? --- src/raspberrypi/command_thread.cpp | 109 ++++++++++--------- src/raspberrypi/command_thread.h | 5 +- src/raspberrypi/rascsi.cpp | 17 ++- src/raspberrypi/rascsi_mgr.cpp | 29 +++--- src/raspberrypi/rascsi_mgr.h | 28 ++--- src/raspberrypi/rasctl.cpp | 59 ++++------- src/raspberrypi/rasctl_command.cpp | 162 ++++++++++++++--------------- src/raspberrypi/rasctl_command.h | 13 ++- 8 files changed, 197 insertions(+), 225 deletions(-) diff --git a/src/raspberrypi/command_thread.cpp b/src/raspberrypi/command_thread.cpp index 9d0a4e7..9d9ec6e 100644 --- a/src/raspberrypi/command_thread.cpp +++ b/src/raspberrypi/command_thread.cpp @@ -1,7 +1,26 @@ -#include "os.h" +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Copyright (C) 2014-2020 GIMONS +// Copyright (C) akuker +// +// Licensed under the BSD 3-Clause License. +// See LICENSE file in the project root folder. +// +// [ Command thread ] +// +// This is a background thread that runs, listening for commands on port +// 6868 for commands from the rasctl utility. This also includes the logic +// for handling the initialization commands that are specified at startup. +// +//--------------------------------------------------------------------------- -#include "rasctl_command.h" #include "command_thread.h" + +#include "os.h" +#include "rasctl_command.h" #include "rascsi_mgr.h" #include "sasihd.h" #include "scsihd.h" @@ -11,23 +30,9 @@ #include "scsimo.h" #include "scsi_host_bridge.h" -BOOL Command_Thread::m_running = FALSE; int Command_Thread::m_monsocket = -1; // Monitor Socket pthread_t Command_Thread::m_monthread; // Monitor Thread - -void Command_Thread::Start(){ - m_running = TRUE; -} -void Command_Thread::Stop(){ - m_running = FALSE; -} - -BOOL Command_Thread::IsRunning(){ - return m_running; -} - - //--------------------------------------------------------------------------- // // Initialization @@ -44,7 +49,7 @@ BOOL Command_Thread::Init() m_monsocket = socket(PF_INET, SOCK_STREAM, 0); memset(&server, 0, sizeof(server)); server.sin_family = PF_INET; - server.sin_port = htons(6868); + server.sin_port = htons(Rasctl_Command::PortNumber); server.sin_addr.s_addr = htonl(INADDR_ANY); // allow address reuse @@ -70,6 +75,11 @@ BOOL Command_Thread::Init() return TRUE; } +//--------------------------------------------------------------------------- +// +// Close/Cleanup the command thread +// +//--------------------------------------------------------------------------- void Command_Thread::Close(){ // Close the monitor socket if (m_monsocket >= 0) { @@ -292,15 +302,10 @@ void *Command_Thread::MonThread(void *param) // Set the affinity to a specific processor core FixCpu(2); - // Wait for the execution to start - while (!m_running) { - usleep(1); - } - // Setup the monitor socket to receive commands listen(m_monsocket, 1); - while (1) { + while (Rascsi_Manager::IsRunning()) { // Wait for connection memset(&client, 0, sizeof(client)); len = sizeof(client); @@ -316,16 +321,7 @@ void *Command_Thread::MonThread(void *param) // If we received a command.... if (p) { - // // Remove the newline character - // p[strlen(p) - 1] = 0; - - // // List all of the devices - // if (xstrncasecmp(p, "list", 4) == 0) { - // Rascsi_Manager::GetInstance()->ListDevice(fp); - // goto next; - // } - - new_command = Rasctl_Command::DeSerialize((BYTE*)p,BUFSIZ); + new_command = Rasctl_Command::DeSerialize(p,BUFSIZ); if(new_command != nullptr){ // Execute the command @@ -377,22 +373,20 @@ BOOL Command_Thread::ExecuteCommand(FILE *fp, Rasctl_Command *incoming_command) result = DoDetach(fp,incoming_command); break; default: - printf("UNKNOWN COMMAND RECEIVED\n"); + fprintf(fp, "UNKNOWN COMMAND RECEIVED\n"); } - if(!result){ - fputs("Unknown server error", fp); - } return result; } BOOL Command_Thread::DoShutdown(FILE *fp, Rasctl_Command *incoming_command){ - m_running = FALSE; + fprintf(fp, "Stopping the RaSCSI application\n"); + Rascsi_Manager::Stop(); return TRUE; } BOOL Command_Thread::DoList(FILE *fp, Rasctl_Command *incoming_command){ - Rascsi_Manager::GetInstance()->ListDevice(fp); + Rascsi_Manager::ListDevice(fp); return TRUE; } @@ -405,13 +399,13 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){ case rasctl_dev_sasi_hd: // HDF pUnit = new SASIHD(); break; - case rasctl_dev_scsi_hd: // HDS/HDN/HDI/NHD/HDA + case rasctl_dev_scsi_hd: // HDS/HDI pUnit = new SCSIHD(); break; - case rasctl_dev_scsi_hd_appl: + case rasctl_dev_scsi_hd_appl: // HDA pUnit = new SCSIHD_APPLE(); break; - case rasctl_dev_scsi_hd_nec: + case rasctl_dev_scsi_hd_nec: // HDN/NHD pUnit = new SCSIHD_NEC(); break; case rasctl_dev_mo: @@ -436,15 +430,18 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){ case rasctl_dev_scsi_hd: case rasctl_dev_cd: case rasctl_dev_scsi_hd_appl: - // Set the Path - filepath.SetPath(incoming_command->file); + if((incoming_command->file != nullptr) && (strnlen(incoming_command->file,_MAX_PATH) > 0)){ + // Set the Path + filepath.SetPath(incoming_command->file); - // Open the file path - if (!pUnit->Open(filepath)) { - FPRT(fp, "Error : File open error [%s]\n", incoming_command->file); - delete pUnit; - return FALSE; - } + // Open the file path + if (!pUnit->Open(filepath)) { + FPRT(fp, "Error : File open error [%s]\n", incoming_command->file); + delete pUnit; + return FALSE; + } + + } break; case rasctl_dev_br: case rasctl_dev_invalid: @@ -457,17 +454,17 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){ pUnit->SetCacheWB(FALSE); // Map the controller - return Rascsi_Manager::GetInstance()->AttachDevice(fp, pUnit, incoming_command->id, incoming_command->un); - + return Rascsi_Manager::AttachDevice(fp, pUnit, incoming_command->id, incoming_command->un); } + BOOL Command_Thread::DoDetach(FILE *fp, Rasctl_Command *incoming_command){ - return Rascsi_Manager::GetInstance()->DetachDevice(fp, incoming_command->id, incoming_command->un); + return Rascsi_Manager::DetachDevice(fp, incoming_command->id, incoming_command->un); } BOOL Command_Thread::DoInsert(FILE *fp, Rasctl_Command *incoming_command){ Filepath filepath; - Disk *pUnit = Rascsi_Manager::GetInstance()->GetDevice(fp, incoming_command->id, incoming_command->un); + Disk *pUnit = Rascsi_Manager::GetDevice(fp, incoming_command->id, incoming_command->un); // Does the device exist? @@ -495,7 +492,7 @@ BOOL Command_Thread::DoInsert(FILE *fp, Rasctl_Command *incoming_command){ return TRUE; } BOOL Command_Thread::DoEject(FILE *fp, Rasctl_Command *incoming_command){ - Disk *pUnit = Rascsi_Manager::GetInstance()->GetDevice(fp, incoming_command->id, incoming_command->un); + Disk *pUnit = Rascsi_Manager::GetDevice(fp, incoming_command->id, incoming_command->un); // Does the device exist? if (pUnit == nullptr) { @@ -515,7 +512,7 @@ BOOL Command_Thread::DoEject(FILE *fp, Rasctl_Command *incoming_command){ BOOL Command_Thread::DoProtect(FILE *fp, Rasctl_Command *incoming_command){ - Disk *pUnit = Rascsi_Manager::GetInstance()->GetDevice(fp, incoming_command->id, incoming_command->un); + Disk *pUnit = Rascsi_Manager::GetDevice(fp, incoming_command->id, incoming_command->un); // Does the device exist? if (pUnit == nullptr) { diff --git a/src/raspberrypi/command_thread.h b/src/raspberrypi/command_thread.h index 3887640..75b39a2 100644 --- a/src/raspberrypi/command_thread.h +++ b/src/raspberrypi/command_thread.h @@ -26,9 +26,6 @@ class Command_Thread{ public: static BOOL Init(); - static void Start(); - static void Stop(); - static BOOL IsRunning(); static void Close(); static void KillHandler(); static BOOL ParseArgument(int argc, char* argv[]); @@ -40,7 +37,7 @@ class Command_Thread{ private: static int m_monsocket; // Monitor Socket static pthread_t m_monthread; // Monitor Thread - static BOOL m_running; + static uint16_t m_monitor_port_num; // Port number to listen for commands static BOOL HasSuffix(const char* string, const char* suffix); static BOOL DoShutdown(FILE *fp, Rasctl_Command *incoming_command); diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index d8cc089..52c7663 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -56,7 +56,6 @@ FATFS fatfs; // FatFS #else #endif // BAREMETAL -Rascsi_Manager *mgr; #ifndef CONNECT_DESC #define CONNECT_DESC "UNKNOWN" @@ -71,7 +70,7 @@ Rascsi_Manager *mgr; void KillHandler(int sig) { // Stop instruction - Command_Thread::Stop(); + Rascsi_Manager::Stop(); } #endif // BAREMETAL @@ -127,12 +126,11 @@ void Banner(int argc, char* argv[]) //--------------------------------------------------------------------------- BOOL Init() { - if(!Command_Thread::Init()){ + if(!Rascsi_Manager::Init()){ return FALSE; } - mgr = Rascsi_Manager::GetInstance(); - if(!mgr->Init()){ + if(!Command_Thread::Init()){ return FALSE; } @@ -157,7 +155,7 @@ BOOL Init() //--------------------------------------------------------------------------- void Cleanup() { - mgr->Close(); + Rascsi_Manager::Close(); #ifndef BAREMETAL Command_Thread::Close(); @@ -223,12 +221,9 @@ int main(int argc, char* argv[]) #endif // USE_SEL_EVENT_ENABLE #endif // BAREMETAL - // Start execution - Command_Thread::Start(); - // Main Loop - while (Command_Thread::IsRunning()) { - mgr->Step(); + while (Rascsi_Manager::IsRunning()) { + Rascsi_Manager::Step(); } #ifdef BAREMETAL err_exit: diff --git a/src/raspberrypi/rascsi_mgr.cpp b/src/raspberrypi/rascsi_mgr.cpp index 8d011ec..1a1ce78 100644 --- a/src/raspberrypi/rascsi_mgr.cpp +++ b/src/raspberrypi/rascsi_mgr.cpp @@ -3,9 +3,6 @@ #include "sasidev_ctrl.h" #include "scsidev_ctrl.h" -Rascsi_Manager *Rascsi_Manager::m_instance = (Rascsi_Manager*)nullptr; - - SASIDEV *Rascsi_Manager::m_ctrl[CtrlMax]; // Controller Disk *Rascsi_Manager::m_disk[CtrlMax * UnitNum]; // Disk GPIOBUS *Rascsi_Manager::m_bus; @@ -17,13 +14,7 @@ DWORD Rascsi_Manager::m_now = 0; BOOL Rascsi_Manager::m_active = FALSE; BOOL Rascsi_Manager::m_running = FALSE; std::timed_mutex Rascsi_Manager::m_locked; - -Rascsi_Manager* Rascsi_Manager::GetInstance(){ - if(m_instance != nullptr){ - m_instance = new Rascsi_Manager(); - } - return m_instance; -} +BOOL Rascsi_Manager::m_initialized = FALSE; BOOL Rascsi_Manager::AttachDevice(FILE *fp, Disk *disk, int id, int unit_num){ BOOL result; @@ -54,7 +45,7 @@ BOOL Rascsi_Manager::AttachDevicePrivate(FILE *fp, Disk *disk, int id, int unit_ // Check if something already exists at that SCSI ID / Unit Number if (m_disk[unitno]) { - DetachDevice(fp,id,unit_num); + DetachDevicePrivate(fp,id,unit_num); } // Add the new unit @@ -260,12 +251,11 @@ void Rascsi_Manager::Close(){ BOOL Rascsi_Manager::Init(){ - if(m_instance != nullptr){ + if(m_initialized != FALSE){ printf("Can not initialize Rascsi_Manager twice!!!\n"); return FALSE; } - - m_instance = new Rascsi_Manager(); + m_initialized = TRUE; // GPIOBUS creation m_bus = new GPIOBUS(); @@ -288,10 +278,11 @@ BOOL Rascsi_Manager::Init(){ m_disk[i] = NULL; } - // Reset Reset(); + m_running = TRUE; + return TRUE; } @@ -405,3 +396,11 @@ BOOL Rascsi_Manager::Step() return TRUE; } + + +void Rascsi_Manager::Stop(){ + m_running = FALSE; +} +BOOL Rascsi_Manager::IsRunning(){ + return (m_running == TRUE); +} \ No newline at end of file diff --git a/src/raspberrypi/rascsi_mgr.h b/src/raspberrypi/rascsi_mgr.h index 2140acb..06bac9d 100644 --- a/src/raspberrypi/rascsi_mgr.h +++ b/src/raspberrypi/rascsi_mgr.h @@ -37,18 +37,20 @@ enum Rascsi_Device_Mode_e{ class Rascsi_Manager{ public: static Rascsi_Manager* GetInstance(); - void MapControler(FILE *fp, Disk **map); + static void MapControler(FILE *fp, Disk **map); + static void Stop(); + static BOOL IsRunning(); - BOOL AttachDevice(FILE *fp, Disk *disk, int id, int ui); - BOOL DetachDevice(FILE *fp, int id, int ui); - Disk* GetDevice(FILE *fp, int id, int ui); - void ListDevice(FILE *fp); - BOOL Init(); - void Close(); - void Reset(); - BOOL Step(); - Rascsi_Device_Mode_e GetCurrentDeviceMode(); + static BOOL AttachDevice(FILE *fp, Disk *disk, int id, int ui); + static BOOL DetachDevice(FILE *fp, int id, int ui); + static Disk* GetDevice(FILE *fp, int id, int ui); + static void ListDevice(FILE *fp); + static BOOL Init(); + static void Close(); + static void Reset(); + static BOOL Step(); + static Rascsi_Device_Mode_e GetCurrentDeviceMode(); static const int CtrlMax = 8; // Maximum number of SCSI controllers static const int UnitNum=2; // Number of units around controller @@ -68,12 +70,12 @@ class Rascsi_Manager{ static BUS::phase_t m_phase; static BYTE m_data; static DWORD m_now; - static Rascsi_Manager *m_instance; static BOOL m_active; static BOOL m_running; + static BOOL m_initialized; - BOOL AttachDevicePrivate(FILE *fp, Disk *disk, int id, int ui); - BOOL DetachDevicePrivate(FILE *fp, int id, int ui); + static BOOL AttachDevicePrivate(FILE *fp, Disk *disk, int id, int ui); + static BOOL DetachDevicePrivate(FILE *fp, int id, int ui); // Any PUBLIC functions should lock this before accessing the m_ctrl // m_disk or m_bus data structures. The Public functions could be diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp index 7fd4550..835a340 100644 --- a/src/raspberrypi/rasctl.cpp +++ b/src/raspberrypi/rasctl.cpp @@ -17,7 +17,7 @@ // Send Command // //--------------------------------------------------------------------------- -BOOL SendCommand(BYTE *buf) +BOOL SendCommand(char *buf) { int fd; struct sockaddr_in server; @@ -27,7 +27,7 @@ BOOL SendCommand(BYTE *buf) fd = socket(PF_INET, SOCK_STREAM, 0); memset(&server, 0, sizeof(server)); server.sin_family = PF_INET; - server.sin_port = htons(6868); + server.sin_port = htons(Rasctl_Command::PortNumber); server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // Connect @@ -68,16 +68,14 @@ int main(int argc, char* argv[]) int id; int un; char *file; - int len; - char *ext; - BYTE buf[BUFSIZ]; + char buf[BUFSIZ]; rasctl_command cmd = rasctl_cmd_invalid; rasctl_dev_type type = rasctl_dev_invalid; Rasctl_Command *rasctl_cmd; id = -1; un = 0; - file = NULL; + file = nullptr; // Display help if (argc < 2) { @@ -102,11 +100,11 @@ int main(int argc, char* argv[]) while ((opt = getopt(argc, argv, "i:u:c:t:f:l")) != -1) { switch (opt) { case 'i': - id = optarg[0] - '0'; + id = atoi((char*)optarg); break; case 'u': - un = optarg[0] - '0'; + un = atoi((char*)optarg); break; case 'c': @@ -175,13 +173,13 @@ int main(int argc, char* argv[]) // Check the ID number if (id < 0 || id > 7) { - fprintf(stderr, "Error : Invalid ID\n"); + fprintf(stderr, "Error : Invalid SCSI/SASI ID number %d\n", id); exit(EINVAL); } // Check the unit number if (un < 0 || un > 1) { - fprintf(stderr, "Error : Invalid UNIT\n"); + fprintf(stderr, "Error : Invalid UNIT number %d\n", un); exit(EINVAL); } @@ -190,33 +188,10 @@ int main(int argc, char* argv[]) cmd = rasctl_cmd_attach; // Default command is ATTATCH } - // Type Check - if (cmd == rasctl_cmd_attach && type == rasctl_dev_invalid) { - - // Try to determine the file type from the extension - len = file ? strlen(file) : 0; - if (len > 4 && file[len - 4] == '.') { - ext = &file[len - 3]; - if (xstrcasecmp(ext, "hdf") == 0){ - type = rasctl_dev_sasi_hd; - }else if(xstrcasecmp(ext, "hds") == 0 || - xstrcasecmp(ext, "hdi") == 0 || - xstrcasecmp(ext, "nhd") == 0){ - type = rasctl_dev_scsi_hd; - }else if(xstrcasecmp(ext, "hdn") == 0) { - // NEC HD(SASI/SCSI) - type = rasctl_dev_scsi_hd_appl; - }else if(xstrcasecmp(ext, "hda") == 0) { - // Apple HD(SASI/SCSI) - type = rasctl_dev_scsi_hd_appl; - }else if (xstrcasecmp(ext, "mos") == 0) { - // MO - type = rasctl_dev_mo; - }else if (xstrcasecmp(ext, "iso") == 0) { - // CD - type = rasctl_dev_cd; - } - } + // If the device type is still "invalid" (unknown), try to figure it out + // from the image file name. + if (cmd == rasctl_cmd_attach && type == rasctl_dev_invalid && file != nullptr) { + type = Rasctl_Command::DeviceTypeFromFilename(stderr, file); if (type == rasctl_dev_invalid) { fprintf(stderr, "Error : Invalid type\n"); @@ -255,11 +230,13 @@ int main(int argc, char* argv[]) strncpy(rasctl_cmd->file,file,_MAX_PATH); } - // Generate the command and send it - rasctl_cmd->Serialize(buf,BUFSIZ); + if(rasctl_cmd->IsValid(stderr)){ + // Generate the command and send it + rasctl_cmd->Serialize(buf,BUFSIZ); - if (!SendCommand(buf)) { - exit(ENOTCONN); + if (!SendCommand(buf)) { + exit(ENOTCONN); + } } // All done! diff --git a/src/raspberrypi/rasctl_command.cpp b/src/raspberrypi/rasctl_command.cpp index bae5d4d..e2d13a4 100644 --- a/src/raspberrypi/rasctl_command.cpp +++ b/src/raspberrypi/rasctl_command.cpp @@ -1,23 +1,41 @@ #include "rasctl_command.h" #include "rascsi_mgr.h" +#include -const char* Rasctl_Command::m_delimiter = "\x1E"; // Record separator charater -//const char* Rasctl_Command::m_delimiter = " "; // Record separator charater +// In the serialized string from rasctl +const char* Rasctl_Command::m_delimiter = "\x1E\n"; // Record separator charater +const char* Rasctl_Command::m_no_file = "----"; +const uint16_t Rasctl_Command::PortNumber = 6868; -void Rasctl_Command::Serialize(BYTE *buff, int max_buff_size){ - snprintf((char*)buff, max_buff_size, "%d%s%d%s%d%s%d%s%s%s\n", - this->id, this->m_delimiter, - this->un, this->m_delimiter, - this->cmd, this->m_delimiter, - this->type, this->m_delimiter, - this->file, this->m_delimiter); +const char* Rasctl_Command::dev_type_lookup[] = { + "SASI Hard Drive", // rasctl_dev_sasi_hd = 0, + "SCSI Hard Drive", // rasctl_dev_scsi_hd = 1, + "Magneto Optical Drive", // rasctl_dev_mo = 2, + "CD-ROM", // rasctl_dev_cd = 3, + "Host Bridge", // rasctl_dev_br = 4, + "Apple SCSI Hard Drive", // rasctl_dev_scsi_hd_appl = 5, + "NEC SCSI Hard DRive", // rasctl_dev_scsi_hd_nec = 6, +}; + +void Rasctl_Command::Serialize(char *buff, int max_buff_size){ + // The filename string can't be empty. Otherwise, strtok will + // ignore the field on the receiving end. + if(strlen(this->file) < 1){ + strcpy(this->file,m_no_file); + } + snprintf(buff, max_buff_size, "%d%c%d%c%d%c%d%c%s%c\n", + this->id, this->m_delimiter[0], + this->un, this->m_delimiter[0], + this->cmd, this->m_delimiter[0], + this->type, this->m_delimiter[0], + this->file, this->m_delimiter[0]); } -Rasctl_Command* Rasctl_Command::DeSerialize(BYTE* buff, int size){ +Rasctl_Command* Rasctl_Command::DeSerialize(char* buff, int size){ Rasctl_Command *return_command = new Rasctl_Command(); char err_message[256]; char *cur_token; - char *command = (char*)buff; + char *command = buff; serial_token_order cur_token_idx = serial_token_first_token; cur_token = strtok(command, m_delimiter); @@ -31,7 +49,11 @@ Rasctl_Command* Rasctl_Command::DeSerialize(BYTE* buff, int size){ return_command->type = (rasctl_dev_type)atoi(cur_token); break; case serial_token_file_name: - strncpy(return_command->file,cur_token,_MAX_PATH); + if(strncmp(cur_token,m_no_file,strlen(m_no_file)) != 0){ + strncpy(return_command->file,cur_token,_MAX_PATH); + } else { + strncpy(return_command->file,"",_MAX_PATH); + } break; case serial_token_id: return_command->id = atoi(cur_token); @@ -78,6 +100,7 @@ BOOL Rasctl_Command::rasctl_dev_is_hd(rasctl_dev_type type) BOOL Rasctl_Command::IsValid(FILE *fp){ struct stat stat_buffer; + rasctl_dev_type expected_type = rasctl_dev_invalid; // If the command is "invalid" we can just return FALSE if(cmd == rasctl_cmd_invalid){ @@ -117,7 +140,7 @@ BOOL Rasctl_Command::IsValid(FILE *fp){ return FALSE; } // Check that the file exists if specified - if(stat(file, &stat_buffer) == 0){ + if(stat(file, &stat_buffer) != 0){ FPRT(fp, "File %s is not accessible", file); return FALSE; } @@ -128,74 +151,49 @@ BOOL Rasctl_Command::IsValid(FILE *fp){ } } -// char* path = optarg; -// int type = -1; -// if (HasSuffix(path, ".hdf") -// || HasSuffix(path, ".hds") -// || HasSuffix(path, ".hdn") -// || HasSuffix(path, ".hdi") -// || HasSuffix(path, ".hda") -// || HasSuffix(path, ".nhd")) { -// type = 0; -// } else if (HasSuffix(path, ".mos")) { -// type = 2; -// } else if (HasSuffix(path, ".iso")) { -// type = 3; -// } else if (xstrcasecmp(path, "bridge") == 0) { -// type = 4; -// } else { -// // Cannot determine the file type -// fprintf(stderr, -// "%s: unknown file extension\n", path); -// return false; -// } + // Check if the filename extension matches the device type + expected_type = DeviceTypeFromFilename(fp, file); + if(expected_type != rasctl_dev_invalid){ + if((file != nullptr) && (type != expected_type)) { + FPRT(fp, "Filename specified is for type %s. This isn't compatible with a %s device.", + dev_type_lookup[expected_type], dev_type_lookup[type]); + return FALSE; + } + } -// int un = 0; -// if (is_sasi) { -// un = id % Rascsi_Manager::UnitNum; -// id /= Rascsi_Manager::UnitNum; -// } - -// // Execute the command -// if (!ExecuteCommand(stderr, id, un, 0, type, path)) { -// return false; -// } -// id = -1; -// } - -// // Display the device list -// Rascsi_Manager::GetInstance()->ListDevice(stdout); -// return true; -// } - - - - - - - // if (type == 0) { - // // Passed the check - // if (!file) { - // return FALSE; - // } - - // // Check that command is at least 5 characters long - // len = strlen(file); - // if (len < 5) { - // return FALSE; - // } - - // // Check the extension - // if (file[len - 4] != '.') { - // return FALSE; - // } - - // // If the extension is not SASI type, replace with SCSI - // ext = &file[len - 3]; - // if (xstrcasecmp(ext, "hdf") != 0) { - // type = 1; - // } - -return FALSE; - + // Everything appears to be OK + return TRUE; } + + +rasctl_dev_type Rasctl_Command::DeviceTypeFromFilename(FILE *fp, const char* filename){ + + const char *extension = strrchr(filename,'.'); + rasctl_dev_type ret_type = rasctl_dev_invalid; + + if(extension == nullptr){ + fprintf(fp, "Missing file extension from %s",filename); + return rasctl_dev_invalid; + } + + if(strcasecmp(extension,".hdf") == 0){ + ret_type = rasctl_dev_sasi_hd; + }else if((strcasecmp(extension,".hds") == 0) || + (strcasecmp(extension,".hdi") == 0) || + (strcasecmp(extension,".nhd") == 0)){ + ret_type = rasctl_dev_scsi_hd; + }else if(strcasecmp(extension,".hdn") == 0){ + ret_type = rasctl_dev_scsi_hd_nec; + }else if(strcasecmp(extension,".hdi") == 0){ + ret_type = rasctl_dev_scsi_hd_nec; + }else if(strcasecmp(extension,".hda") == 0){ + ret_type = rasctl_dev_scsi_hd_appl; + }else if(strcasecmp(extension,".mos") == 0){ + ret_type = rasctl_dev_mo; + }else if(strcasecmp(extension,".iso") == 0){ + ret_type = rasctl_dev_cd; + } + + return ret_type; +} + diff --git a/src/raspberrypi/rasctl_command.h b/src/raspberrypi/rasctl_command.h index 12f75db..758590b 100644 --- a/src/raspberrypi/rasctl_command.h +++ b/src/raspberrypi/rasctl_command.h @@ -40,8 +40,8 @@ enum rasctl_dev_type : int { class Rasctl_Command{ public: - void Serialize(BYTE *buff, int max_buff_size); - static Rasctl_Command* DeSerialize(BYTE* buff, int size); + void Serialize(char *buff, int max_buff_size); + static Rasctl_Command* DeSerialize(char* buff, int size); BOOL IsValid(FILE *fp); @@ -49,12 +49,17 @@ class Rasctl_Command{ rasctl_dev_type type = rasctl_dev_invalid; int id = -1; int un = -1; - char file[_MAX_PATH]; + char file[_MAX_PATH] = ""; static BOOL rasctl_dev_is_hd(rasctl_dev_type dev); + static const uint16_t PortNumber; + + static rasctl_dev_type DeviceTypeFromFilename(FILE *fp, const char* filename); private: static const char* m_delimiter; // Record separator charater + static const char* m_no_file; // Special character sequence indicating an empty file name. + enum serial_token_order : int { serial_token_first_token = 0, @@ -65,4 +70,6 @@ class Rasctl_Command{ serial_token_file_name = 4, serial_token_last_token = 5, }; + + static const char* dev_type_lookup[]; }; \ No newline at end of file