diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index c53f70e..b7eccc2 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2012.11.24.181347" +#define Cdrskin_timestamP "2012.11.29.111344" diff --git a/libburn/libburn.h b/libburn/libburn.h index ec4a4b9..f8c0cc4 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -4003,7 +4003,7 @@ BURN_END_DECLS */ #ifdef Libburn_develop_quality_scaN -/* B21108 ts */ +/* ts B21108 */ /* Experiments mit quality scan command F3 on Optiarc drive */ int burn_nec_optiarc_rep_err_rate(struct burn_drive *d, int start_lba, int rate_period, int flag); @@ -4011,4 +4011,46 @@ int burn_nec_optiarc_rep_err_rate(struct burn_drive *d, #endif /* Libburn_develop_quality_scaN */ +/* Early experimental: +*/ +#define Libburn_with_read_audiO + +#ifdef Libburn_with_read_audiO + +/* ts B21119 */ +/** Read CD audio sectors in random access mode. + The drive must be grabbed successfully before calling this function. + Only CD audio tracks with 2352 bytes per sector can be read this way. + I.e. not data tracks, not CD-video-stream, ... + @param d The drive from which to read. + It must be a real MMC drive (i.e. not a stdio file) + and it must have a CD loaded (i.e. not DVD or BD). + @param sector_no The sector number (Logical Block Address) + @param data A memory buffer capable of taking data_size bytes + @param data_size The amount of data to be read. This must be aligned + to full multiples of 2352. + @param data_count The amount of data actually read (interesting on error) + @param flag Bitfield for control purposes: + bit0= - reserved - + bit1= do not submit error message if read error + bit2= on error do not try to read a second time + with single block steps. + bit3= Enable DAP : "flaw obscuring mechanisms like + audio data mute and interpolate" + bit4= return -3 on SCSI error + 5 64 00 ILLEGAL MODE FOR THIS TRACK + and prevent this error from being reported as + event message. Do not retry reading in this case. + (Useful to try the last two blocks of a CD + track which might be non-audio because of TAO.) + @return 1=sucessful , <=0 an error occured + with bit3: -2= permission denied error + @since 1.2.6 +*/ +int burn_read_audio(struct burn_drive *d, int sector_no, + char data[], off_t data_size, off_t *data_count, int flag); + +#endif /* Libburn_with_read_audiO */ + + #endif /*LIBBURN_H*/ diff --git a/libburn/libburn.ver b/libburn/libburn.ver index 4af6852..e92b7ea 100644 --- a/libburn/libburn.ver +++ b/libburn/libburn.ver @@ -100,6 +100,7 @@ burn_os_open_track_src; burn_precheck_write; burn_preset_device_open; burn_random_access_write; +burn_read_audio; burn_read_data; burn_read_opts_free; burn_read_opts_new; diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 6ac8d17..23de1a5 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -596,6 +596,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x0002019a (SORRY,HIGH) = Bad track index number 0x0002019b (SORRY,HIGH) = CD track number exceeds range of 1 to 99 0x0002019c (SORRY,HIGH) = Session has no defined tracks + 0x0002019d (SORRY,HIGH) = Audio read size not properly aligned libdax_audioxtr: diff --git a/libburn/mmc.h b/libburn/mmc.h index 6b1274f..ebf3cdc 100644 --- a/libburn/mmc.h +++ b/libburn/mmc.h @@ -36,9 +36,9 @@ void mmc_erase(struct burn_drive *, int); void mmc_read_toc(struct burn_drive *); void mmc_read_disc_info(struct burn_drive *); void mmc_read_atip(struct burn_drive *); -void mmc_read_sectors(struct burn_drive *, - int, - int, const struct burn_read_opts *, struct buffer *); +int mmc_read_cd(struct burn_drive *d, int start, int len, + int sec_type, int main_ch, + const struct burn_read_opts *o, struct buffer *buf, int flag); void mmc_set_speed(struct burn_drive *, int, int); void mmc_read_lead_in(struct burn_drive *, struct buffer *); void mmc_perform_opc(struct burn_drive *); diff --git a/libburn/options.c b/libburn/options.c index 5919dc9..5964a93 100644 --- a/libburn/options.c +++ b/libburn/options.c @@ -93,6 +93,7 @@ struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive) opts->report_recovered_errors = 0; opts->transfer_damaged_blocks = 0; opts->hardware_error_retries = 3; + opts->dap_bit = 0; return opts; } diff --git a/libburn/options.h b/libburn/options.h index eb92005..53fe49f 100644 --- a/libburn/options.h +++ b/libburn/options.h @@ -129,6 +129,14 @@ struct burn_read_opts /** The number of retries the hardware should make to correct errors. */ unsigned char hardware_error_retries; + + /* ts B21119 */ + /* >>> Needs API access */ + /** Whether to set DAP bit which allows drive to apply + "flaw obscuring mechanisms like audio data mute and interpolate" + */ + unsigned int dap_bit; + }; #endif /* BURN__OPTIONS_H */ diff --git a/libburn/read.c b/libburn/read.c index b5cbc52..729e0e7 100644 --- a/libburn/read.c +++ b/libburn/read.c @@ -159,6 +159,8 @@ drive, or only store a subset of the _opts structs in drives */ drive_lba); /* >>> ts A61009 : ensure page.sectors >= 0 before calling */ + /* >>> ts B21123 : Would now be d->read_cd() with + with sectype = 0 , mainch = 0xf8 */ d->r ead_sectors(d, drive_lba, page.sectors, o, &page); printf("Read %d\n", page.sectors); @@ -538,6 +540,113 @@ ex:; } +#ifdef Libburn_with_read_audiO + +/* ts B21119 : API function*/ +int burn_read_audio(struct burn_drive *d, int sector_no, + char data[], off_t data_size, off_t *data_count, int flag) +{ + int alignment = 2352, start, upto, chunksize = 1, err, cpy_size, i; + int sose_mem = 0, ret; + char msg[81], *wpt; + struct buffer *buf = NULL, *buffer_mem = d->buffer; + + BURN_ALLOC_MEM(buf, struct buffer, 1); + *data_count = 0; + sose_mem = d->silent_on_scsi_error; + + 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 read", 0, 0); + {ret = 0; goto ex;} + } + if (d->drive_role != 1) { + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020146, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + "Drive is a virtual placeholder (stdio-drive or null-drive)", + 0, 0); + {ret = 0; goto ex;} + } + if ((data_size % alignment) != 0) { + sprintf(msg, + "Audio read size not properly aligned (%d bytes)", + alignment); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x0002019d, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + {ret = 0; goto ex;} + } + 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 audio", 0, 0); + {ret = 0; goto ex;} + } + + d->busy = BURN_DRIVE_READING_SYNC; + d->buffer = buf; + + start = sector_no; + upto = start + data_size / alignment; + wpt = data; + for (; start < upto; start += chunksize) { + chunksize = upto - start; + if (chunksize > (BUFFER_SIZE / alignment)) + chunksize = (BUFFER_SIZE / alignment); + cpy_size = chunksize * alignment; + if (flag & 2) + d->silent_on_scsi_error = 1; + if (flag & 16) { + d->had_particular_error &= ~1; + if (!d->silent_on_scsi_error) + d->silent_on_scsi_error = 2; + } + err = d->read_cd(d, start, chunksize, 1, 0x10, NULL, d->buffer, + (flag & 8) >> 3); + if (flag & (2 | 16)) + d->silent_on_scsi_error = sose_mem; + if (err == BE_CANCELLED) { + if ((flag & 16) && (d->had_particular_error & 1)) + {ret = -3; goto ex;} + if(!(flag & 4)) + for (i = 0; i < chunksize - 1; i++) { + if (flag & 2) + d->silent_on_scsi_error = 1; + err = d->read_cd(d, start + i, 1, 1, 0x10, + NULL, d->buffer, (flag & 8) >> 3); + if (flag & 2) + d->silent_on_scsi_error = sose_mem; + if (err == BE_CANCELLED) + break; + memcpy(wpt, d->buffer->data, alignment); + wpt += alignment; + *data_count += alignment; + } + + ret = 0; goto ex; + } + memcpy(wpt, d->buffer->data, cpy_size); + wpt += cpy_size; + *data_count += cpy_size; + } + + ret = 1; +ex: + BURN_FREE_MEM(buf); + d->buffer = buffer_mem; + d->busy = BURN_DRIVE_IDLE; + return ret; +} + + +#endif /* Libburn_with_read_audiO */ + + #ifdef Libburn_develop_quality_scaN /* B21108 ts */ diff --git a/libburn/sg-freebsd.c b/libburn/sg-freebsd.c index ca73b6b..7748ba2 100644 --- a/libburn/sg-freebsd.c +++ b/libburn/sg-freebsd.c @@ -477,7 +477,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no, out.read_toc = mmc_read_toc; out.write = mmc_write; out.erase = mmc_erase; - out.read_sectors = mmc_read_sectors; + out.read_cd = mmc_read_cd; out.perform_opc = mmc_perform_opc; out.set_speed = mmc_set_speed; out.send_parameters = spc_select_error_params; diff --git a/libburn/spc.c b/libburn/spc.c index 7d63df3..af7c044 100644 --- a/libburn/spc.c +++ b/libburn/spc.c @@ -1462,6 +1462,8 @@ static char *scsi_command_name(unsigned int c, int flag) return "READ DISC STRUCTURE"; case 0xb6: return "SET STREAMING"; + case 0xb9: + return "READ CD MSF"; case 0xbb: return "SET CD SPEED"; case 0xbe: @@ -1587,7 +1589,7 @@ int scsi_show_command_reply(unsigned char *opcode, int data_dir, if (data_dir != FROM_DRIVE) return 2; if (opcode[0] == 0x28 || opcode[0] == 0x3C || - opcode[0] == 0xA8 || opcode[0] == 0xBE) { + opcode[0] == 0xA8 || opcode[0] == 0xB9 || opcode[0] == 0xBE) { /* READ commands */ /* >>> report amount of data */; diff --git a/libburn/toc.c b/libburn/toc.c index ee5f3dd..e52cec1 100644 --- a/libburn/toc.c +++ b/libburn/toc.c @@ -147,7 +147,11 @@ void toc_find_modes(struct burn_drive *d) lba = burn_msf_to_lba(e->pmin, e->psec, e->pframe); mem->sectors = 1; + + ts B21119 : Would now be d->read_cd() with + with sectype = 0 , mainch = 0xf8 d->read_sectors(d, lba, mem.sectors, &o, mem); + t->mode = sector_identify(mem->data); */ } diff --git a/libburn/transport.h b/libburn/transport.h index bcf22d3..bdaa495 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -382,10 +382,10 @@ struct burn_drive int is_stopped; void (*read_disc_info) (struct burn_drive *); - void (*read_sectors) (struct burn_drive *, - int start, - int len, - const struct burn_read_opts *, struct buffer *); + int (*read_cd) (struct burn_drive *, int start, int len, + int sec_type, int main_ch, + const struct burn_read_opts *, struct buffer *, + int flag); void (*perform_opc) (struct burn_drive *); void (*set_speed) (struct burn_drive *, int, int); void (*send_parameters) (struct burn_drive *,