diff --git a/include/cdio/Makefile.am b/include/cdio/Makefile.am index fb7d95e8..258b67f8 100644 --- a/include/cdio/Makefile.am +++ b/include/cdio/Makefile.am @@ -1,4 +1,4 @@ -# $Id: Makefile.am,v 1.19 2005/01/05 04:16:11 rocky Exp $ +# $Id: Makefile.am,v 1.20 2005/01/09 16:07:46 rocky Exp $ # # Copyright (C) 2003, 2004 Rocky Bernstein # @@ -37,6 +37,7 @@ libcdioinclude_HEADERS = \ dvd.h \ iso9660.h \ logging.h \ + read.h \ sector.h \ scsi_mmc.h \ track.h \ diff --git a/include/cdio/cdio.h b/include/cdio/cdio.h index 5d3750c0..8142fe5a 100644 --- a/include/cdio/cdio.h +++ b/include/cdio/cdio.h @@ -1,5 +1,5 @@ /* -*- c -*- - $Id: cdio.h,v 1.74 2005/01/05 04:16:11 rocky Exp $ + $Id: cdio.h,v 1.75 2005/01/09 16:07:46 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -30,7 +30,7 @@ /** Application Interface or Protocol version number. If the public * interface changes, we increase this number. */ -#define CDIO_API_VERSION 3 +#define CDIO_API_VERSION 4 #include @@ -67,98 +67,6 @@ extern "C" { */ const char * cdio_get_arg (const CdIo_t *p_cdio, const char key[]); - off_t cdio_lseek(const CdIo_t *p_cdio, off_t offset, int whence); - - /*! - Reads into buf the next size bytes. - Similar to (if not the same as) libc's read() - - @return (ssize_t) -1 on error. - */ - ssize_t cdio_read(const CdIo_t *p_cdio, void *buf, size_t size); - - /*! - Read an audio sector - - @param p_cdio object to read from - @param buf place to read data into - @param lsn sector to read - - @return 0 if no error, nonzero otherwise. - */ - int cdio_read_audio_sector (const CdIo_t *p_cdio, void *buf, lsn_t lsn); - - /*! - Reads audio sectors - - @param p_cdio object to read from - @param buf place to read data into - @param lsn sector to read - @param i_sectors number of sectors to read - - @return 0 if no error, nonzero otherwise. - */ - int cdio_read_audio_sectors (const CdIo_t *p_cdio, void *buf, lsn_t lsn, - unsigned int i_sectors); - - /*! - Reads a mode 1 sector - - @param p_cdio object to read from - @param buf place to read data into - @param lsn sector to read - @param b_form2 true for reading mode1 form 2 sectors or false for - mode 1 form 1 sectors. - - @return 0 if no error, nonzero otherwise. - */ - int cdio_read_mode1_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, - bool b_form2); - - /*! - Reads mode 1 sectors - - @param p_cdio object to read from - @param buf place to read data into - @param lsn sector to read - @param b_form2 true for reading mode 1 form 2 sectors or false for - mode 1 form 1 sectors. - @param i_sectors number of sectors to read - - @return 0 if no error, nonzero otherwise. - */ - int cdio_read_mode1_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, - bool b_form2, unsigned int i_sectors); - - /*! - Reads a mode 2 sector - - @param p_cdio object to read from - @param buf place to read data into - @param lsn sector to read - @param b_form2 true for reading mode 2 form 2 sectors or false for - mode 2 form 1 sectors. - - @return 0 if no error, nonzero otherwise. - */ - int cdio_read_mode2_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, - bool b_form2); - - /*! - Reads mode 2 sectors - - @param p_cdio object to read from - @param buf place to read data into - @param lsn sector to read - @param b_form2 true for reading mode2 form 2 sectors or false for - mode 2 form 1 sectors. - @param i_sectors number of sectors to read - - @return 0 if no error, nonzero otherwise. - */ - int cdio_read_mode2_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, - bool b_form2, unsigned int i_sectors); - /*! Set the arg "key" with "value" in "p_cdio". @@ -169,14 +77,6 @@ extern "C" { */ int cdio_set_arg (CdIo_t *p_cdio, const char key[], const char value[]); - /*! - Get the size of the CD in logical block address (LBA) units. - - @param p_cdio the CD object queried - @return the size - */ - uint32_t cdio_stat_size (const CdIo_t *p_cdio); - /*! Initialize CD Reading and control routines. Should be called first. */ @@ -186,6 +86,9 @@ extern "C" { } #endif /* __cplusplus */ +/* Sector (frame, or block)-related functions. */ +#include + /* CD-Text-related functions. */ #include diff --git a/include/cdio/device.h b/include/cdio/device.h index 735be7b2..e8db59fd 100644 --- a/include/cdio/device.h +++ b/include/cdio/device.h @@ -1,5 +1,5 @@ /* -*- c -*- - $Id: device.h,v 1.2 2005/01/05 04:16:11 rocky Exp $ + $Id: device.h,v 1.3 2005/01/09 16:07:46 rocky Exp $ Copyright (C) 2005 Rocky Bernstein @@ -19,8 +19,9 @@ */ /** \file device.h - * \brief The top-level header for driver or device-related libcdio calls. - * ("device" include CD-image reading devices). + * + * \brief The top-level header for driver- or device-related libcdio + * calls. ("device" include CD-image reading devices). */ #ifndef __CDIO_DEVICE_H__ #define __CDIO_DEVICE_H__ @@ -730,4 +731,3 @@ extern "C" { #endif /* __cplusplus */ #endif /* __CDIO_TRACK_H__ */ - diff --git a/include/cdio/disc.h b/include/cdio/disc.h index b3bc1498..f12012bb 100644 --- a/include/cdio/disc.h +++ b/include/cdio/disc.h @@ -1,5 +1,5 @@ /* -*- c -*- - $Id: disc.h,v 1.2 2005/01/04 10:58:03 rocky Exp $ + $Id: disc.h,v 1.3 2005/01/09 16:07:46 rocky Exp $ Copyright (C) 2004, 2005 Rocky Bernstein @@ -71,15 +71,13 @@ extern "C" { track_t cdio_get_num_tracks (const CdIo_t *p_cdio); /*! - Reposition read offset - Similar to (if not the same as) libc's lseek() + Get the size of the CD in logical block address (LBA) units. - @param p_cdio object to get information from - @param offset amount to seek - @param whence like corresponding parameter in libc's lseek, e.g. - SEEK_SET or SEEK_END. - @return (off_t) -1 on error. + @param p_cdio the CD object queried + @return the size or 0 if there was an error. */ + uint32_t cdio_stat_size (const CdIo_t *p_cdio); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/cdio/read.h b/include/cdio/read.h new file mode 100644 index 00000000..eb3214bf --- /dev/null +++ b/include/cdio/read.h @@ -0,0 +1,141 @@ +/* -*- c -*- + $Id: read.h,v 1.1 2005/01/09 16:07:46 rocky Exp $ + + Copyright (C) 2005 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** \file read.h + * + * \brief The top-level header for sector (block, frame)-related + * libcdio calls. + */ + +#ifndef __CDIO_READ_H__ +#define __CDIO_READ_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! + Reposition read offset + Similar to (if not the same as) libc's lseek() + + @param p_cdio object to get information from + @param offset amount to seek + @param whence like corresponding parameter in libc's lseek, e.g. + SEEK_SET or SEEK_END. + @return (off_t) -1 on error. + */ + + off_t cdio_lseek(const CdIo_t *p_cdio, off_t offset, int whence); + + /*! + Reads into buf the next size bytes. + Similar to (if not the same as) libc's read() + + @return (ssize_t) -1 on error. + */ + ssize_t cdio_read(const CdIo_t *p_cdio, void *p_buf, size_t i_size); + + /*! + Read an audio sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + + @return 0 if no error, nonzero otherwise. + */ + int cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn); + + /*! + Reads audio sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. + */ + int cdio_read_audio_sectors (const CdIo_t *p_cdio, void *buf, lsn_t lsn, + unsigned int i_sectors); + + /*! + Reads a mode 1 sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode 1 form 2 sectors or false for + mode 1 form 1 sectors. + + @return 0 if no error, nonzero otherwise. + */ + int cdio_read_mode1_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2); + + /*! + Reads mode 1 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode 1 form 2 sectors or false for + mode 1 form 1 sectors. + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. + */ + int cdio_read_mode1_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2, unsigned int i_sectors); + + /*! + Reads a mode 2 sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode 2 form 2 sectors or false for + mode 2 form 1 sectors. + + @return 0 if no error, nonzero otherwise. + */ + int cdio_read_mode2_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2); + + /*! + Reads mode 2 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode2 form 2 sectors or false for + mode 2 form 1 sectors. + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. + */ + int cdio_read_mode2_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2, unsigned int i_sectors); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_TRACK_H__ */ diff --git a/lib/cdda_interface/interface.c b/lib/cdda_interface/interface.c index 2ae0b385..fae0cb5a 100644 --- a/lib/cdda_interface/interface.c +++ b/lib/cdda_interface/interface.c @@ -1,5 +1,5 @@ /* - $Id: interface.c,v 1.8 2005/01/08 20:39:40 rocky Exp $ + $Id: interface.c,v 1.9 2005/01/09 16:07:46 rocky Exp $ Copyright (C) 2005 Rocky Bernstein Copyright (C) 1998 Monty xiphmont@mit.edu @@ -110,7 +110,8 @@ cdda_open(cdrom_drive_t *d) return(ret); /* d->select_speed(d,d->maxspeed); most drives are full speed by default */ - if(d->bigendianp==-1)d->bigendianp=data_bigendianp(d); + // if (d->bigendianp==-1) + d->bigendianp=data_bigendianp(d); return(0); } diff --git a/lib/driver/Makefile.am b/lib/driver/Makefile.am index df89e9fc..ba978662 100644 --- a/lib/driver/Makefile.am +++ b/lib/driver/Makefile.am @@ -1,4 +1,4 @@ -# $Id: Makefile.am,v 1.3 2005/01/04 04:33:36 rocky Exp $ +# $Id: Makefile.am,v 1.4 2005/01/09 16:07:46 rocky Exp $ # # Copyright (C) 2003, 2004 Rocky Bernstein # @@ -66,6 +66,7 @@ libcdio_sources = \ cdio.c \ cdtext.c \ cdtext_private.h \ + device.c \ disc.c \ ds.c \ FreeBSD/freebsd.c \ @@ -86,6 +87,7 @@ libcdio_sources = \ MSWindows/win32.c \ MSWindows/win32.h \ logging.c \ + read.c \ scsi_mmc.c \ scsi_mmc_private.h \ sector.c \ diff --git a/lib/driver/cdio.c b/lib/driver/cdio.c index 56d6423b..644c9074 100644 --- a/lib/driver/cdio.c +++ b/lib/driver/cdio.c @@ -1,5 +1,5 @@ /* - $Id: cdio.c,v 1.7 2005/01/09 00:12:21 rocky Exp $ + $Id: cdio.c,v 1.8 2005/01/09 16:07:46 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -29,278 +29,13 @@ #ifdef HAVE_UNISTD_H #include #endif -#include -#include #include "cdio_assert.h" #include -#include #include -#include #include "cdio_private.h" -static const char _rcsid[] = "$Id: cdio.c,v 1.7 2005/01/09 00:12:21 rocky Exp $"; - - -const char *track_format2str[6] = - { - "audio", "CD-i", "XA", "data", "PSX", "error" - }; - -/* Must match discmode enumeration */ -const char *discmode2str[] = { - "CD-DA", - "CD-DATA (Mode 1)", - "CD DATA (Mode 2)", - "CD-ROM Mixed", - "DVD-ROM", - "DVD-RAM", - "DVD-R", - "DVD-RW", - "DVD+R", - "DVD+RW", - "Unknown/unclassified DVD", - "No information", - "Error in getting information", - "CD-i" -}; - - -/* The below array gives of the drivers that are currently available for - on a particular host. */ - -CdIo_driver_t CdIo_driver[CDIO_MAX_DRIVER] = { {0} }; - -/* The last valid entry of Cdio_driver. - -1 or (CDIO_DRIVER_UNINIT) means uninitialzed. - -2 means some sort of error. -*/ - -#define CDIO_DRIVER_UNINIT -1 -int CdIo_last_driver = CDIO_DRIVER_UNINIT; - -#ifdef HAVE_AIX_CDROM -const driver_id_t cdio_os_driver = DRIVER_AIX; -#elif HAVE_BSDI_CDROM -const driver_id_t cdio_os_driver = DRIVER_BSDI; -#elif HAVE_FREEBSD_CDROM -const driver_id_t cdio_os_driver = DRIVER_FREEBSD; -#elif HAVE_LINUX_CDROM -const driver_id_t cdio_os_driver = DRIVER_LINUX; -#elif HAVE_DARWIN_CDROM -const driver_id_t cdio_os_driver = DRIVER_OSX; -#elif HAVE_DARWIN_SOLARIS -const driver_id_t cdio_os_driver = DRIVER_SOLARIS; -#elif HAVE_DARWIN_WIN32 -const driver_id_t cdio_os_driver = DRIVER_WIN32; -#else -const driver_id_t cdio_os_driver = DRIVER_UNKNOWN; -#endif - -static bool -cdio_have_false(void) -{ - return false; -} - -/* The below array gives all drivers that can possibly appear. - on a particular host. */ - -CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { - {DRIVER_UNKNOWN, - 0, - "Unknown", - "No driver", - &cdio_have_false, - NULL, - NULL, - NULL, - NULL, - NULL - }, - - {DRIVER_BSDI, - CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, - "AIX", - "AIX SCSI driver", - &cdio_have_aix, - &cdio_open_aix, - &cdio_open_am_aix, - &cdio_get_default_device_aix, - &cdio_is_device_generic, - &cdio_get_devices_aix - }, - - {DRIVER_BSDI, - CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, - "BSDI", - "BSDI ATAPI and SCSI driver", - &cdio_have_bsdi, - &cdio_open_bsdi, - &cdio_open_am_bsdi, - &cdio_get_default_device_bsdi, - &cdio_is_device_generic, - &cdio_get_devices_bsdi - }, - - {DRIVER_FREEBSD, - CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, - "FreeBSD", - "FreeBSD driver", - &cdio_have_freebsd, - &cdio_open_freebsd, - &cdio_open_am_freebsd, - &cdio_get_default_device_freebsd, - &cdio_is_device_generic, - NULL - }, - - {DRIVER_LINUX, - CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK, - "GNU/Linux", - "GNU/Linux ioctl and MMC driver", - &cdio_have_linux, - &cdio_open_linux, - &cdio_open_am_linux, - &cdio_get_default_device_linux, - &cdio_is_device_generic, - &cdio_get_devices_linux - }, - - {DRIVER_SOLARIS, - CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, - "Solaris", - "Solaris ATAPI and SCSI driver", - &cdio_have_solaris, - &cdio_open_solaris, - &cdio_open_am_solaris, - &cdio_get_default_device_solaris, - &cdio_is_device_generic, - &cdio_get_devices_solaris - }, - - {DRIVER_OSX, - CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, - "OS X", - "Apple Darwin OS X driver", - &cdio_have_osx, - &cdio_open_osx, - &cdio_open_am_osx, - &cdio_get_default_device_osx, - &cdio_is_device_generic, - &cdio_get_devices_osx - }, - - {DRIVER_WIN32, - CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, - "WIN32", - "MS Windows ASPI and ioctl driver", - &cdio_have_win32, - &cdio_open_win32, - &cdio_open_am_win32, - &cdio_get_default_device_win32, - &cdio_is_device_win32, - &cdio_get_devices_win32 - }, - - {DRIVER_CDRDAO, - CDIO_SRC_IS_DISK_IMAGE_MASK, - "CDRDAO", - "cdrdao (TOC) disk image driver", - &cdio_have_cdrdao, - &cdio_open_cdrdao, - &cdio_open_am_cdrdao, - &cdio_get_default_device_cdrdao, - NULL, - &cdio_get_devices_cdrdao - }, - - {DRIVER_BINCUE, - CDIO_SRC_IS_DISK_IMAGE_MASK, - "BIN/CUE", - "bin/cuesheet disk image driver", - &cdio_have_bincue, - &cdio_open_bincue, - &cdio_open_am_bincue, - &cdio_get_default_device_bincue, - NULL, - &cdio_get_devices_bincue - }, - - {DRIVER_NRG, - CDIO_SRC_IS_DISK_IMAGE_MASK, - "NRG", - "Nero NRG disk image driver", - &cdio_have_nrg, - &cdio_open_nrg, - &cdio_open_am_nrg, - &cdio_get_default_device_nrg, - NULL, - &cdio_get_devices_nrg - } - -}; - -static CdIo * -scan_for_driver(driver_id_t start, driver_id_t end, - const char *psz_source, const char *access_mode) -{ - driver_id_t driver_id; - - for (driver_id=start; driver_id<=end; driver_id++) { - if ((*CdIo_all_drivers[driver_id].have_driver)()) { - CdIo *ret= - (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source, access_mode); - if (ret != NULL) { - ret->driver_id = driver_id; - return ret; - } - } - } - return NULL; -} - -const char * -cdio_driver_describe(driver_id_t driver_id) -{ - return CdIo_all_drivers[driver_id].describe; -} - -/*! - Eject media in CD drive if there is a routine to do so. - Return 0 if success and 1 for failure, and 2 if no routine. - If the CD is ejected *obj is freed and obj set to NULL. - */ -int -cdio_eject_media (CdIo **obj) -{ - - if ((obj == NULL) || (*obj == NULL)) return 1; - - if ((*obj)->op.eject_media) { - int ret = (*obj)->op.eject_media ((*obj)->env); - if (0 == ret) { - cdio_destroy(*obj); - *obj = NULL; - } - return ret; - } else { - cdio_destroy(*obj); - *obj = NULL; - return 2; - } -} - -/*! - Free device list returned by cdio_get_devices or - cdio_get_devices_with_cap. -*/ -void cdio_free_device_list (char * device_list[]) -{ - if (NULL == device_list) return; - for ( ; *device_list != NULL ; device_list++ ) - free(*device_list); -} +static const char _rcsid[] = "$Id: cdio.c,v 1.8 2005/01/09 16:07:46 rocky Exp $"; /*! @@ -338,295 +73,6 @@ cdio_get_cdtext (CdIo *obj, track_t i_track) } } -/*! - Return a string containing the default CD device if none is specified. - if CdIo is NULL (we haven't initialized a specific device driver), - then find a suitable one and return the default device for that. - - NULL is returned if we couldn't get a default device. - */ -char * -cdio_get_default_device (const CdIo *obj) -{ - if (obj == NULL) { - driver_id_t driver_id; - /* Scan for driver */ - for (driver_id=DRIVER_UNKNOWN; driver_id<=CDIO_MAX_DRIVER; driver_id++) { - if ( (*CdIo_all_drivers[driver_id].have_driver)() && - *CdIo_all_drivers[driver_id].get_default_device ) { - return (*CdIo_all_drivers[driver_id].get_default_device)(); - } - } - return NULL; - } - - if (obj->op.get_default_device) { - return obj->op.get_default_device (); - } else { - return NULL; - } -} - -/*!Return an array of device names. If you want a specific - devices, dor a driver give that device, if you want hardware - devices, give DRIVER_DEVICE and if you want all possible devices, - image drivers and hardware drivers give DRIVER_UNKNOWN. - - NULL is returned if we couldn't return a list of devices. -*/ -char ** -cdio_get_devices (driver_id_t driver_id) -{ - /* Probably could get away with &driver_id below. */ - driver_id_t driver_id_temp = driver_id; - return cdio_get_devices_ret (&driver_id_temp); -} - -char ** -cdio_get_devices_ret (/*in/out*/ driver_id_t *p_driver_id) -{ - CdIo *p_cdio; - - switch (*p_driver_id) { - /* FIXME: spit out unknown to give image drivers as well. */ - case DRIVER_DEVICE: - p_cdio = scan_for_driver(DRIVER_UNKNOWN, CDIO_MAX_DEVICE_DRIVER, - NULL, NULL); - *p_driver_id = cdio_get_driver_id(p_cdio); - break; - case DRIVER_UNKNOWN: - p_cdio = scan_for_driver(DRIVER_UNKNOWN, CDIO_MAX_DRIVER, NULL, NULL); - *p_driver_id = cdio_get_driver_id(p_cdio); - break; - default: - return (*CdIo_all_drivers[*p_driver_id].get_devices)(); - } - - if (p_cdio == NULL) return NULL; - if (p_cdio->op.get_devices) { - char **devices = p_cdio->op.get_devices (); - cdio_destroy(p_cdio); - return devices; - } else { - return NULL; - } -} - -/*! - Return an array of device names in search_devices that have at - least the capabilities listed by cap. If search_devices is NULL, - then we'll search all possible CD drives. - - If "any" is set false then every capability listed in the extended - portion of capabilities (i.e. not the basic filesystem) must be - satisified. If "any" is set true, then if any of the capabilities - matches, we call that a success. - - To find a CD-drive of any type, use the mask CDIO_FS_MATCH_ALL. - - NULL is returned if we couldn't get a default device. - It is also possible to return a non NULL but after dereferencing the - the value is NULL. This also means nothing was found. -*/ -char ** -cdio_get_devices_with_cap (/*out*/ char* search_devices[], - cdio_fs_anal_t capabilities, bool any) -{ - driver_id_t p_driver_id; - return cdio_get_devices_with_cap_ret (search_devices, capabilities, any, - &p_driver_id); -} - -char ** -cdio_get_devices_with_cap_ret (/*out*/ char* search_devices[], - cdio_fs_anal_t capabilities, bool any, - /*out*/ driver_id_t *p_driver_id) -{ - char **drives=search_devices; - char **drives_ret=NULL; - unsigned int i_drives=0; - - *p_driver_id = DRIVER_DEVICE; - - if (NULL == drives) drives=cdio_get_devices_ret(p_driver_id); - if (NULL == drives) return NULL; - - if (capabilities == CDIO_FS_MATCH_ALL) { - /* Duplicate drives into drives_ret. */ - char **d = drives; - - for( ; *d != NULL; d++ ) { - cdio_add_device_list(&drives_ret, *d, &i_drives); - } - } else { - cdio_fs_anal_t got_fs=0; - cdio_fs_anal_t need_fs = CDIO_FSTYPE(capabilities); - cdio_fs_anal_t need_fs_ext; - char **d = drives; - need_fs_ext = capabilities & ~CDIO_FS_MASK; - - for( ; *d != NULL; d++ ) { - CdIo *cdio = cdio_open(*d, *p_driver_id); - - if (NULL != cdio) { - track_t first_track = cdio_get_first_track_num(cdio); - cdio_iso_analysis_t cdio_iso_analysis; - got_fs = cdio_guess_cd_type(cdio, 0, first_track, - &cdio_iso_analysis); - /* Match on fs and add */ - if ( (CDIO_FS_UNKNOWN == need_fs || CDIO_FSTYPE(got_fs) == need_fs) ) - { - bool doit = any - ? (got_fs & need_fs_ext) != 0 - : (got_fs | ~need_fs_ext) == -1; - if (doit) - cdio_add_device_list(&drives_ret, *d, &i_drives); - } - - cdio_destroy(cdio); - } - } - } - cdio_add_device_list(&drives_ret, NULL, &i_drives); - cdio_free_device_list(drives); - free(drives); - return drives_ret; -} - -/*! - 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. - - */ -void -cdio_get_drive_cap (const CdIo *p_cdio, - cdio_drive_read_cap_t *p_read_cap, - cdio_drive_write_cap_t *p_write_cap, - cdio_drive_misc_cap_t *p_misc_cap) -{ - /* This seems like a safe bet. */ - *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; - *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN; - *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN; - - if (p_cdio && p_cdio->op.get_drive_cap) { - p_cdio->op.get_drive_cap(p_cdio->env, p_read_cap, p_write_cap, p_misc_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. - - */ -void -cdio_get_drive_cap_dev (const char *device, - cdio_drive_read_cap_t *p_read_cap, - cdio_drive_write_cap_t *p_write_cap, - cdio_drive_misc_cap_t *p_misc_cap) -{ - /* This seems like a safe bet. */ - CdIo *cdio=scan_for_driver(CDIO_MIN_DRIVER, CDIO_MAX_DRIVER, - device, NULL); - if (cdio) { - cdio_get_drive_cap(cdio, p_read_cap, p_write_cap, p_misc_cap); - cdio_destroy(cdio); - } else { - *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; - *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN; - *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN; - } -} - - -/*! - Return a string containing the name of the driver in use. - if CdIo is NULL (we haven't initialized a specific device driver), - then return NULL. -*/ -const char * -cdio_get_driver_name (const CdIo *cdio) -{ - if (NULL==cdio) return NULL; - return CdIo_all_drivers[cdio->driver_id].name; -} - - /*! - Return the driver id. - if CdIo is NULL (we haven't initialized a specific device driver), - then return DRIVER_UNKNOWN. - */ -driver_id_t -cdio_get_driver_id (const CdIo *cdio) -{ - if (NULL==cdio) return DRIVER_UNKNOWN; - return cdio->driver_id; -} - -/*! - Return a string containing the name of the driver in use. - if CdIo is NULL (we haven't initialized a specific device driver), - then return NULL. -*/ -bool -cdio_get_hwinfo (const CdIo *p_cdio, cdio_hwinfo_t *hw_info) -{ - if (!p_cdio) return false; - if (p_cdio->op.get_hwinfo) { - return p_cdio->op.get_hwinfo (p_cdio, hw_info); - } else { - /* Perhaps driver forgot to initialize. We are no worse off Using - scsi_mmc than returning false here. */ - return scsi_mmc_get_hwinfo(p_cdio, hw_info); - } -} - -bool -cdio_have_driver(driver_id_t driver_id) -{ - return (*CdIo_all_drivers[driver_id].have_driver)(); -} - -bool -cdio_is_device(const char *psz_source, driver_id_t driver_id) -{ - if (CdIo_all_drivers[driver_id].is_device == NULL) return false; - return (*CdIo_all_drivers[driver_id].is_device)(psz_source); -} - - -/*! - Initialize CD Reading and control routines. Should be called first. - May be implicitly called by other routines if not called first. -*/ -bool -cdio_init(void) -{ - - CdIo_driver_t *all_dp; - CdIo_driver_t *dp = CdIo_driver; - driver_id_t driver_id; - - if (CdIo_last_driver != CDIO_DRIVER_UNINIT) { - cdio_warn ("Init routine called more than once."); - return false; - } - - for (driver_id=DRIVER_UNKNOWN; driver_id<=CDIO_MAX_DRIVER; driver_id++) { - all_dp = &CdIo_all_drivers[driver_id]; - if ((*CdIo_all_drivers[driver_id].have_driver)()) { - *dp++ = *all_dp; - CdIo_last_driver++; - } - } - - return true; -} - CdIo_t * cdio_new (generic_img_private_t *p_env, cdio_funcs *p_funcs) { @@ -643,174 +89,6 @@ cdio_new (generic_img_private_t *p_env, cdio_funcs *p_funcs) return p_new_cdio; } -/*! - Free any resources associated with cdio. -*/ -void -cdio_destroy (CdIo_t *p_cdio) -{ - CdIo_last_driver = CDIO_DRIVER_UNINIT; - if (p_cdio == NULL) return; - - if (p_cdio->op.free != NULL) - p_cdio->op.free (p_cdio->env); - free (p_cdio); -} - -/*! - lseek - reposition read/write file offset - Returns (off_t) -1 on error. - Similar to (if not the same as) libc's lseek() -*/ -off_t -cdio_lseek (const CdIo_t *cdio, off_t offset, int whence) -{ - if (cdio == NULL) return -1; - - if (cdio->op.lseek) - return cdio->op.lseek (cdio->env, offset, whence); - return -1; -} - -/*! - Reads into buf the next size bytes. - Returns -1 on error. - Similar to (if not the same as) libc's read() -*/ -ssize_t -cdio_read (const CdIo_t *p_cdio, void *buf, size_t size) -{ - if (p_cdio == NULL) return -1; - - if (p_cdio->op.read) - return p_cdio->op.read (p_cdio->env, buf, size); - return -1; -} - -/*! - Reads an audio sector from cd device into data starting - from lsn. Returns 0 if no error. -*/ -int -cdio_read_audio_sector (const CdIo_t *p_cdio, void *buf, lsn_t lsn) -{ - - if (NULL == p_cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) - return 0; - - if (p_cdio->op.read_audio_sectors != NULL) - return p_cdio->op.read_audio_sectors (p_cdio->env, buf, lsn, 1); - return -1; -} - -/*! - Reads audio sectors from cd device into data starting - from lsn. Returns 0 if no error. -*/ -int -cdio_read_audio_sectors (const CdIo_t *p_cdio, void *buf, lsn_t lsn, - unsigned int nblocks) -{ - if ( NULL == p_cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) - return 0; - - if (p_cdio->op.read_audio_sectors != NULL) - return p_cdio->op.read_audio_sectors (p_cdio->env, buf, lsn, nblocks); - return -1; -} - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -/*! - Reads a single mode1 form1 or form2 sector from cd device - into data starting from lsn. Returns 0 if no error. - */ -int -cdio_read_mode1_sector (const CdIo_t *p_cdio, void *data, lsn_t lsn, - bool b_form2) -{ - uint32_t size = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE ; - - if (NULL == p_cdio || NULL == data || CDIO_INVALID_LSN == lsn ) - return 0; - - if (p_cdio->op.read_mode1_sector) { - return p_cdio->op.read_mode1_sector(p_cdio->env, data, lsn, b_form2); - } else if (p_cdio->op.lseek && p_cdio->op.read) { - char buf[CDIO_CD_FRAMESIZE] = { 0, }; - if (0 > cdio_lseek(p_cdio, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) - return -1; - if (0 > cdio_read(p_cdio, buf, CDIO_CD_FRAMESIZE)) - return -1; - memcpy (data, buf, size); - return 0; - } - - return 1; - -} - -int -cdio_read_mode1_sectors (const CdIo_t *cdio, void *buf, lsn_t lsn, - bool b_form2, unsigned int num_sectors) -{ - - if (NULL == cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) - return 0; - - cdio_assert (cdio->op.read_mode1_sectors != NULL); - - return cdio->op.read_mode1_sectors (cdio->env, buf, lsn, b_form2, - num_sectors); -} - -/*! - Reads a single mode2 sector from cd device into data starting - from lsn. Returns 0 if no error. - */ -int -cdio_read_mode2_sector (const CdIo_t *cdio, void *buf, lsn_t lsn, - bool b_form2) -{ - if (NULL == cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) - return 0; - - cdio_assert (cdio->op.read_mode2_sector != NULL - || cdio->op.read_mode2_sectors != NULL); - - if (cdio->op.read_mode2_sector) - return cdio->op.read_mode2_sector (cdio->env, buf, lsn, b_form2); - - /* fallback */ - if (cdio->op.read_mode2_sectors != NULL) - return cdio_read_mode2_sectors (cdio, buf, lsn, b_form2, 1); - return 1; -} - -int -cdio_read_mode2_sectors (const CdIo_t *cdio, void *buf, lsn_t lsn, - bool b_form2, unsigned int num_sectors) -{ - - if (NULL == cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) - return 0; - - cdio_assert (cdio->op.read_mode2_sectors != NULL); - - return cdio->op.read_mode2_sectors (cdio->env, buf, lsn, - b_form2, num_sectors); -} - -uint32_t -cdio_stat_size (const CdIo_t *cdio) -{ - cdio_assert (cdio != NULL); - - return cdio->op.stat_size (cdio->env); -} - /*! Set the arg "key" with "value" in the source device. */ @@ -824,119 +102,6 @@ cdio_set_arg (CdIo_t *cdio, const char key[], const char value[]) return cdio->op.set_arg (cdio->env, key, value); } -/*! Sets up to read from place specified by source_name and - driver_id. This should be called before using any other routine, - except cdio_init. This will call cdio_init, if that hasn't been - done previously. - - NULL is returned on error. -*/ -CdIo_t * -cdio_open (const char *orig_source_name, driver_id_t driver_id) -{ - return cdio_open_am(orig_source_name, driver_id, NULL); -} - -/*! Sets up to read from place specified by source_name and - driver_id. This should be called before using any other routine, - except cdio_init. This will call cdio_init, if that hasn't been - done previously. - - NULL is returned on error. -*/ -CdIo_t * -cdio_open_am (const char *psz_orig_source, driver_id_t driver_id, - const char *psz_access_mode) -{ - char *psz_source; - - if (CdIo_last_driver == -1) cdio_init(); - - if (NULL == psz_orig_source || strlen(psz_orig_source)==0) - psz_source = cdio_get_default_device(NULL); - else - psz_source = strdup(psz_orig_source); - - switch (driver_id) { - case DRIVER_UNKNOWN: - { - CdIo_t *cdio=scan_for_driver(CDIO_MIN_DRIVER, CDIO_MAX_DRIVER, - psz_source, psz_access_mode); - free(psz_source); - return cdio; - } - case DRIVER_DEVICE: - { - /* Scan for a driver. */ - CdIo_t *ret = cdio_open_am_cd(psz_source, psz_access_mode); - free(psz_source); - return ret; - } - break; - case DRIVER_AIX: - case DRIVER_BSDI: - case DRIVER_FREEBSD: - case DRIVER_LINUX: - case DRIVER_SOLARIS: - case DRIVER_WIN32: - case DRIVER_OSX: - case DRIVER_NRG: - case DRIVER_BINCUE: - case DRIVER_CDRDAO: - if ((*CdIo_all_drivers[driver_id].have_driver)()) { - CdIo_t *ret = - (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source, - psz_access_mode); - if (ret) ret->driver_id = driver_id; - free(psz_source); - return ret; - } - } - - free(psz_source); - return NULL; -} - - -/*! - Set up CD-ROM for reading. The device_name is - the some sort of device name. - - @return the cdio object for subsequent operations. - NULL on error or there is no driver for a some sort of hardware CD-ROM. -*/ -CdIo_t * -cdio_open_cd (const char *psz_source) -{ - return cdio_open_am_cd(psz_source, NULL); -} - -/*! - Set up CD-ROM for reading. The device_name is - the some sort of device name. - - @return the cdio object for subsequent operations. - NULL on error or there is no driver for a some sort of hardware CD-ROM. -*/ -/* In the future we'll have more complicated code to allow selection - of an I/O routine as well as code to find an appropriate default - routine among the "registered" routines. Possibly classes too - disk-based, SCSI-based, native-based, vendor (e.g. Sony, or - Plextor) based - - For now though, we'll start more simply... -*/ -CdIo_t * -cdio_open_am_cd (const char *psz_source, const char *psz_access_mode) -{ - if (CdIo_last_driver == -1) cdio_init(); - - /* Scan for a driver. */ - return scan_for_driver(CDIO_MIN_DEVICE_DRIVER, CDIO_MAX_DEVICE_DRIVER, - psz_source, psz_access_mode); -} - - /* diff --git a/lib/driver/device.c b/lib/driver/device.c new file mode 100644 index 00000000..02ca972b --- /dev/null +++ b/lib/driver/device.c @@ -0,0 +1,698 @@ +/* + $Id: device.c,v 1.1 2005/01/09 16:07:46 rocky Exp $ + + Copyright (C) 2005 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*! device- and driver-related routines. */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include "cdio_private.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +/* The below array gives of the drivers that are currently available for + on a particular host. */ + +CdIo_driver_t CdIo_driver[CDIO_MAX_DRIVER] = { {0} }; + +/* The last valid entry of Cdio_driver. + -1 or (CDIO_DRIVER_UNINIT) means uninitialzed. + -2 means some sort of error. +*/ + +#define CDIO_DRIVER_UNINIT -1 +int CdIo_last_driver = CDIO_DRIVER_UNINIT; + +#ifdef HAVE_AIX_CDROM +const driver_id_t cdio_os_driver = DRIVER_AIX; +#elif HAVE_BSDI_CDROM +const driver_id_t cdio_os_driver = DRIVER_BSDI; +#elif HAVE_FREEBSD_CDROM +const driver_id_t cdio_os_driver = DRIVER_FREEBSD; +#elif HAVE_LINUX_CDROM +const driver_id_t cdio_os_driver = DRIVER_LINUX; +#elif HAVE_DARWIN_CDROM +const driver_id_t cdio_os_driver = DRIVER_OSX; +#elif HAVE_DARWIN_SOLARIS +const driver_id_t cdio_os_driver = DRIVER_SOLARIS; +#elif HAVE_DARWIN_WIN32 +const driver_id_t cdio_os_driver = DRIVER_WIN32; +#else +const driver_id_t cdio_os_driver = DRIVER_UNKNOWN; +#endif + +static bool +cdio_have_false(void) +{ + return false; +} + +/* The below array gives all drivers that can possibly appear. + on a particular host. */ + +CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { + {DRIVER_UNKNOWN, + 0, + "Unknown", + "No driver", + &cdio_have_false, + NULL, + NULL, + NULL, + NULL, + NULL + }, + + {DRIVER_BSDI, + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, + "AIX", + "AIX SCSI driver", + &cdio_have_aix, + &cdio_open_aix, + &cdio_open_am_aix, + &cdio_get_default_device_aix, + &cdio_is_device_generic, + &cdio_get_devices_aix + }, + + {DRIVER_BSDI, + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, + "BSDI", + "BSDI ATAPI and SCSI driver", + &cdio_have_bsdi, + &cdio_open_bsdi, + &cdio_open_am_bsdi, + &cdio_get_default_device_bsdi, + &cdio_is_device_generic, + &cdio_get_devices_bsdi + }, + + {DRIVER_FREEBSD, + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, + "FreeBSD", + "FreeBSD driver", + &cdio_have_freebsd, + &cdio_open_freebsd, + &cdio_open_am_freebsd, + &cdio_get_default_device_freebsd, + &cdio_is_device_generic, + NULL + }, + + {DRIVER_LINUX, + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK, + "GNU/Linux", + "GNU/Linux ioctl and MMC driver", + &cdio_have_linux, + &cdio_open_linux, + &cdio_open_am_linux, + &cdio_get_default_device_linux, + &cdio_is_device_generic, + &cdio_get_devices_linux + }, + + {DRIVER_SOLARIS, + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, + "Solaris", + "Solaris ATAPI and SCSI driver", + &cdio_have_solaris, + &cdio_open_solaris, + &cdio_open_am_solaris, + &cdio_get_default_device_solaris, + &cdio_is_device_generic, + &cdio_get_devices_solaris + }, + + {DRIVER_OSX, + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, + "OS X", + "Apple Darwin OS X driver", + &cdio_have_osx, + &cdio_open_osx, + &cdio_open_am_osx, + &cdio_get_default_device_osx, + &cdio_is_device_generic, + &cdio_get_devices_osx + }, + + {DRIVER_WIN32, + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, + "WIN32", + "MS Windows ASPI and ioctl driver", + &cdio_have_win32, + &cdio_open_win32, + &cdio_open_am_win32, + &cdio_get_default_device_win32, + &cdio_is_device_win32, + &cdio_get_devices_win32 + }, + + {DRIVER_CDRDAO, + CDIO_SRC_IS_DISK_IMAGE_MASK, + "CDRDAO", + "cdrdao (TOC) disk image driver", + &cdio_have_cdrdao, + &cdio_open_cdrdao, + &cdio_open_am_cdrdao, + &cdio_get_default_device_cdrdao, + NULL, + &cdio_get_devices_cdrdao + }, + + {DRIVER_BINCUE, + CDIO_SRC_IS_DISK_IMAGE_MASK, + "BIN/CUE", + "bin/cuesheet disk image driver", + &cdio_have_bincue, + &cdio_open_bincue, + &cdio_open_am_bincue, + &cdio_get_default_device_bincue, + NULL, + &cdio_get_devices_bincue + }, + + {DRIVER_NRG, + CDIO_SRC_IS_DISK_IMAGE_MASK, + "NRG", + "Nero NRG disk image driver", + &cdio_have_nrg, + &cdio_open_nrg, + &cdio_open_am_nrg, + &cdio_get_default_device_nrg, + NULL, + &cdio_get_devices_nrg + } + +}; + +static CdIo * +scan_for_driver(driver_id_t start, driver_id_t end, + const char *psz_source, const char *access_mode) +{ + driver_id_t driver_id; + + for (driver_id=start; driver_id<=end; driver_id++) { + if ((*CdIo_all_drivers[driver_id].have_driver)()) { + CdIo *ret= + (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source, access_mode); + if (ret != NULL) { + ret->driver_id = driver_id; + return ret; + } + } + } + return NULL; +} + +const char * +cdio_driver_describe(driver_id_t driver_id) +{ + return CdIo_all_drivers[driver_id].describe; +} + +/*! + Initialize CD Reading and control routines. Should be called first. + May be implicitly called by other routines if not called first. +*/ +bool +cdio_init(void) +{ + + CdIo_driver_t *all_dp; + CdIo_driver_t *dp = CdIo_driver; + driver_id_t driver_id; + + if (CdIo_last_driver != CDIO_DRIVER_UNINIT) { + cdio_warn ("Init routine called more than once."); + return false; + } + + for (driver_id=DRIVER_UNKNOWN; driver_id<=CDIO_MAX_DRIVER; driver_id++) { + all_dp = &CdIo_all_drivers[driver_id]; + if ((*CdIo_all_drivers[driver_id].have_driver)()) { + *dp++ = *all_dp; + CdIo_last_driver++; + } + } + + return true; +} + +/*! + Free any resources associated with cdio. +*/ +void +cdio_destroy (CdIo_t *p_cdio) +{ + CdIo_last_driver = CDIO_DRIVER_UNINIT; + if (p_cdio == NULL) return; + + if (p_cdio->op.free != NULL) + p_cdio->op.free (p_cdio->env); + free (p_cdio); +} + +/*! + Eject media in CD drive if there is a routine to do so. + Return 0 if success and 1 for failure, and 2 if no routine. + If the CD is ejected *p_cdio is freed and p_cdio set to NULL. + */ +int +cdio_eject_media (CdIo_t **pp_cdio) +{ + + if ((pp_cdio == NULL) || (*pp_cdio == NULL)) return 1; + + if ((*pp_cdio)->op.eject_media) { + int ret = (*pp_cdio)->op.eject_media ((*pp_cdio)->env); + if (0 == ret) { + cdio_destroy(*pp_cdio); + *pp_cdio = NULL; + } + return ret; + } else { + cdio_destroy(*pp_cdio); + *pp_cdio = NULL; + return 2; + } +} + +/*! + Free device list returned by cdio_get_devices or + cdio_get_devices_with_cap. +*/ +void cdio_free_device_list (char * device_list[]) +{ + if (NULL == device_list) return; + for ( ; *device_list != NULL ; device_list++ ) + free(*device_list); +} + + +/*! + Return a string containing the default CD device if none is specified. + if CdIo is NULL (we haven't initialized a specific device driver), + then find a suitable one and return the default device for that. + + NULL is returned if we couldn't get a default device. + */ +char * +cdio_get_default_device (const CdIo_t *p_cdio) +{ + if (p_cdio == NULL) { + driver_id_t driver_id; + /* Scan for driver */ + for (driver_id=DRIVER_UNKNOWN; driver_id<=CDIO_MAX_DRIVER; driver_id++) { + if ( (*CdIo_all_drivers[driver_id].have_driver)() && + *CdIo_all_drivers[driver_id].get_default_device ) { + return (*CdIo_all_drivers[driver_id].get_default_device)(); + } + } + return NULL; + } + + if (p_cdio->op.get_default_device) { + return p_cdio->op.get_default_device (); + } else { + return NULL; + } +} + +/*!Return an array of device names. If you want a specific + devices, dor a driver give that device, if you want hardware + devices, give DRIVER_DEVICE and if you want all possible devices, + image drivers and hardware drivers give DRIVER_UNKNOWN. + + NULL is returned if we couldn't return a list of devices. +*/ +char ** +cdio_get_devices (driver_id_t driver_id) +{ + /* Probably could get away with &driver_id below. */ + driver_id_t driver_id_temp = driver_id; + return cdio_get_devices_ret (&driver_id_temp); +} + +char ** +cdio_get_devices_ret (/*in/out*/ driver_id_t *p_driver_id) +{ + CdIo_t *p_cdio; + + switch (*p_driver_id) { + /* FIXME: spit out unknown to give image drivers as well. */ + case DRIVER_DEVICE: + p_cdio = scan_for_driver(DRIVER_UNKNOWN, CDIO_MAX_DEVICE_DRIVER, + NULL, NULL); + *p_driver_id = cdio_get_driver_id(p_cdio); + break; + case DRIVER_UNKNOWN: + p_cdio = scan_for_driver(DRIVER_UNKNOWN, CDIO_MAX_DRIVER, NULL, NULL); + *p_driver_id = cdio_get_driver_id(p_cdio); + break; + default: + return (*CdIo_all_drivers[*p_driver_id].get_devices)(); + } + + if (p_cdio == NULL) return NULL; + if (p_cdio->op.get_devices) { + char **devices = p_cdio->op.get_devices (); + cdio_destroy(p_cdio); + return devices; + } else { + return NULL; + } +} + +/*! + Return an array of device names in search_devices that have at + least the capabilities listed by cap. If search_devices is NULL, + then we'll search all possible CD drives. + + If "any" is set false then every capability listed in the extended + portion of capabilities (i.e. not the basic filesystem) must be + satisified. If "any" is set true, then if any of the capabilities + matches, we call that a success. + + To find a CD-drive of any type, use the mask CDIO_FS_MATCH_ALL. + + NULL is returned if we couldn't get a default device. + It is also possible to return a non NULL but after dereferencing the + the value is NULL. This also means nothing was found. +*/ +char ** +cdio_get_devices_with_cap (/*out*/ char* search_devices[], + cdio_fs_anal_t capabilities, bool any) +{ + driver_id_t p_driver_id; + return cdio_get_devices_with_cap_ret (search_devices, capabilities, any, + &p_driver_id); +} + +char ** +cdio_get_devices_with_cap_ret (/*out*/ char* search_devices[], + cdio_fs_anal_t capabilities, bool any, + /*out*/ driver_id_t *p_driver_id) +{ + char **drives=search_devices; + char **drives_ret=NULL; + unsigned int i_drives=0; + + *p_driver_id = DRIVER_DEVICE; + + if (NULL == drives) drives=cdio_get_devices_ret(p_driver_id); + if (NULL == drives) return NULL; + + if (capabilities == CDIO_FS_MATCH_ALL) { + /* Duplicate drives into drives_ret. */ + char **d = drives; + + for( ; *d != NULL; d++ ) { + cdio_add_device_list(&drives_ret, *d, &i_drives); + } + } else { + cdio_fs_anal_t got_fs=0; + cdio_fs_anal_t need_fs = CDIO_FSTYPE(capabilities); + cdio_fs_anal_t need_fs_ext; + char **d = drives; + need_fs_ext = capabilities & ~CDIO_FS_MASK; + + for( ; *d != NULL; d++ ) { + CdIo_t *cdio = cdio_open(*d, *p_driver_id); + + if (NULL != cdio) { + track_t first_track = cdio_get_first_track_num(cdio); + cdio_iso_analysis_t cdio_iso_analysis; + got_fs = cdio_guess_cd_type(cdio, 0, first_track, + &cdio_iso_analysis); + /* Match on fs and add */ + if ( (CDIO_FS_UNKNOWN == need_fs || CDIO_FSTYPE(got_fs) == need_fs) ) + { + bool doit = any + ? (got_fs & need_fs_ext) != 0 + : (got_fs | ~need_fs_ext) == -1; + if (doit) + cdio_add_device_list(&drives_ret, *d, &i_drives); + } + + cdio_destroy(cdio); + } + } + } + cdio_add_device_list(&drives_ret, NULL, &i_drives); + cdio_free_device_list(drives); + free(drives); + return drives_ret; +} + +/*! + 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. + + */ +void +cdio_get_drive_cap (const CdIo_t *p_cdio, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap) +{ + /* This seems like a safe bet. */ + *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN; + + if (p_cdio && p_cdio->op.get_drive_cap) { + p_cdio->op.get_drive_cap(p_cdio->env, p_read_cap, p_write_cap, p_misc_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. + + */ +void +cdio_get_drive_cap_dev (const char *device, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap) +{ + /* This seems like a safe bet. */ + CdIo_t *cdio=scan_for_driver(CDIO_MIN_DRIVER, CDIO_MAX_DRIVER, + device, NULL); + if (cdio) { + cdio_get_drive_cap(cdio, p_read_cap, p_write_cap, p_misc_cap); + cdio_destroy(cdio); + } else { + *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN; + } +} + + +/*! + Return a string containing the name of the driver in use. + if CdIo is NULL (we haven't initialized a specific device driver), + then return NULL. +*/ +const char * +cdio_get_driver_name (const CdIo_t *cdio) +{ + if (NULL==cdio) return NULL; + return CdIo_all_drivers[cdio->driver_id].name; +} + + /*! + Return the driver id. + if CdIo is NULL (we haven't initialized a specific device driver), + then return DRIVER_UNKNOWN. + */ +driver_id_t +cdio_get_driver_id (const CdIo *cdio) +{ + if (NULL==cdio) return DRIVER_UNKNOWN; + return cdio->driver_id; +} + +/*! + Return a string containing the name of the driver in use. + if CdIo is NULL (we haven't initialized a specific device driver), + then return NULL. +*/ +bool +cdio_get_hwinfo (const CdIo_t *p_cdio, cdio_hwinfo_t *hw_info) +{ + if (!p_cdio) return false; + if (p_cdio->op.get_hwinfo) { + return p_cdio->op.get_hwinfo (p_cdio, hw_info); + } else { + /* Perhaps driver forgot to initialize. We are no worse off Using + scsi_mmc than returning false here. */ + return scsi_mmc_get_hwinfo(p_cdio, hw_info); + } +} + +bool +cdio_have_driver(driver_id_t driver_id) +{ + return (*CdIo_all_drivers[driver_id].have_driver)(); +} + +bool +cdio_is_device(const char *psz_source, driver_id_t driver_id) +{ + if (CdIo_all_drivers[driver_id].is_device == NULL) return false; + return (*CdIo_all_drivers[driver_id].is_device)(psz_source); +} + +/*! Sets up to read from place specified by source_name and + driver_id. This should be called before using any other routine, + except cdio_init. This will call cdio_init, if that hasn't been + done previously. + + NULL is returned on error. +*/ +CdIo_t * +cdio_open (const char *orig_source_name, driver_id_t driver_id) +{ + return cdio_open_am(orig_source_name, driver_id, NULL); +} + +/*! Sets up to read from place specified by source_name and + driver_id. This should be called before using any other routine, + except cdio_init. This will call cdio_init, if that hasn't been + done previously. + + NULL is returned on error. +*/ +CdIo_t * +cdio_open_am (const char *psz_orig_source, driver_id_t driver_id, + const char *psz_access_mode) +{ + char *psz_source; + + if (CdIo_last_driver == -1) cdio_init(); + + if (NULL == psz_orig_source || strlen(psz_orig_source)==0) + psz_source = cdio_get_default_device(NULL); + else + psz_source = strdup(psz_orig_source); + + switch (driver_id) { + case DRIVER_UNKNOWN: + { + CdIo_t *cdio=scan_for_driver(CDIO_MIN_DRIVER, CDIO_MAX_DRIVER, + psz_source, psz_access_mode); + free(psz_source); + return cdio; + } + case DRIVER_DEVICE: + { + /* Scan for a driver. */ + CdIo_t *ret = cdio_open_am_cd(psz_source, psz_access_mode); + free(psz_source); + return ret; + } + break; + case DRIVER_AIX: + case DRIVER_BSDI: + case DRIVER_FREEBSD: + case DRIVER_LINUX: + case DRIVER_SOLARIS: + case DRIVER_WIN32: + case DRIVER_OSX: + case DRIVER_NRG: + case DRIVER_BINCUE: + case DRIVER_CDRDAO: + if ((*CdIo_all_drivers[driver_id].have_driver)()) { + CdIo_t *ret = + (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source, + psz_access_mode); + if (ret) ret->driver_id = driver_id; + free(psz_source); + return ret; + } + } + + free(psz_source); + return NULL; +} + + +/*! + Set up CD-ROM for reading. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. +*/ +CdIo_t * +cdio_open_cd (const char *psz_source) +{ + return cdio_open_am_cd(psz_source, NULL); +} + +/*! + Set up CD-ROM for reading. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. +*/ +/* In the future we'll have more complicated code to allow selection + of an I/O routine as well as code to find an appropriate default + routine among the "registered" routines. Possibly classes too + disk-based, SCSI-based, native-based, vendor (e.g. Sony, or + Plextor) based + + For now though, we'll start more simply... +*/ +CdIo_t * +cdio_open_am_cd (const char *psz_source, const char *psz_access_mode) +{ + if (CdIo_last_driver == -1) cdio_init(); + + /* Scan for a driver. */ + return scan_for_driver(CDIO_MIN_DEVICE_DRIVER, CDIO_MAX_DEVICE_DRIVER, + psz_source, psz_access_mode); +} + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/lib/driver/disc.c b/lib/driver/disc.c index a11886c8..1971f16b 100644 --- a/lib/driver/disc.c +++ b/lib/driver/disc.c @@ -1,5 +1,5 @@ /* - $Id: disc.c,v 1.2 2005/01/04 10:58:03 rocky Exp $ + $Id: disc.c,v 1.3 2005/01/09 16:07:46 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -27,6 +27,24 @@ #include #include "cdio_private.h" +/* Must match discmode enumeration */ +const char *discmode2str[] = { + "CD-DA", + "CD-DATA (Mode 1)", + "CD DATA (Mode 2)", + "CD-ROM Mixed", + "DVD-ROM", + "DVD-RAM", + "DVD-R", + "DVD-RW", + "DVD+R", + "DVD+RW", + "Unknown/unclassified DVD", + "No information", + "Error in getting information", + "CD-i" +}; + unsigned int cdio_get_disc_last_lsn(const CdIo *p_cdio) { @@ -63,3 +81,16 @@ cdio_get_mcn (const CdIo *p_cdio) } } +/*! + Get the size of the CD in logical block address (LBA) units. + + @param p_cdio the CD object queried + @return the size or 0 if there was an error. +*/ +uint32_t +cdio_stat_size (const CdIo_t *p_cdio) +{ + if (!p_cdio) return 0; + + return p_cdio->op.stat_size (p_cdio->env); +} diff --git a/lib/driver/read.c b/lib/driver/read.c new file mode 100644 index 00000000..ebba398b --- /dev/null +++ b/lib/driver/read.c @@ -0,0 +1,222 @@ +/* + $Id: read.c,v 1.1 2005/01/09 16:07:46 rocky Exp $ + + Copyright (C) 2005 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/** \file read.h + * + * \brief sector (block, frame)-related libcdio routines. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "cdio_private.h" +#include "cdio_assert.h" + +#ifdef HAVE_STRING_H +#include +#endif + +/*! + lseek - reposition read/write file offset + Returns (off_t) -1 on error. + Similar to (if not the same as) libc's lseek() +*/ +off_t +cdio_lseek (const CdIo_t *p_cdio, off_t offset, int whence) +{ + if (p_cdio == NULL) return -1; + + if (p_cdio->op.lseek) + return p_cdio->op.lseek (p_cdio->env, offset, whence); + return -1; +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + Similar to (if not the same as) libc's read() +*/ +ssize_t +cdio_read (const CdIo_t *p_cdio, void *p_buf, size_t size) +{ + if (p_cdio == NULL) return -1; + + if (p_cdio->op.read) + return p_cdio->op.read (p_cdio->env, p_buf, size); + return -1; +} + +/*! + Reads an audio sector from cd device into data starting + from lsn. Returns 0 if no error. +*/ +int +cdio_read_audio_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t lsn) +{ + + if (NULL == p_cdio || NULL == p_buf || CDIO_INVALID_LSN == lsn ) + return 0; + + if (p_cdio->op.read_audio_sectors != NULL) + return p_cdio->op.read_audio_sectors (p_cdio->env, p_buf, lsn, 1); + return -1; +} + +/*! + Reads audio sectors from cd device into data starting + from lsn. Returns 0 if no error. +*/ +int +cdio_read_audio_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t lsn, + unsigned int nblocks) +{ + if ( NULL == p_cdio || NULL == p_buf || CDIO_INVALID_LSN == lsn ) + return 0; + + if (p_cdio->op.read_audio_sectors != NULL) + return p_cdio->op.read_audio_sectors (p_cdio->env, p_buf, lsn, nblocks); + return -1; +} + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +/*! + Reads a single mode1 form1 or form2 sector from cd device + into data starting from lsn. Returns 0 if no error. + */ +int +cdio_read_mode1_sector (const CdIo_t *p_cdio, void *data, lsn_t lsn, + bool b_form2) +{ + uint32_t size = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE ; + + if (NULL == p_cdio || NULL == data || CDIO_INVALID_LSN == lsn ) + return 0; + + if (p_cdio->op.read_mode1_sector) { + return p_cdio->op.read_mode1_sector(p_cdio->env, data, lsn, b_form2); + } else if (p_cdio->op.lseek && p_cdio->op.read) { + char buf[CDIO_CD_FRAMESIZE] = { 0, }; + if (0 > cdio_lseek(p_cdio, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) + return -1; + if (0 > cdio_read(p_cdio, buf, CDIO_CD_FRAMESIZE)) + return -1; + memcpy (data, buf, size); + return 0; + } + + return 1; + +} + +/*! + Reads mode 1 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode 1 form 2 sectors or false for + mode 1 form 1 sectors. + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. +*/ +int +cdio_read_mode1_sectors (const CdIo_t *cdio, void *p_buf, lsn_t lsn, + bool b_form2, unsigned int num_sectors) +{ + + if (NULL == cdio || NULL == p_buf || CDIO_INVALID_LSN == lsn ) + return 0; + + cdio_assert (cdio->op.read_mode1_sectors != NULL); + + return cdio->op.read_mode1_sectors (cdio->env, p_buf, lsn, b_form2, + num_sectors); +} + +/*! + Reads a mode 2 sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode 2 form 2 sectors or false for + mode 2 form 1 sectors. + + @return 0 if no error, nonzero otherwise. +*/ +int +cdio_read_mode2_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t lsn, + bool b_form2) +{ + if (NULL == p_cdio || NULL == p_buf || CDIO_INVALID_LSN == lsn ) + return 0; + + cdio_assert (p_cdio->op.read_mode2_sector != NULL + || p_cdio->op.read_mode2_sectors != NULL); + + if (p_cdio->op.read_mode2_sector) + return p_cdio->op.read_mode2_sector (p_cdio->env, p_buf, lsn, b_form2); + + /* fallback */ + if (p_cdio->op.read_mode2_sectors != NULL) + return cdio_read_mode2_sectors (p_cdio, p_buf, lsn, b_form2, 1); + return 1; +} + +/*! + Reads mode 2 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode2 form 2 sectors or false for + mode 2 form 1 sectors. + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. +*/ +int +cdio_read_mode2_sectors (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, + bool b_form2, unsigned int i_sectors) +{ + + if (NULL == p_cdio || NULL == p_buf || CDIO_INVALID_LSN == i_lsn ) + return 0; + + cdio_assert (p_cdio->op.read_mode2_sectors != NULL); + + return p_cdio->op.read_mode2_sectors (p_cdio->env, p_buf, i_lsn, + b_form2, i_sectors); +} + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/lib/driver/track.c b/lib/driver/track.c index 86d26afe..88df12cf 100644 --- a/lib/driver/track.c +++ b/lib/driver/track.c @@ -1,5 +1,5 @@ /* - $Id: track.c,v 1.2 2005/01/05 04:16:11 rocky Exp $ + $Id: track.c,v 1.3 2005/01/09 16:07:46 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -18,6 +18,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*! Track-related routines. */ #ifdef HAVE_CONFIG_H @@ -27,6 +28,11 @@ #include #include "cdio_private.h" +const char *track_format2str[6] = + { + "audio", "CD-i", "XA", "data", "PSX", "error" + }; + /*! Return the number of the first track. CDIO_INVALID_TRACK is returned on error.