|
Packit |
dd8086 |
/*
|
|
Packit |
dd8086 |
Copyright (C) 2006, 2008, 2010-2011, 2014, 2017
|
|
Packit |
dd8086 |
Rocky Bernstein <rocky@gnu.org>
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
This program is free software: you can redistribute it and/or modify
|
|
Packit |
dd8086 |
it under the terms of the GNU General Public License as published by
|
|
Packit |
dd8086 |
the Free Software Foundation, either version 3 of the License, or
|
|
Packit |
dd8086 |
(at your option) any later version.
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
dd8086 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
dd8086 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
dd8086 |
GNU General Public License for more details.
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
You should have received a copy of the GNU General Public License
|
|
Packit |
dd8086 |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* A program to using the MMC interface to list CD and drive features
|
|
Packit |
dd8086 |
from the MMC GET_CONFIGURATION command . */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
#include "util.h"
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
#ifdef HAVE_STDIO_H
|
|
Packit |
dd8086 |
#include <stdio.h>
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#ifdef HAVE_SYS_TYPES_H
|
|
Packit |
dd8086 |
#include <sys/types.h>
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#ifdef HAVE_STRING_H
|
|
Packit |
dd8086 |
#include <string.h>
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#ifdef HAVE_STDLIB_H
|
|
Packit |
dd8086 |
#include <stdlib.h>
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#include <cdio/cdio.h>
|
|
Packit |
dd8086 |
#include <cdio/mmc.h>
|
|
Packit |
dd8086 |
#include <cdio/mmc_cmds.h>
|
|
Packit |
dd8086 |
#include "getopt.h"
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Configuration option codes */
|
|
Packit |
dd8086 |
typedef enum {
|
|
Packit |
dd8086 |
OPT_HANDLED = 0,
|
|
Packit |
dd8086 |
OPT_USAGE,
|
|
Packit |
dd8086 |
OPT_DRIVE_CAP,
|
|
Packit |
dd8086 |
OPT_VERSION,
|
|
Packit |
dd8086 |
} option_t;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
typedef enum {
|
|
Packit |
dd8086 |
/* These are the remaining configuration options */
|
|
Packit |
dd8086 |
OP_FINISHED = 0,
|
|
Packit |
dd8086 |
OP_BLOCKSIZE,
|
|
Packit |
dd8086 |
OP_CLOSETRAY,
|
|
Packit |
dd8086 |
OP_EJECT,
|
|
Packit |
dd8086 |
OP_IDLE,
|
|
Packit |
dd8086 |
OP_INQUIRY,
|
|
Packit |
dd8086 |
OP_MODE_SENSE_2A,
|
|
Packit |
dd8086 |
OP_MCN,
|
|
Packit |
dd8086 |
OP_SPEED,
|
|
Packit |
dd8086 |
} operation_enum_t;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
typedef struct
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
operation_enum_t op;
|
|
Packit |
dd8086 |
union
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
long int i_num;
|
|
Packit |
dd8086 |
char * psz;
|
|
Packit |
dd8086 |
} arg;
|
|
Packit |
dd8086 |
} operation_t;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
enum { MAX_OPS = 10 };
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static unsigned int last_op = 0;
|
|
Packit |
dd8086 |
static operation_t operation[MAX_OPS] = { {OP_FINISHED, {0}} };
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static void
|
|
Packit |
dd8086 |
push_op(operation_t *p_op)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
if (last_op < MAX_OPS) {
|
|
Packit |
dd8086 |
memcpy(&operation[last_op], p_op, sizeof(operation_t));
|
|
Packit |
dd8086 |
last_op++;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Parse command-line options. */
|
|
Packit |
dd8086 |
static bool
|
|
Packit |
dd8086 |
parse_options (int argc, char *argv[])
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int opt;
|
|
Packit |
dd8086 |
int rc = EXIT_FAILURE;
|
|
Packit |
dd8086 |
operation_t op;
|
|
Packit |
dd8086 |
int i_blocksize = 0;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static const char helpText[] =
|
|
Packit |
dd8086 |
"Usage: %s [OPTION...]\n"
|
|
Packit |
dd8086 |
" Issues libcdio Multimedia commands. Operations occur in the order\n"
|
|
Packit |
dd8086 |
" in which the options are given and a given operation may appear\n"
|
|
Packit |
dd8086 |
" more than once to have it run more than once.\n"
|
|
Packit |
dd8086 |
"options: \n"
|
|
Packit |
dd8086 |
" -b, --blocksize[=INT] set blocksize. If no block size or a \n"
|
|
Packit |
dd8086 |
" zero blocksize is given we return the\n"
|
|
Packit |
dd8086 |
" current setting.\n"
|
|
Packit |
dd8086 |
" -C, --drive-cap [6|10] print mode sense 2a data\n"
|
|
Packit |
dd8086 |
" using 6-byte or 10-byte form\n"
|
|
Packit |
dd8086 |
" -c, --close drive close drive via ALLOW_MEDIUM_REMOVAL\n"
|
|
Packit |
dd8086 |
" -e, --eject [drive] eject drive via ALLOW_MEDIUM_REMOVAL\n"
|
|
Packit |
dd8086 |
" and a MMC START/STOP command\n"
|
|
Packit |
dd8086 |
" -I, --idle set CD-ROM to idle or power down\n"
|
|
Packit |
dd8086 |
" via MMC START/STOP command\n"
|
|
Packit |
dd8086 |
" -i, --inquiry print HW info via INQUIRY\n"
|
|
Packit |
dd8086 |
" -m, --mcn get media catalog number (AKA UPC)\n"
|
|
Packit |
dd8086 |
" -s, --speed-KB=INT Set drive speed to SPEED K bytes/sec\n"
|
|
Packit |
dd8086 |
" Note: 1x = 176 KB/s \n"
|
|
Packit |
dd8086 |
" -S, --speed-X=INT Set drive speed to INT X\n"
|
|
Packit |
dd8086 |
" Note: 1x = 176 KB/s \n"
|
|
Packit |
dd8086 |
" -V, --version display version and copyright information\n"
|
|
Packit |
dd8086 |
" and exit\n"
|
|
Packit |
dd8086 |
"\n"
|
|
Packit |
dd8086 |
"Help options:\n"
|
|
Packit |
dd8086 |
" -?, --help Show this help message\n"
|
|
Packit |
dd8086 |
" --usage Display brief usage message\n";
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static const char usageText[] =
|
|
Packit |
dd8086 |
"Usage: %s [-b|--blocksize[=INT]] [-m|--mcn]\n"
|
|
Packit |
dd8086 |
" [-I|--idle] [-I|inquiry] [-m[-s|--speed-KB INT]\n"
|
|
Packit |
dd8086 |
" [-V|--version] [-?|--help] [--usage]\n";
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Command-line options */
|
|
Packit |
dd8086 |
static const char optionsString[] = "b::c:C::e::Iis:V?";
|
|
Packit |
dd8086 |
const struct option optionsTable[] = {
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
{"blocksize", optional_argument, &i_blocksize, 'b' },
|
|
Packit |
dd8086 |
{"close", required_argument, NULL, 'c'},
|
|
Packit |
dd8086 |
{"drive-cap", optional_argument, NULL, 'C'},
|
|
Packit |
dd8086 |
{"eject", optional_argument, NULL, 'e'},
|
|
Packit |
dd8086 |
{"idle", no_argument, NULL, 'I'},
|
|
Packit |
dd8086 |
{"inquiry", no_argument, NULL, 'i'},
|
|
Packit |
dd8086 |
{"mcn", no_argument, NULL, 'm'},
|
|
Packit |
dd8086 |
{"speed-KB", required_argument, NULL, 's'},
|
|
Packit |
dd8086 |
{"speed-X", required_argument, NULL, 'S'},
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
{"version", no_argument, NULL, 'V'},
|
|
Packit |
dd8086 |
{"help", no_argument, NULL, '?' },
|
|
Packit |
dd8086 |
{"usage", no_argument, NULL, OPT_USAGE },
|
|
Packit |
dd8086 |
{ NULL, 0, NULL, 0 }
|
|
Packit |
dd8086 |
};
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
while ((opt = getopt_long(argc, argv, optionsString, optionsTable, NULL)) >= 0)
|
|
Packit |
dd8086 |
switch (opt)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
case 'b':
|
|
Packit |
dd8086 |
op.op = OP_BLOCKSIZE;
|
|
Packit |
dd8086 |
op.arg.i_num = i_blocksize;
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'C':
|
|
Packit |
dd8086 |
op.arg.i_num = optarg ? atoi(optarg) : 10;
|
|
Packit |
dd8086 |
switch (op.arg.i_num) {
|
|
Packit |
dd8086 |
case 10:
|
|
Packit |
dd8086 |
op.op = OP_MODE_SENSE_2A;
|
|
Packit |
dd8086 |
op.arg.i_num = 10;
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 6:
|
|
Packit |
dd8086 |
op.op = OP_MODE_SENSE_2A;
|
|
Packit |
dd8086 |
op.arg.i_num = 6;
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
default:
|
|
Packit |
dd8086 |
report( stderr, "%s: Expecting 6 or 10 or nothing\n", program_name );
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'c':
|
|
Packit |
dd8086 |
op.op = OP_CLOSETRAY;
|
|
Packit |
dd8086 |
op.arg.psz = strdup(optarg);
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'e':
|
|
Packit |
dd8086 |
op.op = OP_EJECT;
|
|
Packit |
dd8086 |
op.arg.psz=NULL;
|
|
Packit |
dd8086 |
if (optarg) op.arg.psz = strdup(optarg);
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'i':
|
|
Packit |
dd8086 |
op.op = OP_INQUIRY;
|
|
Packit |
dd8086 |
op.arg.psz=NULL;
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'I':
|
|
Packit |
dd8086 |
op.op = OP_IDLE;
|
|
Packit |
dd8086 |
op.arg.psz=NULL;
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'm':
|
|
Packit |
dd8086 |
op.op = OP_MCN;
|
|
Packit |
dd8086 |
op.arg.psz=NULL;
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 's':
|
|
Packit |
dd8086 |
op.op = OP_SPEED;
|
|
Packit |
dd8086 |
op.arg.i_num=atoi(optarg);
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'S':
|
|
Packit |
dd8086 |
op.op = OP_SPEED;
|
|
Packit |
dd8086 |
op.arg.i_num=176 * atoi(optarg);
|
|
Packit |
dd8086 |
push_op(&op);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 'V':
|
|
Packit |
dd8086 |
print_version(program_name, VERSION, 0, true);
|
|
Packit |
dd8086 |
rc = EXIT_SUCCESS;
|
|
Packit |
dd8086 |
goto error_exit;
|
|
Packit |
dd8086 |
case '?':
|
|
Packit |
dd8086 |
fprintf(stdout, helpText, program_name);
|
|
Packit |
dd8086 |
goto error_exit;
|
|
Packit |
dd8086 |
case OPT_USAGE:
|
|
Packit |
dd8086 |
fprintf(stderr, usageText, program_name);
|
|
Packit |
dd8086 |
goto error_exit;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
case OPT_HANDLED:
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (optind < argc) {
|
|
Packit |
dd8086 |
const char *remaining_arg = argv[optind++];
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (source_name != NULL) {
|
|
Packit |
dd8086 |
report( stderr, "%s: Source specified in option %s and as %s\n",
|
|
Packit |
dd8086 |
program_name, source_name, remaining_arg );
|
|
Packit |
dd8086 |
goto error_exit;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
source_name = strdup(remaining_arg);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (optind < argc) {
|
|
Packit |
dd8086 |
report( stderr, "%s: Source specified in previously %s and %s\n",
|
|
Packit |
dd8086 |
program_name, source_name, remaining_arg );
|
|
Packit |
dd8086 |
free(source_name);
|
|
Packit |
dd8086 |
goto error_exit;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return true;
|
|
Packit |
dd8086 |
error_exit:
|
|
Packit |
dd8086 |
free(program_name);
|
|
Packit |
dd8086 |
exit(rc);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static void
|
|
Packit |
dd8086 |
_log_handler (cdio_log_level_t level, const char message[])
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
if (level == CDIO_LOG_ERROR) {
|
|
Packit |
dd8086 |
// print an error like default, but *don't* exit.
|
|
Packit |
dd8086 |
fprintf (stderr, "**ERROR: %s\n", message);
|
|
Packit |
dd8086 |
fflush (stderr);
|
|
Packit |
dd8086 |
return;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
gl_default_cdio_log_handler (level, message);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static void
|
|
Packit |
dd8086 |
init(const char *argv0)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
gl_default_cdio_log_handler = cdio_log_set_handler (_log_handler);
|
|
Packit |
dd8086 |
program_name = strrchr(argv0,'/');
|
|
Packit |
dd8086 |
program_name = program_name ? strdup(program_name+1) : strdup(argv0);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static void
|
|
Packit |
dd8086 |
print_mode_sense (unsigned int i_mmc_size, const uint8_t buf[30])
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
printf("Mode sense %d information\n", i_mmc_size);
|
|
Packit |
dd8086 |
if (buf[2] & 0x01) {
|
|
Packit |
dd8086 |
printf("\tReads CD-R media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[2] & 0x02) {
|
|
Packit |
dd8086 |
printf("\tReads CD-RW media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[2] & 0x04) {
|
|
Packit |
dd8086 |
printf("\tReads fixed-packet tracks when Addressing type is method 2.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[2] & 0x08) {
|
|
Packit |
dd8086 |
printf("\tReads DVD ROM media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[2] & 0x10) {
|
|
Packit |
dd8086 |
printf("\tReads DVD-R media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[2] & 0x20) {
|
|
Packit |
dd8086 |
printf("\tReads DVD-RAM media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[2] & 0x40) {
|
|
Packit |
dd8086 |
printf("\tReads DVD-RAM media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[3] & 0x01) {
|
|
Packit |
dd8086 |
printf("\tWrites CD-R media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[3] & 0x02) {
|
|
Packit |
dd8086 |
printf("\tWrites CD-RW media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[3] & 0x04) {
|
|
Packit |
dd8086 |
printf("\tSupports emulation write.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[3] & 0x10) {
|
|
Packit |
dd8086 |
printf("\tWrites DVD-R media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[3] & 0x20) {
|
|
Packit |
dd8086 |
printf("\tWrites DVD-RAM media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x01) {
|
|
Packit |
dd8086 |
printf("\tCan play audio.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x02) {
|
|
Packit |
dd8086 |
printf("\tDelivers composition A/V stream.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x04) {
|
|
Packit |
dd8086 |
printf("\tSupports digital output on port 2.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x08) {
|
|
Packit |
dd8086 |
printf("\tSupports digital output on port 1.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x10) {
|
|
Packit |
dd8086 |
printf("\tReads Mode-2 form 1 (e.g. XA) media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x20) {
|
|
Packit |
dd8086 |
printf("\tReads Mode-2 form 2 media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x40) {
|
|
Packit |
dd8086 |
printf("\tReads multi-session CD media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x80) {
|
|
Packit |
dd8086 |
printf("\tSupports Buffer under-run free recording on CD-R/RW media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x01) {
|
|
Packit |
dd8086 |
printf("\tCan read audio data with READ CD.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[4] & 0x02) {
|
|
Packit |
dd8086 |
printf("\tREAD CD data stream is accurate.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[5] & 0x04) {
|
|
Packit |
dd8086 |
printf("\tReads R-W subchannel information.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[5] & 0x08) {
|
|
Packit |
dd8086 |
printf("\tReads de-interleaved R-W subchannel.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[5] & 0x10) {
|
|
Packit |
dd8086 |
printf("\tSupports C2 error pointers.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[5] & 0x20) {
|
|
Packit |
dd8086 |
printf("\tReads ISRC information.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[5] & 0x40) {
|
|
Packit |
dd8086 |
printf("\tReads ISRC informaton.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[5] & 0x40) {
|
|
Packit |
dd8086 |
printf("\tReads media catalog number (MCN also known as UPC).\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[5] & 0x80) {
|
|
Packit |
dd8086 |
printf("\tReads bar codes.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[6] & 0x01) {
|
|
Packit |
dd8086 |
printf("\tPREVENT/ALLOW may lock media.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
printf("\tLock state is %slocked.\n", (buf[6] & 0x02) ? "" : "un");
|
|
Packit |
dd8086 |
printf("\tPREVENT/ALLOW jumper is %spresent.\n", (buf[6] & 0x04) ? "": "not ");
|
|
Packit |
dd8086 |
if (buf[6] & 0x08) {
|
|
Packit |
dd8086 |
printf("\tEjects media with START STOP UNIT.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
const unsigned int i_load_type = (buf[6]>>5 & 0x07);
|
|
Packit |
dd8086 |
printf("\tLoading mechanism type is %d: ", i_load_type);
|
|
Packit |
dd8086 |
switch (buf[6]>>5 & 0x07) {
|
|
Packit |
dd8086 |
case 0:
|
|
Packit |
dd8086 |
printf("caddy type loading mechanism.\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 1:
|
|
Packit |
dd8086 |
printf("tray type loading mechanism.\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 2:
|
|
Packit |
dd8086 |
printf("popup type loading mechanism.\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 3:
|
|
Packit |
dd8086 |
printf("reserved\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 4:
|
|
Packit |
dd8086 |
printf("changer with individually changeable discs.\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 5:
|
|
Packit |
dd8086 |
printf("changer using Magazine mechanism.\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case 6:
|
|
Packit |
dd8086 |
printf("changer using Magazine mechanism.\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
default:
|
|
Packit |
dd8086 |
printf("Invalid.\n");
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (buf[7] & 0x01) {
|
|
Packit |
dd8086 |
printf("\tVolume controls each channel separately.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[7] & 0x02) {
|
|
Packit |
dd8086 |
printf("\tHas a changer that supports disc present reporting.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[7] & 0x04) {
|
|
Packit |
dd8086 |
printf("\tCan load empty slot in changer.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[7] & 0x08) {
|
|
Packit |
dd8086 |
printf("\tSide change capable.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (buf[7] & 0x10) {
|
|
Packit |
dd8086 |
printf("\tReads raw R-W subchannel information from lead in.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
const unsigned int i_speed_Kbs = CDIO_MMC_GETPOS_LEN16(buf, 8);
|
|
Packit |
dd8086 |
printf("\tMaximum read speed is %d K bytes/sec (about %dX)\n",
|
|
Packit |
dd8086 |
i_speed_Kbs, i_speed_Kbs / 176) ;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
printf("\tNumber of Volume levels is %d\n", CDIO_MMC_GETPOS_LEN16(buf, 10));
|
|
Packit |
dd8086 |
printf("\tBuffers size for data is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 12));
|
|
Packit |
dd8086 |
printf("\tCurrent read speed is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 14));
|
|
Packit |
dd8086 |
printf("\tMaximum write speed is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 18));
|
|
Packit |
dd8086 |
printf("\tCurrent write speed is %d KB\n", CDIO_MMC_GETPOS_LEN16(buf, 28));
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
int
|
|
Packit |
dd8086 |
main(int argc, char *argv[])
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
CdIo_t *p_cdio;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
driver_return_code_t rc = DRIVER_OP_SUCCESS;
|
|
Packit |
dd8086 |
unsigned int i;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
init(argv[0]);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
parse_options(argc, argv);
|
|
Packit |
dd8086 |
p_cdio = cdio_open (source_name, DRIVER_DEVICE);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (NULL == p_cdio) {
|
|
Packit |
dd8086 |
printf("Couldn't find CD\n");
|
|
Packit |
dd8086 |
rc = 1;
|
|
Packit |
dd8086 |
goto exit;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
for (i=0; i < last_op; i++) {
|
|
Packit |
dd8086 |
const operation_t *p_op = &operation[i];
|
|
Packit |
dd8086 |
switch (p_op->op) {
|
|
Packit |
dd8086 |
case OP_SPEED:
|
|
Packit |
dd8086 |
rc = mmc_set_speed(p_cdio, p_op->arg.i_num, 0);
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_set_speed): %s\n", program_name,
|
|
Packit |
dd8086 |
cdio_driver_errmsg(rc));
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case OP_BLOCKSIZE:
|
|
Packit |
dd8086 |
if (p_op->arg.i_num) {
|
|
Packit |
dd8086 |
driver_return_code_t blocksize_rc = mmc_set_blocksize(p_cdio, p_op->arg.i_num);
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_set_blocksize): %s\n", program_name,
|
|
Packit |
dd8086 |
cdio_driver_errmsg(blocksize_rc));
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
int i_blocksize = mmc_get_blocksize(p_cdio);
|
|
Packit |
dd8086 |
if (i_blocksize > 0) {
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_get_blocksize): %d\n", program_name,
|
|
Packit |
dd8086 |
i_blocksize);
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_get_blocksize): can't retrieve.\n",
|
|
Packit |
dd8086 |
program_name);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case OP_MODE_SENSE_2A:
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
uint8_t buf[30] = { 0, }; /* Place to hold returned data */
|
|
Packit |
dd8086 |
if (p_op->arg.i_num == 10) {
|
|
Packit |
dd8086 |
rc = mmc_mode_sense_10(p_cdio, buf, sizeof(buf),
|
|
Packit |
dd8086 |
CDIO_MMC_CAPABILITIES_PAGE);
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
rc = mmc_mode_sense_6(p_cdio, buf, sizeof(buf),
|
|
Packit |
dd8086 |
CDIO_MMC_CAPABILITIES_PAGE);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (DRIVER_OP_SUCCESS == rc) {
|
|
Packit |
dd8086 |
print_mode_sense(p_op->arg.i_num, buf);
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_mode_sense 2a - drive_cap %d): %s\n",
|
|
Packit |
dd8086 |
program_name, p_op->arg.i_num, cdio_driver_errmsg(rc));
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case OP_CLOSETRAY:
|
|
Packit |
dd8086 |
rc = mmc_close_tray(p_cdio);
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_close_tray): %s\n", program_name,
|
|
Packit |
dd8086 |
cdio_driver_errmsg(rc));
|
|
Packit |
dd8086 |
free(p_op->arg.psz);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case OP_EJECT:
|
|
Packit |
dd8086 |
rc = mmc_eject_media(p_cdio);
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_eject_media): %s\n", program_name,
|
|
Packit |
dd8086 |
cdio_driver_errmsg(rc));
|
|
Packit |
dd8086 |
if (p_op->arg.psz) free(p_op->arg.psz);
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case OP_IDLE:
|
|
Packit |
dd8086 |
rc = mmc_start_stop_unit(p_cdio, false, false, true, 0);
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_start_stop_media - powerdown): %s\n",
|
|
Packit |
dd8086 |
program_name, cdio_driver_errmsg(rc));
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case OP_INQUIRY:
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
cdio_hwinfo_t hw_info = { "", "", ""};
|
|
Packit |
dd8086 |
if (mmc_get_hwinfo(p_cdio, &hw_info)) {
|
|
Packit |
dd8086 |
printf("%-8s: %s\n%-8s: %s\n%-8s: %s\n",
|
|
Packit |
dd8086 |
"Vendor" , hw_info.psz_vendor,
|
|
Packit |
dd8086 |
"Model" , hw_info.psz_model,
|
|
Packit |
dd8086 |
"Revision", hw_info.psz_revision);
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_gpcmd_inquiry error)\n", program_name);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
case OP_MCN:
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
char *psz_mcn = mmc_get_mcn(p_cdio);
|
|
Packit |
dd8086 |
if (psz_mcn) {
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_get_mcn): %s\n", program_name, psz_mcn);
|
|
Packit |
dd8086 |
cdio_free(psz_mcn);
|
|
Packit |
dd8086 |
} else
|
|
Packit |
dd8086 |
report(stdout, "%s (mmc_get_mcn): can't retrieve\n", program_name);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
default:
|
|
Packit |
dd8086 |
;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
exit:
|
|
Packit |
dd8086 |
free(source_name);
|
|
Packit |
dd8086 |
free(program_name);
|
|
Packit |
dd8086 |
cdio_destroy(p_cdio);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return rc;
|
|
Packit |
dd8086 |
}
|