Trying to find out whether READ CAPACITY on CD media includes 2 TAO end blocks

This commit is contained in:
Thomas Schmitt 2016-03-08 07:33:45 +00:00
parent df1483c78d
commit 69d12929e3
6 changed files with 86 additions and 7 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2016.02.18.114857" #define Cdrskin_timestamP "2016.03.08.073402"

View File

@ -419,6 +419,7 @@ int burn_drive_grab_stdio(struct burn_drive *d, int flag)
/* despite its name : last valid address, not size */ /* despite its name : last valid address, not size */
d->media_read_capacity = d->media_read_capacity =
read_size / 2048 - !(read_size % 2048); read_size / 2048 - !(read_size % 2048);
d->mr_capacity_trusted = 1;
if ((stat_ret == -1 || is_rdwr) && d->devname[0]) { if ((stat_ret == -1 || is_rdwr) && d->devname[0]) {
ret = burn_os_stdio_capacity(d->devname, 0, &size); ret = burn_os_stdio_capacity(d->devname, 0, &size);
if (ret > 0) if (ret > 0)
@ -1782,10 +1783,12 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
strcpy(d->current_profile_text,"stdio file"); strcpy(d->current_profile_text,"stdio file");
d->current_is_cd_profile = 0; d->current_is_cd_profile = 0;
d->current_is_supported_profile = 1; d->current_is_supported_profile = 1;
if (read_size >= 0) if (read_size >= 0) {
/* despite its name : last valid address, not size */ /* despite its name : last valid address, not size */
d->media_read_capacity = d->media_read_capacity =
read_size / 2048 - !(read_size % 2048); read_size / 2048 - !(read_size % 2048);
d->mr_capacity_trusted = 1;
}
burn_drive_set_media_capacity_remaining(d, size); burn_drive_set_media_capacity_remaining(d, size);
} else } else
d->current_profile = 0; /* Drives return this if empty */ d->current_profile = 0; /* Drives return this if empty */
@ -3322,7 +3325,8 @@ int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value)
/* ts A81215 : API */ /* ts A81215 : API */
int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag) int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag)
{ {
*capacity = d->media_read_capacity + 1; *capacity = d->media_read_capacity +
(d->media_read_capacity != 0x7fffffff);
return (d->media_read_capacity != 0x7fffffff); return (d->media_read_capacity != 0x7fffffff);
} }

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2015 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
This is the official API definition of libburn. This is the official API definition of libburn.
@ -3935,7 +3935,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
/* ts A81215 */ /* ts A81215 */
/** Inquire the maximum amount of readable data. /** Inquire the maximum amount of readable data.
It is supposed that all LBAs in the range from 0 to media_read_acpacity-1 It is supposed that all LBAs in the range from 0 to capacity - 1
can be read via burn_read_data() although some of them may never have been can be read via burn_read_data() although some of them may never have been
recorded. If tracks are recognizable then it is better to only read recorded. If tracks are recognizable then it is better to only read
LBAs which are part of some track. LBAs which are part of some track.

View File

@ -1485,6 +1485,20 @@ ex:;
} }
static int mmc_register_leadout(struct burn_drive *d, int *highest_leadout,
int toc_idx)
{
int lba;
lba = burn_msf_to_lba(d->toc_entry[toc_idx].pmin,
d->toc_entry[toc_idx].psec,
d->toc_entry[toc_idx].pframe);
if (lba > *highest_leadout)
*highest_leadout = lba;
return 1;
}
static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len) static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
{ {
/* read full toc, all sessions, in m/s/f form, 4k buffer */ /* read full toc, all sessions, in m/s/f form, 4k buffer */
@ -1494,7 +1508,7 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
struct buffer *buf = NULL; struct buffer *buf = NULL;
struct command *c = NULL; struct command *c = NULL;
int dlen; int dlen;
int i, old_alloc_len, t_idx, ret; int i, old_alloc_len, t_idx, ret, highest_leadout = -1;
unsigned char *tdata; unsigned char *tdata;
char *msg = NULL; char *msg = NULL;
@ -1652,9 +1666,12 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
d->disc->session[tdata[0] - 1]->firsttrack = tdata[8]; d->disc->session[tdata[0] - 1]->firsttrack = tdata[8];
if (tdata[3] == 0xA1) if (tdata[3] == 0xA1)
d->disc->session[tdata[0] - 1]->lasttrack = tdata[8]; d->disc->session[tdata[0] - 1]->lasttrack = tdata[8];
if (tdata[3] == 0xA2) if (tdata[3] == 0xA2) {
d->disc->session[tdata[0] - 1]->leadout_entry = d->disc->session[tdata[0] - 1]->leadout_entry =
&d->toc_entry[i]; &d->toc_entry[i];
/* ts B60305 */
mmc_register_leadout(d, &highest_leadout, i);
}
} }
/* ts A70131 : was (d->status != BURN_DISC_BLANK) */ /* ts A70131 : was (d->status != BURN_DISC_BLANK) */
@ -1701,6 +1718,23 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
/* A80808 */ /* A80808 */
burn_disc_cd_toc_extensions(d, 0); burn_disc_cd_toc_extensions(d, 0);
/* ts B60304
Most drives report READ CAPACITY of TAO CD too high by 2 blocks.
TOC format 2 always reports 2 blocks more than are readable.
So here it is possible to check and mark as trusted.
*/
if (highest_leadout > 0 && d->media_read_capacity != 0x7fffffff &&
!d->mr_capacity_trusted) {
if (highest_leadout - 3 == d->media_read_capacity) {
d->mr_capacity_trusted = 1;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00000002, LIBDAX_MSGS_SEV_DEBUG,
LIBDAX_MSGS_PRIO_ZERO,
"Trusting READ CAPACITY by 2 extra blocks in TOC. Assuming TAO.",
0, 0);
}
}
ret = 1; ret = 1;
ex:; ex:;
BURN_FREE_MEM(msg); BURN_FREE_MEM(msg);
@ -1909,6 +1943,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
/* ts A81210 */ /* ts A81210 */
d->media_read_capacity = 0x7fffffff; d->media_read_capacity = 0x7fffffff;
d->mr_capacity_trusted = -1;
/* ts A61202 */ /* ts A61202 */
d->toc_entries = 0; d->toc_entries = 0;
@ -4836,6 +4871,7 @@ int mmc_read_capacity(struct burn_drive *d)
BURN_ALLOC_MEM(buf, struct buffer, 1); BURN_ALLOC_MEM(buf, struct buffer, 1);
BURN_ALLOC_MEM(c, struct command, 1); BURN_ALLOC_MEM(c, struct command, 1);
d->media_read_capacity = 0x7fffffff; d->media_read_capacity = 0x7fffffff;
d->mr_capacity_trusted = -1;
mmc_start_if_needed(d, 1); mmc_start_if_needed(d, 1);
if (mmc_function_spy(d, "mmc_read_capacity") <= 0) if (mmc_function_spy(d, "mmc_read_capacity") <= 0)
{ret = 0; goto ex;} {ret = 0; goto ex;}
@ -4853,6 +4889,10 @@ int mmc_read_capacity(struct burn_drive *d)
d->media_read_capacity = 0x7fffffff; d->media_read_capacity = 0x7fffffff;
{ret = 0; goto ex;} {ret = 0; goto ex;}
} }
if (d->current_profile >= 0x08 && d->current_profile <= 0x0A)
d->mr_capacity_trusted = 0;
else
d->mr_capacity_trusted = 1;
ret = 1; ret = 1;
ex:; ex:;
BURN_FREE_MEM(c); BURN_FREE_MEM(c);
@ -5367,6 +5407,7 @@ int mmc_setup_drive(struct burn_drive *d)
d->media_capacity_remaining = 0; d->media_capacity_remaining = 0;
d->media_lba_limit = 0; d->media_lba_limit = 0;
d->media_read_capacity = 0x7fffffff; d->media_read_capacity = 0x7fffffff;
d->mr_capacity_trusted = 0;
d->pessimistic_buffer_free = 0; d->pessimistic_buffer_free = 0;
d->pbf_altered = 0; d->pbf_altered = 0;
d->wait_for_buffer_free = Libburn_wait_for_buffer_freE; d->wait_for_buffer_free = Libburn_wait_for_buffer_freE;

View File

@ -749,10 +749,23 @@ int burn_session_get_hidefirst(struct burn_session *session)
} }
static void burn_track_info_high_read(unsigned char *data,
int *higest_readable)
{
int ret;
ret = mmc_four_char_to_int(data + 8) +
mmc_four_char_to_int(data + 24);
if (ret - 1> *higest_readable)
*higest_readable = ret - 1;
}
/* ts A80808 : Enhance CD toc to DVD toc */ /* ts A80808 : Enhance CD toc to DVD toc */
int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag) int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
{ {
int sidx= 0, tidx= 0, ret, track_offset, alloc_len = 34; int sidx= 0, tidx= 0, ret, track_offset, alloc_len = 34;
int higest_readable = -1;
struct burn_toc_entry *entry, *prev_entry= NULL; struct burn_toc_entry *entry, *prev_entry= NULL;
struct burn_disc *d; struct burn_disc *d;
/* ts A81126 : ticket 146 : There was a SIGSEGV in here */ /* ts A81126 : ticket 146 : There was a SIGSEGV in here */
@ -835,6 +848,9 @@ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
((!drive->current_is_cd_profile) || ((!drive->current_is_cd_profile) ||
ret < prev_entry->track_blocks - 2)) ret < prev_entry->track_blocks - 2))
prev_entry->track_blocks = ret; prev_entry->track_blocks = ret;
if (!drive->mr_capacity_trusted)
burn_track_info_high_read(
buf->data, &higest_readable);
} }
prev_entry->extensions_valid |= 1; prev_entry->extensions_valid |= 1;
} }
@ -847,6 +863,19 @@ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
prev_entry = entry; prev_entry = entry;
} }
} }
if (!drive->mr_capacity_trusted) {
if (higest_readable == drive->media_read_capacity - 2) {
drive->media_read_capacity = higest_readable;
drive->mr_capacity_trusted = 1;
libdax_msgs_submit(libdax_messenger,
drive->global_index, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"Corrected READ CAPACITY by READ TRACK INFORMATION. Assuming TAO.",
0, 0);
}
}
{ret = 1; goto ex;} {ret = 1; goto ex;}
failure: failure:
libdax_msgs_submit(libdax_messenger, -1, 0x0002015f, libdax_msgs_submit(libdax_messenger, -1, 0x0002015f,

View File

@ -369,6 +369,11 @@ struct burn_drive
0x7ffffff0 = 32 bit overflow, or unknown stdio size 0x7ffffff0 = 32 bit overflow, or unknown stdio size
*/ */
int media_read_capacity; int media_read_capacity;
/* ts B60305 : Whether READ CAPACITY of CD is credible:
-1= no READ CAPACITY yet , 0= untrusted READ CAPACITY
1= READ CAPACITY confirmed or corrected by other commands
*/
int mr_capacity_trusted;
/* ts B10314 : Next Writeable Adress for drive_role == 5 */ /* ts B10314 : Next Writeable Adress for drive_role == 5 */
int role_5_nwa; int role_5_nwa;