|
Packit |
dd8086 |
/* -*- C -*-
|
|
Packit |
dd8086 |
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>
|
|
Packit |
dd8086 |
Copyright (C) 2010, 2012-2013, 2017 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 |
/*
|
|
Packit |
dd8086 |
Regression test for MMC commands involving read/write access.
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
dd8086 |
#include "config.h"
|
|
Packit |
dd8086 |
#define __CDIO_CONFIG_H__ 1
|
|
Packit |
dd8086 |
#endif
|
|
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_STDLIB_H
|
|
Packit |
dd8086 |
#include <stdlib.h>
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
dd8086 |
#include <unistd.h>
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#ifdef HAVE_STRING_H
|
|
Packit |
dd8086 |
#include <string.h>
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#ifdef _WIN32
|
|
Packit |
dd8086 |
# undef HAVE_SLEEP
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
#if !defined(HAVE_SLEEP)
|
|
Packit |
dd8086 |
# if defined(_WIN32)
|
|
Packit |
dd8086 |
# include <windows.h>
|
|
Packit |
dd8086 |
# define sleep(s) Sleep(1000*s)
|
|
Packit |
dd8086 |
# elif defined(HAVE_USLEEP)
|
|
Packit |
dd8086 |
# define sleep(s) usleep(1000000*s)
|
|
Packit |
dd8086 |
# else
|
|
Packit |
dd8086 |
# define sleep(s) { int i; for(i=0; i<=1000*s; i++); }
|
|
Packit |
dd8086 |
# endif
|
|
Packit |
dd8086 |
#endif
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
#include <cdio/cdio.h>
|
|
Packit |
dd8086 |
#include <cdio/logging.h>
|
|
Packit |
dd8086 |
#include <cdio/mmc_cmds.h>
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
#define SKIP_TEST 77
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* gcc may warn if no prototypes are given before function definition */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int handle_outcome(CdIo_t *p_cdio, int i_status,
|
|
Packit |
dd8086 |
unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t * p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int load_eject(CdIo_t *p_cdio, unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t * p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static void print_status_sense(int i_status, int sense_valid,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *,
|
|
Packit |
dd8086 |
unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int test_eject_load_cycle(CdIo_t *p_cdio, unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int test_eject_test_load(CdIo_t *p_cdio, unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int test_mode_select(CdIo_t *p_cdio,
|
|
Packit |
dd8086 |
unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *p_sense_reply,
|
|
Packit |
dd8086 |
unsigned char *p_buf, unsigned int i_size,
|
|
Packit |
dd8086 |
unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int mode_sense(CdIo_t *p_cdio, unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t * p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_page_code,
|
|
Packit |
dd8086 |
unsigned int subpage_code, int i_alloc_len,
|
|
Packit |
dd8086 |
unsigned char *buf, int *i_size,
|
|
Packit |
dd8086 |
unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int test_unit_ready(CdIo_t *p_cdio,
|
|
Packit |
dd8086 |
unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t * p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int test_rwr_mode_page(CdIo_t *p_cdio, unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int test_write(char *psz_drive_path, unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
static int wait_for_drive(CdIo_t *p_cdio, unsigned int max_tries, unsigned int i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* ------------------------- Helper functions ---------------------------- */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* @param i_flag bit0= verbose
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
handle_outcome(CdIo_t *p_cdio, driver_return_code_t i_status,
|
|
Packit |
dd8086 |
unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t * p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *p_temp_sense_reply = NULL;
|
|
Packit |
dd8086 |
*pi_sense_avail = mmc_last_cmd_sense(p_cdio, &p_temp_sense_reply);
|
|
Packit |
dd8086 |
print_status_sense(i_status, *pi_sense_avail, p_temp_sense_reply, i_flag & 1);
|
|
Packit |
dd8086 |
if (18 <= *pi_sense_avail) {
|
|
Packit |
dd8086 |
memset(p_sense_reply, 0, sizeof(cdio_mmc_request_sense_t));
|
|
Packit |
dd8086 |
memcpy(p_sense_reply, p_temp_sense_reply, *pi_sense_avail);
|
|
Packit |
dd8086 |
} else
|
|
Packit |
dd8086 |
memset(p_sense_reply, 0, sizeof(cdio_mmc_request_sense_t));
|
|
Packit |
dd8086 |
cdio_free(p_temp_sense_reply);
|
|
Packit |
dd8086 |
return i_status;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
@param flag bit0= verbose
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static void
|
|
Packit |
dd8086 |
print_status_sense(int i_status, int sense_valid,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
if (!(i_flag & 1))
|
|
Packit |
dd8086 |
return;
|
|
Packit |
dd8086 |
printf("return= %d , sense(%d)", i_status, sense_valid);
|
|
Packit |
dd8086 |
if (sense_valid >= 14)
|
|
Packit |
dd8086 |
printf(": KEY=%s (%1.1X), ASC= %2.2X , ASCQ= %2.2X",
|
|
Packit |
dd8086 |
mmc_sense_key2str[p_sense_reply->sense_key],
|
|
Packit |
dd8086 |
p_sense_reply->sense_key,
|
|
Packit |
dd8086 |
p_sense_reply->asc,
|
|
Packit |
dd8086 |
p_sense_reply->ascq);
|
|
Packit |
dd8086 |
printf("\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* --------------------------- MMC commands ------------------------------ */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* OBTRUSIVE. PHYSICAL EFFECT: DANGER OF HUMAN INJURY */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
@param i_flag bit0= verbose
|
|
Packit |
dd8086 |
bit1= Asynchronous operation
|
|
Packit |
dd8086 |
bit2= Load (else Eject)
|
|
Packit |
dd8086 |
@return return value of mmc_run_cmd()
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
load_eject(CdIo_t *p_cdio, unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int i_status;
|
|
Packit |
dd8086 |
bool b_eject = !!(i_flag & 4);
|
|
Packit |
dd8086 |
bool b_immediate = !!(i_flag & 2);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
i_status = mmc_start_stop_unit(p_cdio, b_eject, b_immediate, 0, 0);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (i_flag & 1)
|
|
Packit |
dd8086 |
printf("load_eject(0x%X) ... ", i_flag);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return handle_outcome(p_cdio, i_status, pi_sense_avail, p_sense_reply,
|
|
Packit |
dd8086 |
i_flag & 1);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* BARELY OBTRUSIVE: MIGHT RUIN A SIMULTANEOUS BURNING OPERATION ON THE DRIVE */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
Fetch a mode page or a part of it from the drive.
|
|
Packit |
dd8086 |
@param i_alloc_len The number of bytes to be requested from the drive and to
|
|
Packit |
dd8086 |
be copied into parameter buf.
|
|
Packit |
dd8086 |
This has to include the 8 bytes of header and may not
|
|
Packit |
dd8086 |
be less than 10.
|
|
Packit |
dd8086 |
@param p_buf Will contain at most alloc_len many bytes. The first 8 are
|
|
Packit |
dd8086 |
a Mode Parameter Header as of SPC-3 7.4.3, table 240.
|
|
Packit |
dd8086 |
The further bytes are the mode page, typically as of
|
|
Packit |
dd8086 |
MMC-5 7.2. There are meanwhile deprecated mode pages which
|
|
Packit |
dd8086 |
appear only in older versions of MMC.
|
|
Packit |
dd8086 |
@param i_size Will return the number of actually read bytes resp. the
|
|
Packit |
dd8086 |
number of available bytes. See flag bit1.
|
|
Packit |
dd8086 |
@param i_flag bit0= verbose
|
|
Packit |
dd8086 |
bit1= Peek mode:
|
|
Packit |
dd8086 |
Reply number of available bytes in *i_size and not
|
|
Packit |
dd8086 |
the number of actually read bytes.
|
|
Packit |
dd8086 |
@return return value of mmc_run_cmd(),
|
|
Packit |
dd8086 |
or other driver_return_code_t
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static driver_return_code_t
|
|
Packit |
dd8086 |
mode_sense(CdIo_t *p_cdio, unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_page_code, unsigned int subpage_code, int i_alloc_len,
|
|
Packit |
dd8086 |
unsigned char *p_buf, int *pi_size, unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
driver_return_code_t i_status;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (i_alloc_len < 10)
|
|
Packit |
dd8086 |
return DRIVER_OP_BAD_PARAMETER;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (i_flag & 1)
|
|
Packit |
dd8086 |
printf("mode_sense(0x%X, %X, %d) ... ",
|
|
Packit |
dd8086 |
i_page_code, subpage_code, i_alloc_len);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
i_status = mmc_mode_sense_10(p_cdio, p_buf, i_alloc_len, i_page_code);
|
|
Packit |
dd8086 |
handle_outcome(p_cdio, i_status, pi_sense_avail, p_sense_reply, i_flag & 1);
|
|
Packit |
dd8086 |
if (DRIVER_OP_SUCCESS != i_status)
|
|
Packit |
dd8086 |
return i_status;
|
|
Packit |
dd8086 |
if (i_flag & 2)
|
|
Packit |
dd8086 |
*pi_size = p_buf[9] + 10; /* MMC-5 7.2.3 */
|
|
Packit |
dd8086 |
else
|
|
Packit |
dd8086 |
*pi_size = p_buf[0] * 256 + p_buf[1] + 2; /* SPC-3 7.4.3, table 240 */
|
|
Packit |
dd8086 |
return i_status;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* OBTRUSIVE. RUINS A SIMULTANEOUS BURNING OPERATION ON THE DRIVE
|
|
Packit |
dd8086 |
and might return minor failure with -ROM drives */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
Send a mode page to the drive.
|
|
Packit |
dd8086 |
@param buf Contains the payload bytes. The first 8 shall be a Mode
|
|
Packit |
dd8086 |
Parameter Header as of SPC-3 7.4.3, table 240.
|
|
Packit |
dd8086 |
The further bytes are the mode page, typically as of
|
|
Packit |
dd8086 |
MMC-5 7.2. There are meanwhile deprecated mode pages which
|
|
Packit |
dd8086 |
appear only in older versions of MMC.
|
|
Packit |
dd8086 |
@param i_size The number of bytes in buf.
|
|
Packit |
dd8086 |
@param flag bit0= verbose
|
|
Packit |
dd8086 |
@return return value of mmc_run_cmd(),
|
|
Packit |
dd8086 |
or other driver_return_code_t
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
test_mode_select(CdIo_t *p_cdio,
|
|
Packit |
dd8086 |
unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *p_sense_reply,
|
|
Packit |
dd8086 |
unsigned char *p_buf, unsigned int i_size, unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int i_status, i;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (i_size < 10)
|
|
Packit |
dd8086 |
return DRIVER_OP_BAD_PARAMETER;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (i_flag & 1) {
|
|
Packit |
dd8086 |
printf("-- test_mode_select to drive: %d bytes\n", i_size);
|
|
Packit |
dd8086 |
for (i = 0; i < i_size; i++) {
|
|
Packit |
dd8086 |
printf("%2.2X ", (unsigned int) p_buf[i]);
|
|
Packit |
dd8086 |
if ((i % 20) == 19)
|
|
Packit |
dd8086 |
printf("\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if ((i % 20))
|
|
Packit |
dd8086 |
printf("\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (i_flag & 1)
|
|
Packit |
dd8086 |
printf("-- test_mode_select(0x%X, %d, %d) ... ",
|
|
Packit |
dd8086 |
(unsigned int) p_buf[8], (unsigned int) p_buf[9], i_size);
|
|
Packit |
dd8086 |
i_status = mmc_mode_select_10(p_cdio, p_buf, i_size, 0x10, 10000);
|
|
Packit |
dd8086 |
return handle_outcome(p_cdio, i_status, pi_sense_avail, p_sense_reply,
|
|
Packit |
dd8086 |
i_flag & 1);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* UNOBTRUSIVE */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
@param pi_sense_avail Number of available sense bytes
|
|
Packit |
dd8086 |
(18 get copied if all 18 exist)
|
|
Packit |
dd8086 |
@param p_sense_reply eventual sense bytes
|
|
Packit |
dd8086 |
@param i_flag bit0= verbose
|
|
Packit |
dd8086 |
@return return value of mmc_run_cmd()
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
test_unit_ready(CdIo_t *p_cdio,
|
|
Packit |
dd8086 |
unsigned int *pi_sense_avail,
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t *p_sense_reply,
|
|
Packit |
dd8086 |
unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int i_status;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (i_flag & 1)
|
|
Packit |
dd8086 |
printf("-- test_unit_ready ... ");
|
|
Packit |
dd8086 |
i_status = mmc_test_unit_ready(p_cdio, 0);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return handle_outcome(p_cdio, i_status, pi_sense_avail, p_sense_reply,
|
|
Packit |
dd8086 |
i_flag & 1);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* --------------------------- Larger gestures ----------------------------- */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* UNOBTRUSIVE */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
Watch drive by test unit ready loop until ready, no media or timeout.
|
|
Packit |
dd8086 |
@param flag bit0= verbose
|
|
Packit |
dd8086 |
bit1= expect media (do not end on no-media sense)
|
|
Packit |
dd8086 |
@return 1= all seems well , 0= minor failure , -1= severe failure
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
wait_for_drive(CdIo_t *p_cdio, unsigned int i_max_tries, unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int i_ret, i;
|
|
Packit |
dd8086 |
unsigned int i_sense_avail;
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t sense_reply;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
for (i = 0; i < i_max_tries; i++) {
|
|
Packit |
dd8086 |
i_ret = test_unit_ready(p_cdio, &i_sense_avail, &sense_reply, !!(i_flag & 1));
|
|
Packit |
dd8086 |
if (i_ret == 0) /* Unit is ready */
|
|
Packit |
dd8086 |
return 1;
|
|
Packit |
dd8086 |
if (i_sense_avail < 18)
|
|
Packit |
dd8086 |
return -1;
|
|
Packit |
dd8086 |
if (2 == sense_reply.sense_key && 0x04 == sense_reply.asc) {
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Not ready */;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
} else if (6 == sense_reply.sense_key && 0x28 == sense_reply.asc &&
|
|
Packit |
dd8086 |
0 == sense_reply.ascq) {
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Media change notice = try again */;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
} else if (2 == sense_reply.sense_key && 0x3a == sense_reply.asc) {
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Medium not present */;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (!(i_flag & 2))
|
|
Packit |
dd8086 |
return 1;
|
|
Packit |
dd8086 |
} else if (0 == sense_reply.sense_key && 0 == sense_reply.asc) {
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Error with no sense */;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return -1;
|
|
Packit |
dd8086 |
break;
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Other error */;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return 0;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
sleep(1);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
fprintf(stderr, "wait_for_drive: Drive not ready after %d retries\n",
|
|
Packit |
dd8086 |
i_max_tries);
|
|
Packit |
dd8086 |
return -1;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* OBTRUSIVE. Opens and closes drive door - watch your fingers! */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
Eject, wait, load asynchronously, and watch by test unit ready loop.
|
|
Packit |
dd8086 |
@param i_flag bit0= verbose
|
|
Packit |
dd8086 |
bit1= expect media (do not end on no-media sense)
|
|
Packit |
dd8086 |
@return 1= all seems well , 0= minor failure , -1= severe failure
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
test_eject_load_cycle(CdIo_t *p_cdio, unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int i_ret;
|
|
Packit |
dd8086 |
unsigned int i_sense_avail;
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t sense_reply;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Eject synchronously */
|
|
Packit |
dd8086 |
printf("test_eject_load_cycle: WARNING: EJECTING THE TRAY !\n");
|
|
Packit |
dd8086 |
sleep(2);
|
|
Packit |
dd8086 |
load_eject(p_cdio, &i_sense_avail, &sense_reply, 0 | (i_flag & 1));
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
printf("test_eject_load_cycle: waiting for 5 seconds. DO NOT TOUCH THE TRAY !\n");
|
|
Packit |
dd8086 |
sleep(3);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Load asynchronously */
|
|
Packit |
dd8086 |
printf("test_eject_load_cycle: WARNING: LOADING THE TRAY !\n");
|
|
Packit |
dd8086 |
sleep(2);
|
|
Packit |
dd8086 |
load_eject(p_cdio, &i_sense_avail, &sense_reply, 4 | 2 | (i_flag & 1));
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Wait for drive attention */
|
|
Packit |
dd8086 |
i_ret = wait_for_drive(p_cdio, 30, i_flag & 3);
|
|
Packit |
dd8086 |
return i_ret;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* OBTRUSIVE , PHYSICAL EFFECT , DANGER OF HUMAN INJURY */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
Eject, wait, test, load. All synchronously.
|
|
Packit |
dd8086 |
@param flag bit0= verbose
|
|
Packit |
dd8086 |
@return 1= all seems well , 0= minor failure , -1= severe failure
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
test_eject_test_load(CdIo_t *p_cdio, unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int i_ret;
|
|
Packit |
dd8086 |
unsigned int i_sense_avail;
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t sense_reply;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Eject synchronously */
|
|
Packit |
dd8086 |
printf("test_eject_test_load: WARNING: EJECTING THE TRAY !\n");
|
|
Packit |
dd8086 |
sleep(2);
|
|
Packit |
dd8086 |
load_eject(p_cdio, &i_sense_avail, &sense_reply, 0 | (i_flag & 1));
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
printf("test_eject_test_load: waiting for 5 seconds. DO NOT TOUCH THE TRAY !\n");
|
|
Packit |
dd8086 |
sleep(3);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
i_ret = test_unit_ready(p_cdio, &i_sense_avail, &sense_reply, i_flag & 1);
|
|
Packit |
dd8086 |
if (i_ret == 0) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_eject_test_load: Drive ready although tray ejected.\n");
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_eject_test_load: Test aborted. Tray will stay ejected.\n");
|
|
Packit |
dd8086 |
return -1;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (i_ret == 0 || i_sense_avail < 18) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_eject_test_load: Only %d sense reply bytes returned. Expected >= 18.\n",
|
|
Packit |
dd8086 |
i_sense_avail);
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_eject_test_load: Test aborted. Tray will stay ejected.\n");
|
|
Packit |
dd8086 |
return -1;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Load synchronously */
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_eject_test_load: WARNING: LOADING THE TRAY !\n");
|
|
Packit |
dd8086 |
sleep(2);
|
|
Packit |
dd8086 |
load_eject(p_cdio, &i_sense_avail, &sense_reply, 4 | (i_flag & 1));
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return 1;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* OBTRUSIVE */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
Read Mode Page 05h "Write Parameters", change a value, write the page,
|
|
Packit |
dd8086 |
check effect, restore old value, check again.
|
|
Packit |
dd8086 |
@param flag bit0= verbose
|
|
Packit |
dd8086 |
@return 1= all seems well , 0= minor failure , -1= severe failure
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
test_rwr_mode_page(CdIo_t *p_cdio, unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
int i_ret;
|
|
Packit |
dd8086 |
unsigned int i_sense_avail = 0;
|
|
Packit |
dd8086 |
int page_code = 5, subpage_code = 0, i_alloc_len, i_size = 0;
|
|
Packit |
dd8086 |
int write_type, final_return = 1, new_write_type, old_i_size;
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t sense_reply;
|
|
Packit |
dd8086 |
unsigned char buf[265], old_buf[265]; /* page size is max. 255 + 10 */
|
|
Packit |
dd8086 |
static char w_types[4][8] = {"Packet", "TAO", "SAO", "Raw"};
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
memset(buf, 0, sizeof(buf));
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
i_alloc_len = 10;
|
|
Packit |
dd8086 |
i_ret = mode_sense(p_cdio, &i_sense_avail, &sense_reply,
|
|
Packit |
dd8086 |
page_code, subpage_code, i_alloc_len,
|
|
Packit |
dd8086 |
buf, &i_size, 2 | (i_flag & 1));
|
|
Packit |
dd8086 |
if (i_ret != 0) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"-- test_rwr_mode_page: Cannot obtain mode page 05h.\n");
|
|
Packit |
dd8086 |
return 0;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
i_alloc_len = (i_size <= sizeof(buf)) ? i_size : sizeof(buf);
|
|
Packit |
dd8086 |
i_ret = mode_sense(p_cdio, &i_sense_avail, &sense_reply,
|
|
Packit |
dd8086 |
page_code, subpage_code, i_alloc_len,
|
|
Packit |
dd8086 |
buf, &i_size, (i_flag & 1));
|
|
Packit |
dd8086 |
if (i_ret != 0) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"-- test_rwr_mode_page: Cannot obtain mode page 05h.\n");
|
|
Packit |
dd8086 |
return 0;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
memcpy(old_buf, buf, sizeof(buf));
|
|
Packit |
dd8086 |
old_i_size = i_size;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
write_type = buf[10] & 0x0f;
|
|
Packit |
dd8086 |
if (i_flag & 1)
|
|
Packit |
dd8086 |
printf("test_rwr_mode_page: Write type = %d (%s)\n",
|
|
Packit |
dd8086 |
write_type, write_type < 4 ? w_types[write_type] : "Reserved");
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Choose a conservative CD writer setting.
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
memset(buf, 0, 8);
|
|
Packit |
dd8086 |
if (write_type == 1) { /* is TAO -> make SAO */
|
|
Packit |
dd8086 |
buf[10] = (buf[10] & 0xf0) | 2; /* SAO */
|
|
Packit |
dd8086 |
new_write_type = 2;
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
buf[10] = (buf[10] & 0xf0) | 1; /* TAO */
|
|
Packit |
dd8086 |
new_write_type = 1;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
buf[11] = 4; /* Track Mode 4, no multi-session,
|
|
Packit |
dd8086 |
variable Packet size */
|
|
Packit |
dd8086 |
buf[12] = 8; /* Data Block Type : CD-ROM Mode 1 */
|
|
Packit |
dd8086 |
buf[16] = 0; /* Session Format : "CD-DA or CD-ROM" */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
i_ret = test_mode_select(p_cdio, &i_sense_avail, &sense_reply,
|
|
Packit |
dd8086 |
buf, i_size, i_flag & 1);
|
|
Packit |
dd8086 |
if (i_ret != 0) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"-- test_rwr_mode_page: Cannot set mode page 05h.\n");
|
|
Packit |
dd8086 |
if (DRIVER_OP_NOT_PERMITTED == i_ret) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_rwr_mode_page: DRIVER_OP_NOT_PERMITTED with MODE SELECT.\n");
|
|
Packit |
dd8086 |
return -1;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
return 0;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Read mode page and check whether effect visible in buf[10] */
|
|
Packit |
dd8086 |
i_ret = mode_sense(p_cdio, &i_sense_avail, &sense_reply,
|
|
Packit |
dd8086 |
page_code, subpage_code, i_alloc_len,
|
|
Packit |
dd8086 |
buf, &i_size, (i_flag & 1));
|
|
Packit |
dd8086 |
if (0 != i_ret) {
|
|
Packit |
dd8086 |
fprintf(stderr, "test_rwr_mode_page: Cannot obtain mode page 05h.\n");
|
|
Packit |
dd8086 |
final_return = final_return > 0 ? 0 : final_return;
|
|
Packit |
dd8086 |
} else if ((buf[10] & 0xf) != new_write_type) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_rwr_mode_page: Mode page did not get into effect. (expected %d, got %d)\n",
|
|
Packit |
dd8086 |
new_write_type, buf[10] & 0xf);
|
|
Packit |
dd8086 |
/* One of my DVD burners does this if no media is loaded */
|
|
Packit |
dd8086 |
final_return = final_return > 0 ? 0 : final_return;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Restore old mode page */
|
|
Packit |
dd8086 |
i_ret = test_mode_select(p_cdio, &i_sense_avail, &sense_reply,
|
|
Packit |
dd8086 |
old_buf, old_i_size, i_flag & 1);
|
|
Packit |
dd8086 |
if (0 != i_ret) {
|
|
Packit |
dd8086 |
fprintf(stderr, "test_rwr_mode_page: Cannot set mode page 05h.\n");
|
|
Packit |
dd8086 |
if (i_ret == DRIVER_OP_NOT_PERMITTED) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_rwr_mode_page: DRIVER_OP_NOT_PERMITTED with MODE SELECT.\n");
|
|
Packit |
dd8086 |
return -1;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
final_return = final_return > 0 ? 0 : final_return;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Read mode page and check whether old_buf is in effect again */
|
|
Packit |
dd8086 |
i_ret = mode_sense(p_cdio, &i_sense_avail, &sense_reply,
|
|
Packit |
dd8086 |
page_code, subpage_code, i_alloc_len,
|
|
Packit |
dd8086 |
buf, &i_size, (i_flag & 1));
|
|
Packit |
dd8086 |
if (0 != i_ret) {
|
|
Packit |
dd8086 |
fprintf(stderr, "test_rwr_mode_page: Cannot obtain mode page 05h.\n");
|
|
Packit |
dd8086 |
return final_return > 0 ? 0 : final_return;
|
|
Packit |
dd8086 |
} else if (memcmp(buf, old_buf, i_size) != 0) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"test_rwr_mode_page: Mode page was not restored to old state.\n");
|
|
Packit |
dd8086 |
final_return = final_return > 0 ? -1 : final_return;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
if (i_flag & 1)
|
|
Packit |
dd8086 |
printf("test_rwr_mode_page: Mode page 2Ah restored to previous state\n");
|
|
Packit |
dd8086 |
return final_return;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* ----------- Test of MMC driver enhancements , december 2009 ------------- */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* OBTRUSIVE */
|
|
Packit |
dd8086 |
/**
|
|
Packit |
dd8086 |
This function bundles tests for the capability to perform MMC commands
|
|
Packit |
dd8086 |
of payload direction SCSI_MMC_DATA_WRITE and to detect the sense reply of
|
|
Packit |
dd8086 |
MMC commands, which indicates error causes or important drive events.
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
The default configuration is not very obtrusive to the drive, although the
|
|
Packit |
dd8086 |
drive should not be used for other operations at the same time.
|
|
Packit |
dd8086 |
There are static variables in this function which enable additional
|
|
Packit |
dd8086 |
more obtrusive tests or simulate the lack of write capabilities.
|
|
Packit |
dd8086 |
See the statements about obtrusiveness and undesired side effects above
|
|
Packit |
dd8086 |
the descriptions of the single functions.
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
@param psz_drive_path a drive address suitable for cdio_open_am()
|
|
Packit |
dd8086 |
@param flag bit0= verbose
|
|
Packit |
dd8086 |
@return 0= no severe failure
|
|
Packit |
dd8086 |
else an proposal for an exit() value is returned
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
static int
|
|
Packit |
dd8086 |
test_write(char *psz_drive_path, unsigned int i_flag)
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
unsigned int i_sense_avail = 0;
|
|
Packit |
dd8086 |
unsigned int i_sense_valid;
|
|
Packit |
dd8086 |
int i_ret;
|
|
Packit |
dd8086 |
bool b_verbose = !!(i_flag & 1);
|
|
Packit |
dd8086 |
int old_log_level = cdio_loglevel_default;
|
|
Packit |
dd8086 |
cdio_mmc_request_sense_t sense_reply;
|
|
Packit |
dd8086 |
CdIo_t *p_cdio;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* If true, then the tray will get ejected and loaded again */
|
|
Packit |
dd8086 |
static bool with_tray_dance = false;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* If true, then an asynchronous test loop will wait 30 s for loaded media */
|
|
Packit |
dd8086 |
static bool test_cycle_with_media = false;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* If true, then a lack of w-permission will be emulated by using the
|
|
Packit |
dd8086 |
insufficient access mode "IOCTL" */
|
|
Packit |
dd8086 |
static bool emul_lack_of_wperm = false;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
p_cdio = cdio_open_am(psz_drive_path, DRIVER_DEVICE, "MMC_RDWR_EXCL");
|
|
Packit |
dd8086 |
if (!p_cdio)
|
|
Packit |
dd8086 |
i_ret = SKIP_TEST - 16;
|
|
Packit |
dd8086 |
else {
|
|
Packit |
dd8086 |
const char *psz_access_mode = cdio_get_arg(p_cdio, "access-mode");
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (0 != strncmp(psz_access_mode,
|
|
Packit |
dd8086 |
"MMC_RDWR_EXCL", strlen("MMC_RDWR_EXCL"))) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"Got %s; Should get back %s, the access mode requested.\n",
|
|
Packit |
dd8086 |
psz_access_mode, "MMC_RDWR_EXCL");
|
|
Packit |
dd8086 |
i_ret = 1; goto ex;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* The further code produces some intentional failures which should not be
|
|
Packit |
dd8086 |
reported by mmc_run_cmd() as INFO messages.
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
cdio_loglevel_default = CDIO_LOG_WARN;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Test availability of sense reply in case of unready drive.
|
|
Packit |
dd8086 |
E.g. if the tray is already ejected.
|
|
Packit |
dd8086 |
*/
|
|
Packit |
dd8086 |
i_ret = test_unit_ready(p_cdio, &i_sense_avail, &sense_reply, b_verbose);
|
|
Packit |
dd8086 |
if (0 != i_ret && i_sense_avail < 18) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"Error: Drive not ready. Only %u sense bytes. Expected >= 18.\n",
|
|
Packit |
dd8086 |
i_sense_avail);
|
|
Packit |
dd8086 |
i_ret = 2; goto ex;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (emul_lack_of_wperm) { /* To check behavior with lack of w-permission */
|
|
Packit |
dd8086 |
printf("-- test_write: SIMULATING LACK OF WRITE CAPABILITIES by access mode IOCTL\n");
|
|
Packit |
dd8086 |
cdio_destroy(p_cdio);
|
|
Packit |
dd8086 |
p_cdio = cdio_open_am(psz_drive_path, DRIVER_DEVICE, "IOCTL");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Test write permission */ /* Try whether a mode page 2Ah can be set */
|
|
Packit |
dd8086 |
i_ret = test_rwr_mode_page(p_cdio, b_verbose);
|
|
Packit |
dd8086 |
if (i_ret <= 0) {
|
|
Packit |
dd8086 |
if (i_ret < 0) {
|
|
Packit |
dd8086 |
fprintf(stderr, "Error: test_rwr_mode_page() had severe failure.\n");
|
|
Packit |
dd8086 |
i_ret = 3; goto ex;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
printf("-- Warning: test_rwr_mode_page() had minor failure.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if (with_tray_dance) {
|
|
Packit |
dd8086 |
/* More surely provoke a non-trivial sense reply */
|
|
Packit |
dd8086 |
if (test_cycle_with_media) {
|
|
Packit |
dd8086 |
/* Eject, wait, load, watch by test unit ready loop */
|
|
Packit |
dd8086 |
i_ret = test_eject_load_cycle(p_cdio, 2 | b_verbose);
|
|
Packit |
dd8086 |
if (i_ret <= 0) {
|
|
Packit |
dd8086 |
if (i_ret < 0) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"Error: test_eject_load_cycle() had severe failure.\n");
|
|
Packit |
dd8086 |
i_ret = 4; goto ex;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
printf("Warning: test_eject_load_cycle() had minor failure.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
/* Eject, test for proper unreadiness, load */
|
|
Packit |
dd8086 |
i_ret = test_eject_test_load(p_cdio, b_verbose);
|
|
Packit |
dd8086 |
if (i_ret <= 0) {
|
|
Packit |
dd8086 |
if (i_ret < 0) {
|
|
Packit |
dd8086 |
fprintf(stderr,
|
|
Packit |
dd8086 |
"Error: test_eject_test_load() had severe failure.\n");
|
|
Packit |
dd8086 |
i_ret = 5; goto ex;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
printf("Warning: test_eject_test_load() had minor failure.\n");
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
/* Wait for drive attention */
|
|
Packit |
dd8086 |
wait_for_drive(p_cdio, 15, 2 | b_verbose);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* How are we, finally ? */
|
|
Packit |
dd8086 |
i_ret = test_unit_ready(p_cdio, &i_sense_valid, &sense_reply, b_verbose);
|
|
Packit |
dd8086 |
if ((i_flag & 1) && 0 != i_ret && 2 == sense_reply.sense_key &&
|
|
Packit |
dd8086 |
0x3a == sense_reply.asc)
|
|
Packit |
dd8086 |
fprintf(stderr, "test_unit_ready: Note: No loaded media detected.\n");
|
|
Packit |
dd8086 |
i_ret = 0;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
ex:;
|
|
Packit |
dd8086 |
cdio_loglevel_default = old_log_level;
|
|
Packit |
dd8086 |
cdio_destroy(p_cdio);
|
|
Packit |
dd8086 |
return i_ret;
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* --------------------------- main ----------------------------- */
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
int
|
|
Packit |
dd8086 |
main(int argc, const char *argv[])
|
|
Packit |
dd8086 |
{
|
|
Packit |
dd8086 |
CdIo_t *p_cdio;
|
|
Packit |
dd8086 |
char **ppsz_drives=NULL;
|
|
Packit |
dd8086 |
int ret;
|
|
Packit |
dd8086 |
int exitrc = 0;
|
|
Packit |
dd8086 |
bool b_verbose = (argc > 1);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
cdio_loglevel_default = b_verbose ? CDIO_LOG_DEBUG : CDIO_LOG_WARN;
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
ppsz_drives = cdio_get_devices(DRIVER_DEVICE);
|
|
Packit |
dd8086 |
if (!ppsz_drives) {
|
|
Packit |
dd8086 |
printf("Can't find a CD-ROM drive. Skipping test.\n");
|
|
Packit |
dd8086 |
exit(SKIP_TEST);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
p_cdio = cdio_open(ppsz_drives[0], DRIVER_DEVICE);
|
|
Packit |
dd8086 |
if (p_cdio) {
|
|
Packit |
dd8086 |
const char *psz_have_mmc = cdio_get_arg(p_cdio, "mmc-supported?");
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
if ( psz_have_mmc
|
|
Packit |
dd8086 |
&& 0 == strncmp("true", psz_have_mmc, sizeof("true")) ) {
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
/* Test the MMC enhancements of version 0.83 in december 2009 */
|
|
Packit |
dd8086 |
ret = test_write(ppsz_drives[0],
|
|
Packit |
dd8086 |
cdio_loglevel_default == CDIO_LOG_DEBUG);
|
|
Packit |
dd8086 |
if (ret != 0) exit(ret + 16);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
cdio_destroy(p_cdio);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
} else {
|
|
Packit |
dd8086 |
fprintf(stderr, "cdio_open('%s') failed\n", ppsz_drives[0]);
|
|
Packit |
dd8086 |
exit(2);
|
|
Packit |
dd8086 |
}
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
cdio_free_device_list(ppsz_drives);
|
|
Packit |
dd8086 |
|
|
Packit |
dd8086 |
return exitrc;
|
|
Packit |
dd8086 |
}
|