Obtain TOC from non-CD via 52h READ TRACK INFORMATION

This commit is contained in:
Thomas Schmitt 2007-02-01 16:15:09 +00:00
parent dde52c1971
commit e876f90e6c
7 changed files with 385 additions and 58 deletions

View File

@ -149,9 +149,6 @@ Note: The support for sequentially recordable media is still emerging.
DVD-R have not been tested yet. If no Incremental Streaming feature (21h) DVD-R have not been tested yet. If no Incremental Streaming feature (21h)
is offered, then the media is regarded as unsuitable without further is offered, then the media is regarded as unsuitable without further
explanation. (One can torture DVD-RW to make them offer only DAO (2Fh)). explanation. (One can torture DVD-RW to make them offer only DAO (2Fh)).
Multi-session works, but -toc is not implemented yet. -msinfo works although
otherwise predicted by MMC-3 to MMC-5. Be mistrusting when appending a third
session for the first time with your drive.
.br .br
--------------- ---------------
.br .br

View File

@ -129,6 +129,7 @@ or
#define Cdrskin_libburn_from_pykix_svN 1 #define Cdrskin_libburn_from_pykix_svN 1
#define Cdrskin_libburn_has_get_msc1 1 #define Cdrskin_libburn_has_get_msc1 1
#define Cdrskin_libburn_has_toc_entry_extensionS 1
#endif /* Cdrskin_libburn_0_3_1 */ #endif /* Cdrskin_libburn_0_3_1 */
@ -3509,8 +3510,17 @@ int Cdrskin_msinfo(struct CdrskiN *skin, int flag)
if(tracks==NULL || num_tracks<=0) if(tracks==NULL || num_tracks<=0)
continue; continue;
burn_track_get_entry(tracks[0],&toc_entry); burn_track_get_entry(tracks[0],&toc_entry);
#ifdef Cdrskin_libburn_has_toc_entry_extensionS
if(toc_entry.extensions_valid&1) { /* DVD extension valid */
lba= toc_entry.start_lba;
} else {
#else
{
#endif
lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe); lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
} }
}
if(lba==-123456789) { if(lba==-123456789) {
fprintf(stderr,"cdrskin: FATAL : Cannot find any track on CD\n"); fprintf(stderr,"cdrskin: FATAL : Cannot find any track on CD\n");
{ret= 0; goto ex;} {ret= 0; goto ex;}
@ -3522,7 +3532,15 @@ obtain_nwa:;
fprintf(stderr, fprintf(stderr,
"cdrskin: NOTE : Guessing next writeable address from leadout\n"); "cdrskin: NOTE : Guessing next writeable address from leadout\n");
burn_session_get_leadout_entry(sessions[num_sessions-1],&toc_entry); burn_session_get_leadout_entry(sessions[num_sessions-1],&toc_entry);
#ifdef Cdrskin_libburn_has_toc_entry_extensionS
if(toc_entry.extensions_valid&1) { /* DVD extension valid */
aux_lba= toc_entry.start_lba;
} else {
#else
{
#endif
aux_lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe); aux_lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
}
if(num_sessions>0) if(num_sessions>0)
nwa= aux_lba+6900; nwa= aux_lba+6900;
else else
@ -3570,7 +3588,7 @@ ex:;
int Cdrskin_toc(struct CdrskiN *skin, int flag) int Cdrskin_toc(struct CdrskiN *skin, int flag)
{ {
int num_sessions= 0,num_tracks= 0,lba= 0,track_count= 0,total_tracks= 0; int num_sessions= 0,num_tracks= 0,lba= 0,track_count= 0,total_tracks= 0;
int session_no, track_no; int session_no, track_no, pmin, psec, pframe;
struct burn_drive *drive; struct burn_drive *drive;
struct burn_disc *disc= NULL; struct burn_disc *disc= NULL;
struct burn_session **sessions; struct burn_session **sessions;
@ -3599,11 +3617,26 @@ int Cdrskin_toc(struct CdrskiN *skin, int flag)
for(track_no= 0; track_no<num_tracks; track_no++) { for(track_no= 0; track_no<num_tracks; track_no++) {
track_count++; track_count++;
burn_track_get_entry(tracks[track_no], &toc_entry); burn_track_get_entry(tracks[track_no], &toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
#ifdef Cdrskin_libburn_has_toc_entry_extensionS
if(toc_entry.extensions_valid&1) { /* DVD extension valid */
lba= toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
#else
{
#endif
pmin= toc_entry.pmin;
psec= toc_entry.psec;
pframe= toc_entry.pframe;
lba= burn_msf_to_lba(pmin,psec,pframe);
}
if(track_no==0 && burn_session_get_hidefirst(sessions[session_no])) if(track_no==0 && burn_session_get_hidefirst(sessions[session_no]))
printf("cdrskin: NOTE : first track is marked as \"hidden\".\n"); printf("cdrskin: NOTE : first track is marked as \"hidden\".\n");
printf("track: %2d lba: %9d (%9d) %2.2u:%2.2u:%2.2u",track_count, printf("track: %2d lba: %9d (%9d) %2.2d:%2.2d:%2.2d",track_count,
lba,4*lba,toc_entry.pmin,toc_entry.psec,toc_entry.pframe); lba,4*lba,pmin,psec,pframe);
printf(" adr: %d control: %d",toc_entry.adr,toc_entry.control); printf(" adr: %d control: %d",toc_entry.adr,toc_entry.control);
/* >>> From where does cdrecord take "mode" ? */ /* >>> From where does cdrecord take "mode" ? */
@ -3618,9 +3651,23 @@ int Cdrskin_toc(struct CdrskiN *skin, int flag)
if((flag&1) && session_no<num_sessions-1) if((flag&1) && session_no<num_sessions-1)
continue; continue;
burn_session_get_leadout_entry(sessions[session_no],&toc_entry); burn_session_get_leadout_entry(sessions[session_no],&toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
printf("track:lout lba: %9d (%9d) %2.2u:%2.2u:%2.2u", #ifdef Cdrskin_libburn_has_toc_entry_extensionS
lba,4*lba,toc_entry.pmin,toc_entry.psec,toc_entry.pframe); if(toc_entry.extensions_valid&1) { /* DVD extension valid */
lba= toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
#else
{
#endif
pmin= toc_entry.pmin;
psec= toc_entry.psec;
pframe= toc_entry.pframe;
lba= burn_msf_to_lba(pmin,psec,pframe);
}
printf("track:lout lba: %9d (%9d) %2.2d:%2.2d:%2.2d",
lba,4*lba,pmin,psec,pframe);
printf(" adr: %d control: %d",toc_entry.adr,toc_entry.control); printf(" adr: %d control: %d",toc_entry.adr,toc_entry.control);
printf(" mode: -1\n"); printf(" mode: -1\n");
} }

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2007.01.31.173611" #define Cdrskin_timestamP "2007.02.01.161634"

View File

@ -241,9 +241,18 @@ enum burn_drive_status
}; };
/** Information about a track on a disc - this is from the q sub channel of the /** Information about a track on a disc - this is from the q sub channel of the
lead-in area of a disc. The documentation here is very terse. lead-in area of a disc. The documentation here is very terse.
See a document such as mmc3 for proper information. See a document such as mmc3 for proper information.
CAUTION : This structure is prone to future extension !
Do not restrict your application to unsigned char with any counter like
"session", "point", "pmin", ...
Do not rely on the current size of a burn_toc_entry.
ts A70201 : DVD extension, see below
*/ */
struct burn_toc_entry struct burn_toc_entry
{ {
@ -267,6 +276,23 @@ struct burn_toc_entry
unsigned char psec; unsigned char psec;
/** Track start time frames for normal tracks */ /** Track start time frames for normal tracks */
unsigned char pframe; unsigned char pframe;
/* Indicates wether extension data are valid and eventually override
older elements in this structure:
bit0= DVD extension is valid
*/
unsigned char extensions_valid;
/* ts A70201 : DVD extension.
If invalid the members are guaranteed to be 0. */
/* Tracks and session numbers are 16 bit. Here are the high bytes. */
unsigned char session_msb;
unsigned char point_msb;
/* pmin, psec, and pframe may be too small if DVD extension is valid */
int start_lba;
/* min, sec, and frame may be too small if DVD extension is valid */
int track_blocks;
}; };

View File

@ -150,6 +150,25 @@ int mmc_function_spy_ctrl(int do_tell)
} }
/* ts A70201 */
int mmc_four_char_to_int(unsigned char *data)
{
return (data[0] << 24) | (data[1] << 16) |
(data[2] << 8) | data[3];
}
/* ts A70201 */
int mmc_int_to_four_char(unsigned char *data, int num)
{
data[0] = (num >> 24) & 0xff;
data[1] = (num >> 16) & 0xff;
data[2] = (num >> 8) & 0xff;
data[3] = num & 0xff;
return 1;
}
void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s) void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
{ {
struct buffer buf; struct buffer buf;
@ -171,16 +190,16 @@ void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
d->issue_command(d, &c); d->issue_command(d, &c);
} }
/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
@return 1=nwa is valid , 0=nwa is not valid , -1=error */ /* ts A70201 :
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa) Common track info fetcher for mmc_get_nwa() and mmc_fake_toc()
*/
int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf)
{ {
struct buffer buf;
struct command c; struct command c;
unsigned char *data;
int i; int i;
mmc_function_spy("mmc_get_nwa"); mmc_function_spy("mmc_read_track_info");
c.retry = 1; c.retry = 1;
c.oplen = sizeof(MMC_TRACK_INFO); c.oplen = sizeof(MMC_TRACK_INFO);
memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO)); memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
@ -196,6 +215,52 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */ else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
trackno = 0xFF; trackno = 0xFF;
} }
for (i = 0; i < 4; i++)
c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff;
c.page = buf;
memset(buf->data, 0, BUFFER_SIZE);
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
if (c.error)
return 0;
return 1;
}
/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
@return 1=nwa is valid , 0=nwa is not valid , -1=error */
/* ts A70201 : outsourced 52h READ TRACK INFO command */
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
{
struct buffer buf;
int ret;
#ifdef Libburn_get_nwa_standalonE
struct command c;
int i;
#endif
unsigned char *data;
mmc_function_spy("mmc_get_nwa");
if(trackno<=0) {
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12 )
/* DVD+RW , DVD-RW restricted overwrite , DVD-RAM */
trackno = 1;
else if (d->current_profile == 0x11 ||
d->current_profile == 0x14) /* DVD-R[W] Sequential */
trackno = d->last_track_no;
else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
trackno = 0xFF;
}
#ifdef Libburn_get_nwa_standalonE
c.retry = 1;
c.oplen = sizeof(MMC_TRACK_INFO);
memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
c.opcode[1] = 1;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff; c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff;
c.page = &buf; c.page = &buf;
@ -203,6 +268,16 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
d->issue_command(d, &c); d->issue_command(d, &c);
data = c.page->data; data = c.page->data;
#else /* Libburn_get_nwa_standalonE */
ret = mmc_read_track_info(d, trackno, &buf);
if (ret <= 0)
return ret;
data = buf.data;
#endif /* ! Libburn_get_nwa_standalonE */
*lba = (data[8] << 24) + (data[9] << 16) *lba = (data[8] << 24) + (data[9] << 16)
+ (data[10] << 8) + data[11]; + (data[10] << 8) + data[11];
*nwa = (data[12] << 24) + (data[13] << 16) *nwa = (data[12] << 24) + (data[13] << 16)
@ -410,9 +485,156 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
return 0; return 0;
} }
/* ts A70201 : Set up an entry for mmc_fake_toc() */
int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
int track_number,
unsigned char *size_data, unsigned char *start_data)
{
int min, sec, frames, num;
/* mark DVD extensions as valid */
entry->extensions_valid |= 1;
/* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */
entry->session = session_number & 0xff;
entry->session_msb = (session_number >> 8) & 0xff;
entry->adr = 1;
entry->control = 4;
entry->tno = 0;
entry->point = track_number & 0xff;
entry->point_msb = (track_number >> 8) & 0xff;
num = (size_data[0] << 24) | (size_data[1] << 16) |
(size_data[2] << 8) | size_data[3];
entry->track_blocks = num;
burn_lba_to_msf(num, &min, &sec, &frames);
if (min > 255) {
min = 255;
sec = 255;
frames = 255;
}
entry->min = min;
entry->sec = sec;
entry->frame = frames;
entry->zero = 0;
num = (start_data[0] << 24) | (start_data[1] << 16) |
(start_data[2] << 8) | start_data[3];
entry->start_lba = num;
burn_lba_to_msf(num, &min, &sec, &frames);
if (min > 255) {
min = 255;
sec = 255;
frames = 255;
}
entry->pmin = min;
entry->psec = sec;
entry->pframe = frames;
return 1;
}
/* ts A70131 : compose a disc TOC structure from d->complete_sessions
and 52h READ TRACK INFORMATION */
int mmc_fake_toc(struct burn_drive *d)
{
struct burn_track *track;
struct burn_session *session;
struct burn_toc_entry *entry;
struct buffer buf;
int i, session_number, prev_session = -1, ret, lba;
unsigned char *tdata, size_data[4], start_data[4];
if (d->last_track_no <= 0 || d->complete_sessions <= 0 ||
d->status == BURN_DISC_BLANK)
return 2;
d->disc = burn_disc_create();
if (d->disc == NULL)
return -1;
d->toc_entries = d->last_track_no + d->complete_sessions;
d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry));
if (d->toc_entry == NULL)
return -1;
memset(d->toc_entry, 0,d->toc_entries * sizeof(struct burn_toc_entry));
for (i = 0; i < d->complete_sessions; i++) {
session = burn_session_create();
burn_disc_add_session(d->disc, session, BURN_POS_END);
burn_session_free(session);
}
memset(size_data, 0, 4);
memset(start_data, 0, 4);
/* Entry Layout :
session 1 track 1 entry 0
...
session 1 track N entry N-1
leadout 1 entry N
session 2 track N+1 entry N+1
...
session 2 track M+1 entry M+1
leadout 2 entry M+2
session X track K entry (K-1)+(X-1)
...
session X track i+1 entry i+(X-1)
leadout X entry i+X
*/
for (i = 0; i < d->last_track_no; i++) {
ret = mmc_read_track_info(d, i+1, &buf);
if (ret < 0)
return ret;
if (ret == 0)
continue;
tdata = buf.data;
session_number = (tdata[33] << 8) | tdata[3];
if (session_number <= 0)
continue;
if (session_number != prev_session && prev_session > 0) {
entry = &(d->toc_entry[(i - 1) + prev_session]);
lba = mmc_four_char_to_int(start_data) +
mmc_four_char_to_int(size_data);
mmc_int_to_four_char(start_data, lba);
mmc_int_to_four_char(size_data, 0);
mmc_fake_toc_entry(entry, session_number, 0xA2,
size_data, start_data);
entry->min= entry->sec= entry->frame= 0;
d->disc->session[prev_session - 1]->leadout_entry =
entry;
}
if (session_number > d->disc->sessions)
continue;
entry = &(d->toc_entry[i + session_number - 1]);
track = burn_track_create();
if (track == NULL)
return -1;
burn_session_add_track(
d->disc->session[session_number - 1],
track, BURN_POS_END);
track->entry = entry;
burn_track_free(track);
memcpy(size_data, tdata + 24, 4);
memcpy(start_data, tdata + 8, 4);
mmc_fake_toc_entry(entry, session_number, i + 1,
size_data, start_data);
if (session_number < d->disc->sessions) {
if (prev_session != session_number)
d->disc->session[session_number - 1]->
firsttrack = i+1;
d->disc->session[session_number - 1]->lasttrack = i+1;
}
prev_session = session_number;
}
return 1;
}
void mmc_read_toc(struct burn_drive *d) void mmc_read_toc(struct burn_drive *d)
{ {
/* read full toc, all sessions, in m/s/f form, 4k buffer */ /* read full toc, all sessions, in m/s/f form, 4k buffer */
/* ts A70201 : or fake a toc from track information */
struct burn_track *track; struct burn_track *track;
struct burn_session *session; struct burn_session *session;
struct buffer buf; struct buffer buf;
@ -422,19 +644,24 @@ void mmc_read_toc(struct burn_drive *d)
unsigned char *tdata; unsigned char *tdata;
mmc_function_spy("mmc_read_toc"); mmc_function_spy("mmc_read_toc");
memcpy(c.opcode, MMC_GET_TOC, sizeof(MMC_GET_TOC)); if (!(d->current_profile == -1 || d->current_is_cd_profile)) {
if(!d->current_is_cd_profile) {
/* ts A70131 : MMC_GET_TOC uses Response Format 2 /* ts A70131 : MMC_GET_TOC uses Response Format 2
For DVD this fails with 5,24,00 */ For DVD this fails with 5,24,00 */
/* One could try Response Format 0: mmc5r03.pdf 6.26.3.2 */ /* One could try Response Format 0: mmc5r03.pdf 6.26.3.2
/* One could try which does not yield the same result wit the same disc
51h READ DISC INFORMATION and 52h READ TRACK INFORMATION on different drives.
where 51h gives the number of tracks and 52h tells the */
session number with each track. */ /* ts A70201 :
This uses the session count from 51h READ DISC INFORMATION
/* >>> One must do someting */; and the track records from 52h READ TRACK INFORMATION
*/
mmc_fake_toc(d);
if (d->status == BURN_DISC_UNREADY)
d->status = BURN_DISC_FULL;
return;
} }
memcpy(c.opcode, MMC_GET_TOC, sizeof(MMC_GET_TOC));
c.retry = 1; c.retry = 1;
c.oplen = sizeof(MMC_GET_TOC); c.oplen = sizeof(MMC_GET_TOC);
c.page = &buf; c.page = &buf;
@ -461,6 +688,7 @@ void mmc_read_toc(struct burn_drive *d)
d->toc_entries = 0; d->toc_entries = 0;
/* Prefering memory leaks over fandangos */ /* Prefering memory leaks over fandangos */
d->toc_entry = malloc(sizeof(struct burn_toc_entry)); d->toc_entry = malloc(sizeof(struct burn_toc_entry));
memset(&(d->toc_entry[0]), 0, sizeof(struct burn_toc_entry));
return; return;
} }
@ -474,6 +702,8 @@ void mmc_read_toc(struct burn_drive *d)
a ssert(((dlen - 2) % 11) == 0); a ssert(((dlen - 2) % 11) == 0);
*/ */
d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry)); d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry));
for (i = 0; i < d->toc_entries; i++)
memset(&(d->toc_entry[i]), 0, sizeof(struct burn_toc_entry));
tdata = c.page->data + 4; tdata = c.page->data + 4;
burn_print(12, "TOC:\n"); burn_print(12, "TOC:\n");
@ -497,8 +727,7 @@ void mmc_read_toc(struct burn_drive *d)
burn_print(bpl, " MSF(%d:%d:%d)", tdata[4],tdata[5],tdata[6]); burn_print(bpl, " MSF(%d:%d:%d)", tdata[4],tdata[5],tdata[6]);
burn_print(bpl, " PMSF(%d:%d:%d %d)", burn_print(bpl, " PMSF(%d:%d:%d %d)",
tdata[8], tdata[9], tdata[10], tdata[8], tdata[9], tdata[10],
burn_msf_to_lba(tdata[8], tdata[9], tdata[10]) burn_msf_to_lba(tdata[8], tdata[9], tdata[10]));
);
burn_print(bpl, " - control %d, adr %d\n", tdata[1] & 0xF, burn_print(bpl, " - control %d, adr %d\n", tdata[1] & 0xF,
tdata[1] >> 4); tdata[1] >> 4);
@ -550,7 +779,8 @@ void mmc_read_toc(struct burn_drive *d)
/* ts A61022 */ /* ts A61022 */
burn_print(bpl, "-----------------------------------\n"); burn_print(bpl, "-----------------------------------\n");
if (d->status != BURN_DISC_APPENDABLE) /* ts A70131 : was (d->status != BURN_DISC_BLANK) */
if (d->status == BURN_DISC_UNREADY)
d->status = BURN_DISC_FULL; d->status = BURN_DISC_FULL;
toc_find_modes(d); toc_find_modes(d);
} }
@ -571,11 +801,13 @@ int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
My drives return useful data, though. My drives return useful data, though.
MMC-3 states that DVD had not tracks. So maybe this fake is MMC-3 states that DVD had not tracks. So maybe this fake is
a legacy ? a legacy ?
>>> Possibly one will have to fake this reply from
51h READ DISC INFORMATION and 52h READ TRACK INFORMATION
(I still have to find out what growisofs is using)
*/ */
/* >>>
mmc_fake_toc() meanwhile tries to establish a useable TOC.
Evaluate this first before issueing a MMC command.
*/
memcpy(c.opcode, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO)); memcpy(c.opcode, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO));
c.retry = 1; c.retry = 1;
c.oplen = sizeof(MMC_GET_MSINFO); c.oplen = sizeof(MMC_GET_MSINFO);
@ -602,6 +834,8 @@ void mmc_read_disc_info(struct burn_drive *d)
unsigned char *data; unsigned char *data;
struct command c; struct command c;
char msg[160]; char msg[160];
/* ts A70131 : had to move mmc_read_toc() to end of function */
int do_read_toc = 0, session_state;
/* ts A61020 */ /* ts A61020 */
d->start_lba = d->end_lba = -2000000000; d->start_lba = d->end_lba = -2000000000;
@ -647,10 +881,6 @@ void mmc_read_disc_info(struct burn_drive *d)
data = c.page->data; data = c.page->data;
d->erasable = !!(data[2] & 16); d->erasable = !!(data[2] & 16);
/*
fprintf(stderr, "libburn_experimental: data[2]= %d 0x%x\n",
(unsigned) data[2], (unsigned) data[2]);
*/
switch (data[2] & 3) { switch (data[2] & 3) {
case 0: case 0:
d->toc_entries = 0; d->toc_entries = 0;
@ -668,8 +898,9 @@ void mmc_read_disc_info(struct burn_drive *d)
case 1: case 1:
d->status = BURN_DISC_APPENDABLE; d->status = BURN_DISC_APPENDABLE;
case 2: case 2:
if (d->current_profile == -1 || d->current_is_cd_profile) if ((data[2] & 3) == 2)
mmc_read_toc(d); d->status = BURN_DISC_FULL;
do_read_toc = 1;
break; break;
} }
@ -687,13 +918,22 @@ void mmc_read_disc_info(struct burn_drive *d)
*/ */
d->bg_format_status = data[7] & 3; d->bg_format_status = data[7] & 3;
if (d->status == BURN_DISC_BLANK) if (d->status == BURN_DISC_BLANK) {
d->last_track_no = 1; /* The "incomplete track" */ d->last_track_no = 1; /* The "incomplete track" */
else d->complete_sessions = 0;
} else {
/* ts A70131 : number of non-empty sessions */
d->complete_sessions = (data[9] << 8) | data[4];
session_state = (data[2] >> 2) & 3;
/* mmc5r03c.pdf 6.22.3.1.3 State of Last Session: 3=complete */
if (session_state != 3 && d->complete_sessions >= 1)
d->complete_sessions--;
/* ts A70129 : mmc5r03c.pdf 6.22.3.1.7 /* ts A70129 : mmc5r03c.pdf 6.22.3.1.7
This includes the "incomplete track" if the disk is This includes the "incomplete track" if the disk is
appendable. I.e number of complete tracks + 1. */ appendable. I.e number of complete tracks + 1. */
d->last_track_no = (data[11] << 8) | data[6]; d->last_track_no = (data[11] << 8) | data[6];
}
/* Preliminarily declare blank: /* Preliminarily declare blank:
ts A61219 : DVD+RW (is not bg_format_status==0 "blank") ts A61219 : DVD+RW (is not bg_format_status==0 "blank")
@ -703,6 +943,9 @@ void mmc_read_disc_info(struct burn_drive *d)
if (d->current_profile == 0x1a || d->current_profile == 0x13 || if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12) d->current_profile == 0x12)
d->status = BURN_DISC_BLANK; d->status = BURN_DISC_BLANK;
if (do_read_toc)
mmc_read_toc(d);
} }
void mmc_read_atip(struct burn_drive *d) void mmc_read_atip(struct burn_drive *d)
@ -1885,6 +2128,7 @@ int mmc_setup_drive(struct burn_drive *d)
d->needs_close_session = 0; d->needs_close_session = 0;
d->bg_format_status = -1; d->bg_format_status = -1;
d->num_format_descr = 0; d->num_format_descr = 0;
d->complete_sessions = 0;
d->last_track_no = 1; d->last_track_no = 1;
return 1; return 1;

View File

@ -199,10 +199,14 @@ struct burn_drive
int start_lba; int start_lba;
int end_lba; int end_lba;
/* ts A70131 : from 51h READ DISC INFORMATION Number of Sessions (-1)*/
int complete_sessions;
/* ts A70129 : /* ts A70129 :
from 51h READ DISC INFORMATION Last Track Number in Last Session */ from 51h READ DISC INFORMATION Last Track Number in Last Session */
int last_track_no; int last_track_no;
int toc_temp; int toc_temp;
struct burn_disc *disc; /* disc structure */ struct burn_disc *disc; /* disc structure */
int block_types[4]; int block_types[4];

View File

@ -375,7 +375,7 @@ int telltoc_formatlist(struct burn_drive *drive)
int telltoc_toc(struct burn_drive *drive) int telltoc_toc(struct burn_drive *drive)
{ {
int num_sessions = 0 , num_tracks = 0 , lba = 0; int num_sessions = 0 , num_tracks = 0 , lba = 0, pmin, psec, pframe;
int track_count = 0; int track_count = 0;
int session_no, track_no; int session_no, track_no;
struct burn_disc *disc= NULL; struct burn_disc *disc= NULL;
@ -397,27 +397,36 @@ int telltoc_toc(struct burn_drive *drive)
for(track_no= 0; track_no<num_tracks; track_no++) { for(track_no= 0; track_no<num_tracks; track_no++) {
track_count++; track_count++;
burn_track_get_entry(tracks[track_no], &toc_entry); burn_track_get_entry(tracks[track_no], &toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec, if (toc_entry.extensions_valid & 1) {
toc_entry.pframe); /* DVD extension valid */
lba = toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
pmin = toc_entry.pmin;
psec = toc_entry.psec;
pframe = toc_entry.pframe;
lba= burn_msf_to_lba(pmin, psec, pframe);
}
printf("Media content: session %2d ", session_no+1); printf("Media content: session %2d ", session_no+1);
printf("track %2d %s lba: %9d %2.2u:%2.2u:%2.2u\n", printf("track %2d %s lba: %9d %4.2d:%2.2d:%2.2d\n",
track_count, track_count,
((toc_entry.control&7)<4?"audio":"data "), ((toc_entry.control&7)<4?"audio":"data "),
lba, lba, pmin, psec, pframe);
toc_entry.pmin,
toc_entry.psec,
toc_entry.pframe);
} }
burn_session_get_leadout_entry(sessions[session_no], burn_session_get_leadout_entry(sessions[session_no],
&toc_entry); &toc_entry);
lba = burn_msf_to_lba(toc_entry.pmin, if (toc_entry.extensions_valid & 1) {
toc_entry.psec, toc_entry.pframe); lba = toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
pmin = toc_entry.pmin;
psec = toc_entry.psec;
pframe = toc_entry.pframe;
lba= burn_msf_to_lba(pmin, psec, pframe);
}
printf("Media content: session %2d ", session_no+1); printf("Media content: session %2d ", session_no+1);
printf("leadout lba: %9d %2.2u:%2.2u:%2.2u\n", printf("leadout lba: %9d %4.2d:%2.2d:%2.2d\n",
lba, lba, pmin, psec, pframe);
toc_entry.pmin,
toc_entry.psec,
toc_entry.pframe);
} }
if (disc!=NULL) if (disc!=NULL)
burn_disc_free(disc); burn_disc_free(disc);