/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <libintl.h>
#include <limits.h>
#include "transport.h"
#include "mmc.h"
#include "device.h"
#include "util.h"
#include "msgs.h"
#include "misc_scsi.h"
#include "toshiba.h"
#include "main.h"
/*
* Also they use a different method for extracting audio.
* We have the device inquiry strings at this time. This is used to enable
* us to use older sun drives to extract audio.
*/
static int
{
/*
* If we have a SONY CDU 561, CDU 8012, or TOSHIBA model with XMa we
* need to handle these drives a bit differently.
*/
return (1);
return (1);
}
/* Changing speed is not allowed for 32X TOSHIBA drives */
product_id[16] = 0;
return (1);
}
return (0);
}
/*
* returns a cd_device handle for a node returned by lookup_device()
* also takes the user supplied name and stores it inside the node
*/
{
int fd;
int size;
int use_cd_speed = 0;
/*
* we need to resolve any link paths to avoid fake files
*/
return (NULL);
/* resolvepath may not return a null terminated string */
return (NULL);
/*
* Since we are currently running with the user euid it is
* safe to try to open the file without checking access.
*/
if (fd < 0) {
return (NULL);
}
if (debug) {
(void) printf("USCSI ioctl failed %d\n",
}
return (NULL);
}
if (debug) {
(void) printf("Checking device type\n");
(void) printf("DVD-R read support\n");
(void) printf("DVD-R write support\n");
(void) printf("R-W supported\n");
(void) printf("DVD-RAM read supported\n");
(void) printf("DVD-RAM write supported\n");
} else {
(void) printf("Could not read mode page 2A! \n");
}
}
/* Detect if it's a Lite-ON drive with a streaming CD problem */
use_cd_speed = 1;
}
/*
* a workaround for the firmware problem in LITE-ON COMBO drives.
* streaming for these drives sets it only to max speed regardless
* of requested speed. cd_speed_ctrl allow speeds less than max
* to be set but not max thus the code below. (x48 is max speed
* for these drives).
*/
(strncmp("COMBO SOHC-4836VS",
if (requested_speed < 48)
use_cd_speed = 1;
if (is_old_sun_drive(dev)) {
} else {
/*
* If the CD Read Feature is supported, READ CD will work
* and will return jitter free audio data. Otherwise, look
* at Page Code 2A for this information.
*/
}
}
/*
* If the Real Time Streaming Feature is supported then
* Real-time streaming commands can be used for speed control
* (except when we want to use cd_speed_ctrl explicitly which
* is specified by setting use_cd_speed to 1).
* Otherwise try SET CD SPEED.
*/
!use_cd_speed) {
if (debug)
(void) printf("using rt speed ctrl\n");
} else {
if (debug)
(void) printf("using cd speed ctrl\n");
}
}
/*
* Find the block size of the device so we can translate
*/
/*
* If DKIOCGMEDIAINFO fails we'll try to get
* the blocksize from the device itself.
*/
if (debug)
(void) printf("DKIOCGMEDIAINFO failed\n");
} else {
}
if (debug) {
(void) printf("read_format_capacity = %d \n",
}
/*
* Some devices will return invalid blocksizes. ie. Toshiba
* drives will return 2352 when an audio CD is inserted.
* Older Sun drives will use 512 byte block sizes. All newer
* drives should have 2k blocksizes.
*/
if (is_old_sun_drive(dev)) {
} else {
}
if (debug)
}
if (user_supplied) {
}
return (dev);
}
void
{
}
/*
* Given a /dev path resolve that path to a symbolic
* name such as cdrom0 if hald is running. If hald is
* not running, or does not have a symbolic name for the
* the specified /dev path return NULL.
*/
static char *
{
int ndevs = 0, i;
/* Make sure hald is running */
if (vol_running == 0)
return (p);
return (p);
goto done;
/* Look for the node that contains the valid (non-null) symdev */
for (i = 0; i < ndevs; i++) {
break;
else
}
done:
if (dbus_error_is_set(&error))
return (p);
}
/*
* Given a name resolve that name to a raw device in the case
* that it is a symbolic name or just return what is given if
* we are given a /dev path or hald is not running.
*/
static char *
{
int ndevs = 0, i;
/*
* We already have a raw path lets return it in a copied buffer
* as our caller assumes that they need to free memory.
*/
if (symname[0] == '/') {
return (path);
}
/* Get the raw device from the hal record */
if (vol_running != 0) {
return (path);
goto done;
/*
* Loop over the returned UDIs to access the raw
* device path.
*/
for (i = 0; i < ndevs; i++) {
break;
else
}
done:
if (dbus_error_is_set(&error))
return (path);
} else {
return (NULL);
}
}
static int
{
char *p1;
int i;
return (0);
return (0);
return (0);
}
for (i = 0; i < 16; i++) {
break;
}
if (i == 16) {
return (0);
}
} else {
}
return (1);
}
/*
* Builds an open()able device path from a user supplied node which can be
* cdrom[n]
* returns the path found in 'found' and returns 1. Otherwise returns 0.
*/
int
{
int fd;
/* If everything is fine and proper, no need to analyze */
return (1);
}
/*
* Hal only allows access to a device when the user is
* on the console, therefore if hal is running and we can't
* open the /dev/rdsk or /dev/removable-media/rdsk device
* file we will return 0 marking this device as not avaiable.
*/
return (0);
return (1);
}
/* This device can't be opened mark it as unavailable. */
return (0);
}
supplied);
}
return (1);
}
/* This device can't be opened mark it as unavailable. */
return (0);
}
}
/*
* Opens the device node name passed and returns 1 (true) if the
* device is a CD.
*/
static int
{
int fd;
if (fd < 0) {
ret = 0;
ret = 0;
ret = 0;
}
if (fd >= 0) {
}
return (ret);
}
static void
print_header(void)
{
/* l10n_NOTE : Column spacing should be kept same */
/* l10n_NOTE : Column spacing should be kept same */
(void) printf(
"----------------------+--------------------------------");
(void) printf("+-----------------\n");
}
/*
* the first device found depending on the mode argument.
* possible mode values are:
* SCAN_WRITERS Scan all CD-RW devices. Return first one found.
* SCAN_LISTDEVS List all devices found.
*/
int
{
int writers_found = 0;
int header_printed = 0;
int is_writer;
int total_devices_found;
if (mode) {
}
return (0);
writers_found = 0;
total_devices_found = 0;
continue;
continue;
continue;
continue;
continue;
}
if (is_writer) {
}
/* We found a CD-ROM or DVD-ROM */
}
if (mode == SCAN_LISTDEVS) {
char *sn;
if (!header_printed) {
print_header();
header_printed = 1;
}
/* show vendor, model, firmware rev and device type */
(void) printf(" %-21.21s| %.8s %.16s %.4s | %s%s\n",
gettext("CD Reader"),
if (sn)
}
}
return (writers_found);
else
return (total_devices_found);
}
/*
* Check device for various conditions/capabilities
* If EXIT_IF_CHECK_FAILED set in cond then it will also exit after
* printing a message.
*/
int
{
errmsg =
gettext("Specified device does not appear to be a CDROM");
}
}
/* Look at the capabilities page for this information */
}
}
/* medium not present */
}
}
/* Issue READ DISC INFORMATION mmc command */
(cond & CHECK_MEDIA_IS_NOT_WRITABLE) ||
(cond & CHECK_MEDIA_IS_NOT_ERASABLE))) {
} else {
}
"Media in the device is not erasable");
else if ((disc_status != 0) &&
"Media in the device is not blank");
else if ((disc_status == 2) &&
(cond & CHECK_MEDIA_IS_NOT_WRITABLE) &&
((device_type != DVD_PLUS_W) &&
(device_type != DVD_PLUS)))
"Media in the device is not writable");
}
}
if (errmsg) {
if (cond & EXIT_IF_CHECK_FAILED) {
exit(1);
}
return (1);
}
return (0);
}
/*
* Generic routine for writing whatever the next track is and taking
* care of the progress bar. Mode tells the track type (audio or data).
* Data from track is taken from the byte stream h
*/
void
{
DVD_PLUS_W)) {
} else {
"Cannot get writable address for the media.\n"));
exit(1);
}
}
"Media state is not suitable for this write mode.\n"));
exit(1);
}
if (mode == TRACK_MODE_DATA) {
/* Write track depends upon this bit */
}
}
size = 0;
h->bstr_rewind(h);
} else {
if (device_type != DVD_PLUS_W) {
/* l10n_NOTE : 'failed' as in Writing Track...failed */
}
}
}
/* l10n_NOTE : 'done' as in "Writing track 1...done" */
}
void
list(void)
{
if (vol_running) {
"No CD writers found, no media in the drive "
"or not on the console.\n"));
} else {
if (cur_uid != 0) {
"Volume manager is not running.\n"));
"Please start volume manager or run cdrw as root to access all devices.\n"));
} else {
}
}
}
exit(0);
}
void
{
MMC_FTR_HDR_LEN, cap)) {
if (debug)
(void) print_profile_list(fd);
case 0x8: /* CD-ROM */
if (debug)
(void) printf("CD-ROM found\n");
/*
* To avoid regression issues, treat as
* A cdrw, we will check the writable
* mode page to see if the media is
* actually writable.
*/
device_type = CD_RW;
break;
case 0x9: /* CD-R */
if (debug)
(void) printf("CD-R found\n");
device_type = CD_RW;
break;
case 0x10: /* DVD-ROM */
/*
* Have seen drives return DVD+RW media
* DVD-ROM, so try treating it as a DVD+RW
* profile. checking for writable media
* is done through mode page 5.
*/
if (debug)
(void) printf("DVD-ROM found\n");
break;
case 0xA: /* CD-RW */
if (debug)
(void) printf("CD-RW found\n");
device_type = CD_RW;
break;
case 0x11: /* DVD-R */
if (debug)
(void) printf("DVD-R found\n");
break;
case 0x12: /* DVD-RAM */
if (debug)
(void) printf("DVD-RAM found\n");
/* treat as CD-RW, may be a legacy drive */
device_type = CD_RW;
break;
case 0x13: /* DVD-RW restricted overwrite */
case 0x14: /* DVD-RW sequential */
if (debug)
(void) printf("DVD-RW found\n");
break;
case 0x15: /* DVD-R Dual Layer Sequential Recording */
case 0x16: /* DVD-R Dual Layer Jump Recording */
if (debug)
(void) printf("DVD-R DL found\n");
break;
case 0x17: /* DVD-RW Dual Layer */
if (debug)
(void) printf("DVD-RW DL found\n");
break;
case 0x1A: /* DVD+RW */
if (debug)
(void) printf("DVD+RW found\n");
break;
case 0x1B: /* DVD+R */
if (debug)
(void) printf("DVD+R found\n");
break;
case 0x2A: /* DVD+RW Dual Layer */
if (debug)
(void) printf("DVD+RW DL found\n");
break;
case 0x2B: /* DVD+R Dual Layer */
if (debug)
(void) printf("DVD+R DL found\n");
break;
default:
if (debug)
(void) printf(
"unknown drive found\n type = 0x%x",
cap[7]);
/*
* Treat as CD_RW to avoid regression, may
* be a legacy drive.
*/
device_type = CD_RW;
}
}
}
/* Translate a transfer rate (eg, KB/s) into a Speed (eg, "2X") */
{
switch (device_type) {
case DVD_PLUS_W:
case DVD_MINUS:
case DVD_PLUS:
return (DVD_RATE_TO_X(rate));
default:
case CD_RW:
return (CD_RATE_TO_X(rate));
}
}
/* Translate a Speed (eg, "2X") into a transfer rate (eg, KB/s) */
{
switch (device_type) {
case DVD_PLUS_W:
case DVD_MINUS:
case DVD_PLUS:
return (DVD_X_TO_RATE(x));
default:
case CD_RW:
return (CD_X_TO_RATE(x));
}
}