From 9a1e8a34a535db3e8942f5842934b290d4ab1838 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sun, 12 Aug 2007 15:25:56 +0000 Subject: [PATCH] New API function burn_read_data() --- libburn/trunk/cdrskin/cdrskin_timestamp.h | 2 +- libburn/trunk/libburn/libburn.h | 30 +++++++++- libburn/trunk/libburn/libdax_msgs.h | 3 + libburn/trunk/libburn/mmc.c | 44 ++++++++++++++ libburn/trunk/libburn/mmc.h | 5 ++ libburn/trunk/libburn/read.c | 71 +++++++++++++++++++++++ libburn/trunk/libburn/transport.h | 5 ++ libburn/trunk/libburn/write.c | 5 +- 8 files changed, 161 insertions(+), 4 deletions(-) diff --git a/libburn/trunk/cdrskin/cdrskin_timestamp.h b/libburn/trunk/cdrskin/cdrskin_timestamp.h index 0b7db2fd..4281970e 100644 --- a/libburn/trunk/cdrskin/cdrskin_timestamp.h +++ b/libburn/trunk/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.08.12.095623" +#define Cdrskin_timestamP "2007.08.12.152937" diff --git a/libburn/trunk/libburn/libburn.h b/libburn/trunk/libburn/libburn.h index b3d1479b..b2e80375 100644 --- a/libburn/trunk/libburn/libburn.h +++ b/libburn/trunk/libburn/libburn.h @@ -1061,6 +1061,9 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc, Note: write_type BURN_WRITE_SAO is currently not capable of writing a mix of data and audio tracks. You must use BURN_WRITE_TAO for such sessions. To be set by burn_write_opts_set_write_type(). + Note: This function is not suitable for overwriting data in the middle of + a valid data area because it is allowed to append trailing data. + For exact random access overwriting use burn_random_access_write(). @param o The options for the writing operation. @param disc The struct burn_disc * that described the disc to be created */ @@ -1813,8 +1816,10 @@ 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 */ -/** The drive must be grabbed successfully before calling this function. It +/** Write data in random access mode. + The drive must be grabbed successfully before calling this function which circumvents usual libburn session processing and rather writes 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 @@ -1843,6 +1848,29 @@ void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, int burn_random_access_write(struct burn_drive *d, off_t byte_address, char *data, off_t data_count, int flag); + +/* ts A70812 */ +/** Read data in random access mode. + The drive must be grabbed successfully before calling this function. + With all currently supported drives and media the byte_address has to + be aligned to 2048 bytes. Only data tracks with 2048 bytes per sector + can be read this way. I.e. not CD-audio, not CD-video-stream ... + This is a synchronous call which returns only after the full read job + has ended (sucessfully or not). So it is wise not to read giant amounts + of data in a single call. + @param d The drive to which to write + @param byte_address The start address of the read in byte (aligned to 2048) + @param data A memory buffer capable of taking data_size bytes + @param data_size The amount of data to be read. This does not have to + be aligned to any block size. + @param data_count The amount of data actually read (interesting on error) + @param flag Bitfield for control purposes: (unused yet, submit 0) + @return 1=sucessful , <=0 an error occured +*/ +int burn_read_data(struct burn_drive *d, off_t byte_address, + char data[], off_t data_size, off_t *data_count, int flag); + + #ifndef DOXYGEN BURN_END_DECLS diff --git a/libburn/trunk/libburn/libdax_msgs.h b/libburn/trunk/libburn/libdax_msgs.h index 641bd5ef..dca2457f 100644 --- a/libburn/trunk/libburn/libdax_msgs.h +++ b/libburn/trunk/libburn/libdax_msgs.h @@ -374,6 +374,9 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020140 (FATAL,HIGH) = Drive is busy on attempt to write random access 0x00020141 (SORRY,HIGH) = Write data count not properly aligned 0x00020142 (FATAL,HIGH) = Drive is not grabbed on random access write + 0x00020143 (SORRY,HIGH) = Read start address not properly aligned + 0x00020144 (SORRY,HIGH) = SCSI error on read + 0x00020145 (FATAL,HIGH) = Drive is busy on attempt to read data libdax_audioxtr: diff --git a/libburn/trunk/libburn/mmc.c b/libburn/trunk/libburn/mmc.c index ee1d87c5..597ee5d9 100644 --- a/libburn/trunk/libburn/mmc.c +++ b/libburn/trunk/libburn/mmc.c @@ -165,6 +165,10 @@ static unsigned char MMC_READ_FORMAT_CAPACITIES[] = static unsigned char MMC_RESERVE_TRACK[] = { 0x53, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +/* ts A70812 : Read data sectors (for types with 2048 bytes/sector only) */ +static unsigned char MMC_READ_10[] = + { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + static int mmc_function_spy_do_tell = 0; @@ -2793,6 +2797,45 @@ int mmc_compose_mode_page_5(struct burn_drive *d, } +/* A70812 ts */ +int mmc_read_10(struct burn_drive *d, int start,int amount, struct buffer *buf) +{ + struct command c; + + mmc_function_spy("mmc_read_10"); + if (amount > BUFFER_SIZE / 2048) + return -1; + + scsi_init_command(&c, MMC_READ_10, sizeof(MMC_READ_10)); + c.dxfer_len = amount * 2048; + c.retry = 1; + mmc_int_to_four_char(c.opcode + 2, start); + c.opcode[7] = (amount >> 8) & 0xFF; + c.opcode[8] = amount & 0xFF; + c.page = buf; + c.page->bytes = 0; + c.page->sectors = 0; + c.dir = FROM_DRIVE; + d->issue_command(d, &c); + if (c.error) { + char msg[160]; + printf(msg, + "SCSI error on read_10(%d,%d): key=%X asc=%2.2Xh ascq=%2.2Xh", + start, amount, + c.sense[2],c.sense[12],c.sense[13]); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020144, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + return BE_CANCELLED; + } + + buf->sectors = amount; + buf->bytes = amount * 2048; + return 0; +} + + /* ts A61021 : the mmc specific part of sg.c:enumerate_common() */ int mmc_setup_drive(struct burn_drive *d) @@ -2815,6 +2858,7 @@ int mmc_setup_drive(struct burn_drive *d) d->read_buffer_capacity = mmc_read_buffer_capacity; d->format_unit = mmc_format_unit; d->read_format_capacities = mmc_read_format_capacities; + d->read_10 = mmc_read_10; /* ts A70302 */ diff --git a/libburn/trunk/libburn/mmc.h b/libburn/trunk/libburn/mmc.h index 0812bea5..9b075976 100644 --- a/libburn/trunk/libburn/mmc.h +++ b/libburn/trunk/libburn/mmc.h @@ -68,6 +68,11 @@ int mmc_compose_mode_page_5(struct burn_drive *d, const struct burn_write_opts *o, unsigned char *pd); +/* ts A70812 : return 0 = ok , return BE_CANCELLED = error occured */ +int mmc_read_10(struct burn_drive *d, int start, int amount, + struct buffer *buf); + + /* mmc5r03c.pdf 4.3.4.4.1 d) "The maximum number of RZones is 2 302." */ #define BURN_MMC_FAKE_TOC_MAX_SIZE 2302 diff --git a/libburn/trunk/libburn/read.c b/libburn/trunk/libburn/read.c index 72f60d78..716e16b2 100644 --- a/libburn/trunk/libburn/read.c +++ b/libburn/trunk/libburn/read.c @@ -31,6 +31,12 @@ #include "read.h" #include "options.h" +/* ts A70812 */ +#include "error.h" +#include "libdax_msgs.h" +extern struct libdax_msgs *libdax_messenger; + + void burn_disc_read(struct burn_drive *d, const struct burn_read_opts *o) { #if 0 @@ -280,3 +286,68 @@ static void flipq(unsigned char *sub) *(sub + 12 + 11) = ~*(sub + 12 + 11); } */ + + +/* ts A70812 : API function */ +int burn_read_data(struct burn_drive *d, off_t byte_address, + char data[], off_t data_size, off_t *data_count, int flag) +{ + int alignment = 2048, start, upto, chunksize, err, cpy_size; + char msg[81], *wpt; + struct buffer buf; + + *data_count = 0; + if (d->released) { + libdax_msgs_submit(libdax_messenger, + d->global_index, 0x00020142, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Drive is not grabbed on random access write", 0, 0); + return 0; + } + if ((byte_address % alignment) != 0) { + sprintf(msg, + "Read start address not properly aligned (%d bytes)", + alignment); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020143, + 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, 0x00020145, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Drive is busy on attempt to read data", 0, 0); + return 0; + } + d->busy = BURN_DRIVE_READING; + d->buffer = &buf; + + start = byte_address / 2048; + upto = start + data_size / 2048; + if (data_size % 2048) + upto++; + wpt = data; + for (; start < upto; start += 16) { + chunksize = upto - start; + if (chunksize > 16) { + chunksize = 16; + cpy_size = 16 * 2048; + } else + cpy_size = data_size - *data_count; + err = d->read_10(d, start, chunksize, d->buffer); + if (err == BE_CANCELLED) { + d->busy = BURN_DRIVE_IDLE; + return 0; + } + memcpy(wpt, d->buffer->data, cpy_size); + wpt += cpy_size; + *data_count += cpy_size; + } + + d->buffer = NULL; + d->busy = BURN_DRIVE_IDLE; + return 1; +} diff --git a/libburn/trunk/libburn/transport.h b/libburn/trunk/libburn/transport.h index 9466c392..ad76315c 100644 --- a/libburn/trunk/libburn/transport.h +++ b/libburn/trunk/libburn/transport.h @@ -320,6 +320,11 @@ struct burn_drive /* mmc5r03c.pdf 6.24 : get list of available formats */ int (*read_format_capacities) (struct burn_drive *d, int top_wanted); + /* ts A70812 */ + /* mmc5r03c.pdf 6.15 : read data sectors (start and amount in LBA) */ + int (*read_10) (struct burn_drive *d, int start, int amount, + struct buffer *buf); + }; /* end of generic 'drive' data structures */ diff --git a/libburn/trunk/libburn/write.c b/libburn/trunk/libburn/write.c index d9dc5c62..462fda28 100644 --- a/libburn/trunk/libburn/write.c +++ b/libburn/trunk/libburn/write.c @@ -1970,9 +1970,9 @@ fail_wo_sync:; d->busy = BURN_DRIVE_IDLE; } - +/* ts A70811 : API function */ int burn_random_access_write(struct burn_drive *d, off_t byte_address, - char *data, off_t data_count, int flag) + char *data, off_t data_count, int flag) { int alignment = 0, start, upto, chunksize, err; char msg[81], *rpt; @@ -2051,6 +2051,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address, if (flag & 1) d->sync_cache(d); + d->buffer = NULL; d->busy = BURN_DRIVE_IDLE; return(1); }