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:
parent
34a81c2f00
commit
ee072b68f7
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue