From dde52c1971a4a950fad33b6c85990c003481b595 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 31 Jan 2007 17:34:49 +0000 Subject: [PATCH] Provisorily obtain multi-session -C parameters (violates MMC specs but works) --- cdrskin/cdrskin.1 | 7 +++-- cdrskin/cdrskin.c | 23 ++++++++++----- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 26 +++++++++++++++++ libburn/libburn.h | 10 +++++++ libburn/mmc.c | 58 ++++++++++++++++++++++++++++++++++++- libburn/transport.h | 5 ++++ 7 files changed, 120 insertions(+), 11 deletions(-) diff --git a/cdrskin/cdrskin.1 b/cdrskin/cdrskin.1 index 44cfce2..15851e1 100644 --- a/cdrskin/cdrskin.1 +++ b/cdrskin/cdrskin.1 @@ -149,8 +149,9 @@ Note: The support for sequentially recordable media is still emerging. DVD-R have not been tested yet. If no Incremental Streaming feature (21h) is offered, then the media is regarded as unsuitable without further explanation. (One can torture DVD-RW to make them offer only DAO (2Fh)). -Only single-track sessions have been tested yet. Multi-session works but --toc and -msinfo are not implemented yet. +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 @@ -165,6 +166,8 @@ It resembles much TAO writing with CD, as it allows track sources of unpredicted length and to keep media appendable by option .B -multi . Only restriction towards CD-RW is the lack of support for -audio tracks. +Multiple tracks per session are permissible. A reasonable use case for +this has still to be found, though. .br (The other write mode, DAO, is not implemented yet. It will allow no -multi and only a single track.) diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index a188ce9..52bfb98 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -127,6 +127,9 @@ or #ifdef Cdrskin_libburn_0_3_1 #define Cdrskin_libburn_versioN "0.3.1" #define Cdrskin_libburn_from_pykix_svN 1 + +#define Cdrskin_libburn_has_get_msc1 1 + #endif /* Cdrskin_libburn_0_3_1 */ #ifndef Cdrskin_libburn_versioN @@ -3484,12 +3487,19 @@ int Cdrskin_msinfo(struct CdrskiN *skin, int flag) s= burn_disc_get_status(drive); if(s!=BURN_DISC_APPENDABLE) { Cdrskin_report_disc_status(skin,s,0); - fprintf(stderr, - "cdrskin: FATAL : -msinfo can only operate on appendable (i.e. -multi) CD\n"); + fprintf(stderr,"cdrskin: FATAL : -msinfo can only operate on appendable (i.e. -multi) discs\n"); {ret= 0; goto ex;} } disc= burn_drive_get_disc(drive); if(disc==NULL) { + +#ifdef Cdrskin_libburn_has_get_msc1 + /* No TOC available. Try to inquire directly. */ + ret= burn_disc_get_msc1(drive,&lba); + if(ret>0) + goto obtain_nwa; +#endif /* Cdrskin_libburn_has_get_msc1 */ + fprintf(stderr,"cdrskin: FATAL : Cannot obtain info about CD content\n"); {ret= 0; goto ex;} } @@ -3506,6 +3516,7 @@ int Cdrskin_msinfo(struct CdrskiN *skin, int flag) {ret= 0; goto ex;} } +obtain_nwa:; ret= Cdrskin_obtain_nwa(skin,&nwa,flag); if(ret<=0) { fprintf(stderr, @@ -4394,8 +4405,9 @@ int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s, strcpy(skin->preskin->write_mode_name,"TAO"); was_still_default= 2; /* prevents trying of SAO if drive dislikes TAO*/ } else if(profile_number==0x1a || profile_number==0x13 || - profile_number==0x12) { - /* DVD+RW , DVD-RW Restricted Overwrite , DVD-RAM */ + profile_number==0x12 || + profile_number==0x11 || profile_number==0x14) { + /* DVD+RW, DVD-RW Restr. Overwrite, DVD-RAM, DVD-R, DVD-RW Sequential */ strcpy(skin->preskin->write_mode_name,"TAO"); } else { strcpy(skin->preskin->write_mode_name,"SAO"); @@ -4639,9 +4651,6 @@ burn_failed:; burn_write_opts_set_perform_opc(o, 0); #ifdef Cdrskin_libburn_has_multI - if(skin->multi) - fprintf(stderr, - "cdrskin: NOTE : Option -multi set. Media will be appendable.\n"); burn_write_opts_set_multi(o,skin->multi); #endif diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 51aaaf9..77bfa96 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.01.31.130100" +#define Cdrskin_timestamP "2007.01.31.173611" diff --git a/libburn/drive.c b/libburn/drive.c index 531d983..015c931 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -1409,6 +1409,32 @@ int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, } +/* ts A70131 : new API function */ +int burn_disc_get_msc1(struct burn_drive *d, int *start) +{ + int ret, trackno; + + if (burn_drive_is_released(d)) { + libdax_msgs_submit(libdax_messenger, + d->global_index, 0x0002011b, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Attempt to read track info from ungrabbed drive", + 0, 0); + return -1; + } + if (d->busy != BURN_DRIVE_IDLE) { + libdax_msgs_submit(libdax_messenger, + d->global_index, 0x0002011c, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Attempt to read track info from busy drive", + 0, 0); + return -1; + } + ret = d->read_multi_session_c1(d, &trackno, start); + return ret; +} + + /* ts A61202 : New API function */ int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80]) { diff --git a/libburn/libburn.h b/libburn/libburn.h index 9fb1481..8472c8b 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -788,6 +788,16 @@ int burn_drive_get_start_end_lba(struct burn_drive *drive, int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, int trackno, int *lba, int *nwa); +/* ts A70131 */ +/** Read start lba of the first track in the last complete session. + This is the first parameter of mkisofs option -C. The second parameter + is nwa as obtained by burn_disc_track_lba_nwa() with trackno 0. + @param d The drive to query. + @param start_lba returns the start address of that track + @return <= 0 : failure, 1 = ok +*/ +int burn_disc_get_msc1(struct burn_drive *d, int *start_lba); + /* ts A61202 */ /** Tells the MMC Profile identifier of the loaded media. The drive must be grabbed in order to get a non-zero result. diff --git a/libburn/mmc.c b/libburn/mmc.c index bb5117c..5d397bc 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -84,6 +84,8 @@ Todo: */ +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_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 }; static unsigned char MMC_GET_DISC_INFO[] = @@ -421,6 +423,18 @@ void mmc_read_toc(struct burn_drive *d) mmc_function_spy("mmc_read_toc"); memcpy(c.opcode, MMC_GET_TOC, sizeof(MMC_GET_TOC)); + if(!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 */ + /* One could try + 51h READ DISC INFORMATION and 52h READ TRACK INFORMATION + where 51h gives the number of tracks and 52h tells the + session number with each track. */ + + /* >>> One must do someting */; + + } c.retry = 1; c.oplen = sizeof(MMC_GET_TOC); c.page = &buf; @@ -442,7 +456,7 @@ void mmc_read_toc(struct burn_drive *d) libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010d, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, - "Could not inquire TOC (non-blank DVD media ?)", 0,0); + "Could not inquire TOC", 0,0); d->status = BURN_DISC_UNSUITABLE; d->toc_entries = 0; /* Prefering memory leaks over fandangos */ @@ -541,6 +555,47 @@ void mmc_read_toc(struct burn_drive *d) toc_find_modes(d); } + +/* ts A70131 : If no TOC is at hand, this tries to get the start of the + last complete session (mksifs -c first parameter) */ +int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start) +{ + struct buffer buf; + struct command c; + unsigned char *tdata; + + mmc_function_spy("mmc_read_multi_session_c"); + + /* mmc5r03.pdf 6.26.3.3.3 states that with non-CD this would + be a useless fake always starting at track 1, lba 0. + My drives return useful data, though. + MMC-3 states that DVD had not tracks. So maybe this fake is + 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) + */ + memcpy(c.opcode, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO)); + c.retry = 1; + c.oplen = sizeof(MMC_GET_MSINFO); + c.page = &buf; + c.page->bytes = 0; + c.page->sectors = 0; + c.dir = FROM_DRIVE; + d->issue_command(d, &c); + + if (c.error) + return 0; + + tdata = c.page->data + 4; + *trackno = tdata[2]; + *start = (tdata[4] << 24) | (tdata[5] << 16) + | (tdata[6] << 8) | tdata[7]; + return 1; +} + + void mmc_read_disc_info(struct burn_drive *d) { struct buffer buf; @@ -1806,6 +1861,7 @@ int mmc_setup_drive(struct burn_drive *d) d->send_cue_sheet = mmc_send_cue_sheet; d->sync_cache = mmc_sync_cache; d->get_nwa = mmc_get_nwa; + d->read_multi_session_c1 = mmc_read_multi_session_c1; d->close_disc = mmc_close_disc; d->close_session = mmc_close_session; d->close_track_session = mmc_close; diff --git a/libburn/transport.h b/libburn/transport.h index 31cf3cf..bbc71ce 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -250,6 +250,11 @@ struct burn_drive int (*get_erase_progress) (struct burn_drive *); int (*get_nwa) (struct burn_drive *, int trackno, int *lba, int *nwa); + /* ts A70131 : obtain (possibly fake) TOC number and start lba of + first track in last complete session */ + int (*read_multi_session_c1)(struct burn_drive *d, + int *trackno, int *start); + /* ts A61009 : removed d in favor of o->drive */ /* void (*close_disc) (struct burn_drive * d, struct burn_write_opts * o);