summaryrefslogtreecommitdiff
path: root/src/input/vcd/libcdio/_cdio_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/vcd/libcdio/_cdio_linux.c')
-rw-r--r--src/input/vcd/libcdio/_cdio_linux.c1153
1 files changed, 613 insertions, 540 deletions
diff --git a/src/input/vcd/libcdio/_cdio_linux.c b/src/input/vcd/libcdio/_cdio_linux.c
index e5dd47551..86a34133f 100644
--- a/src/input/vcd/libcdio/_cdio_linux.c
+++ b/src/input/vcd/libcdio/_cdio_linux.c
@@ -1,5 +1,5 @@
/*
- $Id: _cdio_linux.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $
+ $Id: _cdio_linux.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
@@ -27,15 +27,18 @@
# include "config.h"
#endif
-static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $";
+static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $";
#include <string.h>
#include <cdio/sector.h>
#include <cdio/util.h>
+#include <cdio/types.h>
+#include <cdio/scsi_mmc.h>
+#include <cdio/cdtext.h>
+#include "cdtext_private.h"
#include "cdio_assert.h"
#include "cdio_private.h"
-#include "scsi_mmc.h"
#ifdef HAVE_LINUX_CDROM
@@ -67,24 +70,25 @@ static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.2 2004/04/11 12:20:31 migue
#include <sys/types.h>
#include <sys/ioctl.h>
-#define TOTAL_TRACKS (_obj->tochdr.cdth_trk1)
-#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0)
+typedef enum {
+ _AM_NONE,
+ _AM_IOCTL,
+ _AM_READ_CD,
+ _AM_READ_10
+} access_mode_t;
typedef struct {
/* Things common to all drivers like this.
This must be first. */
generic_img_private_t gen;
- enum {
- _AM_NONE,
- _AM_IOCTL,
- _AM_READ_CD,
- _AM_READ_10
- } access_mode;
+ access_mode_t access_mode;
+
+ /* Some of the more OS specific things. */
+ /* Entry info for each track, add 1 for leadout. */
+ struct cdrom_tocentry tocent[CDIO_CD_MAX_TRACKS+1];
- /* Track information */
struct cdrom_tochdr tochdr;
- struct cdrom_tocentry tocent[100]; /* entry info for each track */
} _img_private_t;
@@ -92,40 +96,39 @@ typedef struct {
#define ERRNO_TRAYEMPTY(errno) \
((errno == EIO) || (errno == ENOENT) || (errno == EINVAL))
-
-/* Check a drive to see if it is a CD-ROM
- Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive
- and -1 if no device exists .
-*/
-static bool
-cdio_is_cdrom(char *drive, char *mnttype)
+/**** prototypes for static functions ****/
+static bool is_cdrom_linux(const char *drive, char *mnttype);
+static bool read_toc_linux (void *p_user_data);
+static int run_scsi_cmd_linux( const void *p_user_data,
+ unsigned int i_timeout,
+ unsigned int i_cdb,
+ const scsi_mmc_cdb_t *p_cdb,
+ scsi_mmc_direction_t e_direction,
+ unsigned int i_buf,
+ /*in/out*/ void *p_buf );
+static access_mode_t
+
+str_to_access_mode_linux(const char *psz_access_mode)
{
- bool is_cd=false;
- int cdfd;
- struct cdrom_tochdr tochdr;
-
- /* If it doesn't exist, return -1 */
- if ( !cdio_is_device_quiet_generic(drive) ) {
- return(false);
- }
+ const access_mode_t default_access_mode = _AM_IOCTL;
+
+ if (NULL==psz_access_mode) return default_access_mode;
- /* If it does exist, verify that it's an available CD-ROM */
- cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0);
- if ( cdfd >= 0 ) {
- if ( ioctl(cdfd, CDROMREADTOCHDR, &tochdr) != -1 ) {
- is_cd = true;
- }
- close(cdfd);
- }
- /* Even if we can't read it, it might be mounted */
- else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) {
- is_cd = true;
+ if (!strcmp(psz_access_mode, "IOCTL"))
+ return _AM_IOCTL;
+ else if (!strcmp(psz_access_mode, "READ_CD"))
+ return _AM_READ_CD;
+ else if (!strcmp(psz_access_mode, "READ_10"))
+ return _AM_READ_10;
+ else {
+ cdio_warn ("unknown access type: %s. Default IOCTL used.",
+ psz_access_mode);
+ return default_access_mode;
}
- return(is_cd);
}
static char *
-cdio_check_mounts(const char *mtab)
+check_mounts_linux(const char *mtab)
{
FILE *mntfp;
struct mntent *mntent;
@@ -176,7 +179,7 @@ cdio_check_mounts(const char *mtab)
}
}
if ( strcmp(mnt_type, "iso9660") == 0 ) {
- if (cdio_is_cdrom(mnt_dev, mnt_type) > 0) {
+ if (is_cdrom_linux(mnt_dev, mnt_type) > 0) {
free(mnt_type);
endmntent(mntfp);
return mnt_dev;
@@ -190,146 +193,408 @@ cdio_check_mounts(const char *mtab)
return NULL;
}
-static int
-_set_bsize (int fd, unsigned int bsize)
+/*!
+ Return the value associated with the key "arg".
+*/
+static const char *
+get_arg_linux (void *env, const char key[])
{
- struct cdrom_generic_command cgc;
+ _img_private_t *_obj = env;
- struct
- {
- uint8_t reserved1;
- uint8_t medium;
- uint8_t reserved2;
- uint8_t block_desc_length;
- uint8_t density;
- uint8_t number_of_blocks_hi;
- uint8_t number_of_blocks_med;
- uint8_t number_of_blocks_lo;
- uint8_t reserved3;
- uint8_t block_length_hi;
- uint8_t block_length_med;
- uint8_t block_length_lo;
- } mh;
-
- memset (&mh, 0, sizeof (mh));
- memset (&cgc, 0, sizeof (struct cdrom_generic_command));
+ if (!strcmp (key, "source")) {
+ return _obj->gen.source_name;
+ } else if (!strcmp (key, "access-mode")) {
+ switch (_obj->access_mode) {
+ case _AM_IOCTL:
+ return "ioctl";
+ case _AM_READ_CD:
+ return "READ_CD";
+ case _AM_READ_10:
+ return "READ_10";
+ case _AM_NONE:
+ return "no access method";
+ }
+ }
+ return NULL;
+}
+
+#undef USE_LINUX_CAP
+#ifdef USE_LINUX_CAP
+/*!
+ Return the the kind of drive capabilities of device.
+
+ Note: string is malloc'd so caller should free() then returned
+ string when done with it.
+
+ */
+static void
+get_drive_cap_linux (const void *p_user_data,
+ /*out*/ cdio_drive_read_cap_t *p_read_cap,
+ /*out*/ cdio_drive_write_cap_t *p_write_cap,
+ /*out*/ cdio_drive_misc_cap_t *p_misc_cap)
+{
+ const _img_private_t *p_env = p_user_data;
+ int32_t i_drivetype;
+
+ i_drivetype = ioctl (p_env->gen.fd, CDROM_GET_CAPABILITY, CDSL_CURRENT);
+
+ if (i_drivetype < 0) {
+ *p_read_cap = CDIO_DRIVE_CAP_ERROR;
+ *p_write_cap = CDIO_DRIVE_CAP_ERROR;
+ *p_misc_cap = CDIO_DRIVE_CAP_ERROR;
+ return;
+ }
- cgc.cmd[0] = 0x15;
- cgc.cmd[1] = 1 << 4;
- cgc.cmd[4] = 12;
+ *p_read_cap = 0;
+ *p_write_cap = 0;
+ *p_misc_cap = 0;
+
+ /* Reader */
+ if (i_drivetype & CDC_PLAY_AUDIO)
+ *p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO;
+ if (i_drivetype & CDC_CD_R)
+ *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_R;
+ if (i_drivetype & CDC_CD_RW)
+ *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_RW;
+ if (i_drivetype & CDC_DVD)
+ *p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM;
+
+ /* Writer */
+ if (i_drivetype & CDC_CD_RW)
+ *p_read_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW;
+ if (i_drivetype & CDC_DVD_R)
+ *p_read_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R;
+ if (i_drivetype & CDC_DVD_RAM)
+ *p_read_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM;
+
+ /* Misc */
+ if (i_drivetype & CDC_CLOSE_TRAY)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY;
+ if (i_drivetype & CDC_OPEN_TRAY)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_EJECT;
+ if (i_drivetype & CDC_LOCK)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_LOCK;
+ if (i_drivetype & CDC_SELECT_SPEED)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_SELECT_SPEED;
+ if (i_drivetype & CDC_SELECT_DISC)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_SELECT_DISC;
+ if (i_drivetype & CDC_MULTI_SESSION)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION;
+ if (i_drivetype & CDC_MEDIA_CHANGED)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED;
+ if (i_drivetype & CDC_RESET)
+ *p_misc_cap |= CDIO_DRIVE_CAP_MISC_RESET;
+}
+#endif
+
+/*!
+ Return the media catalog number MCN.
+
+ Note: string is malloc'd so caller should free() then returned
+ string when done with it.
+
+ */
+static char *
+get_mcn_linux (const void *p_user_data) {
+
+ struct cdrom_mcn mcn;
+ const _img_private_t *p_env = p_user_data;
+ memset(&mcn, 0, sizeof(mcn));
+ if (ioctl(p_env->gen.fd, CDROM_GET_MCN, &mcn) != 0)
+ return NULL;
+ return strdup(mcn.medium_catalog_number);
+}
+
+/*!
+ Get format of track.
+*/
+static track_format_t
+get_track_format_linux(void *p_user_data, track_t i_track)
+{
+ _img_private_t *p_env = p_user_data;
- cgc.buflen = sizeof (mh);
- cgc.buffer = (void *) &mh;
+ if ( !p_env ) return TRACK_FORMAT_ERROR;
- cgc.data_direction = CGC_DATA_WRITE;
+ if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;
- mh.block_desc_length = 0x08;
- mh.block_length_hi = (bsize >> 16) & 0xff;
- mh.block_length_med = (bsize >> 8) & 0xff;
- mh.block_length_lo = (bsize >> 0) & 0xff;
+ if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track)
+ || i_track < p_env->gen.i_first_track)
+ return TRACK_FORMAT_ERROR;
+
+ i_track -= p_env->gen.i_first_track;
- return ioctl (fd, CDROM_SEND_PACKET, &cgc);
+ /* This is pretty much copied from the "badly broken" cdrom_count_tracks
+ in linux/cdrom.c.
+ */
+ if (p_env->tocent[i_track].cdte_ctrl & CDIO_CDROM_DATA_TRACK) {
+ if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK)
+ return TRACK_FORMAT_CDI;
+ else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK)
+ return TRACK_FORMAT_XA;
+ else
+ return TRACK_FORMAT_DATA;
+ } else
+ return TRACK_FORMAT_AUDIO;
+
}
-/* Packet driver to read mode2 sectors.
- Can read only up to 25 blocks.
+/*!
+ Return true if we have XA data (green, mode2 form1) or
+ XA data (green, mode2 form2). That is track begins:
+ sync - header - subheader
+ 12 4 - 8
+
+ FIXME: there's gotta be a better design for this and get_track_format?
*/
-static int
-_cdio_mmc_read_sectors (int fd, void *buf, lba_t lba, int sector_type,
- unsigned int nblocks)
+static bool
+get_track_green_linux(void *p_user_data, track_t i_track)
{
- typedef struct cdrom_generic_command cgc_t;
- cgc_t cgc;
+ _img_private_t *p_env = p_user_data;
+
+ if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;
- memset (&cgc, 0, sizeof (cgc_t));
+ if (i_track >= (p_env->gen.i_tracks+p_env->gen.i_first_track)
+ || i_track < p_env->gen.i_first_track)
+ return false;
- cgc.cmd[0] = CDIO_MMC_GPCMD_READ_CD;
- CDIO_MMC_SET_READ_TYPE (cgc.cmd, sector_type);
- CDIO_MMC_SET_READ_LBA (cgc.cmd, lba);
- CDIO_MMC_SET_READ_LENGTH(cgc.cmd, nblocks);
- CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cgc.cmd, CDIO_MMC_MCSB_ALL_HEADERS);
+ i_track -= p_env->gen.i_first_track;
- cgc.buflen = CDIO_CD_FRAMESIZE_RAW * nblocks;
- cgc.buffer = buf;
+ /* FIXME: Dunno if this is the right way, but it's what
+ I was using in cd-info for a while.
+ */
+ return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0);
+}
-#ifdef HAVE_LINUX_CDROM_TIMEOUT
- cgc.timeout = 500;
-#endif
- cgc.data_direction = CGC_DATA_READ;
+/*!
+ Return the starting MSF (minutes/secs/frames) for track number
+ track_num in obj. Track numbers usually start at something
+ greater than 0, usually 1.
- return ioctl (fd, CDROM_SEND_PACKET, &cgc);
+ The "leadout" track is specified either by
+ using i_track LEADOUT_TRACK or the total tracks+1.
+ False is returned if there is no track entry.
+*/
+static bool
+get_track_msf_linux(void *p_user_data, track_t i_track, msf_t *msf)
+{
+ _img_private_t *p_env = p_user_data;
- return 0;
+ if (NULL == msf) return false;
+
+ if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;
+
+ if (i_track == CDIO_CDROM_LEADOUT_TRACK)
+ i_track = p_env->gen.i_tracks + p_env->gen.i_first_track;
+
+ if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track)
+ || i_track < p_env->gen.i_first_track) {
+ return false;
+ } else {
+ struct cdrom_msf0 *msf0=
+ &p_env->tocent[i_track-p_env->gen.i_first_track].cdte_addr.msf;
+ msf->m = cdio_to_bcd8(msf0->minute);
+ msf->s = cdio_to_bcd8(msf0->second);
+ msf->f = cdio_to_bcd8(msf0->frame);
+ return true;
+ }
+}
+
+/*!
+ Eject media in CD drive.
+ Return 0 if success and 1 for failure, and 2 if no routine.
+ */
+static int
+eject_media_linux (void *p_user_data) {
+
+ _img_private_t *p_env = p_user_data;
+ int ret=2;
+ int status;
+ int fd;
+
+ if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) {
+ if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) {
+ switch(status) {
+ case CDS_TRAY_OPEN:
+ if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) {
+ cdio_warn ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno));
+ ret = 1;
+ }
+ break;
+ case CDS_DISC_OK:
+ if((ret = ioctl(fd, CDROMEJECT)) != 0) {
+ int eject_error = errno;
+ /* Try ejecting the MMC way... */
+ ret = scsi_mmc_eject_media(p_env->gen.cdio);
+ if (0 != ret) {
+ cdio_warn("ioctl CDROMEJECT failed: %s\n",
+ strerror(eject_error));
+ ret = 1;
+ }
+ }
+ /* force kernel to reread partition table when new disc inserted */
+ ret = ioctl(p_env->gen.fd, BLKRRPART);
+ break;
+ default:
+ cdio_warn ("Unknown CD-ROM (%d)\n", status);
+ ret = 1;
+ }
+ } else {
+ cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno));
+ ret=1;
+ }
+ close(fd);
+ } else
+ ret = 2;
+ close(p_env->gen.fd);
+ p_env->gen.fd = -1;
+ return ret;
+}
+
+/*!
+ Get disc type associated with the cd object.
+*/
+static discmode_t
+get_discmode_linux (void *p_user_data)
+{
+ _img_private_t *p_env = p_user_data;
+
+ int32_t i_discmode;
+
+ /* See if this is a DVD. */
+ cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */
+
+ dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL;
+ dvd.physical.layer_num = 0;
+ if (0 == ioctl (p_env->gen.fd, DVD_READ_STRUCT, &dvd)) {
+ switch(dvd.physical.layer[0].book_type) {
+ case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM;
+ case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM;
+ case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R;
+ case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW;
+ case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR;
+ case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW;
+ default: return CDIO_DISC_MODE_DVD_OTHER;
+ }
+ }
+
+ i_discmode = ioctl (p_env->gen.fd, CDROM_DISC_STATUS);
+
+ if (i_discmode < 0) return CDIO_DISC_MODE_ERROR;
+
+ /* FIXME Need to add getting DVD types. */
+ switch(i_discmode) {
+ case CDS_AUDIO:
+ return CDIO_DISC_MODE_CD_DA;
+ case CDS_DATA_1:
+ case CDS_DATA_2:
+ return CDIO_DISC_MODE_CD_DATA;
+ case CDS_MIXED:
+ return CDIO_DISC_MODE_CD_MIXED;
+ case CDS_XA_2_1:
+ case CDS_XA_2_2:
+ return CDIO_DISC_MODE_CD_XA;
+ case CDS_NO_INFO:
+ return CDIO_DISC_MODE_NO_INFO;
+ default:
+ return CDIO_DISC_MODE_ERROR;
+ }
+}
+
+/* Check a drive to see if it is a CD-ROM
+ Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive
+ and -1 if no device exists .
+*/
+static bool
+is_cdrom_linux(const char *drive, char *mnttype)
+{
+ bool is_cd=false;
+ int cdfd;
+ struct cdrom_tochdr tochdr;
+
+ /* If it doesn't exist, return -1 */
+ if ( !cdio_is_device_quiet_generic(drive) ) {
+ return(false);
+ }
+
+ /* If it does exist, verify that it's an available CD-ROM */
+ cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0);
+ if ( cdfd >= 0 ) {
+ if ( ioctl(cdfd, CDROMREADTOCHDR, &tochdr) != -1 ) {
+ is_cd = true;
+ }
+ close(cdfd);
+ }
+ /* Even if we can't read it, it might be mounted */
+ else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) {
+ is_cd = true;
+ }
+ return(is_cd);
}
/* MMC driver to read audio sectors.
Can read only up to 25 blocks.
*/
static int
-_cdio_read_audio_sectors (void *env, void *buf, lsn_t lsn,
- unsigned int nblocks)
+_read_audio_sectors_linux (void *p_user_data, void *buf, lsn_t lsn,
+ unsigned int nblocks)
{
- _img_private_t *_obj = env;
- return _cdio_mmc_read_sectors( _obj->gen.fd, buf, lsn,
- CDIO_MMC_READ_TYPE_CDDA, nblocks);
+ _img_private_t *p_env = p_user_data;
+ return scsi_mmc_read_sectors( p_env->gen.cdio, buf, lsn,
+ CDIO_MMC_READ_TYPE_CDDA, nblocks);
}
/* Packet driver to read mode2 sectors.
Can read only up to 25 blocks.
*/
static int
-__read_packet_mode2_sectors (int fd, void *buf, lba_t lba,
- unsigned int nblocks, bool use_read_10)
+_read_mode2_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba,
+ unsigned int nblocks, bool b_read_10)
{
- struct cdrom_generic_command cgc;
-
- memset (&cgc, 0, sizeof (struct cdrom_generic_command));
-
- cgc.cmd[0] = use_read_10 ? GPCMD_READ_10 : CDIO_MMC_GPCMD_READ_CD;
-
- CDIO_MMC_SET_READ_LBA(cgc.cmd, lba);
- CDIO_MMC_SET_READ_LENGTH(cgc.cmd, nblocks);
-
- if (!use_read_10)
- {
- cgc.cmd[1] = 0; /* sector size mode2 */
-
- cgc.cmd[9] = 0x58; /* 2336 mode2 */
- }
+ scsi_mmc_cdb_t cdb = {{0, }};
- cgc.buflen = 2336 * nblocks;
- cgc.buffer = buf;
+ CDIO_MMC_SET_READ_LBA(cdb.field, lba);
-#ifdef HAVE_LINUX_CDROM_TIMEOUT
- cgc.timeout = 500;
-#endif
- cgc.data_direction = CGC_DATA_READ;
-
- if (use_read_10)
- {
- int retval;
+ if (b_read_10) {
+ int retval;
+
+ CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_10);
+ CDIO_MMC_SET_READ_LENGTH16(cdb.field, nblocks);
- if ((retval = _set_bsize (fd, 2336)))
+ if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, M2RAW_SECTOR_SIZE)))
+ return retval;
+
+ if ((retval = run_scsi_cmd_linux (p_env, 0,
+ scsi_mmc_get_cmd_len(cdb.field[0]),
+ &cdb,
+ SCSI_MMC_DATA_READ,
+ M2RAW_SECTOR_SIZE * nblocks,
+ p_buf)))
+ {
+ scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE);
return retval;
+ }
+
+ if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE)))
+ return retval;
+ } else
- if ((retval = ioctl (fd, CDROM_SEND_PACKET, &cgc)))
- {
- _set_bsize (fd, 2048);
- return retval;
- }
+ cdb.field[1] = 0; /* sector size mode2 */
+ cdb.field[9] = 0x58; /* 2336 mode2 */
- if ((retval = _set_bsize (fd, 2048)))
- return retval;
- }
- else
- return ioctl (fd, CDROM_SEND_PACKET, &cgc);
+ CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD);
+ CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks);
+ return run_scsi_cmd_linux (p_env, 0,
+ scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
+ SCSI_MMC_DATA_READ,
+ M2RAW_SECTOR_SIZE * nblocks, p_buf);
+
return 0;
}
static int
-_read_packet_mode2_sectors (int fd, void *buf, lba_t lba,
- unsigned int nblocks, bool use_read_10)
+_read_mode2_sectors (_img_private_t *p_env, void *p_buf, lba_t lba,
+ unsigned int nblocks, bool b_read_10)
{
unsigned int l = 0;
int retval = 0;
@@ -337,10 +602,10 @@ _read_packet_mode2_sectors (int fd, void *buf, lba_t lba,
while (nblocks > 0)
{
const unsigned nblocks2 = (nblocks > 25) ? 25 : nblocks;
- void *buf2 = ((char *)buf ) + (l * 2336);
+ void *p_buf2 = ((char *)p_buf ) + (l * M2RAW_SECTOR_SIZE);
- retval |= __read_packet_mode2_sectors (fd, buf2, lba + l, nblocks2,
- use_read_10);
+ retval |= _read_mode2_sectors_mmc (p_env, p_buf2, lba + l,
+ nblocks2, b_read_10);
if (retval)
break;
@@ -357,32 +622,32 @@ _read_packet_mode2_sectors (int fd, void *buf, lba_t lba,
from lsn. Returns 0 if no error.
*/
static int
-_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn,
+_read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn,
bool b_form2)
{
- char buf[M2RAW_SECTOR_SIZE] = { 0, };
#if FIXED
- struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
+ char buf[M2RAW_SECTOR_SIZE] = { 0, };
+ struct cdrom_msf *p_msf = (struct cdrom_msf *) &buf;
msf_t _msf;
- _img_private_t *_obj = env;
+ _img_private_t *p_env = p_user_data;
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
- msf->cdmsf_min0 = from_bcd8(_msf.m);
- msf->cdmsf_sec0 = from_bcd8(_msf.s);
- msf->cdmsf_frame0 = from_bcd8(_msf.f);
+ msf->cdmsf_min0 = cdio_from_bcd8(_msf.m);
+ msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s);
+ msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f);
retry:
- switch (_obj->access_mode)
+ switch (p_env->access_mode)
{
case _AM_NONE:
- cdio_error ("no way to read mode1");
+ cdio_warn ("no way to read mode1");
return 1;
break;
case _AM_IOCTL:
- if (ioctl (_obj->gen.fd, CDROMREADMODE1, &buf) == -1)
+ if (ioctl (p_env->gen.fd, CDROMREADMODE1, &buf) == -1)
{
perror ("ioctl()");
return 1;
@@ -392,20 +657,20 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn,
case _AM_READ_CD:
case _AM_READ_10:
- if (_read_packet_mode2_sectors (_obj->gen.fd, buf, lsn, 1,
- (_obj->access_mode == _AM_READ_10)))
+ if (_read_mode2_sectors (p_env->gen.fd, buf, lsn, 1,
+ (p_env->access_mode == _AM_READ_10)))
{
perror ("ioctl()");
- if (_obj->access_mode == _AM_READ_CD)
+ if (p_env->access_mode == _AM_READ_CD)
{
cdio_info ("READ_CD failed; switching to READ_10 mode...");
- _obj->access_mode = _AM_READ_10;
+ p_env->access_mode = _AM_READ_10;
goto retry;
}
else
{
cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode...");
- _obj->access_mode = _AM_IOCTL;
+ p_env->access_mode = _AM_IOCTL;
goto retry;
}
return 1;
@@ -417,11 +682,7 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn,
b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE);
#else
- if (0 > cdio_generic_lseek(env, CDIO_CD_FRAMESIZE*lsn, SEEK_SET))
- return -1;
- if (0 > cdio_generic_read(env, buf, CDIO_CD_FRAMESIZE))
- return -1;
- memcpy (data, buf, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE);
+ return cdio_generic_read_form1_sector(p_user_data, p_data, lsn);
#endif
return 0;
}
@@ -432,17 +693,17 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn,
Returns 0 if no error.
*/
static int
-_cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn,
+_read_mode1_sectors_linux (void *p_user_data, void *p_data, lsn_t lsn,
bool b_form2, unsigned int nblocks)
{
- _img_private_t *_obj = env;
+ _img_private_t *p_env = p_user_data;
unsigned int i;
int retval;
unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
for (i = 0; i < nblocks; i++) {
- if ( (retval = _cdio_read_mode1_sector (_obj,
- ((char *)data) + (blocksize * i),
+ if ( (retval = _read_mode1_sector_linux (p_env,
+ ((char *)p_data) + (blocksize*i),
lsn + i, b_form2)) )
return retval;
}
@@ -454,30 +715,30 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn,
from lsn. Returns 0 if no error.
*/
static int
-_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn,
- bool b_form2)
+_read_mode2_sector_linux (void *p_user_data, void *p_data, lsn_t lsn,
+ bool b_form2)
{
char buf[M2RAW_SECTOR_SIZE] = { 0, };
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
msf_t _msf;
- _img_private_t *_obj = env;
+ _img_private_t *p_env = p_user_data;
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
- msf->cdmsf_min0 = from_bcd8(_msf.m);
- msf->cdmsf_sec0 = from_bcd8(_msf.s);
- msf->cdmsf_frame0 = from_bcd8(_msf.f);
+ msf->cdmsf_min0 = cdio_from_bcd8(_msf.m);
+ msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s);
+ msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f);
retry:
- switch (_obj->access_mode)
+ switch (p_env->access_mode)
{
case _AM_NONE:
- cdio_error ("no way to read mode2");
+ cdio_warn ("no way to read mode2");
return 1;
break;
case _AM_IOCTL:
- if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1)
+ if (ioctl (p_env->gen.fd, CDROMREADMODE2, &buf) == -1)
{
perror ("ioctl()");
return 1;
@@ -487,20 +748,20 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn,
case _AM_READ_CD:
case _AM_READ_10:
- if (_read_packet_mode2_sectors (_obj->gen.fd, buf, lsn, 1,
- (_obj->access_mode == _AM_READ_10)))
+ if (_read_mode2_sectors (p_env, buf, lsn, 1,
+ (p_env->access_mode == _AM_READ_10)))
{
perror ("ioctl()");
- if (_obj->access_mode == _AM_READ_CD)
+ if (p_env->access_mode == _AM_READ_CD)
{
cdio_info ("READ_CD failed; switching to READ_10 mode...");
- _obj->access_mode = _AM_READ_10;
+ p_env->access_mode = _AM_READ_10;
goto retry;
}
else
{
cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode...");
- _obj->access_mode = _AM_IOCTL;
+ p_env->access_mode = _AM_IOCTL;
goto retry;
}
return 1;
@@ -509,9 +770,9 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn,
}
if (b_form2)
- memcpy (data, buf, M2RAW_SECTOR_SIZE);
+ memcpy (p_data, buf, M2RAW_SECTOR_SIZE);
else
- memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
+ memcpy (((char *)p_data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
return 0;
}
@@ -522,115 +783,57 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn,
Returns 0 if no error.
*/
static int
-_cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn,
+_read_mode2_sectors_linux (void *p_user_data, void *data, lsn_t lsn,
bool b_form2, unsigned int nblocks)
{
- _img_private_t *_obj = env;
+ _img_private_t *p_env = p_user_data;
unsigned int i;
- int retval;
- unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
+ unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
+ /* For each frame, pick out the data part we need */
for (i = 0; i < nblocks; i++) {
- if ( (retval = _cdio_read_mode2_sector (_obj,
- ((char *)data) + (blocksize * i),
+ int retval;
+ if ( (retval = _read_mode2_sector_linux (p_env,
+ ((char *)data) + (i_blocksize*i),
lsn + i, b_form2)) )
return retval;
}
return 0;
}
-/*!
- Return the size of the CD in logical block address (LBA) units.
- */
-static uint32_t
-_cdio_stat_size (void *env)
-{
- _img_private_t *_obj = env;
-
- struct cdrom_tocentry tocent;
- uint32_t size;
-
- tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK;
- tocent.cdte_format = CDROM_LBA;
- if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
- {
- perror ("ioctl(CDROMREADTOCENTRY)");
- exit (EXIT_FAILURE);
- }
-
- size = tocent.cdte_addr.lba;
-
- return size;
-}
-
-/*!
- Set the arg "key" with "value" in the source device.
- Currently "source" and "access-mode" are valid keys.
- "source" sets the source device in I/O operations
- "access-mode" sets the the method of CD access
-
- 0 is returned if no error was found, and nonzero if there as an error.
-*/
-static int
-_cdio_set_arg (void *env, const char key[], const char value[])
-{
- _img_private_t *_obj = env;
-
- if (!strcmp (key, "source"))
- {
- if (!value)
- return -2;
-
- free (_obj->gen.source_name);
-
- _obj->gen.source_name = strdup (value);
- }
- else if (!strcmp (key, "access-mode"))
- {
- if (!strcmp(value, "IOCTL"))
- _obj->access_mode = _AM_IOCTL;
- else if (!strcmp(value, "READ_CD"))
- _obj->access_mode = _AM_READ_CD;
- else if (!strcmp(value, "READ_10"))
- _obj->access_mode = _AM_READ_10;
- else {
- cdio_warn ("unknown access type: %s. ignored.", value);
- }
- }
- else
- return -1;
-
- return 0;
-}
-
/*!
Read and cache the CD's Track Table of Contents and track info.
Return false if successful or true if an error.
*/
static bool
-_cdio_read_toc (_img_private_t *_obj)
+read_toc_linux (void *p_user_data)
{
+ _img_private_t *p_env = p_user_data;
int i;
/* read TOC header */
- if ( ioctl(_obj->gen.fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) {
- cdio_error("%s: %s\n",
+ if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) {
+ cdio_warn("%s: %s\n",
"error in ioctl CDROMREADTOCHDR", strerror(errno));
return false;
}
+ p_env->gen.i_first_track = p_env->tochdr.cdth_trk0;
+ p_env->gen.i_tracks = p_env->tochdr.cdth_trk1;
+
/* read individual tracks */
- for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) {
- _obj->tocent[i-1].cdte_track = i;
- _obj->tocent[i-1].cdte_format = CDROM_MSF;
- if ( ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) {
- cdio_error("%s %d: %s\n",
+ for (i= p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++) {
+ p_env->tocent[i-p_env->gen.i_first_track].cdte_track = i;
+ p_env->tocent[i-p_env->gen.i_first_track].cdte_format = CDROM_MSF;
+ if ( ioctl(p_env->gen.fd, CDROMREADTOCENTRY,
+ &p_env->tocent[i-p_env->gen.i_first_track]) == -1 ) {
+ cdio_warn("%s %d: %s\n",
"error in ioctl CDROMREADTOCENTRY for track",
i, strerror(errno));
return false;
}
/****
- struct cdrom_msf0 *msf= &_obj->tocent[i-1].cdte_addr.msf;
+ struct cdrom_msf0 *msf= &env->tocent[i-1].cdte_addr.msf;
fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n",
i, msf->minute, msf->second, msf->frame);
@@ -639,282 +842,120 @@ _cdio_read_toc (_img_private_t *_obj)
}
/* read the lead-out track */
- _obj->tocent[TOTAL_TRACKS].cdte_track = CDIO_CDROM_LEADOUT_TRACK;
- _obj->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF;
+ p_env->tocent[p_env->gen.i_tracks].cdte_track = CDIO_CDROM_LEADOUT_TRACK;
+ p_env->tocent[p_env->gen.i_tracks].cdte_format = CDROM_MSF;
- if (ioctl(_obj->gen.fd, CDROMREADTOCENTRY,
- &_obj->tocent[TOTAL_TRACKS]) == -1 ) {
- cdio_error("%s: %s\n",
+ if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY,
+ &p_env->tocent[p_env->gen.i_tracks]) == -1 ) {
+ cdio_warn("%s: %s\n",
"error in ioctl CDROMREADTOCENTRY for lead-out",
strerror(errno));
return false;
}
/*
- struct cdrom_msf0 *msf= &_obj->tocent[TOTAL_TRACKS].cdte_addr.msf;
+ struct cdrom_msf0 *msf= &env->tocent[p_env->gen.i_tracks].cdte_addr.msf;
fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n",
i, msf->minute, msf->second, msf->frame);
*/
- _obj->gen.toc_init = true;
+ p_env->gen.toc_init = true;
return true;
}
-/*
- * Eject using SCSI commands. Return 1 if successful, 0 otherwise.
- */
-static int
-_cdio_eject_scsi(int fd)
-{
- int status;
- struct sdata {
- int inlen;
- int outlen;
- char cmd[256];
- } scsi_cmd;
-
- scsi_cmd.inlen = 0;
- scsi_cmd.outlen = 0;
- scsi_cmd.cmd[0] = ALLOW_MEDIUM_REMOVAL;
- scsi_cmd.cmd[1] = 0;
- scsi_cmd.cmd[2] = 0;
- scsi_cmd.cmd[3] = 0;
- scsi_cmd.cmd[4] = 0;
- scsi_cmd.cmd[5] = 0;
- status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
- if (status != 0)
- return 0;
-
- scsi_cmd.inlen = 0;
- scsi_cmd.outlen = 0;
- scsi_cmd.cmd[0] = START_STOP;
- scsi_cmd.cmd[1] = 0;
- scsi_cmd.cmd[2] = 0;
- scsi_cmd.cmd[3] = 0;
- scsi_cmd.cmd[4] = 1;
- scsi_cmd.cmd[5] = 0;
- status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
- if (status != 0)
- return 0;
-
- scsi_cmd.inlen = 0;
- scsi_cmd.outlen = 0;
- scsi_cmd.cmd[0] = START_STOP;
- scsi_cmd.cmd[1] = 0;
- scsi_cmd.cmd[2] = 0;
- scsi_cmd.cmd[3] = 0;
- scsi_cmd.cmd[4] = 2;
- scsi_cmd.cmd[5] = 0;
- status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
- if (status != 0)
- return 0;
-
- /* force kernel to reread partition table when new disc inserted */
- status = ioctl(fd, BLKRRPART);
- return (status == 0);
-}
-
/*!
- Eject media in CD drive.
- Return 0 if success and 1 for failure, and 2 if no routine.
+ Run a SCSI MMC command.
+
+ cdio CD structure set by cdio_open().
+ i_timeout time in milliseconds we will wait for the command
+ to complete. If this value is -1, use the default
+ time-out value.
+ p_buf Buffer for data, both sending and receiving
+ i_buf Size of buffer
+ e_direction direction the transfer is to go.
+ cdb CDB bytes. All values that are needed should be set on
+ input. We'll figure out what the right CDB length should be.
+
+ We return true if command completed successfully and false if not.
*/
-static int
-_cdio_eject_media (void *env) {
-
- _img_private_t *_obj = env;
- int ret=2;
- int status;
- int fd;
-
- close(_obj->gen.fd);
- _obj->gen.fd = -1;
- if ((fd = open (_obj->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) {
- if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) {
- switch(status) {
- case CDS_TRAY_OPEN:
- if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) {
- cdio_error ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno));
- ret = 1;
- }
- break;
- case CDS_DISC_OK:
- if((ret = ioctl(fd, CDROMEJECT)) != 0) {
- int eject_error = errno;
- /* Try ejecting the SCSI way... */
- ret = _cdio_eject_scsi(fd);
- if (0 != ret) {
- cdio_error("ioctl CDROMEJECT failed: %s\n", strerror(eject_error));
- ret = 1;
- }
- }
- break;
- default:
- cdio_error ("Unknown CD-ROM (%d)\n", status);
- ret = 1;
- }
- } else {
- cdio_error ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno));
- ret=1;
- }
- close(fd);
- return ret;
- }
- return 2;
-}
-
-/*!
- Return the value associated with the key "arg".
-*/
-static const char *
-_cdio_get_arg (void *env, const char key[])
+static int
+run_scsi_cmd_linux( const void *p_user_data,
+ unsigned int i_timeout_ms,
+ unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb,
+ scsi_mmc_direction_t e_direction,
+ unsigned int i_buf, /*in/out*/ void *p_buf )
{
- _img_private_t *_obj = env;
-
- if (!strcmp (key, "source")) {
- return _obj->gen.source_name;
- } else if (!strcmp (key, "access-mode")) {
- switch (_obj->access_mode) {
- case _AM_IOCTL:
- return "ioctl";
- case _AM_READ_CD:
- return "READ_CD";
- case _AM_READ_10:
- return "READ_10";
- case _AM_NONE:
- return "no access method";
- }
- }
- return NULL;
-}
+ const _img_private_t *p_env = p_user_data;
+ struct cdrom_generic_command cgc;
+ memset (&cgc, 0, sizeof (struct cdrom_generic_command));
+ memcpy(&cgc.cmd, p_cdb, i_cdb);
+ cgc.buflen = i_buf;
+ cgc.buffer = p_buf;
+ cgc.data_direction = (SCSI_MMC_DATA_READ == cgc.data_direction)
+ ? CGC_DATA_READ : CGC_DATA_WRITE;
-/*!
- Return the number of of the first track.
- CDIO_INVALID_TRACK is returned on error.
-*/
-static track_t
-_cdio_get_first_track_num(void *env)
-{
- _img_private_t *_obj = env;
-
- if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ;
+#ifdef HAVE_LINUX_CDROM_TIMEOUT
+ cgc.timeout = i_timeout_ms;
+#endif
- return FIRST_TRACK_NUM;
+ return ioctl (p_env->gen.fd, CDROM_SEND_PACKET, &cgc);
}
/*!
- Return the media catalog number MCN.
-
- Note: string is malloc'd so caller should free() then returned
- string when done with it.
-
+ Return the size of the CD in logical block address (LBA) units.
*/
-static char *
-_cdio_get_mcn (void *env) {
-
- struct cdrom_mcn mcn;
- _img_private_t *_obj = env;
- memset(&mcn, 0, sizeof(mcn));
- if (ioctl(_obj->gen.fd, CDROM_GET_MCN, &mcn) != 0)
- return NULL;
- return strdup(mcn.medium_catalog_number);
-}
-
-/*!
- Return the number of tracks in the current medium.
- CDIO_INVALID_TRACK is returned on error.
-*/
-static track_t
-_cdio_get_num_tracks(void *env)
+static uint32_t
+stat_size_linux (void *p_user_data)
{
- _img_private_t *_obj = env;
-
- if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ;
+ _img_private_t *p_env = p_user_data;
- return TOTAL_TRACKS;
-}
+ struct cdrom_tocentry tocent;
+ uint32_t size;
-/*!
- Get format of track.
-*/
-static track_format_t
-_cdio_get_track_format(void *env, track_t track_num)
-{
- _img_private_t *_obj = env;
-
- if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ;
+ tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK;
+ tocent.cdte_format = CDROM_LBA;
+ if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
+ {
+ perror ("ioctl(CDROMREADTOCENTRY)");
+ exit (EXIT_FAILURE);
+ }
- if (track_num > TOTAL_TRACKS || track_num == 0)
- return TRACK_FORMAT_ERROR;
+ size = tocent.cdte_addr.lba;
- /* This is pretty much copied from the "badly broken" cdrom_count_tracks
- in linux/cdrom.c.
- */
- if (_obj->tocent[track_num-1].cdte_ctrl & CDROM_DATA_TRACK) {
- if (_obj->tocent[track_num-1].cdte_format == 0x10)
- return TRACK_FORMAT_CDI;
- else if (_obj->tocent[track_num-1].cdte_format == 0x20)
- return TRACK_FORMAT_XA;
- else
- return TRACK_FORMAT_DATA;
- } else
- return TRACK_FORMAT_AUDIO;
-
+ return size;
}
/*!
- Return true if we have XA data (green, mode2 form1) or
- XA data (green, mode2 form2). That is track begins:
- sync - header - subheader
- 12 4 - 8
-
- FIXME: there's gotta be a better design for this and get_track_format?
-*/
-static bool
-_cdio_get_track_green(void *env, track_t track_num)
-{
- _img_private_t *_obj = env;
-
- if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ;
-
- if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1;
-
- if (track_num > TOTAL_TRACKS+1 || track_num == 0)
- return false;
-
- /* FIXME: Dunno if this is the right way, but it's what
- I was using in cdinfo for a while.
- */
- return ((_obj->tocent[track_num-1].cdte_ctrl & 2) != 0);
-}
+ Set the arg "key" with "value" in the source device.
+ Currently "source" and "access-mode" are valid keys.
+ "source" sets the source device in I/O operations
+ "access-mode" sets the the method of CD access
-/*!
- Return the starting MSF (minutes/secs/frames) for track number
- track_num in obj. Track numbers start at 1.
- The "leadout" track is specified either by
- using track_num LEADOUT_TRACK or the total tracks+1.
- False is returned if there is no track entry.
+ 0 is returned if no error was found, and nonzero if there as an error.
*/
-static bool
-_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf)
+static int
+set_arg_linux (void *p_user_data, const char key[], const char value[])
{
- _img_private_t *_obj = env;
-
- if (NULL == msf) return false;
+ _img_private_t *p_env = p_user_data;
- if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ;
+ if (!strcmp (key, "source"))
+ {
+ if (!value)
+ return -2;
- if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1;
+ free (p_env->gen.source_name);
+
+ p_env->gen.source_name = strdup (value);
+ }
+ else if (!strcmp (key, "access-mode"))
+ {
+ return str_to_access_mode_linux(value);
+ }
+ else
+ return -1;
- if (track_num > TOTAL_TRACKS+1 || track_num == 0) {
- return false;
- } else {
- struct cdrom_msf0 *msf0= &_obj->tocent[track_num-1].cdte_addr.msf;
- msf->m = to_bcd8(msf0->minute);
- msf->s = to_bcd8(msf0->second);
- msf->f = to_bcd8(msf0->frame);
- return true;
- }
+ return 0;
}
/* checklist: /dev/cdrom, /dev/dvd /dev/hd?, /dev/scd? /dev/sr? */
@@ -947,19 +988,19 @@ cdio_get_devices_linux (void)
*/
for ( i=0; strlen(checklist1[i]) > 0; ++i ) {
sprintf(drive, "/dev/%s", checklist1[i]);
- if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) {
+ if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
cdio_add_device_list(&drives, drive, &num_drives);
}
}
/* Now check the currently mounted CD drives */
- if (NULL != (ret_drive = cdio_check_mounts("/etc/mtab"))) {
+ if (NULL != (ret_drive = check_mounts_linux("/etc/mtab"))) {
cdio_add_device_list(&drives, ret_drive, &num_drives);
free(ret_drive);
}
/* Finally check possible mountable drives in /etc/fstab */
- if (NULL != (ret_drive = cdio_check_mounts("/etc/fstab"))) {
+ if (NULL != (ret_drive = check_mounts_linux("/etc/fstab"))) {
cdio_add_device_list(&drives, ret_drive, &num_drives);
free(ret_drive);
}
@@ -977,7 +1018,7 @@ cdio_get_devices_linux (void)
if ( insert != NULL ) {
*insert = j;
}
- if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) {
+ if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
cdio_add_device_list(&drives, drive, &num_drives);
}
}
@@ -1006,17 +1047,17 @@ cdio_get_default_device_linux(void)
*/
for ( i=0; strlen(checklist1[i]) > 0; ++i ) {
sprintf(drive, "/dev/%s", checklist1[i]);
- if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) {
+ if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
return strdup(drive);
}
}
/* Now check the currently mounted CD drives */
- if (NULL != (ret_drive = cdio_check_mounts("/etc/mtab")))
+ if (NULL != (ret_drive = check_mounts_linux("/etc/mtab")))
return ret_drive;
/* Finally check possible mountable drives in /etc/fstab */
- if (NULL != (ret_drive = cdio_check_mounts("/etc/fstab")))
+ if (NULL != (ret_drive = check_mounts_linux("/etc/fstab")))
return ret_drive;
/* Scan the system for CD-ROM drives.
@@ -1032,7 +1073,7 @@ cdio_get_default_device_linux(void)
if ( insert != NULL ) {
*insert = j;
}
- if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) {
+ if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
return(strdup(drive));
}
}
@@ -1046,57 +1087,91 @@ cdio_get_default_device_linux(void)
ones to set that up.
*/
CdIo *
-cdio_open_linux (const char *orig_source_name)
+cdio_open_linux (const char *psz_source_name)
+{
+ return cdio_open_am_linux(psz_source_name, NULL);
+}
+
+/*!
+ Initialization routine. This is the only thing that doesn't
+ get called via a function pointer. In fact *we* are the
+ ones to set that up.
+ */
+CdIo *
+cdio_open_am_linux (const char *psz_orig_source, const char *access_mode)
{
#ifdef HAVE_LINUX_CDROM
CdIo *ret;
_img_private_t *_data;
- char *source_name;
+ char *psz_source;
cdio_funcs _funcs = {
- .eject_media = _cdio_eject_media,
+ .eject_media = eject_media_linux,
.free = cdio_generic_free,
- .get_arg = _cdio_get_arg,
- .get_devices = cdio_get_devices_linux,
+ .get_arg = get_arg_linux,
+ .get_cdtext = get_cdtext_generic,
.get_default_device = cdio_get_default_device_linux,
- .get_first_track_num= _cdio_get_first_track_num,
- .get_mcn = _cdio_get_mcn,
- .get_num_tracks = _cdio_get_num_tracks,
- .get_track_format = _cdio_get_track_format,
- .get_track_green = _cdio_get_track_green,
+ .get_devices = cdio_get_devices_linux,
+ .get_discmode = get_discmode_linux,
+#if USE_LINUX_CAP
+ .get_drive_cap = get_drive_cap_linux,
+#else
+ .get_drive_cap = scsi_mmc_get_drive_cap_generic,
+#endif
+ .get_first_track_num= get_first_track_num_generic,
+ .get_hwinfo = NULL,
+ .get_mcn = get_mcn_linux,
+ .get_num_tracks = get_num_tracks_generic,
+ .get_track_format = get_track_format_linux,
+ .get_track_green = get_track_green_linux,
.get_track_lba = NULL, /* This could be implemented if need be. */
- .get_track_msf = _cdio_get_track_msf,
+ .get_track_msf = get_track_msf_linux,
.lseek = cdio_generic_lseek,
.read = cdio_generic_read,
- .read_audio_sectors = _cdio_read_audio_sectors,
- .read_mode1_sector = _cdio_read_mode1_sector,
- .read_mode1_sectors = _cdio_read_mode1_sectors,
- .read_mode2_sector = _cdio_read_mode2_sector,
- .read_mode2_sectors = _cdio_read_mode2_sectors,
- .set_arg = _cdio_set_arg,
- .stat_size = _cdio_stat_size
+ .read_audio_sectors = _read_audio_sectors_linux,
+ .read_mode1_sector = _read_mode1_sector_linux,
+ .read_mode1_sectors = _read_mode1_sectors_linux,
+ .read_mode2_sector = _read_mode2_sector_linux,
+ .read_mode2_sectors = _read_mode2_sectors_linux,
+ .read_toc = read_toc_linux,
+ .run_scsi_mmc_cmd = run_scsi_cmd_linux,
+ .set_arg = set_arg_linux,
+ .stat_size = stat_size_linux
};
_data = _cdio_malloc (sizeof (_img_private_t));
- _data->access_mode = _AM_READ_CD;
+
+ _data->access_mode = str_to_access_mode_linux(access_mode);
_data->gen.init = false;
+ _data->gen.toc_init = false;
_data->gen.fd = -1;
+ _data->gen.b_cdtext_init = false;
+ _data->gen.b_cdtext_error = false;
+
+ if (NULL == psz_orig_source) {
+ psz_source=cdio_get_default_device_linux();
+ if (NULL == psz_source) return NULL;
+ set_arg_linux(_data, "source", psz_source);
+ free(psz_source);
+ } else {
+ if (cdio_is_device_generic(psz_orig_source))
+ set_arg_linux(_data, "source", psz_orig_source);
+ else {
+ /* The below would be okay if all device drivers worked this way. */
+#if 0
+ cdio_info ("source %s is not a device", psz_orig_source);
+#endif
+ return NULL;
+ }
+ }
- if (NULL == orig_source_name) {
- source_name=cdio_get_default_device_linux();
- if (NULL == source_name) return NULL;
- _cdio_set_arg(_data, "source", source_name);
- free(source_name);
- } else
- _cdio_set_arg(_data, "source", orig_source_name);
-
- ret = cdio_new (_data, &_funcs);
+ ret = cdio_new ((void *)_data, &_funcs);
if (ret == NULL) return NULL;
- if (cdio_generic_init(_data))
+ if (cdio_generic_init(_data)) {
return ret;
- else {
+ } else {
cdio_generic_free (_data);
return NULL;
}
@@ -1116,5 +1191,3 @@ cdio_have_linux (void)
return false;
#endif /* HAVE_LINUX_CDROM */
}
-
-