mmc: add mmc_close_tray().

mmc-tool: add option for close tray and to get mode-sense 2A data.
This commit is contained in:
rocky
2006-04-12 09:30:14 +00:00
parent a87210b686
commit 0c2b1bfa9e
8 changed files with 276 additions and 88 deletions

View File

@@ -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 <rocky@panix.com> Copyright (C) 2006 Rocky Bernstein <rocky@cpan.org>
This program is free software; you can redistribute it and/or modify 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 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. /* Sample program to show use of the MMC interface.
An optional drive name can be supplied as an argument. An optional drive name can be supplied as an argument.
This basically the libdio mmc_get_hwinfo() routine. This basically calls to the libdio mmc_mode_sense_10() and mmc_mode_sense_6
See also corresponding C++ programs. routines.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"

View File

@@ -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 <rocky@panix.com> Copyright (C) 2003, 2006 Rocky Bernstein <rocky@cpan.org>
Copyright (C) 1996,1997,1998 Gerd Knorr <kraxel@bytesex.org> Copyright (C) 1996,1997,1998 Gerd Knorr <kraxel@bytesex.org>
and Heiko Ei<45>feldt <heiko@hexco.de> and Heiko Ei<45>feldt <heiko@hexco.de>

View File

@@ -1,7 +1,7 @@
/* -*- c -*- /* -*- 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 <rocky@panix.com> Copyright (C) 2005, 2006 Rocky Bernstein <rocky@cpan.org>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@@ -1,5 +1,5 @@
/* /*
Copyright (c) 2005, 2006 Rocky Bernstein <rocky@panix.com> Copyright (c) 2005, 2006 Rocky Bernstein <rocky@cpan.org>
Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu> Copyright (c) 2001-2002 Ben Fennema <bfennema@falcon.csc.calpoly.edu>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@@ -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 <rocky@panix.com> Copyright (C) 2003, 2004, 2005, 2006 Rocky Bernstein <rocky@cpan.org>
This program is free software; you can redistribute it and/or modify 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 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 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/*! /**
* \file mmc.h * \file mmc.h
* *
* \brief Common definitions for MMC (Multimedia Commands). Applications * \brief Common definitions for MMC (Multimedia Commands). Applications
@@ -37,22 +37,22 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #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. */ wait on an MMC command. */
extern uint32_t mmc_timeout_ms; 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 #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. */ wait on an MMC read command. */
extern uint32_t mmc_read_timeout_ms; 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 #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 In general, those opcodes that end in 6 take a 6-byte command
descriptor, those that end in 10 take a 10-byte descriptor, those that end in 10 take a 10-byte
@@ -175,7 +175,7 @@ extern "C" {
return */ return */
} cdio_mmc_read_sub_state_t; } cdio_mmc_read_sub_state_t;
/*! Level values that can go into READ_CD */ /** Level values that can go into READ_CD */
typedef enum { typedef enum {
CDIO_MMC_READ_TYPE_ANY = 0, /**< All types */ CDIO_MMC_READ_TYPE_ANY = 0, /**< All types */
CDIO_MMC_READ_TYPE_CDDA = 1, /**< Only CD-DA sectors */ 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_TYPE_M2F2 = 5 /**< mode2 sectors form2 */
} cdio_mmc_read_cd_type_t; } cdio_mmc_read_cd_type_t;
/*! Format values for READ_TOC */ /** Format values for READ_TOC */
typedef enum { typedef enum {
CDIO_MMC_READTOC_FMT_TOC = 0, CDIO_MMC_READTOC_FMT_TOC = 0,
CDIO_MMC_READTOC_FMT_SESSION = 1, CDIO_MMC_READTOC_FMT_SESSION = 1,
@@ -195,7 +195,7 @@ extern "C" {
CDIO_MMC_READTOC_FMT_CDTEXT = 5 /**< CD-TEXT info */ CDIO_MMC_READTOC_FMT_CDTEXT = 5 /**< CD-TEXT info */
} cdio_mmc_readtoc_t; } cdio_mmc_readtoc_t;
/*! Page codes for MODE SENSE and MODE SET. */ /** Page codes for MODE SENSE and MODE SET. */
typedef enum { typedef enum {
CDIO_MMC_R_W_ERROR_PAGE = 0x01, CDIO_MMC_R_W_ERROR_PAGE = 0x01,
CDIO_MMC_WRITE_PARMS_PAGE = 0x05, 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; 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 struct mmc_audio_volume_s
{ {
mmc_audio_volume_entry_t port[4]; mmc_audio_volume_entry_t port[4];
@@ -229,7 +229,7 @@ PRAGMA_BEGIN_PACKED
PRAGMA_END_PACKED PRAGMA_END_PACKED
/*! Return type codes for GET_CONFIGURATION. */ /** Return type codes for GET_CONFIGURATION. */
typedef enum { typedef enum {
CDIO_MMC_GET_CONF_ALL_FEATURES = 0, /**< all features without regard CDIO_MMC_GET_CONF_ALL_FEATURES = 0, /**< all features without regard
to currency. */ to currency. */
@@ -241,7 +241,7 @@ typedef enum {
} cdio_mmc_get_conf_t; } cdio_mmc_get_conf_t;
/*! FEATURE codes used in GET CONFIGURATION. */ /** FEATURE codes used in GET CONFIGURATION. */
typedef enum { typedef enum {
CDIO_MMC_FEATURE_PROFILE_LIST = 0x000, /**< Profile List Feature */ CDIO_MMC_FEATURE_PROFILE_LIST = 0x000, /**< Profile List Feature */
@@ -302,7 +302,7 @@ typedef enum {
report */ report */
} cdio_mmc_feature_t; } cdio_mmc_feature_t;
/*! Profile profile codes used in GET_CONFIGURATION - PROFILE LIST. */ /** Profile profile codes used in GET_CONFIGURATION - PROFILE LIST. */
typedef enum { typedef enum {
CDIO_MMC_FEATURE_PROF_NON_REMOVABLE = 0x0001, /**< Re-writable disk, capable CDIO_MMC_FEATURE_PROF_NON_REMOVABLE = 0x0001, /**< Re-writable disk, capable
of changing behavior */ of changing behavior */
@@ -350,19 +350,19 @@ typedef enum {
} cdio_mmc_feature_interface_t; } 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. The possible sizes are 6, 10, and 12 bytes.
*/ */
#define MAX_CDB_LEN 12 #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. commands.
*/ */
typedef struct mmc_cdb_s { typedef struct mmc_cdb_s {
uint8_t field[MAX_CDB_LEN]; uint8_t field[MAX_CDB_LEN];
} mmc_cdb_t; } 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. GET_CONFIGURATION command.
*/ */
typedef struct mmc_feature_list_header_s { typedef struct mmc_feature_list_header_s {
@@ -376,7 +376,7 @@ typedef struct mmc_cdb_s {
unsigned char profile_lsb; unsigned char profile_lsb;
} cdio_mmc_feature_list_header_t; } 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. data or getting data.
*/ */
typedef enum mmc_direction_s { typedef enum mmc_direction_s {
@@ -442,7 +442,7 @@ typedef struct mmc_cdb_s {
#define CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb, val) \ #define CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb, val) \
cdb[9] = val << 3; cdb[9] = val << 3;
/*! /**
Read Audio Subchannel information Read Audio Subchannel information
@param p_cdio the CD object to be acted upon. @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, mmc_audio_read_subchannel (CdIo_t *p_cdio,
/*out*/ cdio_subchannel_t *p_subchannel); /*out*/ cdio_subchannel_t *p_subchannel);
/*! /**
Return a string containing the name of the audio state as returned from Return a string containing the name of the audio state as returned from
the Q_SUBCHANNEL. the Q_SUBCHANNEL.
*/ */
const char *mmc_audio_state2str( uint8_t i_audio_state ); const char *mmc_audio_state2str( uint8_t i_audio_state );
/*! /**
Eject using MMC commands. If CD-ROM is "locked" we'll unlock it. 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. 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. 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 ); driver_return_code_t mmc_eject_media( const CdIo_t *p_cdio );
/*! /**
Return a string containing the name of the given feature Return a string containing the name of the given feature
*/ */
const char *mmc_feature2str( int i_feature ); const char *mmc_feature2str( int i_feature );
/*! /**
Return a string containing the name of the given feature Return a string containing the name of the given feature
*/ */
const char *mmc_feature_profile2str( int i_feature_profile ); const char *mmc_feature_profile2str( int i_feature_profile );
/*! /**
Return the length in bytes of the Command Descriptor Return the length in bytes of the Command Descriptor
Buffer (CDB) for a given MMC command. The length will be Buffer (CDB) for a given MMC command. The length will be
either 6, 10, or 12. either 6, 10, or 12.
*/ */
uint8_t mmc_get_cmd_len(uint8_t mmc_cmd); uint8_t mmc_get_cmd_len(uint8_t mmc_cmd);
/*! /**
Get the block size used in read requests, via MMC. Get the block size used in read requests, via MMC.
@return the blocksize if > 0; error if <= 0 @return the blocksize if > 0; error if <= 0
*/ */
int mmc_get_blocksize ( CdIo_t *p_cdio ); 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. * Close tray using a MMC START STOP command.
*/ */
driver_return_code_t mmc_close_tray( const char *psz_device ); driver_return_code_t mmc_close_tray( CdIo_t *p_cdio );
#endif
/*! /**
Get the lsn of the end of the CD Get the lsn of the end of the CD
@return the lsn. On error return CDIO_INVALID_LSN. @return the lsn. On error return CDIO_INVALID_LSN.
*/ */
lsn_t mmc_get_disc_last_lsn( const CdIo_t *p_cdio ); lsn_t mmc_get_disc_last_lsn( const CdIo_t *p_cdio );
/*! /**
Return the discmode as reported by the MMC Read (FULL) TOC Return the discmode as reported by the MMC Read (FULL) TOC
command. command.
@@ -515,7 +512,7 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio,
discmode_t mmc_get_discmode( const CdIo_t *p_cdio ); discmode_t mmc_get_discmode( const CdIo_t *p_cdio );
/*! /**
Get drive capabilities for a device. Get drive capabilities for a device.
@return the drive capabilities. @return the drive capabilities.
*/ */
@@ -532,13 +529,13 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio,
CDIO_MMC_LEVEL_NONE CDIO_MMC_LEVEL_NONE
} cdio_mmc_level_t; } cdio_mmc_level_t;
/*! /**
Get the MMC level supported by the device. Get the MMC level supported by the device.
*/ */
cdio_mmc_level_t mmc_get_drive_mmc_cap(CdIo_t *p_cdio); cdio_mmc_level_t mmc_get_drive_mmc_cap(CdIo_t *p_cdio);
/*! /**
Get the DVD type associated with cd object. Get the DVD type associated with cd object.
@return the DVD discmode. @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, discmode_t mmc_get_dvd_struct_physical ( const CdIo_t *p_cdio,
cdio_dvd_struct_t *s); cdio_dvd_struct_t *s);
/*! /**
Get the CD-ROM hardware info via an MMC INQUIRY command. 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 @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 ); /* out*/ cdio_hwinfo_t *p_hw_info );
/*! /**
Find out if media has changed since the last call. Find out if media has changed since the last call.
@param p_cdio the CD object to be acted upon. @param p_cdio the CD object to be acted upon.
@return 1 if media has changed since last call, 0 if not. Error @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); int mmc_get_media_changed(const CdIo_t *p_cdio);
/*! /**
Get the media catalog number (MCN) from the CD via MMC. Get the media catalog number (MCN) from the CD via MMC.
@return the media catalog number r NULL if there is none or we @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*/ driver_return_code_t mmc_audio_get_volume (CdIo_t *p_cdio, /*out*/
mmc_audio_volume_t *p_volume); mmc_audio_volume_t *p_volume);
/*! /**
Report if CD-ROM has a praticular kind of interface (ATAPI, SCSCI, ...) Report if CD-ROM has a praticular kind of interface (ATAPI, SCSCI, ...)
Is it possible for an interface to have serveral? If not this Is it possible for an interface to have serveral? If not this
routine could probably return the single mmc_feature_interface_t. 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, bool_3way_t mmc_have_interface( CdIo_t *p_cdio,
cdio_mmc_feature_interface_t e_interface ); 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 and put the results in p_buf
@return DRIVER_OP_SUCCESS if we ran the command ok. @return DRIVER_OP_SUCCESS if we ran the command ok.
*/ */
@@ -600,21 +597,21 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio,
int page); 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 and put the results in p_buf
@return DRIVER_OP_SUCCESS if we ran the command ok. @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 mmc_mode_sense_10( CdIo_t *p_cdio, /*out*/ void *p_buf, int i_size,
int page); 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 and put the results in p_buf
@return DRIVER_OP_SUCCESS if we ran the command ok. @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 mmc_mode_sense_6( CdIo_t *p_cdio, /*out*/ void *p_buf, int i_size,
int page); int page);
/*! Issue a MMC READ_CD command. /** Issue a MMC READ_CD command.
@param p_cdio object to read from @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, uint8_t subchannel_selection, uint16_t i_blocksize,
uint32_t i_blocks ); 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). mmc_read_cd).
@param p_cdio object to read from @param p_cdio object to read from
@@ -745,14 +742,14 @@ mmc_audio_read_subchannel (CdIo_t *p_cdio,
uint16_t i_blocksize, uint16_t i_blocksize,
uint32_t i_blocks ); 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. Can read only up to 25 blocks.
*/ */
driver_return_code_t mmc_read_sectors ( const CdIo_t *p_cdio, void *p_buf, driver_return_code_t mmc_read_sectors ( const CdIo_t *p_cdio, void *p_buf,
lsn_t i_lsn, int read_sector_type, lsn_t i_lsn, int read_sector_type,
uint32_t i_blocks); uint32_t i_blocks);
/*! /**
Run a Multimedia command (MMC). Run a Multimedia command (MMC).
@param p_cdio CD structure set by cdio_open(). @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, const mmc_cdb_t *p_cdb,
cdio_mmc_direction_t e_direction, unsigned int i_buf, cdio_mmc_direction_t e_direction, unsigned int i_buf,
/*in/out*/ void *p_buf ); /*in/out*/ void *p_buf );
/*! /**
Set the block size for subsequest read requests, via MMC. Set the block size for subsequest read requests, via MMC.
*/ */
driver_return_code_t mmc_set_blocksize ( const CdIo_t *p_cdio, driver_return_code_t mmc_set_blocksize ( const CdIo_t *p_cdio,
uint16_t i_blocksize); uint16_t i_blocksize);
/*! /**
Set the drive speed in CD-ROM speed units. Set the drive speed in CD-ROM speed units.
@param p_cdio CD structure set by cdio_open(). @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, driver_return_code_t mmc_set_drive_speed( const CdIo_t *p_cdio,
int i_drive_speed ); int i_drive_speed );
/*! /**
Set the drive speed in K bytes per second. Set the drive speed in K bytes per second.
@param p_cdio CD structure set by cdio_open(). @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, driver_return_code_t mmc_set_speed( const CdIo_t *p_cdio,
int i_Kbs_speed ); int i_Kbs_speed );
/*! /**
Load or Unload media using a MMC START STOP command. Load or Unload media using a MMC START STOP command.
@param p_cdio the CD object to be acted upon. @param p_cdio the CD object to be acted upon.

View File

@@ -1,6 +1,6 @@
/* /*
$Id: udf_file.h,v 1.8 2006/04/11 05:47:57 rocky Exp $ $Id: udf_file.h,v 1.9 2006/04/12 09:30:14 rocky Exp $
Copyright (C) 2005, 2006 Rocky Bernstein <rockyb@users.sourceforge.net> Copyright (C) 2005, 2006 Rocky Bernstein <rocky@cpan.org>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@@ -1,8 +1,8 @@
/* Common Multimedia Command (MMC) routines. /* 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 <rocky@panix.com> Copyright (C) 2004, 2005, 2006 Rocky Bernstein <rocky@cpan.org>
This program is free software; you can redistribute it and/or modify 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 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); SCSI_MMC_DATA_WRITE, 0, &buf);
} }
#if 0 /**
/*!
* Close tray using a MMC START STOP command. * Close tray using a MMC START STOP command.
*/ */
driver_return_code_t driver_return_code_t
mmc_close_tray( const CdIo_t *p_cdio ) 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. Eject using MMC commands. If CD-ROM is "locked" we'll unlock it.

View File

@@ -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 <rocky@panix.com> Copyright (C) 2006 Rocky Bernstein <rocky@cpan.org>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -38,26 +38,18 @@
#include "util.h" #include "util.h"
#include "getopt.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 static void
init(const char *argv0) init(const char *argv0)
{ {
program_name = strrchr(argv0,'/'); program_name = strrchr(argv0,'/');
program_name = program_name ? strdup(program_name+1) : strdup(argv0); program_name = program_name ? strdup(program_name+1) : strdup(argv0);
opts.i_blocksize = 0;
} }
/* Configuration option codes */ /* Configuration option codes */
typedef enum { typedef enum {
OPT_HANDLED = 0, OPT_HANDLED = 0,
OPT_USAGE, OPT_USAGE,
OPT_DRIVE_CAP,
OPT_VERSION, OPT_VERSION,
} option_t; } option_t;
@@ -68,6 +60,7 @@ typedef enum {
OP_CLOSETRAY, OP_CLOSETRAY,
OP_EJECT, OP_EJECT,
OP_IDLE, OP_IDLE,
OP_MODE_SENSE_2A,
OP_MCN, OP_MCN,
OP_SPEED, OP_SPEED,
} operation_enum_t; } operation_enum_t;
@@ -103,6 +96,7 @@ parse_options (int argc, char *argv[])
{ {
int opt; int opt;
operation_t op; operation_t op;
int i_blocksize = 0;
const char* helpText = const char* helpText =
"Usage: %s [OPTION...]\n" "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" " -b, --blocksize[=INT] set blocksize. If no block size or a \n"
" zero blocksize is given we return the\n" " zero blocksize is given we return the\n"
" current setting.\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" " -e, --eject [drive] eject drive via ALLOW_MEDIUM_REMOVAL\n"
" and a MMC START/STOP command\n" " and a MMC START/STOP command\n"
" -I, --idle set CD-ROM to idle or power down\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"; " [-V|--version] [-?|--help] [--usage]\n";
/* Command-line options */ /* Command-line options */
const char* optionsString = "b::c:e::Is:V?"; const char* optionsString = "b::c:C::e::Is:V?";
struct option optionsTable[] = { struct option optionsTable[] = {
{"blocksize", optional_argument, &opts.i_blocksize, 'b' }, {"blocksize", optional_argument, &i_blocksize, 'b' },
/* {"close", required_argument, NULL, 'c'}, */ {"close", required_argument, NULL, 'c'},
{"drive-cap", optional_argument, NULL, 'C'},
{"eject", optional_argument, NULL, 'e'}, {"eject", optional_argument, NULL, 'e'},
{"idle", no_argument, NULL, 'I'}, {"idle", no_argument, NULL, 'I'},
{"mcn", no_argument, NULL, 'm'}, {"mcn", no_argument, NULL, 'm'},
@@ -155,9 +153,26 @@ parse_options (int argc, char *argv[])
{ {
case 'b': case 'b':
op.op = OP_BLOCKSIZE; op.op = OP_BLOCKSIZE;
op.arg.i_num = opts.i_blocksize; op.arg.i_num = i_blocksize;
push_op(&op); push_op(&op);
break; 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': case 'c':
op.op = OP_CLOSETRAY; op.op = OP_CLOSETRAY;
op.arg.psz = strdup(optarg); op.arg.psz = strdup(optarg);
@@ -209,6 +224,7 @@ parse_options (int argc, char *argv[])
case OPT_HANDLED: case OPT_HANDLED:
break; break;
i_blocksize = 0;
} }
if (optind < argc) { if (optind < argc) {
@@ -234,6 +250,163 @@ parse_options (int argc, char *argv[])
return true; 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 int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@@ -276,14 +449,30 @@ main(int argc, char *argv[])
} }
} }
break; 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: 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, report(stdout, "%s (mmc_close_tray): %s\n", program_name,
cdio_driver_errmsg(rc)); cdio_driver_errmsg(rc));
free(p_op->arg.psz); free(p_op->arg.psz);
break; break;
#endif
case OP_EJECT: case OP_EJECT:
rc = mmc_eject_media(p_cdio); rc = mmc_eject_media(p_cdio);
report(stdout, "%s (mmc_eject_media): %s\n", program_name, report(stdout, "%s (mmc_eject_media): %s\n", program_name,