diff --git a/NEWS b/NEWS index a291890c..46182c4a 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ version 0.83 (git) programs that wanto to cd-record compatible. - Tolerance for OS's without timezone in their struct tm (e.g. Solaris) added iso9660_set_{d,l}time_with_timezone +- Add mmc_get_disk_erasable version 0.82 2009-10-27 diff --git a/THANKS b/THANKS index f2a855b8..afcc8802 100644 --- a/THANKS +++ b/THANKS @@ -10,6 +10,9 @@ Carlo Bramini Diego 'Flameeyes' Pettenò patches to FreeBSD and making Gentoo-friendly +Frank Endres + mmc_get_disc_erasable + Frantisek Dvorak : bug reports and miscellaneous fixes diff --git a/include/cdio/mmc.h b/include/cdio/mmc.h index baa7f098..d6eb9a64 100644 --- a/include/cdio/mmc.h +++ b/include/cdio/mmc.h @@ -321,9 +321,8 @@ typedef enum { report */ } cdio_mmc_feature_t; -/** - Profile profile codes used in GET_CONFIGURATION - PROFILE LIST. -*/ +/** + Profile profile codes used in GET_CONFIGURATION - PROFILE LIST. */ typedef enum { CDIO_MMC_FEATURE_PROF_NON_REMOVABLE = 0x0001, /**< Re-writable disk, capable of changing behavior */ @@ -377,14 +376,16 @@ typedef enum { */ #define MAX_CDB_LEN 12 -/** \brief A Command Descriptor Block (CDB) used in sending MMC +/** + \brief A Command Descriptor Block (CDB) used in sending MMC commands. */ typedef struct mmc_cdb_s { uint8_t field[MAX_CDB_LEN]; } mmc_cdb_t; - /** \brief Format of header block in data returned from an MMC + /** + \brief Format of header block in data returned from an MMC GET_CONFIGURATION command. */ typedef struct mmc_feature_list_header_s { @@ -398,18 +399,20 @@ typedef struct mmc_cdb_s { unsigned char profile_lsb; } cdio_mmc_feature_list_header_t; - /** An enumeration indicating whether an MMC command is sending - data, or getting data, or does none of both. + /** + An enumeration indicating whether an MMC command is sending + data, or getting data, or does none of both. */ typedef enum mmc_direction_s { SCSI_MMC_DATA_READ, SCSI_MMC_DATA_WRITE, SCSI_MMC_DATA_NONE } cdio_mmc_direction_t; - /** Indicate to applications that SCSI_MMC_DATA_NONE is available. - It has been added after version 0.82 and should be used with commands - that neither read nor write payload bytes. (At least on Linux such - commands did work with SCSI_MMC_DATA_READ or SCSI_MMC_DATA_WRITE, too.) + /** + Indicate to applications that SCSI_MMC_DATA_NONE is available. + It has been added after version 0.82 and should be used with commands + that neither read nor write payload bytes. (At least on Linux such + commands did work with SCSI_MMC_DATA_READ or SCSI_MMC_DATA_WRITE, too.) */ #define SCSI_MMC_HAS_DIR_NONE 1 @@ -471,6 +474,17 @@ typedef struct mmc_cdb_s { #define CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb, val) \ cdb[9] = val << 3; +/** + Get the output port volumes and port selections used on AUDIO PLAY + commands via a MMC MODE SENSE command using the CD Audio Control + Page. + @param p_cdio the CD object to be acted upon. + @param p_volume volume parameters retrieved + @return DRIVER_OP_SUCCESS if we ran the command ok. +*/ +driver_return_code_t mmc_audio_get_volume (CdIo_t *p_cdio, /*out*/ + mmc_audio_volume_t *p_volume); + /** Read Audio Subchannel information @@ -508,13 +522,6 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, */ const char *mmc_feature_profile2str( int i_feature_profile ); - /** - Return the length in bytes of the Command Descriptor - Buffer (CDB) for a given MMC command. The length will be - either 6, 10, or 12. - */ - uint8_t mmc_get_cmd_len(uint8_t mmc_cmd); - /** Get the block size used in read requests, via MMC (e.g. READ_10, READ_MSF, ...) @@ -524,13 +531,21 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, int mmc_get_blocksize ( CdIo_t *p_cdio ); /** - Close tray using a MMC START STOP command. - @param p_cdio the CD object to be acted upon. - @return DRIVER_OP_SUCCESS (0) if we got the status. - return codes are the same as driver_return_code_t + Return the length in bytes of the Command Descriptor + Buffer (CDB) for a given MMC command. The length will be + either 6, 10, or 12. */ - driver_return_code_t mmc_close_tray( CdIo_t *p_cdio ); + uint8_t mmc_get_cmd_len(uint8_t mmc_cmd); + /** + Detects if a disc (CD or DVD) is erasable or not. + @param p_user_data the CD object to be acted upon. + @return true if the disc is detected as erasable (rewritable), false + otherwise. + */ + bool + mmc_get_disc_erasable( const CdIo_t *p_cdio ); + /** Get the lsn of the end of the CD @@ -539,6 +554,14 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, */ lsn_t mmc_get_disc_last_lsn( const CdIo_t *p_cdio ); + /** + Close tray using a MMC START STOP command. + @param p_cdio the CD object to be acted upon. + @return DRIVER_OP_SUCCESS (0) if we got the status. + return codes are the same as driver_return_code_t + */ + driver_return_code_t mmc_close_tray( CdIo_t *p_cdio ); + /** Return the discmode as reported by the MMC Read (FULL) TOC command. @@ -640,17 +663,6 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, */ char * mmc_get_mcn ( const CdIo_t *p_cdio ); - /** - Get the output port volumes and port selections used on AUDIO PLAY - commands via a MMC MODE SENSE command using the CD Audio Control - Page. - @param p_cdio the CD object to be acted upon. - @param p_volume volume parameters retrieved - @return DRIVER_OP_SUCCESS if we ran the command ok. - */ - driver_return_code_t mmc_audio_get_volume (CdIo_t *p_cdio, /*out*/ - mmc_audio_volume_t *p_volume); - /** Report if CD-ROM has a praticular kind of interface (ATAPI, SCSCI, ...) Is it possible for an interface to have serveral? If not this diff --git a/lib/driver/mmc.c b/lib/driver/mmc.c index b5356180..0d1e3ead 100644 --- a/lib/driver/mmc.c +++ b/lib/driver/mmc.c @@ -1,7 +1,4 @@ /* Common Multimedia Command (MMC) routines. - - $Id: mmc.c,v 1.40 2008/05/09 09:54:39 edsdead Exp $ - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Rocky Bernstein @@ -580,60 +577,6 @@ mmc_set_blocksize_private ( void *p_env, /*********************************************************** User-accessible Operations. ************************************************************/ -/** - Return the number of length in bytes of the Command Descriptor - buffer (CDB) for a given MMC command. The length will be - either 6, 10, or 12. -*/ -uint8_t -mmc_get_cmd_len(uint8_t scsi_cmd) -{ - static const uint8_t scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; - return scsi_cdblen[((scsi_cmd >> 5) & 7)]; -} - -/** - Return the size of the CD in logical block address (LBA) units. - @param p_cdio the CD object to be acted upon. - @return the lsn. On error 0 or CDIO_INVALD_LSN. - */ -lsn_t -mmc_get_disc_last_lsn ( const CdIo_t *p_cdio ) -{ - mmc_cdb_t cdb = {{0, }}; - uint8_t buf[12] = { 0, }; - - lsn_t retval = 0; - int i_status; - - /* Operation code */ - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); - - cdb.field[1] = 0; /* lba; msf: 0x2 */ - - /* Format */ - cdb.field[2] = CDIO_MMC_READTOC_FMT_TOC; - - CDIO_MMC_SET_START_TRACK(cdb.field, CDIO_CDROM_LEADOUT_TRACK); - - CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf)); - - i_status = mmc_run_cmd(p_cdio, mmc_timeout_ms, &cdb, SCSI_MMC_DATA_READ, - sizeof(buf), buf); - - if (i_status) return CDIO_INVALID_LSN; - - { - int i; - for (i = 8; i < 12; i++) { - retval <<= 8; - retval += buf[i]; - } - } - - return retval; -} - /** Read Audio Subchannel information @@ -679,6 +622,132 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, cdio_subchannel_t *p_subchannel) return i_rc; } +/** + Get the block size used in read requests, via MMC (e.g. READ_10, + READ_MSF, ...) + + @param p_cdio the CD object to be acted upon. + @return the blocksize if > 0; error if <= 0 +*/ +int +mmc_get_blocksize ( CdIo_t *p_cdio) +{ + int i_status; + + uint8_t buf[255] = { 0, }; + uint8_t *p; + + /* First try using the 6-byte MODE SENSE command. */ + i_status = mmc_mode_sense_6(p_cdio, buf, sizeof(buf), + CDIO_MMC_R_W_ERROR_PAGE); + + if (DRIVER_OP_SUCCESS == i_status && buf[3]>=8) { + p = &buf[4+5]; + return CDIO_MMC_GET_LEN16(p); + } + + /* Next try using the 10-byte MODE SENSE command. */ + i_status = mmc_mode_sense_10(p_cdio, buf, sizeof(buf), + CDIO_MMC_R_W_ERROR_PAGE); + p = &buf[6]; + if (DRIVER_OP_SUCCESS == i_status && CDIO_MMC_GET_LEN16(p)>=8) { + return CDIO_MMC_GET_LEN16(p); + } + +#ifdef IS_THIS_CORRECT + /* Lastly try using the READ CAPACITY command. */ + { + lba_t lba = 0; + uint16_t i_blocksize; + + i_status = mmc_read_capacity(p_cdio, &lba, &i_blocksize); + if ( DRIVER_OP_SUCCESS == i_status ) + return i_blocksize; +#endif + + return DRIVER_OP_UNSUPPORTED; +} + +/** + Return the number of length in bytes of the Command Descriptor + buffer (CDB) for a given MMC command. The length will be + either 6, 10, or 12. +*/ +uint8_t +mmc_get_cmd_len(uint8_t scsi_cmd) +{ + static const uint8_t scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; + return scsi_cdblen[((scsi_cmd >> 5) & 7)]; +} + +/** + Detects if a disc (CD or DVD) is erasable or not. + @param p_user_data the CD object to be acted upon. + @return true if the disc is detected as erasable (rewritable), false +otherwise. + */ +bool +mmc_get_disc_erasable( const CdIo_t *p_cdio ) { + mmc_cdb_t cdb = {{0, }}; + uint8_t buf[42] = { 0, }; + int i_status; + + CDIO_MMC_SET_COMMAND (cdb.field, CDIO_MMC_GPCMD_READ_DISC_INFO); + CDIO_MMC_SET_READ_LENGTH8 (cdb.field, sizeof(buf)); + + i_status = mmc_run_cmd (p_cdio, 0, &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), &buf); + if (i_status == 0) { + if (buf[2] & 0x10) + return true; + else + return false; + } else + return false; +} + +/** + Return the size of the CD in logical block address (LBA) units. + @param p_cdio the CD object to be acted upon. + @return the lsn. On error 0 or CDIO_INVALD_LSN. + */ +lsn_t +mmc_get_disc_last_lsn ( const CdIo_t *p_cdio ) +{ + mmc_cdb_t cdb = {{0, }}; + uint8_t buf[12] = { 0, }; + + lsn_t retval = 0; + int i_status; + + /* Operation code */ + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); + + cdb.field[1] = 0; /* lba; msf: 0x2 */ + + /* Format */ + cdb.field[2] = CDIO_MMC_READTOC_FMT_TOC; + + CDIO_MMC_SET_START_TRACK(cdb.field, CDIO_CDROM_LEADOUT_TRACK); + + CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf)); + + i_status = mmc_run_cmd(p_cdio, mmc_timeout_ms, &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), buf); + + if (i_status) return CDIO_INVALID_LSN; + + { + int i; + for (i = 8; i < 12; i++) { + retval <<= 8; + retval += buf[i]; + } + } + + return retval; +} + /** Return the discmode as reported by the SCSI-MMC Read (FULL) TOC command. @@ -972,6 +1041,40 @@ int mmc_get_tray_status(const CdIo_t *p_cdio) return (status_buf[1] & 0x01) ? 1 : 0; } +/* Added in version 0.83 by scdbackup */ +/** + Obtain the SCSI sense reply of the most-recently-performed MMC command. + These bytes give an indication of possible problems which occured in + the drive while the command was performed. With some commands they tell + about the current state of the drive (e.g. 00h TEST UNIT READY). + @param sense returns the sense bytes received from the drive. + This is allocated memory or NULL if no sense bytes are + available. Dispose non-NULL pointers by free() when + no longer needed. + See SPC-3 4.5.3 Fixed format sense data. + SCSI error codes as of SPC-3 Annex D, MMC-5 Annex F: + sense[2]&15 = Key , sense[12] = ASC , sense[13] = ASCQ + @return number of valid bytes in sense, + 0 in case of no sense bytes available, + <0 in case of internal error. +*/ +int +mmc_last_cmd_sense( const CdIo_t *p_cdio, unsigned char **sense) +{ + generic_img_private_t *gen; + + if (!p_cdio) return DRIVER_OP_UNINIT; + gen = p_cdio->env; + *sense = NULL; + if (gen->scsi_mmc_sense_valid <= 0) + return 0; + *sense = calloc(1, gen->scsi_mmc_sense_valid); + if (*sense == NULL) + return DRIVER_OP_ERROR; + memcpy(*sense, gen->scsi_mmc_sense, gen->scsi_mmc_sense_valid); + return gen->scsi_mmc_sense_valid; +} + /** Run a MMC command. @@ -1019,6 +1122,7 @@ mmc_run_cmd( const CdIo_t *p_cdio, unsigned int i_timeout_ms, @return 0 if command completed successfully. */ + driver_return_code_t mmc_run_cmd_len( const CdIo_t *p_cdio, unsigned int i_timeout_ms, const mmc_cdb_t *p_cdb, unsigned int i_cdb, @@ -1032,87 +1136,6 @@ mmc_run_cmd_len( const CdIo_t *p_cdio, unsigned int i_timeout_ms, p_cdb, e_direction, i_buf, p_buf); } -/* Added in version 0.83 by scdbackup */ -/** - Obtain the SCSI sense reply of the most-recently-performed MMC command. - These bytes give an indication of possible problems which occured in - the drive while the command was performed. With some commands they tell - about the current state of the drive (e.g. 00h TEST UNIT READY). - @param sense returns the sense bytes received from the drive. - This is allocated memory or NULL if no sense bytes are - available. Dispose non-NULL pointers by free() when - no longer needed. - See SPC-3 4.5.3 Fixed format sense data. - SCSI error codes as of SPC-3 Annex D, MMC-5 Annex F: - sense[2]&15 = Key , sense[12] = ASC , sense[13] = ASCQ - @return number of valid bytes in sense, - 0 in case of no sense bytes available, - <0 in case of internal error. -*/ -int -mmc_last_cmd_sense( const CdIo_t *p_cdio, unsigned char **sense) -{ - generic_img_private_t *gen; - - if (!p_cdio) return DRIVER_OP_UNINIT; - gen = p_cdio->env; - *sense = NULL; - if (gen->scsi_mmc_sense_valid <= 0) - return 0; - *sense = calloc(1, gen->scsi_mmc_sense_valid); - if (*sense == NULL) - return DRIVER_OP_ERROR; - memcpy(*sense, gen->scsi_mmc_sense, gen->scsi_mmc_sense_valid); - return gen->scsi_mmc_sense_valid; -} - - -/** - Get the block size used in read requests, via MMC (e.g. READ_10, - READ_MSF, ...) - - @param p_cdio the CD object to be acted upon. - @return the blocksize if > 0; error if <= 0 -*/ -int -mmc_get_blocksize ( CdIo_t *p_cdio) -{ - int i_status; - - uint8_t buf[255] = { 0, }; - uint8_t *p; - - /* First try using the 6-byte MODE SENSE command. */ - i_status = mmc_mode_sense_6(p_cdio, buf, sizeof(buf), - CDIO_MMC_R_W_ERROR_PAGE); - - if (DRIVER_OP_SUCCESS == i_status && buf[3]>=8) { - p = &buf[4+5]; - return CDIO_MMC_GET_LEN16(p); - } - - /* Next try using the 10-byte MODE SENSE command. */ - i_status = mmc_mode_sense_10(p_cdio, buf, sizeof(buf), - CDIO_MMC_R_W_ERROR_PAGE); - p = &buf[6]; - if (DRIVER_OP_SUCCESS == i_status && CDIO_MMC_GET_LEN16(p)>=8) { - return CDIO_MMC_GET_LEN16(p); - } - -#ifdef IS_THIS_CORRECT - /* Lastly try using the READ CAPACITY command. */ - { - lba_t lba = 0; - uint16_t i_blocksize; - - i_status = mmc_read_capacity(p_cdio, &lba, &i_blocksize); - if ( DRIVER_OP_SUCCESS == i_status ) - return i_blocksize; -#endif - - return DRIVER_OP_UNSUPPORTED; -} - /** Load or Unload media using a MMC START STOP command. diff --git a/lib/driver/mmc_private.h b/lib/driver/mmc_private.h index d06d2387..dea2b303 100644 --- a/lib/driver/mmc_private.h +++ b/lib/driver/mmc_private.h @@ -1,7 +1,4 @@ /* private MMC helper routines. - - $Id: mmc_private.h,v 1.12 2008/04/22 15:29:12 karl Exp $ - Copyright (C) 2004, 2005, 2006, 2008 Rocky Bernstein This program is free software: you can redistribute it and/or modify diff --git a/test/driver/mmc.c b/test/driver/mmc.c index 1f921d43..dae94043 100644 --- a/test/driver/mmc.c +++ b/test/driver/mmc.c @@ -1,5 +1,6 @@ /* -*- C -*- Copyright (C) 2009 Thomas Schmitt + Copyright (C) 20010 Rocky Bernstein This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,44 +41,52 @@ /* The compiler warns if no prototypes are given before function definition */ -static void -tmmc_print_status_sense(int i_status, int sense_valid, - unsigned char sense_reply[18], int flag); -static int -tmmc_handle_outcome(CdIo_t *p_cdio, int i_status, - int *sense_avail, unsigned char sense_reply[18], int flag); +static int tmmc_eject_load_cycle(CdIo_t *p_cdio, int flag); -int -tmmc_test_unit_ready(CdIo_t *p_cdio, int *sense_avail, - unsigned char sense_reply[18], int flag); -int -tmmc_load_eject(CdIo_t *p_cdio, int *sense_avail, - unsigned char sense_reply[18], int flag); -int -tmmc_mode_sense(CdIo_t *p_cdio, int *sense_avail,unsigned char sense_reply[18], - int page_code, int subpage_code, int alloc_len, - unsigned char *buf, int *buf_fill, int flag); -int -tmmc_mode_select(CdIo_t *p_cdio, - int *sense_avail, unsigned char sense_reply[18], - unsigned char *buf, int buf_fill, int flag); +static int tmmc_eject_test_load(CdIo_t *p_cdio, int flag); -int -tmmc_wait_for_drive(CdIo_t *p_cdio, int max_tries, int flag); -int -tmmc_eject_load_cycle(CdIo_t *p_cdio, int flag); -int -tmmc_eject_test_load(CdIo_t *p_cdio, int flag); -int -tmmc_rwr_mode_page(CdIo_t *p_cdio, int flag); +static void tmmc_get_disc_erasable(const CdIo_t *p_cdio, const char *psz_source, + int verbose); -int -tmmc_test(char *drive_path, int flag); +static int tmmc_handle_outcome(CdIo_t *p_cdio, int i_status, + int *sense_avail, + unsigned char sense_reply[18], int flag); + +static void tmmc_print_status_sense(int i_status, int sense_valid, + unsigned char sense_reply[18], int flag); + +static int tmmc_load_eject(CdIo_t *p_cdio, int *sense_avail, + unsigned char sense_reply[18], int flag); +static int tmmc_mode_select(CdIo_t *p_cdio, + int *sense_avail, unsigned char sense_reply[18], + unsigned char *buf, int buf_fill, int flag); + +static int tmmc_mode_sense(CdIo_t *p_cdio, int *sense_avail, + unsigned char sense_reply[18], + int page_code, int subpage_code, int alloc_len, + unsigned char *buf, int *buf_fill, int flag); + +static int tmmc_test_unit_ready(CdIo_t *p_cdio, int *sense_avail, + unsigned char sense_reply[18], int flag); +static int tmmc_wait_for_drive(CdIo_t *p_cdio, int max_tries, int flag); + +static int tmmc_rwr_mode_page(CdIo_t *p_cdio, int flag); + +static int tmmc_test(char *drive_path, int flag); /* ------------------------- Helper functions ---------------------------- */ +static void +tmmc_get_disc_erasable(const CdIo_t *p_cdio, const char *psz_source, + int verbose) +{ + bool b_erasable = mmc_get_disc_erasable(p_cdio); + printf("disk is %serasable.\n", b_erasable ? "" : "not "); +} + + /* @param flag bit0= verbose */ static void @@ -125,7 +134,7 @@ tmmc_handle_outcome(CdIo_t *p_cdio, int i_status, @param sense_reply eventual sense bytes @return return value of mmc_run_cmd() */ -int +static int tmmc_test_unit_ready(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], int flag) { @@ -151,7 +160,7 @@ tmmc_test_unit_ready(CdIo_t *p_cdio, bit2= Load (else Eject) @return return value of mmc_run_cmd() */ -int +static int tmmc_load_eject(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], int flag) { @@ -193,7 +202,7 @@ tmmc_load_eject(CdIo_t *p_cdio, int *sense_avail, @return return value of mmc_run_cmd(), or other driver_return_code_t */ -int +static int tmmc_mode_sense(CdIo_t *p_cdio, int *sense_avail,unsigned char sense_reply[18], int page_code, int subpage_code, int alloc_len, unsigned char *buf, int *buf_fill, int flag) @@ -238,7 +247,7 @@ tmmc_mode_sense(CdIo_t *p_cdio, int *sense_avail,unsigned char sense_reply[18], @return return value of mmc_run_cmd(), or other driver_return_code_t */ -int +static int tmmc_mode_select(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], unsigned char *buf, int buf_fill, int flag) @@ -284,7 +293,7 @@ tmmc_mode_select(CdIo_t *p_cdio, bit1= expect media (do not end on no-media sense) @return 1= all seems well , 0= minor failure , -1= severe failure */ -int +static int tmmc_wait_for_drive(CdIo_t *p_cdio, int max_tries, int flag) { int ret, i, sense_avail; @@ -338,7 +347,7 @@ tmmc_wait_for_drive(CdIo_t *p_cdio, int max_tries, int flag) bit1= expect media (do not end on no-media sense) @return 1= all seems well , 0= minor failure , -1= severe failure */ -int +static int tmmc_eject_load_cycle(CdIo_t *p_cdio, int flag) { int ret, sense_avail; @@ -371,7 +380,7 @@ tmmc_eject_load_cycle(CdIo_t *p_cdio, int flag) @param flag bit0= verbose @return 1= all seems well , 0= minor failure , -1= severe failure */ -int +static int tmmc_eject_test_load(CdIo_t *p_cdio, int flag) { int ret, sense_avail; @@ -420,7 +429,7 @@ tmmc_eject_test_load(CdIo_t *p_cdio, int flag) @param flag bit0= verbose @return 1= all seems well , 0= minor failure , -1= severe failure */ -int +static int tmmc_rwr_mode_page(CdIo_t *p_cdio, int flag) { int ret, sense_avail, page_code = 5, subpage_code = 0, alloc_len, buf_fill; @@ -547,7 +556,7 @@ tmmc_rwr_mode_page(CdIo_t *p_cdio, int flag) @return 0= no severe failure else an proposal for an exit() value is returned */ -int +static int tmmc_test(char *drive_path, int flag) { int sense_avail = 0, ret, sense_valid, buf_fill, alloc_len = 10, verbose; @@ -734,8 +743,9 @@ main(int argc, const char *argv[]) char **ppsz_drives=NULL; const char *psz_source = NULL; int ret; + bool b_verbose = (argc > 1); - cdio_loglevel_default = (argc > 1) ? CDIO_LOG_DEBUG : CDIO_LOG_INFO; + cdio_loglevel_default = b_verbose ? CDIO_LOG_DEBUG : CDIO_LOG_INFO; /* snprintf(psz_nrgfile, sizeof(psz_nrgfile)-1, "%s/%s", TEST_DIR, cue_file[i]); @@ -759,6 +769,8 @@ main(int argc, const char *argv[]) exit(1); } + tmmc_get_disc_erasable(p_cdio, psz_source, b_verbose); + if ( psz_have_mmc && 0 == strncmp("true", psz_have_mmc, sizeof("true")) && (DRIVER_WIN32 != cdio_get_driver_id(p_cdio)) ) {