Skip to content

Commit

Permalink
scsi: Fix CD media change not properly detected on some hosts
Browse files Browse the repository at this point in the history
Tested with MSCDEX and SHSUCDX, without this change they do not detect the media change, and keep reporting the file system of the first loaded CD image.
If after changing image the user then attempts to navigate the new CD regardless, eventually the OS driver will get into a weird state and be unable to use the drive again.
  • Loading branch information
nielsmh authored and erichelgeson committed May 20, 2024
1 parent 8cb85f8 commit 30495fd
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/BlueSCSI_Toolbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ void onSetNextCD(const char * img_dir)
next_cd.getName(name, sizeof(name));
next_cd.close();
snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", img_dir, name);
cdromSwitch(img, full_path);
cdromSwitchNextImage(img, full_path);
}

FsFile gFile; // global so we can keep it open while transferring.
Expand Down
53 changes: 19 additions & 34 deletions src/BlueSCSI_cdrom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,7 +1181,7 @@ void cdromPerformEject(image_config_t &img)
debuglog("------ CDROM open tray on ID ", (int)target);
img.ejected = true;
img.cdrom_events = 3; // Media removal
cdromSwitchNextImage(img); // Switch media for next time
cdromSwitchNextImage(img, nullptr); // Switch media for next time
}
else
{
Expand All @@ -1199,7 +1199,7 @@ void cdromReinsertFirstImage(image_config_t &img)
debuglog("---- Restarting from first CD-ROM image for ID ", (int)target);
img.image_index = -1;
img.current_image[0] = '\0';
cdromSwitchNextImage(img);
cdromSwitchNextImage(img, nullptr);
}
else if (img.ejected)
{
Expand All @@ -1209,12 +1209,19 @@ void cdromReinsertFirstImage(image_config_t &img)
}

// Check if we have multiple CD-ROM images to cycle when drive is ejected.
bool cdromSwitchNextImage(image_config_t &img)
bool cdromSwitchNextImage(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.
char filename[MAX_FILE_PATH];
int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
scsiDiskGetNextImageName(img, filename, sizeof(filename));
if (next_filename == nullptr)
{
scsiDiskGetNextImageName(img, filename, sizeof(filename));
}
else
{
strncpy(filename, next_filename, MAX_FILE_PATH);
}

if (filename[0] != '\0')
{
Expand All @@ -1231,36 +1238,14 @@ bool cdromSwitchNextImage(image_config_t &img)

if (status)
{
return true;
}
}

return false;
}

// Check if we have multiple CD-ROM images to cycle when drive is ejected.
bool cdromSwitch(image_config_t &img, const char* filename)
{
// Check if we have a next image to load, so that drive is closed next time the host asks.
int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;

if (filename[0] != '\0')
{
#ifdef ENABLE_AUDIO_OUTPUT
// if in progress for this device, terminate audio playback immediately (Annex C)
audio_stop(target_idx);
// Reset position tracking for the new image
audio_get_status_code(target_idx); // trash audio status code
#endif
log("Switching to next CD-ROM image for ", target_idx, ": ", filename);
img.file.close();
int block_size = getBlockSize(const_cast<char*>(filename), target_idx, 2048);
bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, block_size);

if (status)
{
img.ejected = false;
img.cdrom_events = 2; // New media
if (next_filename != nullptr)
{
// present the drive as ejected until the host queries it again,
// to make sure host properly detects the media change
img.ejected = true;
img.reinsert_after_eject = true;
img.cdrom_events = 2; // New Media
}
return true;
}
}
Expand Down
5 changes: 1 addition & 4 deletions src/BlueSCSI_cdrom.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void cdromPerformEject(image_config_t &img);
void cdromReinsertFirstImage(image_config_t &img);

// Switch to next CD-ROM image if multiple have been configured
bool cdromSwitchNextImage(image_config_t &img);
bool cdromSwitchNextImage(image_config_t &img, const char* filename);

// Check if the currently loaded cue sheet for the image can be parsed
// and print warnings about unsupported track types
Expand All @@ -32,6 +32,3 @@ bool cdromValidateCueSheet(image_config_t &img);
// boolean flag is true if just basic mechanism status (playback true/false)
// is desired, or false if historical audio status codes should be returned
void cdromGetAudioPlaybackStatus(uint8_t *status, uint32_t *current_lba, bool current_only);

// switch to a given filename for the cd.
bool cdromSwitch(image_config_t &img, const char* filename);

0 comments on commit 30495fd

Please sign in to comment.