diff options
Diffstat (limited to 'src/input/vcd/libcdio/_cdio_bsdi.c')
-rw-r--r-- | src/input/vcd/libcdio/_cdio_bsdi.c | 475 |
1 files changed, 282 insertions, 193 deletions
diff --git a/src/input/vcd/libcdio/_cdio_bsdi.c b/src/input/vcd/libcdio/_cdio_bsdi.c index 7fd60a9d9..aef535752 100644 --- a/src/input/vcd/libcdio/_cdio_bsdi.c +++ b/src/input/vcd/libcdio/_cdio_bsdi.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_bsdi.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: _cdio_bsdi.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,8 +27,9 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; +#include <cdio/logging.h> #include <cdio/sector.h> #include <cdio/util.h> #include "cdio_assert.h" @@ -54,31 +55,109 @@ static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.2 2004/04/11 12:20:31 miguel #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> +#include </sys/dev/scsi/scsi.h> +#include </sys/dev/scsi/scsi_ioctl.h> +#include "cdtext_private.h" -#define TOTAL_TRACKS (_obj->tochdr.cdth_trk1) -#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0) +typedef enum { + _AM_NONE, + _AM_IOCTL, +} 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, - } access_mode; - - char *source_name; - - bool init; + access_mode_t access_mode; + /* Some of the more OS specific things. */ /* Track information */ - bool toc_init; /* if true, info below is valid. */ struct cdrom_tochdr tochdr; - struct cdrom_tocentry tocent[100]; /* entry info for each track */ + struct cdrom_tocentry tocent[CDIO_CD_MAX_TRACKS+1]; } _img_private_t; +/* Define the Cdrom Generic Command structure */ +typedef struct cgc +{ + scsi_mmc_cdb_t cdb; + u_char *buf; + int buflen; + int rw; + unsigned int timeout; + scsi_user_sense_t *sus; +} cgc_t; + + +/* + This code adapted from Steven M. Schultz's libdvd +*/ +static int +run_scsi_cmd_bsdi(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 ) +{ + const _img_private_t *p_env = p_user_data; + int i_status, i_asc; + struct scsi_user_cdb suc; + struct scsi_sense *sp; + + again: + suc.suc_flags = SCSI_MMC_DATA_READ == e_direction ? + SUC_READ : SUC_WRITE; + suc.suc_cdblen = i_cdb; + memcpy(suc.suc_cdb, p_cdb, i_cdb); + suc.suc_data = p_buf; + suc.suc_datalen = i_buf; + suc.suc_timeout = msecs2secs(i_timeout_ms); + if (ioctl(p_env->gen.fd, SCSIRAWCDB, &suc) == -1) + return(errno); + i_status = suc.suc_sus.sus_status; + +#if 0 + /* + * If the device returns a scsi sense error and debugging is enabled print + * some hopefully useful information on stderr. + */ + if (i_status && debug) + { + unsigned char *cp; + int i; + cp = suc.suc_sus.sus_sense; + fprintf(stderr,"i_status = %x cdb =", + i_status); + for (i = 0; i < cdblen; i++) + fprintf(stderr, " %x", cgc->cdb[i]); + fprintf(stderr, "\nsense ="); + for (i = 0; i < 16; i++) + fprintf(stderr, " %x", cp[i]); + fprintf(stderr, "\n"); + } +#endif + + /* + * HACK! Some drives return a silly "medium changed" on the first + * command AND a non-zero i_status which gets turned into a fatal + * (EIO) error even though the operation was a success. Retrying + * the operation clears the media changed status and gets the + * answer. */ + + sp = (struct scsi_sense *)&suc.suc_sus.sus_sense; + i_asc = XSENSE_ASC(sp); + if (i_status == STS_CHECKCOND && i_asc == 0x28) + goto again; +#if 0 + if (cgc->sus) + memcpy(cgc->sus, &suc.suc_sus, sizeof (struct scsi_user_sense)); +#endif + + return(i_status); +} + + + /* 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 . @@ -119,68 +198,68 @@ cdio_is_cdrom(char *drive, char *mnttype) Initialize CD device. */ static bool -_cdio_init (_img_private_t *_obj) +_cdio_init (_img_private_t *p_env) { - if (_obj->gen.init) { - cdio_error ("init called more than once"); + if (p_env->gen.init) { + cdio_warn ("init called more than once"); return false; } - _obj->gen.fd = open (_obj->source_name, O_RDONLY, 0); + p_env->gen.fd = open (p_env->gen.source_name, O_RDONLY, 0); - if (_obj->gen.fd < 0) + if (p_env->gen.fd < 0) { - cdio_error ("open (%s): %s", _obj->source_name, strerror (errno)); + cdio_warn ("open (%s): %s", p_env->gen.source_name, strerror (errno)); return false; } - _obj->gen.init = true; - _obj->toc_init = false; + p_env->gen.init = true; + p_env->gen.toc_init = false; return true; } /* Read audio sectors */ static int -_read_audio_sectors (void *env, void *data, lsn_t lsn, - unsigned int nblocks) +_read_audio_sectors_bsdi (void *user_data, void *data, lsn_t lsn, + unsigned int nblocks) { char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; struct cdrom_msf *msf = (struct cdrom_msf *) &buf; msf_t _msf; - _img_private_t *_obj = env; + _img_private_t *p_env = 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); - if (_obj->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (_obj->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (_obj->gen.ioctls_debugged < 75 - || (_obj->gen.ioctls_debugged < (30 * 75) - && _obj->gen.ioctls_debugged % 75 == 0) - || _obj->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %2.2d:%2.2d:%2.2d", msf->cdmsf_min0, msf->cdmsf_sec0, msf->cdmsf_frame0); - _obj->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; - switch (_obj->access_mode) { + switch (p_env->access_mode) { case _AM_NONE: - cdio_error ("no way to read audio"); + cdio_warn ("no way to read audio"); return 1; break; case _AM_IOCTL: { unsigned int i; for (i=0; i < nblocks; i++) { - if (ioctl (_obj->gen.fd, CDROMREADRAW, &buf) == -1) { + if (ioctl (p_env->gen.fd, CDROMREADRAW, &buf) == -1) { perror ("ioctl()"); return 1; /* exit (EXIT_FAILURE); */ @@ -200,19 +279,15 @@ _read_audio_sectors (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, +_read_mode1_sector_bsdi (void *user_data, void *data, lsn_t lsn, bool b_form2) { - char buf[M2RAW_SECTOR_SIZE] = { 0, }; #if FIXED + char buf[M2RAW_SECTOR_SIZE] = { 0, }; do something here. #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(user_data, data, lsn); #endif return 0; } @@ -223,16 +298,16 @@ _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_bsdi (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *p_env = 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, + if ( (retval = _read_mode1_sector_bsdi (p_env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; @@ -245,44 +320,44 @@ _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, +_read_mode2_sector_bsdi (void *user_data, void *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 = 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); - if (_obj->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (_obj->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (_obj->gen.ioctls_debugged < 75 - || (_obj->gen.ioctls_debugged < (30 * 75) - && _obj->gen.ioctls_debugged % 75 == 0) - || _obj->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %2.2d:%2.2d:%2.2d", msf->cdmsf_min0, msf->cdmsf_sec0, msf->cdmsf_frame0); - _obj->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; - 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; @@ -305,27 +380,20 @@ _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_bsdi (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; - int i; - int retval; + _img_private_t *p_env = user_data; + unsigned int i; + 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 (b_form2) { - if ( (retval = _cdio_read_mode2_sector (_obj, - ((char *)data) + (M2RAW_SECTOR_SIZE * i), - lsn + i, true)) ) - return retval; - } else { - char buf[M2RAW_SECTOR_SIZE] = { 0, }; - if ( (retval = _cdio_read_mode2_sector (_obj, buf, lsn + i, true)) ) - return retval; - - memcpy (((char *)data) + (CDIO_CD_FRAMESIZE * i), - buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); - } + int retval = _read_mode2_sector_bsdi(p_env, + ((char *)data) + + (i_blocksize * i), + lsn + i, b_form2); + if (retval) return retval; } return 0; } @@ -334,16 +402,16 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *env) +_stat_size_bsdi (void *user_data) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; 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) + if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) { perror ("ioctl(CDROMREADTOCENTRY)"); exit (EXIT_FAILURE); @@ -358,25 +426,25 @@ _cdio_stat_size (void *env) Set the key "arg" to "value" in source device. */ static int -_cdio_set_arg (void *env, const char key[], const char value[]) +_set_arg_bsdi (void *user_data, const char key[], const char value[]) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; if (!strcmp (key, "source")) { if (!value) return -2; - free (_obj->source_name); + free (p_env->gen.source_name); - _obj->source_name = strdup (value); + p_env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { if (!strcmp(value, "IOCTL")) - _obj->access_mode = _AM_IOCTL; + p_env->access_mode = _AM_IOCTL; else - cdio_error ("unknown access type: %s. ignored.", value); + cdio_warn ("unknown access type: %s. ignored.", value); } else return -1; @@ -389,29 +457,33 @@ _cdio_set_arg (void *env, const char key[], const char value[]) Return false if successful or true if an error. */ static bool -_cdio_read_toc (_img_private_t *_obj) +read_toc_bsdi (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-1].cdte_track = i; + p_env->tocent[i-1].cdte_format = CDROM_MSF; + if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, &p_env->tocent[i-1]) == -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= &p_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); @@ -420,24 +492,25 @@ _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= &p_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); */ + p_env->gen.toc_init = true; return true; } @@ -446,32 +519,32 @@ _cdio_read_toc (_img_private_t *_obj) also free obj. */ static int -_cdio_eject_media (void *env) { +_eject_media_bsdi (void *user_data) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; int ret=2; int status; int fd; - close(_obj->gen.fd); - _obj->gen.fd = -1; - if ((fd = open (_obj->source_name, O_RDONLY|O_NONBLOCK)) > -1) { + close(p_env->gen.fd); + p_env->gen.fd = -1; + if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { if((status = ioctl(fd, CDROM_DRIVE_STATUS, (void *) CDSL_CURRENT)) > 0) { switch(status) { case CDS_TRAY_OPEN: if((ret = ioctl(fd, CDROMCLOSETRAY, 0)) != 0) { - cdio_error ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); + cdio_warn ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); } break; case CDS_DISC_OK: if((ret = ioctl(fd, CDROMEJECT, 0)) != 0) { - cdio_error("ioctl CDROMEJECT failed: %s\n", strerror(errno)); + cdio_warn("ioctl CDROMEJECT failed: %s\n", strerror(errno)); } break; } ret=0; } else { - cdio_error ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); + cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); ret=1; } close(fd); @@ -483,14 +556,14 @@ _cdio_eject_media (void *env) { Return the value associated with the key "arg". */ static const char * -_cdio_get_arg (void *env, const char key[]) +_get_arg_bsdi (void *user_data, const char key[]) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; if (!strcmp (key, "source")) { - return _obj->source_name; + return p_env->gen.source_name; } else if (!strcmp (key, "access-mode")) { - switch (_obj->access_mode) { + switch (p_env->access_mode) { case _AM_IOCTL: return "ioctl"; case _AM_NONE: @@ -501,68 +574,42 @@ _cdio_get_arg (void *env, const char key[]) } /*! - 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->toc_init) _cdio_read_toc (_obj) ; - - return FIRST_TRACK_NUM; -} - -/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned string when done with it. */ static char * -_cdio_get_mcn (void *env) { +_get_mcn_bsdi (const void *user_data) { struct cdrom_mcn mcn; - _img_private_t *_obj = env; - if (ioctl(_obj->gen.fd, CDROM_GET_MCN, &mcn) != 0) + const _img_private_t *p_env = user_data; + if (ioctl(p_env->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) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - return TOTAL_TRACKS; -} - /*! Get format of track. */ static track_format_t -_cdio_get_track_format(void *env, track_t track_num) +get_track_format_bsdi(void *user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; - if (track_num > TOTAL_TRACKS || track_num == 0) + if (i_track > p_env->gen.i_tracks || i_track == 0) return TRACK_FORMAT_ERROR; + i_track -= p_env->gen.i_first_track; + /* 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) + if (p_env->tocent[i_track].cdte_ctrl & CDROM_DATA_TRACK) { + if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK) return TRACK_FORMAT_CDI; - else if (_obj->tocent[track_num-1].cdte_format == 0x20) + else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK) return TRACK_FORMAT_XA; else return TRACK_FORMAT_DATA; @@ -580,48 +627,52 @@ _cdio_get_track_format(void *env, track_t track_num) 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) +_get_track_green_bsdi(void *user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) + if (i_track > p_env->gen.i_tracks+1 || i_track == 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); + return ((p_env->tocent[i_track-1].cdte_ctrl & 2) != 0); } /*! Return the starting MSF (minutes/secs/frames) for track number - track_num in obj. Track numbers start at 1. + i_track in obj. Track numbers start at 1. The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. + using i_track LEADOUT_TRACK or the total tracks+1. False is returned if there is no track entry. */ static bool -_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) +_get_track_msf_bsdi(void *user_data, track_t i_track, msf_t *msf) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; if (NULL == msf) return false; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) { + if (i_track > p_env->gen.i_tracks+1 || i_track == 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); + } + + i_track -= p_env->gen.i_first_track; + + { + struct cdrom_msf0 *msf0= &p_env->tocent[i_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; } } @@ -690,46 +741,85 @@ cdio_get_default_device_bsdi(void) ones to set that up. */ CdIo * -cdio_open_bsdi (const char *source_name) +cdio_open_am_bsdi (const char *psz_source_name, const char *psz_access_mode) +{ + if (psz_access_mode != NULL) + cdio_warn ("there is only one access mode for bsdi. Arg %s ignored", + psz_access_mode); + return cdio_open_bsdi(psz_source_name); +} + + +/*! + 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_bsdi (const char *psz_orig_source) { #ifdef HAVE_BSDI_CDROM CdIo *ret; _img_private_t *_data; + char *psz_source; cdio_funcs _funcs = { - .eject_media = _cdio_eject_media, + .eject_media = _eject_media_bsdi, .free = cdio_generic_free, - .get_arg = _cdio_get_arg, + .get_arg = _get_arg_bsdi, + .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_bsdi, .get_devices = cdio_get_devices_bsdi, - .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_drive_cap = scsi_mmc_get_drive_cap_generic, + .get_discmode = get_discmode_generic, + .get_first_track_num= get_first_track_num_generic, + .get_hwinfo = NULL, + .get_mcn = _get_mcn_bsdi, + .get_num_tracks = get_num_tracks_generic, + .get_track_format = get_track_format_bsdi, + .get_track_green = _get_track_green_bsdi, .get_track_lba = NULL, /* This could be implemented if need be. */ - .get_track_msf = _cdio_get_track_msf, + .get_track_msf = _get_track_msf_bsdi, .lseek = cdio_generic_lseek, .read = cdio_generic_read, - .read_audio_sectors = _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_bsdi, + .read_mode1_sector = _read_mode1_sector_bsdi, + .read_mode1_sectors = _read_mode1_sectors_bsdi, + .read_mode2_sector = _read_mode2_sector_bsdi, + .read_mode2_sectors = _read_mode2_sectors_bsdi, + .read_toc = &read_toc_bsdi, + .run_scsi_mmc_cmd = &run_scsi_cmd_bsdi, + .set_arg = _set_arg_bsdi, + .stat_size = _stat_size_bsdi }; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = _AM_IOCTL; _data->gen.init = false; _data->gen.fd = -1; + _data->gen.toc_init = false; + _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_bsdi(_data, "source", psz_source); + free(psz_source); + } else { + if (cdio_is_device_generic(psz_orig_source)) + _set_arg_bsdi(_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; + } + } - _cdio_set_arg(_data, "source", (NULL == source_name) - ? DEFAULT_CDIO_DEVICE: source_name); - - ret = cdio_new (_data, &_funcs); + ret = cdio_new ( (void *) _data, &_funcs); if (ret == NULL) return NULL; if (_cdio_init(_data)) @@ -754,4 +844,3 @@ cdio_have_bsdi (void) return false; #endif /* HAVE_BSDI_CDROM */ } - |