Now handles "sessions" with multiple "tracks" correctly.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2548 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder 2003-01-25 09:16:32 +00:00
parent 34a81c2f00
commit ee072b68f7
1 changed files with 142 additions and 43 deletions

View File

@ -27,8 +27,8 @@
#include <scsi.h> #include <scsi.h>
#include <disk_scanner/session.h> #include <disk_scanner/session.h>
//#define DBG(y) (y) #define DBG(y) (y)
#define DBG(y) //#define DBG(y)
#define TRACE(x) DBG(dprintf x) #define TRACE(x) DBG(dprintf x)
@ -351,6 +351,8 @@ cdrom_session_identify(int deviceFD, off_t deviceSize, int32 blockSize)
} }
// cdrom_session_get_nth_info // cdrom_session_get_nth_info
/*! \todo Check that read_toc buffer was large enough on success
*/
static static
status_t status_t
cdrom_session_get_nth_info(int deviceFD, int32 index, off_t deviceSize, cdrom_session_get_nth_info(int deviceFD, int32 index, off_t deviceSize,
@ -360,9 +362,9 @@ cdrom_session_get_nth_info(int deviceFD, int32 index, off_t deviceSize,
uchar data[2048]; uchar data[2048];
int32 session = index+1; int32 session = index+1;
bool found_track = false; // bool found_track = false;
bool found_start = false; // bool found_start = false;
bool found_end = false; // bool found_end = false;
off_t start_lba = 0; off_t start_lba = 0;
off_t end_lba = 0; off_t end_lba = 0;
@ -372,11 +374,11 @@ cdrom_session_get_nth_info(int deviceFD, int32 index, off_t deviceSize,
// Attempt to read the table of contents, first in lba mode, then in msf mode // Attempt to read the table of contents, first in lba mode, then in msf mode
if (!error) { if (!error) {
error = read_table_of_contents(deviceFD, index+1, data, 2048, false); error = read_table_of_contents(deviceFD, 1, data, 2048, false);
} }
if (error) { if (error) {
TRACE(("%s: lba read_toc failed, trying msf instead\n", kModuleDebugName)); TRACE(("%s: lba read_toc failed, trying msf instead\n", kModuleDebugName));
error = read_table_of_contents(deviceFD, index+1, data, 2048, true); error = read_table_of_contents(deviceFD, 1, data, 2048, true);
} }
// Interpret the data returned, if successful // Interpret the data returned, if successful
@ -384,7 +386,6 @@ cdrom_session_get_nth_info(int deviceFD, int32 index, off_t deviceSize,
cdrom_table_of_contents_header *header; cdrom_table_of_contents_header *header;
cdrom_full_table_of_contents_entry *entries; cdrom_full_table_of_contents_entry *entries;
int i, count; int i, count;
int first_track = session;
header = (cdrom_table_of_contents_header*)data; header = (cdrom_table_of_contents_header*)data;
entries = (cdrom_full_table_of_contents_entry*)(data+4); entries = (cdrom_full_table_of_contents_entry*)(data+4);
@ -393,45 +394,145 @@ cdrom_session_get_nth_info(int deviceFD, int32 index, off_t deviceSize,
count = (header->length-2) / sizeof(cdrom_full_table_of_contents_entry); count = (header->length-2) / sizeof(cdrom_full_table_of_contents_entry);
// Check for a valid session index // Check for a valid session index
if (session < header->first || session > header->last) if (session < 1 || session > 99)
error = B_ENTRY_NOT_FOUND; error = B_ENTRY_NOT_FOUND;
// Extract the data of interest // Extract the data of interest
if (!error) { if (!error) {
for (i = 0; i < count; i++) { uint32 current_session = 0; // The number given the current session
switch (entries[i].point) { uint32 current_toc_session = 0; // The number given the current "session"
case 0xa0: uint first_track = 0; // Track # of first track in "session"
// PMin holds first track in session uint last_track = 0; // Track # of last track in "session"
if (entries[i].session == session) { off_t lead_out_lba; // The address of the end of the current "session"
first_track = entries[i].pminutes; enum {
found_track = true; cdromStart,
} cdromFoundFirstTrack,
break; cdromFoundLastTrack,
case 0xa2: cdromFoundLeadOut,
// PMSF holds end of session cdromNeedEndLBA,
if (entries[i].session == session) { cdromFinished,
end_lba = msf_to_lba(make_msf_address(entries[i].pminutes, cdromError,
entries[i].pseconds, entries[i].pframes)); } state = cdromStart;
found_end = true;
} for (i = 0; i < count && state != cdromError && state != cdromFinished; i++) {
break; // We're only interested in positional info for data tracks
if ((entries[i].control == 0x04 || entries[i].control == 0x06)
default: // 0x04 == data track, digital copy prohibited
if (entries[i].session == session && entries[i].point == first_track) { // 0x06 == data track, digital copy allowed
if (!found_track) { && entries[i].adr == 0x01)
TRACE(("WARNING: %s: No \"first track in session\" info found; " // 0x01 == positional information
"using session as first track number\n", kModuleDebugName)); {
switch (entries[i].point) {
// first track number (in pmin)
case 0xa0:
if (entries[i].session == current_toc_session+1) {
current_toc_session++;
first_track = entries[i].pminutes;
state = cdromFoundFirstTrack;
} else {
// something screwy
state = cdromError;
TRACE(("%s: Point 0xA0 found in state %d\n",
kModuleDebugName, state));
} }
// PMSF holds start of session break;
start_lba = msf_to_lba(make_msf_address(entries[i].pminutes,
entries[i].pseconds, entries[i].pframes)); // last track number (in pmin)
found_start = true; case 0xa1:
} if (entries[i].session == current_toc_session
break; && state == cdromFoundFirstTrack)
{
last_track = entries[i].pminutes;
state = cdromFoundLastTrack;
} else {
// something screwy
state = cdromError;
TRACE(("%s: Point 0xA1 found in state %d\n",
kModuleDebugName, state));
}
break;
// start position of lead-out (in pmsf)
case 0xa2:
if (entries[i].session == current_toc_session
&& state == cdromFoundLastTrack)
{
lead_out_lba = msf_to_lba(make_msf_address(
entries[i].pminutes,
entries[i].pseconds,
entries[i].pframes));
state = cdromFoundLeadOut;
} else {
// something screwy
state = cdromError;
TRACE(("%s: Point 0xA2 found in state %d\n",
kModuleDebugName, state));
}
break;
default:
// start position of track (in pmsf)
if (1 <= entries[i].point && entries[i].point <= 99
// valid track number
&& entries[i].session == current_toc_session)
{
switch (state) {
case cdromFoundLeadOut:
current_session++;
if ((int)current_session == session) {
// This is the session we're interested in
start_lba = msf_to_lba(make_msf_address(
entries[i].pminutes,
entries[i].pseconds,
entries[i].pframes));
if (entries[i].point == last_track) {
// Hooray! This the last track in the "session", so
// we already know the end_lba
end_lba = lead_out_lba;
state = cdromFinished;
} else {
// Damn, we have to look up the start of the next
// track still...
state = cdromNeedEndLBA;
}
}
break;
case cdromNeedEndLBA:
end_lba = msf_to_lba(make_msf_address(
entries[i].pminutes,
entries[i].pseconds,
entries[i].pframes));
state = cdromFinished;
break;
default:
// something screwy
state = cdromError;
TRACE(("%s: Session of interest found in state %d\n",
kModuleDebugName, state));
break;
}
} else {
// something screwy
state = cdromError;
if (entries[i].session == current_toc_session) {
TRACE(("%s: New session encountered with track information; "
" session == %d, previous session == %d, track == %d\n",
kModuleDebugName, entries[i].session, current_toc_session,
entries[i].point));
} else {
TRACE(("%s: Invalid track encountered: %d\n", kModuleDebugName,
entries[i].point));
}
}
break;
}
} }
} }
if (found_start && found_end) { if (state == cdromFinished) {
TRACE(("%s: found session #%ld info\n", kModuleDebugName, session)); TRACE(("%s: found session #%ld info\n", kModuleDebugName, session));
sessionInfo->offset = start_lba * blockSize; sessionInfo->offset = start_lba * blockSize;
sessionInfo->size = (end_lba - start_lba) * blockSize; sessionInfo->size = (end_lba - start_lba) * blockSize;
@ -439,10 +540,8 @@ cdrom_session_get_nth_info(int deviceFD, int32 index, off_t deviceSize,
sessionInfo->index = index; sessionInfo->index = index;
sessionInfo->flags = B_DATA_SESSION; // possibly B_AUDIO_SESSION for audio tracks? sessionInfo->flags = B_DATA_SESSION; // possibly B_AUDIO_SESSION for audio tracks?
} else { } else {
TRACE(("%s: error in table of contents data: %s\n", kModuleDebugName, TRACE(("%s: error reading table of contents, ended up in state %d\n",
(found_start ? (found_end ? "(can't happen)" : "session end not found") kModuleDebugName, state));
: (found_end ? "session start not found"
: "no session info found"))));
error = B_ENTRY_NOT_FOUND; error = B_ENTRY_NOT_FOUND;
} }
} }