ソースを参照

Allow for CD's to start ejected and prevent door close till BlueSCSI
Toolbox app or button is pressed.

Eric Helgeson 4 ヶ月 前
コミット
a369e49f14

+ 14 - 7
src/BlueSCSI_cdrom.cpp

@@ -1242,9 +1242,13 @@ bool cdromValidateCueSheet(image_config_t &img)
 // Close CDROM tray and note media change event
 void cdromCloseTray(image_config_t &img)
 {
+    const uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
+
+    if (g_scsi_settings.getDevice(target)->startEjected) {
+        return;
+    }
     if (img.ejected)
     {
-        uint8_t target = img.scsiId & 7;
         dbgmsg("------ CDROM close tray on ID ", (int)target);
         img.ejected = false;
         img.cdrom_events = 2; // New media
@@ -1261,7 +1265,7 @@ void cdromCloseTray(image_config_t &img)
 // Switch image on ejection.
 void cdromPerformEject(image_config_t &img)
 {
-    uint8_t target = img.scsiId & 7;
+    uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
 #if ENABLE_AUDIO_OUTPUT
     // terminate audio playback if active on this target (MMC-1 Annex C)
     audio_stop(target);
@@ -1284,11 +1288,15 @@ void cdromPerformEject(image_config_t &img)
 // Reinsert any ejected CDROMs on reboot
 void cdromReinsertFirstImage(image_config_t &img)
 {
+    const uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
+    if (g_scsi_settings.getDevice(target)->startEjected) {
+        return;
+    }
+
     if (img.image_index > 0)
     {
         // Multiple images for this drive, force restart from first one
-        uint8_t target = img.scsiId & 7;
-        dbgmsg("---- Restarting from first CD-ROM image for ID ", (int)target);
+        logmsg("---- Restarting from first CD-ROM image for ID ", (int)target);
         img.image_index = -1;
         img.current_image[0] = '\0';
         switchNextImage(img);
@@ -2078,11 +2086,10 @@ extern "C" int scsiCDRomCommand()
         // terminate audio playback if active on this target (MMC-1 Annex C)
         audio_stop(img.scsiId & 7);
 #endif
-        if ((scsiDev.cdb[4] & 2))
+        if (scsiDev.cdb[4] & LOAD_EJECT_BIT)
         {
             // CD-ROM load & eject
-            int start = scsiDev.cdb[4] & 1;
-            if (start)
+            if (scsiDev.cdb[4] & START_STOP_BIT)
             {
                 cdromCloseTray(img);
             }

+ 3 - 0
src/BlueSCSI_cdrom.h

@@ -8,6 +8,9 @@
 
 #include "BlueSCSI_disk.h"
 
+#define LOAD_EJECT_BIT 2
+#define START_STOP_BIT 1
+
 // Called by scsi.c from SCSI2SD
 extern "C" int scsiCDRomCommand(void);
 

+ 41 - 17
src/BlueSCSI_disk.cpp

@@ -467,6 +467,11 @@ bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_lun, in
             {
                 logmsg("---- Plextor 0xD8 vendor extension enabled");
             }
+            if (g_scsi_settings.getDevice(target_idx)->startEjected)
+            {
+                img.ejected = true;
+                logmsg("---- CD-ROM drive starts ejected");
+            }
         }
         else if (type == S2S_CFG_FLOPPY_14MB)
         {
@@ -819,7 +824,7 @@ static void doCloseTray(image_config_t &img)
 {
     if (img.ejected)
     {
-        uint8_t target = img.scsiId & 7;
+        uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
         dbgmsg("------ Device close tray on ID ", (int)target);
         img.ejected = false;
 
@@ -833,13 +838,17 @@ static void doCloseTray(image_config_t &img)
 
  
 // Eject and switch image
+// This is really press eject button for close and open.
 static void doPerformEject(image_config_t &img)
 {
-    uint8_t target = img.scsiId & 7;
+    const uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
+    // Now that we have a request from a button or an explicit start SCSI command to close the drive,
+    g_scsi_settings.getDevice(target)->startEjected = false;
+
     if (!img.ejected)
     {
         blink_cancel();
-        blinkStatus(g_scsi_settings.getDevice(target)->ejectBlinkTimes, g_scsi_settings.getDevice(target)->ejectBlinkPeriod);;
+        blinkStatus(g_scsi_settings.getDevice(target)->ejectBlinkTimes, g_scsi_settings.getDevice(target)->ejectBlinkPeriod);
         dbgmsg("------ Device open tray on ID ", (int)target);
         img.ejected = true;
         switchNextImage(img); // Switch media for next time
@@ -852,7 +861,7 @@ static void doPerformEject(image_config_t &img)
 
 int findNextImageAfter(image_config_t &img,
         const char* dirname, const char* filename,
-        char* buf, size_t buflen, bool ignore_prefix)
+        char* nextname, size_t nextname_len, bool ignore_prefix)
 {
     FsFile dir;
     if (dirname[0] == '\0')
@@ -881,38 +890,52 @@ int findNextImageAfter(image_config_t &img,
     char first_name[MAX_FILE_PATH] = {'\0'};
     char candidate_name[MAX_FILE_PATH] = {'\0'};
     FsFile file;
+    const uint8_t target = img.scsiId & S2S_CFG_TARGET_ID_BITS;
+    char section[6] = "SCSI0";
+    section[4] = '0' + target;
+
+    // See if we have a current image set in the ini file:
+    ini_gets(section, "Img0", "", candidate_name, sizeof(candidate_name), CONFIGFILE);
+    if (candidate_name[0] != '\0')
+    {
+        img.image_index++;
+        strncpy(img.current_image, candidate_name, sizeof(img.current_image));
+        strncpy(nextname, candidate_name, nextname_len);
+        return strlen(candidate_name);
+    }
+
     while (file.openNext(&dir, O_RDONLY))
     {
         if (file.isDir() && !scsiDiskFolderContainsCueSheet(&file)) continue;
-        if (!file.getName(buf, MAX_FILE_PATH))
+        if (!file.getName(nextname, MAX_FILE_PATH))
         {
             logmsg("Image directory '", dirname, "' had invalid file");
             continue;
         }
-        if (!scsiDiskFilenameValid(buf)) continue;
+        if (!scsiDiskFilenameValid(nextname)) continue;
         if (file.isHidden()) {
-            logmsg("Image '", dirname, "/", buf, "' is hidden, skipping file");
+            logmsg("Image '", dirname, "/", nextname, "' is hidden, skipping file");
             continue;
         }
 
-        if (!ignore_prefix && img.use_prefix && !compare_prefix(filename, buf)) continue;
+        if (!ignore_prefix && img.use_prefix && !compare_prefix(filename, nextname)) continue;
 
         // keep track of the first item to allow wrapping
         // without having to iterate again
-        if (first_name[0] == '\0' || strcasecmp(buf, first_name) < 0)
+        if (first_name[0] == '\0' || strcasecmp(nextname, first_name) < 0)
         {
-            strncpy(first_name, buf, sizeof(first_name));
+            strncpy(first_name, nextname, sizeof(first_name));
         }
 
         // discard if no selected name, or if candidate is before (or is) selected
         // or prefix searching is enabled and file doesn't contain current prefix
-        if (filename[0] == '\0' || strcasecmp(buf, filename) <= 0) continue;
+        if (filename[0] == '\0' || strcasecmp(nextname, filename) <= 0) continue;
 
         // if we got this far and the candidate is either 1) not set, or 2) is a
         // lower item than what has been encountered thus far, it is the best choice
-        if (candidate_name[0] == '\0' || strcasecmp(buf, candidate_name) < 0)
+        if (candidate_name[0] == '\0' || strcasecmp(nextname, candidate_name) < 0)
         {
-            strncpy(candidate_name, buf, sizeof(candidate_name));
+            strncpy(candidate_name, nextname, sizeof(candidate_name));
         }
     }
 
@@ -920,14 +943,14 @@ int findNextImageAfter(image_config_t &img,
     {
         img.image_index++;
         strncpy(img.current_image, candidate_name, sizeof(img.current_image));
-        strncpy(buf, candidate_name, buflen);
+        strncpy(nextname, candidate_name, nextname_len);
         return strlen(candidate_name);
     }
     else if (first_name[0] != '\0')
     {
         img.image_index = 0;
         strncpy(img.current_image, first_name, sizeof(img.current_image));
-        strncpy(buf, first_name, buflen);
+        strncpy(nextname, first_name, nextname_len);
         return strlen(first_name);
     }
     else
@@ -1124,8 +1147,7 @@ void setEjectButton(uint8_t idx, int8_t eject_button)
 bool switchNextImage(image_config_t &img, const char* next_filename)
 {
     // Check if we have a next image to load, so that drive is closed next time the host asks.
-    
-    int target_idx = img.scsiId & 7;
+    int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
     char filename[MAX_FILE_PATH];
     if (next_filename == nullptr)
     {
@@ -1160,6 +1182,8 @@ bool switchNextImage(image_config_t &img, const char* next_filename)
                 // to make sure host properly detects the media change
                 img.ejected = true;
                 img.reinsert_after_eject = true;
+                // Now that we have a request from the BlueSCSI Toolbox app, don't block close tray.
+                g_scsi_settings.getDevice(target_idx & S2S_CFG_TARGET_ID_BITS)->startEjected = false;
                 if (img.deviceType == S2S_CFG_OPTICAL) img.cdrom_events = 2; // New Media
             }
             return true;

+ 1 - 1
src/BlueSCSI_disk.h

@@ -162,7 +162,7 @@ bool scsiDiskCheckAnyImagesConfigured();
 // Finds filename with the lowest lexical order _after_ the given filename in
 // the given folder. If there is no file after the given one, or if there is
 // no current file, this will return the lowest filename encountered.
-int findNextImageAfter(image_config_t &img, const char* dirname, const char* filename, char* buf, size_t buflen, bool ignore_prefix = false);
+int findNextImageAfter(image_config_t &img, const char* dirname, const char* filename, char* nextname, size_t nextname_len, bool ignore_prefix = false);
 
 // Gets the next image filename for the target, if configured for multiple
 // images. As a side effect this advances image tracking to the next image.

+ 2 - 0
src/BlueSCSI_settings.cpp

@@ -244,6 +244,7 @@ static void readIniSCSIDeviceSetting(scsi_device_settings_t &cfg, const char *se
     cfg.rightAlignStrings = ini_getbool(section, "RightAlignStrings", cfg.rightAlignStrings , CONFIGFILE);
     cfg.reinsertOnInquiry = ini_getbool(section, "ReinsertCDOnInquiry", cfg.reinsertOnInquiry, CONFIGFILE);
     cfg.reinsertAfterEject = ini_getbool(section, "ReinsertAfterEject", cfg.reinsertAfterEject, CONFIGFILE);
+    cfg.startEjected = ini_getbool(section, "StartEjected", cfg.startEjected, CONFIGFILE);
     cfg.disableMacSanityCheck = ini_getbool(section, "DisableMacSanityCheck", cfg.disableMacSanityCheck, CONFIGFILE);
 
     cfg.sectorSDBegin = ini_getl(section, "SectorSDBegin", cfg.sectorSDBegin, CONFIGFILE);
@@ -338,6 +339,7 @@ scsi_system_settings_t *BlueSCSISettings::initSystem(const char *presetName)
     cfgDev.rightAlignStrings = false;
     cfgDev.reinsertOnInquiry = true;
     cfgDev.reinsertAfterEject = true;
+    cfgDev.startEjected = false; // if true, reinsert after eject and reinsert on inquiry will be set to false.
     cfgDev.disableMacSanityCheck = false;
 
     cfgDev.sectorSDBegin = 0;

+ 1 - 0
src/BlueSCSI_settings.h

@@ -123,6 +123,7 @@ typedef struct __attribute__((__packed__)) scsi_device_settings_t
     bool rightAlignStrings;
     bool reinsertOnInquiry;
     bool reinsertAfterEject;
+    bool startEjected;
     bool disableMacSanityCheck;
 
     uint32_t sectorSDBegin;

+ 1 - 1
src/QuirksCheck.cpp

@@ -87,7 +87,7 @@ static bool isValidMacintoshImage(image_config_t *img)
 static void macQuirksSanityCheck(image_config_t *img)
 {
 
-    if(g_scsi_settings.getDevice(img->scsiId & 7)->disableMacSanityCheck)
+    if(g_scsi_settings.getDevice(img->scsiId & S2S_CFG_TARGET_ID_BITS)->disableMacSanityCheck)
     {
         dbgmsg("---- Skipping Mac sanity check due to DisableMacSanityCheck");
         return;