From c1bd3ced615fa3b81f3d0515931640a3b72c2cf7 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 5 Jan 2012 11:55:22 +0000 Subject: [PATCH] Bug fix: Progress report with blanking and formatting could be bogus --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 46 ++++++++++++++++++++++++++++++++++++- libburn/spc.c | 43 +++++++++++++++++++++++++++------- libburn/spc.h | 5 ++-- 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 8373c98..8370ea9 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2012.01.04.131808" +#define Cdrskin_timestamP "2012.01.05.115516" diff --git a/libburn/drive.c b/libburn/drive.c index 74aa544..dd81029 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -1,7 +1,7 @@ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens - Copyright (c) 2006 - 2011 Thomas Schmitt + Copyright (c) 2006 - 2012 Thomas Schmitt Provided under GPL version 2 or later. */ @@ -863,12 +863,34 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast) d->erase(d, fast); d->busy = BURN_DRIVE_ERASING; +#ifdef Libburn_old_progress_looP + /* read the initial 0 stage */ while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0) sleep(1); while ((d->progress.sector = d->get_erase_progress(d)) > 0 || !d->test_unit_ready(d)) sleep(1); + +#else /* Libburn_old_progress_looP */ + + while (1) { + ret = d->get_erase_progress(d); + if (ret == -2 || ret > 0) + break; + sleep(1); + } + while (1) { + ret = d->get_erase_progress(d); + if(ret == -2) + break; + if (ret >= 0) + d->progress.sector = ret; + sleep(1); + } + +#endif /* ! Libburn_old_progress_looP */ + d->progress.sector = 0x10000; /* ts A61125 : update media state records */ @@ -913,6 +935,8 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag) if (ret <= 0) d->cancel = 1; +#ifdef Libburn_old_progress_looP + while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0) sleep(1); while ((pseudo_sector = d->get_erase_progress(d)) > 0 || @@ -920,6 +944,26 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag) d->progress.sector = pseudo_sector / stages; sleep(1); } + +#else /* Libburn_old_progress_looP */ + + while (1) { + ret = d->get_erase_progress(d); + if (ret == -2 || ret > 0) + break; + sleep(1); + } + while (1) { + pseudo_sector = d->get_erase_progress(d); + if(pseudo_sector == -2) + break; + if (pseudo_sector >= 0) + d->progress.sector = pseudo_sector / stages; + sleep(1); + } + +#endif /* ! Libburn_old_progress_looP */ + d->sync_cache(d); if (size <= 0) diff --git a/libburn/spc.c b/libburn/spc.c index d292537..4a9d771 100644 --- a/libburn/spc.c +++ b/libburn/spc.c @@ -1,7 +1,7 @@ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens - Copyright (c) 2006 - 2011 Thomas Schmitt + Copyright (c) 2006 - 2012 Thomas Schmitt Provided under GPL version 2 or later. */ @@ -102,7 +102,8 @@ int spc_decode_sense(unsigned char *sense, int senselen, } -int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq) +int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq, + int *progress) { struct command *c; @@ -115,8 +116,13 @@ int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq) c->dir = NO_TRANSFER; d->issue_command(d, c); *key = *asc = *ascq = 0; + *progress = -1; if (c->error) { spc_decode_sense(c->sense, 0, key, asc, ascq); + if (c->sense[0] == 0x70 && + ((c->sense[2] & 0x0f) == 0 || (c->sense[2] & 0x0f) == 2) && + (c->sense[15] & 0x80)) + *progress = (c->sense[16] << 8) + c->sense[17]; return (key == 0); } return 1; @@ -125,9 +131,9 @@ int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq) int spc_test_unit_ready(struct burn_drive *d) { - int key,asc,ascq; + int key, asc, ascq, progress; - return spc_test_unit_ready_r(d, &key, &asc, &ascq); + return spc_test_unit_ready_r(d, &key, &asc, &ascq, &progress); } @@ -141,7 +147,7 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text, { int i, ret = 1, key = 0, asc = 0, ascq = 0, clueless_start = 0; static double tests_per_second = 2.0; - int sleep_usecs, loop_limit, clueless_timeout; + int sleep_usecs, loop_limit, clueless_timeout, progress; char *msg = NULL; unsigned char sense[14]; @@ -154,7 +160,7 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text, usleep(sleep_usecs); for(i = !(flag & 1); i < loop_limit; i++) { - ret = spc_test_unit_ready_r(d, &key, &asc, &ascq); + ret = spc_test_unit_ready_r(d, &key, &asc, &ascq, &progress); if (ret > 0) /* ready */ break; if (key!=0x2 || asc!=0x4) { @@ -256,17 +262,38 @@ void spc_request_sense(struct burn_drive *d, struct buffer *buf) d->issue_command(d, c); } +/* @return -2 = drive is ready , -1 = not ready, but no progress reported + >= 0 progress indication between 0 and 65535 +*/ int spc_get_erase_progress(struct burn_drive *d) { struct buffer *b = NULL; - int ret; + int ret, key, asc, ascq, progress; if (mmc_function_spy(d, "get_erase_progress") <= 0) {ret = 0; goto ex;} + /* ts B20104 : + TEST UNIT READY seems to be more reliable than REQUEST SENSE. + Nevertheless growisofs still uses the latter as fallback. + */ + ret = spc_test_unit_ready_r(d, &key, &asc, &ascq, &progress); + if (ret > 0) + {ret = -2; goto ex;} + if (progress >= 0) + {ret = progress; goto ex;} + + /* Fallback to request sense */ BURN_ALLOC_MEM(b, struct buffer, 1); spc_request_sense(d, b); - ret = (b->data[16] << 8) | b->data[17]; + + /* Now checking the the preconditions as of SPC-3 4.5.2.4.4 and 4.5.3 + */ + ret = -1; + if (b->data[0] == 0x70 && + ((b->data[2] & 0x0f) == 0 || (b->data[2] & 0x0f) == 2) && + (b->data[15] & 0x80)) + ret = (b->data[16] << 8) | b->data[17]; ex:; BURN_FREE_MEM(b); return ret; diff --git a/libburn/spc.h b/libburn/spc.h index bf51517..f8b546c 100644 --- a/libburn/spc.h +++ b/libburn/spc.h @@ -1,7 +1,7 @@ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens - Copyright (c) 2006 - 2011 Thomas Schmitt + Copyright (c) 2006 - 2012 Thomas Schmitt Provided under GPL version 2 or later. */ @@ -29,7 +29,8 @@ int spc_block_type(enum burn_block_types b); int spc_get_erase_progress(struct burn_drive *d); /* ts A70315 : test_unit_ready with result parameters */ -int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq); +int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq, + int *progress); int spc_test_unit_ready(struct burn_drive *d);