From cf0dd395f0e7651ce59b3ccb77baaa859513c460 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 11 Aug 2007 20:16:57 +0000 Subject: [PATCH] New API function burn_random_access_write() --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/libburn.h | 41 +++++++++++++++--- libburn/libdax_msgs.h | 2 + libburn/write.c | 85 +++++++++++++++++++++++++++++++++++-- 4 files changed, 121 insertions(+), 9 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index fa00769..1d0c71f 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.08.11.075330" +#define Cdrskin_timestamP "2007.08.11.202027" diff --git a/libburn/libburn.h b/libburn/libburn.h index 66267f1..36263de 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1427,11 +1427,14 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi); /* ts A61222 */ /** Sets a start address for writing to media and write modes which allow to - choose this address at all (DVD+RW, DVD-RAM, formatted DVD-RW only for + choose this address at all (for now: DVD+RW, DVD-RAM, formatted DVD-RW). now). The address is given in bytes. If it is not -1 then a write run will fail if choice of start address is not supported or if the block alignment of the address is not suitable for media and write mode. - (Alignment to 32 kB blocks is advised with DVD media.) + Alignment to 32 kB blocks is supposed to be safe with DVD media. + Call burn_disc_get_multi_caps() can obtain the necessary media info. See + resulting struct burn_multi_caps elements .start_adr , .start_alignment , + .start_range_low , .start_range_high . @param opts The write opts to change @param value The address in bytes (-1 = start at default address) */ @@ -1788,9 +1791,9 @@ int burn_msgs_obtain(char *minimum_severity, /* ts A61002 */ -/* The prototype of a handler function suitable for burn_set_abort_handling(). - Such a function has to return -2 if it does not want the process to - exit with value 1. +/** The prototype of a handler function suitable for burn_set_abort_handling(). + Such a function has to return -2 if it does not want the process to + exit with value 1. */ typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag); @@ -1810,6 +1813,34 @@ typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag); void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, int mode); +/* ts A70811 */ +/** Circumvent usual libburn session processing and rather write data without + preparations or finalizing. This will work only with overwriteable media + which are also suitable for burn_write_opts_set_start_byte(). The same + address alignment restrictions as with this function apply. I.e. for DVD + it is best to align to 32 KiB blocks (= 16 LBA units). The amount of data + to be written is subject to the same media dependent alignment rules. + Again, 32 KiB is most safe. + Call burn_disc_get_multi_caps() can obtain the necessary media info. See + resulting struct burn_multi_caps elements .start_adr , .start_alignment , + .start_range_low , .start_range_high . + Other than burn_disc_write() this is a synchronous call which returns + only after the write transaction has ended (sucessfully or not). So it is + wise not to transfer giant amounts of data in a single call. + @param d The drive to which to write + @param byte_address The start address of the write in byte + (1 LBA unit = 2048 bytes) (do respect media alignment) + @param data The bytes to be written + @param data_count The number of those bytes (do respect media alignment) + data_count == 0 is permitted (e.g. to flush the + drive buffer without further data transfer). + @param flag Bitfield for control purposes: + bit0 = flush the drive buffer after eventual writing + @return 1=sucessful , <=0 : number of tranfered bytes * -1 +*/ +int burn_random_access_write(struct burn_drive *d, off_t byte_address, + char *data, off_t data_count, int flag); + #ifndef DOXYGEN BURN_END_DECLS diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 4c37612..c71e5c0 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -371,6 +371,8 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x0002013d (DEBUG,LOW) = Waiting for free buffer space takes long time 0x0002013e (SORRY,HIGH) = Timeout with waiting for free buffer. Now disabled 0x0002013f (DEBUG,LOW) = Reporting total time spent with waiting for buffer + 0x00020140 (FATAL,HIGH) = Drive is busy on attempt to write random access + 0x00020141 (SORRY,HIGH) = Write data count not properly aligned libdax_audioxtr: diff --git a/libburn/write.c b/libburn/write.c index d00e02b..478b87e 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -1523,7 +1523,7 @@ int burn_dvd_write_sync(struct burn_write_opts *o, sprintf(msg, "Write start address not properly aligned to 2048"); libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020125, + 0x00020126, LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); goto early_failure; @@ -1553,7 +1553,7 @@ int burn_dvd_write_sync(struct burn_write_opts *o, sprintf(msg, "Write start address not properly aligned to 32K"); libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020125, + 0x00020126, LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); goto early_failure; @@ -1636,7 +1636,7 @@ int burn_dvd_write_sync(struct burn_write_opts *o, if (o->start_byte >= 0) { sprintf(msg, "Write start address not supported"); libdax_msgs_submit(libdax_messenger, d->global_index, - 0x00020124, + 0x00020125, LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); goto early_failure; @@ -1969,3 +1969,82 @@ fail_wo_sync:; d->cancel = 1; d->busy = BURN_DRIVE_IDLE; } + + +int burn_random_access_write(struct burn_drive *d, off_t byte_address, + char *data, off_t data_count, int flag) +{ + int alignment = 0, start, upto, chunksize, err; + char msg[81], *rpt; + struct buffer buf; + + if (d->current_profile == 0x12) /* DVD-RAM */ + alignment = 2 * 1024; + if (d->current_profile == 0x13) /* DVD-RW restricted overwrite */ + alignment = 32 * 1024; + if (d->current_profile == 0x1a) /* DVD+RW */ + alignment = 2 * 1024; + if (alignment == 0) { + sprintf(msg, "Write start address not supported"); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020125, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Write start address not supported", 0, 0); + return 0; + } + if ((byte_address % alignment) != 0) { + sprintf(msg, + "Write start address not properly aligned (%d bytes)", + alignment); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020126, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + return 0; + } + if ((data_count % alignment) != 0) { + sprintf(msg, + "Write data count not properly aligned (%ld bytes)", + (long) alignment); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020141, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + return 0; + } + + if (d->busy != BURN_DRIVE_IDLE) { + libdax_msgs_submit(libdax_messenger, + d->global_index, 0x00020140, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Drive is busy on attempt to write random access",0,0); + return 0; + } + d->busy = BURN_DRIVE_WRITING; + d->buffer = &buf; + + start = byte_address / 2048; + upto = start + data_count / 2048; + rpt = data; + for (; start < upto; start += 16) { + chunksize = upto - start; + if (chunksize > 16) + chunksize = 16; + d->buffer->bytes = chunksize * 2048; + memcpy(d->buffer->data, rpt, d->buffer->bytes); + rpt += d->buffer->bytes; + d->buffer->sectors = chunksize; + d->nwa = start; + err = d->write(d, d->nwa, d->buffer); + if (err == BE_CANCELLED) { + d->busy = BURN_DRIVE_IDLE; + return (-(start * 2048 - byte_address)); + } + } + + if (flag & 1) + d->sync_cache(d); + d->busy = BURN_DRIVE_IDLE; + return(1); +} +