diff --git a/example/mmc2a.c b/example/mmc2a.c index f57d0473..ecab7475 100644 --- a/example/mmc2a.c +++ b/example/mmc2a.c @@ -1,7 +1,7 @@ /* - $Id: mmc2a.c,v 1.2 2006/04/03 19:54:06 rocky Exp $ + $Id: mmc2a.c,v 1.3 2006/04/12 09:30:14 rocky Exp $ - Copyright (C) 2006 Rocky Bernstein + Copyright (C) 2006 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 @@ -20,8 +20,8 @@ /* Sample program to show use of the MMC interface. An optional drive name can be supplied as an argument. - This basically the libdio mmc_get_hwinfo() routine. - See also corresponding C++ programs. + This basically calls to the libdio mmc_mode_sense_10() and mmc_mode_sense_6 + routines. */ #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/include/cdio/cd_types.h b/include/cdio/cd_types.h index 8d3a50c9..3d3cefff 100644 --- a/include/cdio/cd_types.h +++ b/include/cdio/cd_types.h @@ -1,7 +1,7 @@ /* - $Id: cd_types.h,v 1.16 2006/03/28 03:26:16 rocky Exp $ + $Id: cd_types.h,v 1.17 2006/04/12 09:30:14 rocky Exp $ - Copyright (C) 2003, 2006 Rocky Bernstein + Copyright (C) 2003, 2006 Rocky Bernstein Copyright (C) 1996,1997,1998 Gerd Knorr and Heiko Eißfeldt diff --git a/include/cdio/device.h b/include/cdio/device.h index dd18d9dd..0387059b 100644 --- a/include/cdio/device.h +++ b/include/cdio/device.h @@ -1,7 +1,7 @@ /* -*- c -*- - $Id: device.h,v 1.35 2006/04/04 02:06:12 rocky Exp $ + $Id: device.h,v 1.36 2006/04/12 09:30:14 rocky Exp $ - Copyright (C) 2005, 2006 Rocky Bernstein + Copyright (C) 2005, 2006 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 diff --git a/include/cdio/ecma_167.h b/include/cdio/ecma_167.h index 4103957e..07f16a0e 100644 --- a/include/cdio/ecma_167.h +++ b/include/cdio/ecma_167.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2006 Rocky Bernstein + Copyright (c) 2005, 2006 Rocky Bernstein Copyright (c) 2001-2002 Ben Fennema 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 diff --git a/include/cdio/mmc.h b/include/cdio/mmc.h index 0140570c..f8dc2d46 100644 --- a/include/cdio/mmc.h +++ b/include/cdio/mmc.h @@ -1,7 +1,7 @@ /* - $Id: mmc.h,v 1.26 2006/04/04 02:06:13 rocky Exp $ + $Id: mmc.h,v 1.27 2006/04/12 09:30:14 rocky Exp $ - Copyright (C) 2003, 2004, 2005, 2006 Rocky Bernstein + Copyright (C) 2003, 2004, 2005, 2006 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 @@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/*! +/** * \file mmc.h * * \brief Common definitions for MMC (Multimedia Commands). Applications @@ -37,22 +37,22 @@ extern "C" { #endif /* __cplusplus */ - /*! Set this to the maximum value in milliseconds that we will + /** Set this to the maximum value in milliseconds that we will wait on an MMC command. */ extern uint32_t mmc_timeout_ms; - /*! The default timeout (non-read) is 6 seconds. */ + /** The default timeout (non-read) is 6 seconds. */ #define MMC_TIMEOUT_DEFAULT 6000 - /*! Set this to the maximum value in milliseconds that we will + /** Set this to the maximum value in milliseconds that we will wait on an MMC read command. */ extern uint32_t mmc_read_timeout_ms; - /*! The default read timeout is 3 minutes. */ + /** The default read timeout is 3 minutes. */ #define MMC_READ_TIMEOUT_DEFAULT 3*60*1000 - /*! \brief The opcode-portion (generic packet commands) of an MMC command. + /** \brief The opcode-portion (generic packet commands) of an MMC command. In general, those opcodes that end in 6 take a 6-byte command descriptor, those that end in 10 take a 10-byte @@ -175,7 +175,7 @@ extern "C" { return */ } cdio_mmc_read_sub_state_t; - /*! Level values that can go into READ_CD */ + /** Level values that can go into READ_CD */ typedef enum { CDIO_MMC_READ_TYPE_ANY = 0, /**< All types */ CDIO_MMC_READ_TYPE_CDDA = 1, /**< Only CD-DA sectors */ @@ -185,7 +185,7 @@ extern "C" { CDIO_MMC_READ_TYPE_M2F2 = 5 /**< mode2 sectors form2 */ } cdio_mmc_read_cd_type_t; - /*! Format values for READ_TOC */ + /** Format values for READ_TOC */ typedef enum { CDIO_MMC_READTOC_FMT_TOC = 0, CDIO_MMC_READTOC_FMT_SESSION = 1, @@ -195,7 +195,7 @@ extern "C" { CDIO_MMC_READTOC_FMT_CDTEXT = 5 /**< CD-TEXT info */ } cdio_mmc_readtoc_t; -/*! Page codes for MODE SENSE and MODE SET. */ +/** Page codes for MODE SENSE and MODE SET. */ typedef enum { CDIO_MMC_R_W_ERROR_PAGE = 0x01, CDIO_MMC_WRITE_PARMS_PAGE = 0x05, @@ -218,7 +218,7 @@ PRAGMA_BEGIN_PACKED typedef struct mmc_audio_volume_entry_s mmc_audio_volume_entry_t; - /*! This struct is used by cdio_audio_get_volume and cdio_audio_set_volume */ + /** This struct is used by cdio_audio_get_volume and cdio_audio_set_volume */ struct mmc_audio_volume_s { mmc_audio_volume_entry_t port[4]; @@ -229,7 +229,7 @@ PRAGMA_BEGIN_PACKED PRAGMA_END_PACKED -/*! Return type codes for GET_CONFIGURATION. */ +/** Return type codes for GET_CONFIGURATION. */ typedef enum { CDIO_MMC_GET_CONF_ALL_FEATURES = 0, /**< all features without regard to currency. */ @@ -241,7 +241,7 @@ typedef enum { } cdio_mmc_get_conf_t; -/*! FEATURE codes used in GET CONFIGURATION. */ +/** FEATURE codes used in GET CONFIGURATION. */ typedef enum { CDIO_MMC_FEATURE_PROFILE_LIST = 0x000, /**< Profile List Feature */ @@ -302,7 +302,7 @@ 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 */ @@ -350,19 +350,19 @@ typedef enum { } cdio_mmc_feature_interface_t; -/*! The largest Command Descriptor Block (CDB) size. +/** The largest Command Descriptor Block (CDB) size. The possible sizes are 6, 10, and 12 bytes. */ #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 { @@ -376,7 +376,7 @@ typedef struct mmc_cdb_s { unsigned char profile_lsb; } cdio_mmc_feature_list_header_t; - /*! An enumeration indicating whether an MMC command is sending + /** An enumeration indicating whether an MMC command is sending data or getting data. */ typedef enum mmc_direction_s { @@ -442,7 +442,7 @@ typedef struct mmc_cdb_s { #define CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb, val) \ cdb[9] = val << 3; -/*! +/** Read Audio Subchannel information @param p_cdio the CD object to be acted upon. @@ -452,58 +452,55 @@ driver_return_code_t mmc_audio_read_subchannel (CdIo_t *p_cdio, /*out*/ cdio_subchannel_t *p_subchannel); - /*! + /** Return a string containing the name of the audio state as returned from the Q_SUBCHANNEL. */ const char *mmc_audio_state2str( uint8_t i_audio_state ); - /*! + /** Eject using MMC commands. If CD-ROM is "locked" we'll unlock it. Command is not "immediate" -- we'll wait for the command to complete. For a more general (and lower-level) routine, @see mmc_start_stop_media. */ driver_return_code_t mmc_eject_media( const CdIo_t *p_cdio ); - /*! + /** Return a string containing the name of the given feature */ const char *mmc_feature2str( int i_feature ); - /*! + /** Return a string containing the name of the given feature */ 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. @return the blocksize if > 0; error if <= 0 */ int mmc_get_blocksize ( CdIo_t *p_cdio ); -#if 0 - /*! Don't know how to implement yet. */ - /*! + /** * Close tray using a MMC START STOP command. */ - driver_return_code_t mmc_close_tray( const char *psz_device ); -#endif + driver_return_code_t mmc_close_tray( CdIo_t *p_cdio ); - /*! + /** Get the lsn of the end of the CD @return the lsn. On error return CDIO_INVALID_LSN. */ lsn_t mmc_get_disc_last_lsn( const CdIo_t *p_cdio ); - /*! + /** Return the discmode as reported by the MMC Read (FULL) TOC command. @@ -515,7 +512,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, discmode_t mmc_get_discmode( const CdIo_t *p_cdio ); - /*! + /** Get drive capabilities for a device. @return the drive capabilities. */ @@ -532,13 +529,13 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, CDIO_MMC_LEVEL_NONE } cdio_mmc_level_t; - /*! + /** Get the MMC level supported by the device. */ cdio_mmc_level_t mmc_get_drive_mmc_cap(CdIo_t *p_cdio); - /*! + /** Get the DVD type associated with cd object. @return the DVD discmode. @@ -546,7 +543,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, discmode_t mmc_get_dvd_struct_physical ( const CdIo_t *p_cdio, cdio_dvd_struct_t *s); - /*! + /** Get the CD-ROM hardware info via an MMC INQUIRY command. @return true if we were able to get hardware info, false if we had @@ -556,7 +553,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, /* out*/ cdio_hwinfo_t *p_hw_info ); - /*! + /** Find out if media has changed since the last call. @param p_cdio the CD object to be acted upon. @return 1 if media has changed since last call, 0 if not. Error @@ -564,7 +561,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, */ int mmc_get_media_changed(const CdIo_t *p_cdio); - /*! + /** Get the media catalog number (MCN) from the CD via MMC. @return the media catalog number r NULL if there is none or we @@ -583,7 +580,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, 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 routine could probably return the single mmc_feature_interface_t. @@ -592,7 +589,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, bool_3way_t mmc_have_interface( CdIo_t *p_cdio, cdio_mmc_feature_interface_t e_interface ); - /*! Run a MODE_SENSE command (6- or 10-byte version) + /** Run a MODE_SENSE command (6- or 10-byte version) and put the results in p_buf @return DRIVER_OP_SUCCESS if we ran the command ok. */ @@ -600,21 +597,21 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, int page); - /*! Run a MODE_SENSE command (10-byte version) + /** Run a MODE_SENSE command (10-byte version) and put the results in p_buf @return DRIVER_OP_SUCCESS if we ran the command ok. */ int mmc_mode_sense_10( CdIo_t *p_cdio, /*out*/ void *p_buf, int i_size, int page); - /*! Run a MODE_SENSE command (6-byte version) + /** Run a MODE_SENSE command (6-byte version) and put the results in p_buf @return DRIVER_OP_SUCCESS if we ran the command ok. */ int mmc_mode_sense_6( CdIo_t *p_cdio, /*out*/ void *p_buf, int i_size, int page); - /*! Issue a MMC READ_CD command. + /** Issue a MMC READ_CD command. @param p_cdio object to read from @@ -722,7 +719,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, uint8_t subchannel_selection, uint16_t i_blocksize, uint32_t i_blocks ); - /*! Read just the user data part of some sort of data sector (via + /** Read just the user data part of some sort of data sector (via mmc_read_cd). @param p_cdio object to read from @@ -745,14 +742,14 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, uint16_t i_blocksize, uint32_t i_blocks ); - /*! Read sectors using SCSI-MMC GPCMD_READ_CD. + /** Read sectors using SCSI-MMC GPCMD_READ_CD. Can read only up to 25 blocks. */ driver_return_code_t mmc_read_sectors ( const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, int read_sector_type, uint32_t i_blocks); - /*! + /** Run a Multimedia command (MMC). @param p_cdio CD structure set by cdio_open(). @@ -771,13 +768,13 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, const mmc_cdb_t *p_cdb, cdio_mmc_direction_t e_direction, unsigned int i_buf, /*in/out*/ void *p_buf ); - /*! + /** Set the block size for subsequest read requests, via MMC. */ driver_return_code_t mmc_set_blocksize ( const CdIo_t *p_cdio, uint16_t i_blocksize); - /*! + /** Set the drive speed in CD-ROM speed units. @param p_cdio CD structure set by cdio_open(). @@ -797,7 +794,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, driver_return_code_t mmc_set_drive_speed( const CdIo_t *p_cdio, int i_drive_speed ); - /*! + /** Set the drive speed in K bytes per second. @param p_cdio CD structure set by cdio_open(). @@ -821,7 +818,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio, driver_return_code_t mmc_set_speed( const CdIo_t *p_cdio, int i_Kbs_speed ); - /*! + /** Load or Unload media using a MMC START STOP command. @param p_cdio the CD object to be acted upon. diff --git a/include/cdio/udf_file.h b/include/cdio/udf_file.h index e4376dd4..eaf952dc 100644 --- a/include/cdio/udf_file.h +++ b/include/cdio/udf_file.h @@ -1,6 +1,6 @@ /* - $Id: udf_file.h,v 1.8 2006/04/11 05:47:57 rocky Exp $ - Copyright (C) 2005, 2006 Rocky Bernstein + $Id: udf_file.h,v 1.9 2006/04/12 09:30:14 rocky Exp $ + Copyright (C) 2005, 2006 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 diff --git a/lib/driver/mmc.c b/lib/driver/mmc.c index 216ee9cd..85a36b08 100644 --- a/lib/driver/mmc.c +++ b/lib/driver/mmc.c @@ -1,8 +1,8 @@ /* Common Multimedia Command (MMC) routines. - $Id: mmc.c,v 1.33 2006/04/05 02:20:06 rocky Exp $ + $Id: mmc.c,v 1.34 2006/04/12 09:30:14 rocky Exp $ - Copyright (C) 2004, 2005, 2006 Rocky Bernstein + Copyright (C) 2004, 2005, 2006 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 @@ -981,16 +981,18 @@ mmc_start_stop_media(const CdIo_t *p_cdio, bool b_eject, bool b_immediate, SCSI_MMC_DATA_WRITE, 0, &buf); } -#if 0 -/*! +/** * Close tray using a MMC START STOP command. */ -driver_return_code_t -mmc_close_tray( const CdIo_t *p_cdio ) +driver_return_code_t +mmc_close_tray( CdIo_t *p_cdio ) { - return mmc_start_stop_media(p_cdio, false, false, 0); + if (p_cdio) { + return mmc_start_stop_media(p_cdio, false, false, 0); + } else { + return DRIVER_OP_ERROR; + } } -#endif /*! Eject using MMC commands. If CD-ROM is "locked" we'll unlock it. diff --git a/src/mmc-tool.c b/src/mmc-tool.c index 5d0ee06a..70459280 100644 --- a/src/mmc-tool.c +++ b/src/mmc-tool.c @@ -1,7 +1,7 @@ /* - $Id: mmc-tool.c,v 1.5 2006/04/12 03:23:46 rocky Exp $ + $Id: mmc-tool.c,v 1.6 2006/04/12 09:30:14 rocky Exp $ - Copyright (C) 2006 Rocky Bernstein + Copyright (C) 2006 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 @@ -38,26 +38,18 @@ #include "util.h" #include "getopt.h" -/* Used by `main' to communicate with `parse_opt'. And global options - */ -struct arguments -{ - int i_speed; - int i_blocksize; -} opts; - static void init(const char *argv0) { program_name = strrchr(argv0,'/'); program_name = program_name ? strdup(program_name+1) : strdup(argv0); - opts.i_blocksize = 0; } /* Configuration option codes */ typedef enum { OPT_HANDLED = 0, OPT_USAGE, + OPT_DRIVE_CAP, OPT_VERSION, } option_t; @@ -68,6 +60,7 @@ typedef enum { OP_CLOSETRAY, OP_EJECT, OP_IDLE, + OP_MODE_SENSE_2A, OP_MCN, OP_SPEED, } operation_enum_t; @@ -103,6 +96,7 @@ parse_options (int argc, char *argv[]) { int opt; operation_t op; + int i_blocksize = 0; const char* helpText = "Usage: %s [OPTION...]\n" @@ -111,6 +105,9 @@ parse_options (int argc, char *argv[]) " -b, --blocksize[=INT] set blocksize. If no block size or a \n" " zero blocksize is given we return the\n" " current setting.\n" + " -C, --drive-cap [6|10] print mode sense 2a data\n" + " using 6-byte or 10-byte form\n" + " -c, --close drive close drive via ALLOW_MEDIUM_REMOVAL\n" " -e, --eject [drive] eject drive via ALLOW_MEDIUM_REMOVAL\n" " and a MMC START/STOP command\n" " -I, --idle set CD-ROM to idle or power down\n" @@ -133,11 +130,12 @@ parse_options (int argc, char *argv[]) " [-V|--version] [-?|--help] [--usage]\n"; /* Command-line options */ - const char* optionsString = "b::c:e::Is:V?"; + const char* optionsString = "b::c:C::e::Is:V?"; struct option optionsTable[] = { - {"blocksize", optional_argument, &opts.i_blocksize, 'b' }, - /* {"close", required_argument, NULL, 'c'}, */ + {"blocksize", optional_argument, &i_blocksize, 'b' }, + {"close", required_argument, NULL, 'c'}, + {"drive-cap", optional_argument, NULL, 'C'}, {"eject", optional_argument, NULL, 'e'}, {"idle", no_argument, NULL, 'I'}, {"mcn", no_argument, NULL, 'm'}, @@ -155,9 +153,26 @@ parse_options (int argc, char *argv[]) { case 'b': op.op = OP_BLOCKSIZE; - op.arg.i_num = opts.i_blocksize; + op.arg.i_num = i_blocksize; push_op(&op); break; + case 'C': + op.arg.i_num = optarg ? atoi(optarg) : 10; + switch (op.arg.i_num) { + case 10: + op.op = OP_MODE_SENSE_2A; + op.arg.i_num = 10; + push_op(&op); + break; + case 6: + op.op = OP_MODE_SENSE_2A; + op.arg.i_num = 6; + push_op(&op); + break; + default: + report( stderr, "%s: Expecting 6 or 10 or nothing\n", program_name ); + } + break; case 'c': op.op = OP_CLOSETRAY; op.arg.psz = strdup(optarg); @@ -209,6 +224,7 @@ parse_options (int argc, char *argv[]) case OPT_HANDLED: break; + i_blocksize = 0; } if (optind < argc) { @@ -234,6 +250,163 @@ parse_options (int argc, char *argv[]) return true; } +static void +print_mode_sense (unsigned int i_mmc_size, const uint8_t buf[22]) +{ + printf("Mode sense %d information\n", i_mmc_size); + if (buf[2] & 0x01) { + printf("\tReads CD-R media.\n"); + } + if (buf[2] & 0x02) { + printf("\tReads CD-RW media.\n"); + } + if (buf[2] & 0x04) { + printf("\tReads fixed-packet tracks when Addressing type is method 2.\n"); + } + if (buf[2] & 0x08) { + printf("\tReads DVD ROM media.\n"); + } + if (buf[2] & 0x10) { + printf("\tReads DVD-R media.\n"); + } + if (buf[2] & 0x20) { + printf("\tReads DVD-RAM media.\n"); + } + if (buf[2] & 0x40) { + printf("\tReads DVD-RAM media.\n"); + } + if (buf[3] & 0x01) { + printf("\tWrites CD-R media.\n"); + } + if (buf[3] & 0x02) { + printf("\tWrites CD-RW media.\n"); + } + if (buf[3] & 0x04) { + printf("\tSupports emulation write.\n"); + } + if (buf[3] & 0x10) { + printf("\tWrites DVD-R media.\n"); + } + if (buf[3] & 0x20) { + printf("\tWrites DVD-RAM media.\n"); + } + if (buf[4] & 0x01) { + printf("\tCan play audio.\n"); + } + if (buf[4] & 0x02) { + printf("\tDelivers composition A/V stream.\n"); + } + if (buf[4] & 0x04) { + printf("\tSupports digital output on port 2.\n"); + } + if (buf[4] & 0x08) { + printf("\tSupports digital output on port 1.\n"); + } + if (buf[4] & 0x10) { + printf("\tReads Mode-2 form 1 (e.g. XA) media.\n"); + } + if (buf[4] & 0x20) { + printf("\tReads Mode-2 form 2 media.\n"); + } + if (buf[4] & 0x40) { + printf("\tReads multi-session CD media.\n"); + } + if (buf[4] & 0x80) { + printf("\tSupports Buffer under-run free recording on CD-R/RW media.\n"); + } + if (buf[4] & 0x01) { + printf("\tCan read audio data with READ CD.\n"); + } + if (buf[4] & 0x02) { + printf("\tREAD CD data stream is accurate.\n"); + } + if (buf[5] & 0x04) { + printf("\tReads R-W subchannel information.\n"); + } + if (buf[5] & 0x08) { + printf("\tReads de-interleaved R-W subchannel.\n"); + } + if (buf[5] & 0x10) { + printf("\tSupports C2 error pointers.\n"); + } + if (buf[5] & 0x20) { + printf("\tReads ISRC information.\n"); + } + if (buf[5] & 0x40) { + printf("\tReads ISRC informaton.\n"); + } + if (buf[5] & 0x40) { + printf("\tReads media catalog number (MCN also known as UPC).\n"); + } + if (buf[5] & 0x80) { + printf("\tReads bar codes.\n"); + } + if (buf[6] & 0x01) { + printf("\tPREVENT/ALLOW may lock media.\n"); + } + printf("\tLock state is %slocked.\n", (buf[6] & 0x02) ? "" : "un"); + printf("\tPREVENT/ALLOW jumper is %spresent.\n", (buf[6] & 0x04) ? "": "not "); + if (buf[6] & 0x08) { + printf("\tEjects media with START STOP UNIT.\n"); + } + { + const unsigned int i_load_type = (buf[6]>>5 & 0x07); + printf("\tLoading mechanism type is %d: ", i_load_type); + switch (buf[6]>>5 & 0x07) { + case 0: + printf("caddy type loading mechanism.\n"); + break; + case 1: + printf("tray type loading mechanism.\n"); + break; + case 2: + printf("popup type loading mechanism.\n"); + break; + case 3: + printf("reserved\n"); + break; + case 4: + printf("changer with individually changeable discs.\n"); + break; + case 5: + printf("changer using Magazine mechanism.\n"); + break; + case 6: + printf("changer using Magazine mechanism.\n"); + break; + default: + printf("Invalid.\n"); + break; + } + } + + if (buf[7] & 0x01) { + printf("\tVolume controls each channel separately.\n"); + } + if (buf[7] & 0x02) { + printf("\tHas a changer that supports disc present reporting.\n"); + } + if (buf[7] & 0x04) { + printf("\tCan load empty slot in changer.\n"); + } + if (buf[7] & 0x08) { + printf("\tSide change capable.\n"); + } + if (buf[7] & 0x10) { + printf("\tReads raw R-W subchannel information from lead in.\n"); + } + { + const unsigned int i_speed_Kbs = CDIO_MMC_GETPOS_LEN16(buf, 8); + printf("\tMaximum read speed is %d K bytes/sec (about %dX)\n", + i_speed_Kbs, i_speed_Kbs / 176) ; + } + printf("\tNumber of Volume levels is %d\n", CDIO_MMC_GETPOS_LEN16(buf, 10)); + printf("\tBuffers size for data is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 12)); + printf("\tCurrent read speed is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 14)); + printf("\tMaximum write speed is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 18)); + printf("\tCurrent write speed is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 28)); +} + int main(int argc, char *argv[]) { @@ -276,14 +449,30 @@ main(int argc, char *argv[]) } } break; -#if 0 + case OP_MODE_SENSE_2A: + { + uint8_t buf[22] = { 0, }; /* Place to hold returned data */ + if (p_op->arg.i_num == 10) { + rc = mmc_mode_sense_10(p_cdio, buf, sizeof(buf), + CDIO_MMC_CAPABILITIES_PAGE); + } else { + rc = mmc_mode_sense_6(p_cdio, buf, sizeof(buf), + CDIO_MMC_CAPABILITIES_PAGE); + } + if (DRIVER_OP_SUCCESS == rc) { + print_mode_sense(p_op->arg.i_num, buf); + } else { + report(stdout, "%s (mmc_mode_sense 2a - drive_cap %d): %s\n", + program_name, p_op->arg.i_num, cdio_driver_errmsg(rc)); + } + } + break; case OP_CLOSETRAY: - rc = mmc_close_tray(p_cdio, op.arg.psz); + rc = mmc_close_tray(p_cdio); report(stdout, "%s (mmc_close_tray): %s\n", program_name, cdio_driver_errmsg(rc)); free(p_op->arg.psz); break; -#endif case OP_EJECT: rc = mmc_eject_media(p_cdio); report(stdout, "%s (mmc_eject_media): %s\n", program_name,