From 82c6e92da01ddbf6820ce4278865934008afb0a3 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 29 Nov 2007 18:55:06 +0000 Subject: [PATCH] Enabled reading of TOC from ROM drives (direly needed for xorriso) --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 4 +- libburn/libdax_msgs.h | 2 +- libburn/mmc.c | 167 +++++++++++++++++++++++++++++++++++- libburn/spc.c | 14 +-- 5 files changed, 177 insertions(+), 12 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 3d6d52d..d468b39 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.11.26.154817" +#define Cdrskin_timestamP "2007.11.29.185342" diff --git a/libburn/drive.c b/libburn/drive.c index 4508259..ab46eb7 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -201,7 +201,9 @@ int burn_drive_inquire_media(struct burn_drive *d) /* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */ - if (d->mdata->cdr_write || d->mdata->cdrw_write || + /* ts A71128 : run read_disc_info() for any recognizeable profile */ + if (d->current_profile > 0 || + d->mdata->cdr_write || d->mdata->cdrw_write || d->mdata->dvdr_write || d->mdata->dvdram_write) { #define Libburn_knows_correct_state_after_loaD 1 diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 4b44209..09a4382 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -441,7 +441,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020156 (SORRY,HIGH) = Desired fifo buffer too small 0x00020157 (FATAL,HIGH) = burn_source is not a fifo object 0x00020158 (DEBUG,LOW) = Reporting thread disposal precautions - + 0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data libdax_audioxtr: 0x00020200 (SORRY,HIGH) = Cannot open audio source file diff --git a/libburn/mmc.c b/libburn/mmc.c index d1c9fae..1a9b623 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -116,6 +116,7 @@ extern struct libdax_msgs *libdax_messenger; static unsigned char MMC_GET_MSINFO[] = { 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 }; static unsigned char MMC_GET_TOC[] = { 0x43, 2, 2, 0, 0, 0, 0, 16, 0, 0 }; +static unsigned char MMC_GET_TOC_FMT0[] = { 0x43, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; static unsigned char MMC_GET_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 }; static unsigned char MMC_GET_DISC_INFO[] = { 0x51, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; @@ -797,6 +798,153 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number, } +/* ts A71128 : for DVD-ROM drives which offer no reliable track information */ +static int mmc_read_toc_fmt0_al(struct burn_drive *d, int *alloc_len) +{ + struct burn_track *track; + struct burn_session *session; + struct burn_toc_entry *entry; + struct buffer buf; + struct command c; + int dlen, i, old_alloc_len, session_number, prev_session = -1; + int lba, size; + unsigned char *tdata, size_data[4], start_data[4]; + + if (*alloc_len < 4) + return 0; + + scsi_init_command(&c, MMC_GET_TOC_FMT0, sizeof(MMC_GET_TOC_FMT0)); + c.dxfer_len = *alloc_len; + c.opcode[7] = (c.dxfer_len >> 8) & 0xff; + c.opcode[8] = c.dxfer_len & 0xff; + c.retry = 1; + c.page = &buf; + c.page->bytes = 0; + c.page->sectors = 0; + c.dir = FROM_DRIVE; + d->issue_command(d, &c); + + if (c.error) { +err_ex:; + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x0002010d, + LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, + "Could not inquire TOC", 0,0); + d->status = BURN_DISC_UNSUITABLE; + d->toc_entries = 0; + /* Prefering memory leaks over fandangos */ + d->toc_entry = calloc(1, sizeof(struct burn_toc_entry)); + return 0; + } + dlen = c.page->data[0] * 256 + c.page->data[1]; + old_alloc_len = *alloc_len; + *alloc_len = dlen + 2; + if (old_alloc_len < 12) + return 1; + if (dlen + 2 > old_alloc_len) + dlen = old_alloc_len - 2; + d->complete_sessions = 1 + c.page->data[3] - c.page->data[2]; + d->last_track_no = d->complete_sessions; + if (dlen - 2 < (d->last_track_no + 1) * 8) { + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020159, + LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, + "TOC Format 0 returns inconsistent data", 0,0); + goto err_ex; + } + + d->toc_entries = d->last_track_no + d->complete_sessions; + if (d->toc_entries < 1) + return 0; + d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry)); + if(d->toc_entry == NULL) + return 0; + + d->disc = burn_disc_create(); + if (d->disc == NULL) + return 0; + for (i = 0; i < d->complete_sessions; i++) { + session = burn_session_create(); + if (session == NULL) + return 0; + burn_disc_add_session(d->disc, session, BURN_POS_END); + burn_session_free(session); + } + + + for (i = 0; i < d->last_track_no; i++) { + tdata = c.page->data + 4 + i * 8; + session_number = i + 1; + if (session_number != prev_session && prev_session > 0) { + /* leadout entry previous session */ + 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, prev_session, 0xA2, + size_data, start_data); + entry->min= entry->sec= entry->frame= 0; + d->disc->session[prev_session - 1]->leadout_entry = + entry; + } + + /* ??? >>> d->media_capacity_remaining , d->media_lba_limit + as of mmc_fake_toc() + */ + + 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(start_data, tdata + 4, 4); + /* size_data are estimated from next track start */ + memcpy(size_data, tdata + 8 + 4, 4); + size = mmc_four_char_to_int(size_data) - + mmc_four_char_to_int(start_data); + mmc_int_to_four_char(size_data, size); + mmc_fake_toc_entry(entry, session_number, i + 1, + size_data, start_data); + 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; + } + if (prev_session > 0 && prev_session <= d->disc->sessions) { + /* leadout entry of last session of closed disc */ + tdata = c.page->data + 4 + d->last_track_no * 8; + entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]); + memcpy(start_data, tdata + 4, 4); + mmc_int_to_four_char(size_data, 0); + mmc_fake_toc_entry(entry, prev_session, 0xA2, + size_data, start_data); + entry->min= entry->sec= entry->frame= 0; + d->disc->session[prev_session - 1]->leadout_entry = entry; + } + return 1; +} + + +/* ts A71128 : for DVD-ROM drives which offer no reliable track information */ +static int mmc_read_toc_fmt0(struct burn_drive *d) +{ + int alloc_len = 4, ret; + + if (mmc_function_spy(d, "mmc_read_toc_fmt0") <= 0) + return -1; + ret = mmc_read_toc_fmt0_al(d, &alloc_len); + if (alloc_len >= 12) + ret = mmc_read_toc_fmt0_al(d, &alloc_len); + return ret; +} + + /* ts A70131 : compose a disc TOC structure from d->complete_sessions and 52h READ TRACK INFORMATION */ int mmc_fake_toc(struct burn_drive *d) @@ -825,6 +973,12 @@ int mmc_fake_toc(struct burn_drive *d) msg, 0,0); return 0; } + /* ts A71128 : My DVD-ROM drive issues no reliable track info. + One has to try 43h READ TOC/PMA/ATIP Form 0. */ + if (d->current_profile == 0x10 && d->last_track_no <= 1) { + ret = mmc_read_toc_fmt0(d); + return ret; + } d->disc = burn_disc_create(); if (d->disc == NULL) return -1; @@ -835,12 +989,15 @@ int mmc_fake_toc(struct burn_drive *d) 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(); + if (session == NULL) + return -1; 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 ... @@ -943,13 +1100,15 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len) if (!(d->current_profile == -1 || d->current_is_cd_profile)) { /* ts A70131 : MMC_GET_TOC uses Response Format 2 For DVD this fails with 5,24,00 */ - /* One could try Response Format 0: mmc5r03.pdf 6.26.3.2 - which does not yield the same result wit the same disc + /* mmc_read_toc_fmt0() uses + Response Format 0: mmc5r03.pdf 6.26.3.2 + which does not yield the same result with the same disc on different drives. */ /* ts A70201 : This uses the session count from 51h READ DISC INFORMATION - and the track records from 52h READ TRACK INFORMATION + and the track records from 52h READ TRACK INFORMATION. + mmc_read_toc_fmt0() is used as fallback for dull DVD-ROM. */ mmc_fake_toc(d); @@ -1251,7 +1410,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len) *alloc_len = len + 2; if (old_alloc_len < 34) return 1; - if (*alloc_len < 24) /* data[23] is the last byte used her */ + if (*alloc_len < 24) /* data[23] is the last byte used here */ return 0; if (len + 2 > old_alloc_len) len = old_alloc_len - 2; diff --git a/libburn/spc.c b/libburn/spc.c index dadd3f6..107abac 100644 --- a/libburn/spc.c +++ b/libburn/spc.c @@ -566,12 +566,16 @@ void spc_sense_write_params(struct burn_drive *d) c.dir = FROM_DRIVE; d->issue_command(d, &c); - size = c.page->data[0] * 256 + c.page->data[1]; + /* ts A71128 : do not interpret reply if error */ m = d->mdata; - page = c.page->data + 8; - burn_print(1, "write page length 0x%x\n", page[1]); - m->write_page_length = page[1]; - m->write_page_valid = 1; + if(!c.error) { + size = c.page->data[0] * 256 + c.page->data[1]; + page = c.page->data + 8; + burn_print(1, "write page length 0x%x\n", page[1]); + m->write_page_length = page[1]; + m->write_page_valid = 1; + } else + m->write_page_valid = 0; mmc_read_disc_info(d); /* ts A70212 : try to setup d->media_capacity_remaining */