From 69d12929e3221e9abee39d0dce61f252b41c46a5 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 8 Mar 2016 07:33:45 +0000 Subject: [PATCH] Trying to find out whether READ CAPACITY on CD media includes 2 TAO end blocks --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 8 +++++-- libburn/libburn.h | 4 ++-- libburn/mmc.c | 45 +++++++++++++++++++++++++++++++++++-- libburn/structure.c | 29 ++++++++++++++++++++++++ libburn/transport.h | 5 +++++ 6 files changed, 86 insertions(+), 7 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 07f0fcb..7b5c8b0 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2016.02.18.114857" +#define Cdrskin_timestamP "2016.03.08.073402" diff --git a/libburn/drive.c b/libburn/drive.c index ae59162..f195d72 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -419,6 +419,7 @@ int burn_drive_grab_stdio(struct burn_drive *d, int flag) /* despite its name : last valid address, not size */ d->media_read_capacity = read_size / 2048 - !(read_size % 2048); + d->mr_capacity_trusted = 1; if ((stat_ret == -1 || is_rdwr) && d->devname[0]) { ret = burn_os_stdio_capacity(d->devname, 0, &size); 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"); d->current_is_cd_profile = 0; d->current_is_supported_profile = 1; - if (read_size >= 0) + if (read_size >= 0) { /* despite its name : last valid address, not size */ d->media_read_capacity = read_size / 2048 - !(read_size % 2048); + d->mr_capacity_trusted = 1; + } burn_drive_set_media_capacity_remaining(d, size); } else 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 */ 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); } diff --git a/libburn/libburn.h b/libburn/libburn.h index 61c0ddb..b381082 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1,7 +1,7 @@ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens - Copyright (c) 2006 - 2015 Thomas Schmitt + Copyright (c) 2006 - 2016 Thomas Schmitt Provided under GPL version 2 or later. 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 */ /** 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 recorded. If tracks are recognizable then it is better to only read LBAs which are part of some track. diff --git a/libburn/mmc.c b/libburn/mmc.c index 6f1892e..f2a8ab5 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -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) { /* 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 command *c = NULL; int dlen; - int i, old_alloc_len, t_idx, ret; + int i, old_alloc_len, t_idx, ret, highest_leadout = -1; unsigned char *tdata; 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]; if (tdata[3] == 0xA1) 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->toc_entry[i]; + /* ts B60305 */ + mmc_register_leadout(d, &highest_leadout, i); + } } /* 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 */ 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; ex:; BURN_FREE_MEM(msg); @@ -1909,6 +1943,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len) /* ts A81210 */ d->media_read_capacity = 0x7fffffff; + d->mr_capacity_trusted = -1; /* ts A61202 */ 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(c, struct command, 1); d->media_read_capacity = 0x7fffffff; + d->mr_capacity_trusted = -1; mmc_start_if_needed(d, 1); if (mmc_function_spy(d, "mmc_read_capacity") <= 0) {ret = 0; goto ex;} @@ -4853,6 +4889,10 @@ int mmc_read_capacity(struct burn_drive *d) d->media_read_capacity = 0x7fffffff; {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; ex:; BURN_FREE_MEM(c); @@ -5367,6 +5407,7 @@ int mmc_setup_drive(struct burn_drive *d) d->media_capacity_remaining = 0; d->media_lba_limit = 0; d->media_read_capacity = 0x7fffffff; + d->mr_capacity_trusted = 0; d->pessimistic_buffer_free = 0; d->pbf_altered = 0; d->wait_for_buffer_free = Libburn_wait_for_buffer_freE; diff --git a/libburn/structure.c b/libburn/structure.c index 3161e4a..b94d820 100644 --- a/libburn/structure.c +++ b/libburn/structure.c @@ -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 */ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag) { 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_disc *d; /* 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) || ret < prev_entry->track_blocks - 2)) prev_entry->track_blocks = ret; + if (!drive->mr_capacity_trusted) + burn_track_info_high_read( + buf->data, &higest_readable); } prev_entry->extensions_valid |= 1; } @@ -847,6 +863,19 @@ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag) 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;} failure: libdax_msgs_submit(libdax_messenger, -1, 0x0002015f, diff --git a/libburn/transport.h b/libburn/transport.h index fdabaa5..009c412 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -369,6 +369,11 @@ struct burn_drive 0x7ffffff0 = 32 bit overflow, or unknown stdio size */ 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 */ int role_5_nwa;