Preparations for supporting DVD+R[/DL]

This commit is contained in:
2007-03-01 12:07:29 +00:00
parent 0c4cfdd359
commit 3b5c80e867
6 changed files with 348 additions and 120 deletions

View File

@ -1696,8 +1696,7 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
o->advised_write_mode = BURN_WRITE_TAO;
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */
o->multi_session = 1;
o->multi_track = 1;
o->multi_session = o->multi_track = 1;
o->might_do_tao = 2;
o->might_do_sao = 1;
o->advised_write_mode = BURN_WRITE_TAO;

View File

@ -89,8 +89,6 @@ extern struct libdax_msgs *libdax_messenger;
size prediction mandatory.
ts A70208 : Finally made tests with DVD-R. Worked exactly as new DVD-RW.
Todo:
Determine first free lba for appending data on overwriteables.
*/
@ -242,7 +240,6 @@ int mmc_reserve_track(struct burn_drive *d, off_t size)
int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf)
{
struct command c;
int i;
mmc_function_spy("mmc_read_track_info");
c.retry = 1;
@ -263,8 +260,7 @@ int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf)
else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
trackno = 0xFF;
}
for (i = 0; i < 4; i++)
c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff;
mmc_int_to_four_char(c.opcode + 2, trackno);
c.page = buf;
memset(buf->data, 0, BUFFER_SIZE);
c.dir = FROM_DRIVE;
@ -285,26 +281,11 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
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 == 0x10 ||
d->current_profile == 0x11 ||
d->current_profile == 0x14 ||
d->current_profile == 0x15)
/* DVD-ROM, DVD-R[W] Sequential */
trackno = d->last_track_no;
else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
trackno = 0xFF;
}
ret = mmc_read_track_info(d, trackno, &buf);
if (ret <= 0)
return ret;
data = buf.data;
*lba = mmc_four_char_to_int(data + 8);
*nwa = mmc_four_char_to_int(data + 12);
num = mmc_four_char_to_int(data + 16);
@ -375,6 +356,11 @@ void mmc_close_session(struct burn_write_opts *o)
mmc_close(d, 1, 0);
}
/* ts A70227 : extended meaning of session to address all possible values
of 5Bh CLOSE TRACK SESSION to address any Close Function.
@param session contains the two high bits of Close Function
@param track if not 0: sets the lowest bit of Close Function
*/
void mmc_close(struct burn_drive *d, int session, int track)
{
struct command c;
@ -385,8 +371,8 @@ void mmc_close(struct burn_drive *d, int session, int track)
c.oplen = sizeof(MMC_CLOSE);
memcpy(c.opcode, MMC_CLOSE, sizeof(MMC_CLOSE));
/* ts A61030 : shifted !!session rather than or-ing plain session */
c.opcode[2] = ((!!session)<<1) | !!track;
/* (ts A61030 : shifted !!session rather than or-ing plain session ) */
c.opcode[2] = ((session & 3) << 1) | !!track;
c.opcode[4] = track >> 8;
c.opcode[5] = track & 0xFF;
c.page = NULL;
@ -431,14 +417,8 @@ void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
memcpy(c.opcode, MMC_WRITE_12, sizeof(MMC_WRITE_12));
c.retry = 1;
c.oplen = sizeof(MMC_WRITE_12);
c.opcode[2] = start >> 24;
c.opcode[3] = (start >> 16) & 0xFF;
c.opcode[4] = (start >> 8) & 0xFF;
c.opcode[5] = start & 0xFF;
c.opcode[6] = len >> 24;
c.opcode[7] = (len >> 16) & 0xFF;
c.opcode[8] = (len >> 8) & 0xFF;
c.opcode[9] = len & 0xFF;
mmc_int_to_four_char(c.opcode + 2, start);
mmc_int_to_four_char(c.opcode + 6, len);
c.page = buf;
c.dir = TO_DRIVE;
@ -491,10 +471,7 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
memcpy(c.opcode, MMC_WRITE_10, sizeof(MMC_WRITE_10));
c.retry = 1;
c.oplen = sizeof(MMC_WRITE_10);
c.opcode[2] = start >> 24;
c.opcode[3] = (start >> 16) & 0xFF;
c.opcode[4] = (start >> 8) & 0xFF;
c.opcode[5] = start & 0xFF;
mmc_int_to_four_char(c.opcode + 2, start);
c.opcode[6] = 0;
c.opcode[7] = (len >> 8) & 0xFF;
c.opcode[8] = len & 0xFF;
@ -1561,6 +1538,11 @@ void mmc_get_configuration(struct burn_drive *d)
if (cp == 0x15 && burn_support_untested_profiles) /* DVD-R/DL */
d->current_is_supported_profile = 1;
#endif
#ifdef Libburn_support_dvd_plusR
if ((cp == 0x1b || cp == 0x2b) &&
burn_support_untested_profiles) /* DVD+R , DVD+R/DL */
d->current_is_supported_profile = 1;
#endif
/* Enable this to get loud and repeated reports about the feature set :
#define Libburn_print_feature_descriptorS 1
@ -1916,8 +1898,8 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
c.page->data[1] = 0x02; /* Immed */
c.page->data[3] = 8; /* Format descriptor length */
num_of_blocks = size / 2048;
for (i = 0; i < 4; i++)
c.page->data[4 + i] = (num_of_blocks >> (24 - 8 * i)) & 0xff;
mmc_int_to_four_char(c.page->data + 4, num_of_blocks);
if (flag & 128) { /* explicitely chosen format descriptor */
/* use case: the app knows what to do */
@ -1947,9 +1929,7 @@ selected_not_suitable:;
if (flag & 4) {
num_of_blocks =
d->format_descriptors[index].size / 2048;
for (i = 0; i < 4; i++)
c.page->data[4 + i] =
(num_of_blocks >> (24 - 8 * i)) & 0xff;
mmc_int_to_four_char(c.page->data + 4, num_of_blocks);
}
if (format_type != 0x26)
for (i = 0; i < 3; i++)
@ -2024,9 +2004,8 @@ selected_not_suitable:;
num_of_blocks = diff;
}
if (num_of_blocks > 0)
for (i = 0; i < 4; i++)
c.page->data[4 + i] =
(num_of_blocks >> (24 - 8 * i)) & 0xff;
mmc_int_to_four_char(c.page->data + 4,
num_of_blocks);
}
/* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */
format_type = 0x13;
@ -2050,9 +2029,8 @@ selected_not_suitable:;
if ((flag & 4)
|| d->best_format_type == full_format_type) {
num_of_blocks = d->best_format_size / 2048;
for (i = 0; i < 4; i++)
c.page->data[4 + i] =
(num_of_blocks >> (24 - 8 * i)) & 0xff;
mmc_int_to_four_char(c.page->data + 4,
num_of_blocks);
}
} else {
@ -2356,6 +2334,10 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
/* Packet Size */
pd[13] = 16;
} else if (d->current_profile == 0x1a || d->current_profile == 0x1b ||
d->current_profile == 0x2b || d->current_profile == 0x12) {
/* not with DVD+R[W][/DL] or DVD-RAM */;
return 0;
} else {
/* Traditional setup for CD */

View File

@ -890,6 +890,84 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
}
/* ts A70219 : API */
int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
char reasons[BURN_REASONS_LEN], int silent)
{
enum burn_write_types wt;
struct burn_drive *d = o->drive;
char msg[160], *reason_pt;
int no_media = 0;
reason_pt= reasons;
reasons[0] = 0;
/* check write mode against write job */
wt = burn_write_opts_auto_write_type(o, disc, reasons, 1);
if (wt == BURN_WRITE_NONE) {
if (strncmp(reasons, "MEDIA: ", 7)==0)
no_media = 1;
goto ex;
}
sprintf(reasons, "%s: ", d->current_profile_text);
reason_pt= reasons + strlen(reasons);
if (d->status == BURN_DISC_UNSUITABLE)
goto unsuitable_profile;
if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1))
strcat(reasons, "unsuitable track mode found, ");
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else if (d->current_profile == 0x1a || d->current_profile == 0x12) {
/* DVD+RW , DVD-RAM */
if (o->start_byte >= 0 && (o->start_byte % 2048))
strcat(reasons,
"write start address not properly aligned to 2048, ");
} else if (d->current_profile == 0x13) {
/* DVD-RW Restricted Overwrite */
if (o->start_byte >= 0 && (o->start_byte % 32768))
strcat(reasons,
"write start address not properly aligned to 32k, ");
} else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15 ||
d->current_profile == 0x1b || d->current_profile == 0x2b ) {
/* DVD-R* Sequential , DVD+R[/DL] */
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else {
unsuitable_profile:;
sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text);
if (!silent)
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011e,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
strcat(reasons, "no suitable media profile detected, ");
return 0;
}
ex:;
if (reason_pt[0]) {
if (no_media) {
if (!silent)
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002013a,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"No suitable media detected", 0, 0);
return -1;
}
if (!silent)
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020139,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Write job parameters are unsuitable", 0, 0);
return 0;
}
return 1;
}
/* ts A70129 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum)
@ -931,6 +1009,46 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
}
/* ts A70226 */
int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum)
{
struct burn_drive *d = o->drive;
char msg[160];
int ret, lba, nwa;
off_t size;
ret = d->get_nwa(d, -1, &lba, &nwa);
sprintf(msg,
"DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d",
tnum+1, nwa, ret, d->nwa);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0);
if (nwa > d->nwa)
d->nwa = nwa;
/* ts A70214 : eventually adjust already expanded size of track */
burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1);
if (o->write_type == BURN_WRITE_SAO) {
/* Round track size up to 32 KiB and reserve track */
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
* (off_t) 2048;
size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff);
ret = d->reserve_track(d, size);
if (ret <= 0) {
sprintf(msg, "Cannot reserve track of %.f bytes",
(double) size);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020138,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
}
return 1;
}
/* ts A70129 */
int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum)
@ -956,6 +1074,28 @@ int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o,
}
/* ts A70226 */
int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum)
{
struct burn_drive *d = o->drive;
char msg[80];
sprintf(msg,
"Closing track %2.2d (absolute track and session number %d)",
tnum + 1, d->last_track_no);
libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0);
d->busy = BURN_DRIVE_CLOSING_SESSION;
d->close_track_session(d, 0, d->last_track_no); /* CLOSE TRACK, 001b */
d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
d->busy = BURN_DRIVE_WRITING;
d->last_track_no++;
return 1;
}
/* ts A61218 - A70129 */
int burn_dvd_write_track(struct burn_write_opts *o,
struct burn_session *s, int tnum)
@ -975,6 +1115,11 @@ int burn_dvd_write_track(struct burn_write_opts *o,
ret = burn_disc_open_track_dvd_minus_r(o, s, tnum);
if (ret <= 0)
goto ex;
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */
ret = burn_disc_open_track_dvd_plus_r(o, s, tnum);
if (ret <= 0)
goto ex;
}
sectors = burn_track_get_sectors(t);
@ -1035,7 +1180,12 @@ int burn_dvd_write_track(struct burn_write_opts *o,
d->current_profile == 0x15) {
/* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */
ret = burn_disc_close_track_dvd_minus_r(o, s, tnum);
if (ret != 2)
if (ret <= 0)
goto ex;
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */
ret = burn_disc_close_track_dvd_plus_r(o, s, tnum);
if (ret <= 0)
goto ex;
}
ret = 1;
@ -1148,6 +1298,8 @@ int burn_dvd_write_session(struct burn_write_opts *o,
if (ret <= 0)
return 0;
}
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL do each track as an own session */;
}
return 1;
}
@ -1258,76 +1410,30 @@ int burn_disc_setup_dvd_minus_r(struct burn_write_opts *o,
}
/* ts A70219 : API */
int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
char reasons[BURN_REASONS_LEN], int silent)
/* ts A70226 : for DVD+R , DVD+R/DL */
int burn_disc_setup_dvd_plus_r(struct burn_write_opts *o,
struct burn_disc *disc)
{
enum burn_write_types wt;
struct burn_drive *d = o->drive;
char msg[160], *reason_pt;
int no_media = 0;
reason_pt= reasons;
reasons[0] = 0;
/* most setup is in burn_disc_setup_track_dvd_plus_r() */;
/* check write mode against write job */
wt = burn_write_opts_auto_write_type(o, disc, reasons, 1);
if (wt == BURN_WRITE_NONE) {
if (strncmp(reasons, "MEDIA: ", 7)==0)
no_media = 1;
goto ex;
}
d->nwa = 0;
return 1;
}
sprintf(reasons, "%s: ", d->current_profile_text);
reason_pt= reasons + strlen(reasons);
if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1))
strcat(reasons, "unsuitable track mode found, ");
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else if (d->current_profile == 0x1a || d->current_profile == 0x12) {
/* DVD+RW , DVD-RAM */
if (o->start_byte >= 0 && (o->start_byte % 2048))
strcat(reasons,
"write start address not properly aligned to 2048, ");
} else if (d->current_profile == 0x13) {
/* DVD-RW Restricted Overwrite */
if (o->start_byte >= 0 && (o->start_byte % 32768))
strcat(reasons,
"write start address not properly aligned to 32k, ");
} else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15) {
/* DVD-R* Sequential */
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else {
sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text);
if (!silent)
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011e,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
strcat(reasons, "no suitable media profile detected, ");
return 0;
}
ex:;
if (reason_pt[0]) {
if (no_media) {
if (!silent)
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002013a,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"No suitable media detected", 0, 0);
return -1;
}
if (!silent)
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020139,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Write job parameters are unsuitable", 0, 0);
return 0;
}
/* ts A70229 */
int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o)
{
struct burn_drive *d = o->drive;
if (o->multi)
return 2;
d->busy = BURN_DRIVE_CLOSING_SESSION;
/* CLOSE SESSION, 101b, Finalize with minimal radius */
d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */
d->busy = BURN_DRIVE_WRITING;
return 1;
}
@ -1534,6 +1640,38 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
/* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */
t = disc->session[0]->track[0];
o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media );
default_size = burn_track_get_default_size(t);
#ifndef Libburn_precheck_write_ruleS
/* >>> oldfashioned checks hopefully never re-enabled */
#endif /* ! Libburn_precheck_write_ruleS */
if (o->write_type == BURN_WRITE_SAO && o_end) {
sprintf(msg, "Activated track default size %.f",
(double) default_size);
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002012e,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
burn_track_set_size(t, default_size);
}
ret = burn_disc_setup_dvd_plus_r(o, disc);
if (ret <= 0) {
sprintf(msg,
"Write preparation setup failed for DVD+R");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020121,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto early_failure;
}
/* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */
} else {
@ -1564,8 +1702,11 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
d->progress.sectors = 0;
}
/* >>> eventual normal finalization measures */
if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
ret = burn_disc_finalize_dvd_plus_r(o);
if (ret <= 0)
goto ex;
}
ret = 1;
ex:;