summaryrefslogtreecommitdiff
path: root/src/input/vcd/libcdio/_cdio_osx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/vcd/libcdio/_cdio_osx.c')
-rw-r--r--src/input/vcd/libcdio/_cdio_osx.c1199
1 files changed, 876 insertions, 323 deletions
diff --git a/src/input/vcd/libcdio/_cdio_osx.c b/src/input/vcd/libcdio/_cdio_osx.c
index 3e479f76d..f754933c6 100644
--- a/src/input/vcd/libcdio/_cdio_osx.c
+++ b/src/input/vcd/libcdio/_cdio_osx.c
@@ -1,5 +1,5 @@
/*
- $Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Exp $
+ $Id: _cdio_osx.c,v 1.4 2005/01/01 02:43:57 rockyb Exp $
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
from vcdimager code:
@@ -9,6 +9,7 @@
Gildas Bazin <gbazin@netcourrier.com>
Jon Lech Johansen <jon-vl@nanocrew.net>
Derk-Jan Hartman <hartman at videolan.org>
+ Justin F. Hallett <thesin@southofheaven.org>
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
@@ -30,11 +31,12 @@
*/
#ifdef HAVE_CONFIG_H
-# include "config.h"
+#include "config.h"
#endif
-static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Exp $";
+static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.4 2005/01/01 02:43:57 rockyb Exp $";
+#include <cdio/logging.h>
#include <cdio/sector.h>
#include <cdio/util.h>
#include "cdio_assert.h"
@@ -43,6 +45,17 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Ex
#include <string.h>
#ifdef HAVE_DARWIN_CDROM
+#undef VERSION
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
+
+#include <mach/mach.h>
+#include <Carbon/Carbon.h>
+#include <IOKit/scsi-commands/SCSITaskLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <mach/mach_error.h>
#include <stdio.h>
#include <stdlib.h>
@@ -54,72 +67,575 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Ex
#include <sys/types.h>
#include <sys/ioctl.h>
+
#include <paths.h>
-#include <CoreFoundation/CFBase.h>
-#include <CoreFoundation/CFString.h>
-#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
+#include <IOKit/scsi-commands/IOSCSIMultimediaCommandsDevice.h>
#include <IOKit/storage/IOCDTypes.h>
+#include <IOKit/storage/IODVDTypes.h>
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IOCDMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
#include <IOKit/storage/IOCDMediaBSDClient.h>
+#include <IOKit/storage/IODVDMediaBSDClient.h>
+#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
+
+#define kIOCDBlockStorageDeviceClassString "IOCDBlockStorageDevice"
+
+/* Note leadout is normally defined 0xAA, But on OSX 0xA0 is "lead in" while
+ 0xA2 is "lead out". Don't ask me why. */
+#define OSX_CDROM_LEADOUT_TRACK 0xA2
-#define TOTAL_TRACKS (_obj->num_tracks)
+#define TOTAL_TRACKS (p_env->i_last_track - p_env->gen.i_first_track + 1)
+#define CDROM_CDI_TRACK 0x1
+#define CDROM_XA_TRACK 0x2
+
+typedef enum {
+ _AM_NONE,
+ _AM_OSX,
+} access_mode_t;
+
+#define MAX_SERVICE_NAME 1000
typedef struct {
/* Things common to all drivers like this.
This must be first. */
generic_img_private_t gen;
- enum {
- _AM_NONE,
- _AM_OSX,
- } access_mode;
+ access_mode_t access_mode;
/* Track information */
- bool toc_init; /* if true, info below is valid. */
CDTOC *pTOC;
int i_descriptors;
- track_t num_tracks;
+ track_t i_last_track; /* highest track number */
+ track_t i_last_session; /* highest session number */
+ track_t i_first_session; /* first session number */
lsn_t *pp_lba;
+ io_service_t MediaClass_service;
+ char psz_MediaClass_service[MAX_SERVICE_NAME];
+ SCSITaskDeviceInterface **pp_scsiTaskDeviceInterface;
} _img_private_t;
-static void
-_cdio_osx_free (void *env) {
- _img_private_t *_obj = env;
- if (NULL == _obj) return;
- cdio_generic_free(_obj);
- if (NULL != _obj->pp_lba) free((void *) _obj->pp_lba);
- if (NULL != _obj->pTOC) free((void *) _obj->pTOC);
+static bool read_toc_osx (void *p_user_data);
+
+/****
+ * GetRegistryEntryProperties - Gets the registry entry properties for
+ * an io_service_t.
+ *****/
+
+static CFMutableDictionaryRef
+GetRegistryEntryProperties ( io_service_t service )
+{
+ IOReturn err = kIOReturnSuccess;
+ CFMutableDictionaryRef dict = 0;
+
+ err = IORegistryEntryCreateCFProperties (service, &dict, kCFAllocatorDefault, 0);
+ if ( err != kIOReturnSuccess )
+ cdio_warn( "IORegistryEntryCreateCFProperties: 0x%08x", err );
+
+ return dict;
}
-/****************************************************************************
- cdio_getNumberOfTracks: get number of tracks in TOC
- This is an internal routine and is called once per CD open.
- ****************************************************************************/
-static track_t
-_cdio_getNumberOfTracks( CDTOC *pTOC, int i_descriptors )
+
+static bool
+init_osx(_img_private_t *p_env) {
+ mach_port_t port;
+ char *psz_devname;
+ kern_return_t ret;
+ io_iterator_t iterator;
+
+ p_env->gen.fd = open( p_env->gen.source_name, O_RDONLY | O_NONBLOCK );
+ if (-1 == p_env->gen.fd) {
+ cdio_warn("Failed to open %s: %s", p_env->gen.source_name,
+ strerror(errno));
+ return false;
+ }
+
+ /* get the device name */
+ psz_devname = strrchr( p_env->gen.source_name, '/');
+ if( NULL != psz_devname )
+ ++psz_devname;
+ else
+ psz_devname = p_env->gen.source_name;
+
+ /* unraw the device name */
+ if( *psz_devname == 'r' )
+ ++psz_devname;
+
+ /* get port for IOKit communication */
+ ret = IOMasterPort( MACH_PORT_NULL, &port );
+
+ if( ret != KERN_SUCCESS )
+ {
+ cdio_warn( "IOMasterPort: 0x%08x", ret );
+ return false;
+ }
+
+ ret = IOServiceGetMatchingServices( port,
+ IOBSDNameMatching(port, 0, psz_devname),
+ &iterator );
+
+ /* get service iterator for the device */
+ if( ret != KERN_SUCCESS )
+ {
+ cdio_warn( "IOServiceGetMatchingServices: 0x%08x", ret );
+ return false;
+ }
+
+ /* first service */
+ p_env->MediaClass_service = IOIteratorNext( iterator );
+ IOObjectRelease( iterator );
+
+ /* search for kIOCDMediaClass or kIOCDVDMediaClass */
+ while( p_env->MediaClass_service &&
+ (!IOObjectConformsTo(p_env->MediaClass_service, kIOCDMediaClass)) &&
+ (!IOObjectConformsTo(p_env->MediaClass_service, kIODVDMediaClass)) )
+ {
+
+ ret = IORegistryEntryGetParentIterator( p_env->MediaClass_service,
+ kIOServicePlane,
+ &iterator );
+ if( ret != KERN_SUCCESS )
+ {
+ cdio_warn( "IORegistryEntryGetParentIterator: 0x%08x", ret );
+ IOObjectRelease( p_env->MediaClass_service );
+ return false;
+ }
+
+ IOObjectRelease( p_env->MediaClass_service );
+ p_env->MediaClass_service = IOIteratorNext( iterator );
+ IOObjectRelease( iterator );
+ }
+
+ if ( 0 == p_env->MediaClass_service ) {
+ cdio_warn( "search for kIOCDMediaClass/kIODVDMediaClass came up empty" );
+ return false;
+ }
+
+ /* Save the name so we can compare against this in case we have to do
+ another scan. FIXME: this is hoaky and there's got to be a better
+ variable to test or way to do.
+ */
+ IORegistryEntryGetPath(p_env->MediaClass_service, kIOServicePlane,
+ p_env->psz_MediaClass_service);
+ return true;
+}
+
+/*!
+ 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
+run_scsi_cmd_osx( 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 )
{
- track_t track = CDIO_INVALID_TRACK;
- int i;
- int i_tracks = 0;
- CDTOCDescriptor *pTrackDescriptors;
- pTrackDescriptors = pTOC->descriptors;
+#ifndef SCSI_MMC_FIXED
+ return 2;
+#else
+ const _img_private_t *p_env = p_user_data;
+ SCSITaskDeviceInterface **sc;
+ SCSITaskInterface **cmd = NULL;
+ IOVirtualRange iov;
+ SCSI_Sense_Data senseData;
+ SCSITaskStatus status;
+ UInt64 bytesTransferred;
+ IOReturn ioReturnValue;
+ int ret = 0;
+
+ if (NULL == p_user_data) return 2;
+
+ /* Make sure pp_scsiTaskDeviceInterface is initialized. FIXME: The code
+ should probably be reorganized better for this. */
+ if (!p_env->gen.toc_init) read_toc_osx (p_user_data) ;
+
+ sc = p_env->pp_scsiTaskDeviceInterface;
+
+ if (NULL == sc) return 3;
+
+ cmd = (*sc)->CreateSCSITask(sc);
+ if (cmd == NULL) {
+ cdio_warn("Failed to create SCSI task");
+ return -1;
+ }
+
+ iov.address = (IOVirtualAddress) p_buf;
+ iov.length = i_buf;
+
+ ioReturnValue = (*cmd)->SetCommandDescriptorBlock(cmd, (UInt8 *) p_cdb,
+ i_cdb);
+ if (ioReturnValue != kIOReturnSuccess) {
+ cdio_warn("SetCommandDescriptorBlock failed with status %x",
+ ioReturnValue);
+ return -1;
+ }
+
+ ioReturnValue = (*cmd)->SetScatterGatherEntries(cmd, &iov, 1, i_buf,
+ (SCSI_MMC_DATA_READ == e_direction ) ?
+ kSCSIDataTransfer_FromTargetToInitiator :
+ kSCSIDataTransfer_FromInitiatorToTarget);
+ if (ioReturnValue != kIOReturnSuccess) {
+ cdio_warn("SetScatterGatherEntries failed with status %x", ioReturnValue);
+ return -1;
+ }
+
+ ioReturnValue = (*cmd)->SetTimeoutDuration(cmd, i_timeout_ms );
+ if (ioReturnValue != kIOReturnSuccess) {
+ cdio_warn("SetTimeoutDuration failed with status %x", ioReturnValue);
+ return -1;
+ }
+
+ memset(&senseData, 0, sizeof(senseData));
- for( i = i_descriptors; i >= 0; i-- )
+ ioReturnValue = (*cmd)->ExecuteTaskSync(cmd,&senseData, &status, &
+ bytesTransferred);
+
+ if (ioReturnValue != kIOReturnSuccess) {
+ cdio_warn("Command execution failed with status %x", ioReturnValue);
+ return -1;
+ }
+
+ if (cmd != NULL) {
+ (*cmd)->Release(cmd);
+ }
+
+ return (ret);
+#endif
+}
+
+/***************************************************************************
+ * GetDeviceIterator - Gets an io_iterator_t for our class type
+ ***************************************************************************/
+
+static io_iterator_t
+GetDeviceIterator ( const char * deviceClass )
+{
+
+ IOReturn err = kIOReturnSuccess;
+ io_iterator_t iterator = MACH_PORT_NULL;
+
+ err = IOServiceGetMatchingServices ( kIOMasterPortDefault,
+ IOServiceMatching ( deviceClass ),
+ &iterator );
+ check ( err == kIOReturnSuccess );
+
+ return iterator;
+
+}
+
+/***************************************************************************
+ * GetFeaturesFlagsForDrive -Gets the bitfield which represents the
+ * features flags.
+ ***************************************************************************/
+
+static bool
+GetFeaturesFlagsForDrive ( CFDictionaryRef dict,
+ uint32_t *i_cdFlags,
+ uint32_t *i_dvdFlags )
+{
+ CFDictionaryRef propertiesDict = 0;
+ CFNumberRef flagsNumberRef = 0;
+
+ *i_cdFlags = 0;
+ *i_dvdFlags= 0;
+
+ propertiesDict = ( CFDictionaryRef )
+ CFDictionaryGetValue ( dict,
+ CFSTR ( kIOPropertyDeviceCharacteristicsKey ) );
+
+ if ( propertiesDict == 0 ) return false;
+
+ /* Get the CD features */
+ flagsNumberRef = ( CFNumberRef )
+ CFDictionaryGetValue ( propertiesDict,
+ CFSTR ( kIOPropertySupportedCDFeatures ) );
+ if ( flagsNumberRef != 0 ) {
+ CFNumberGetValue ( flagsNumberRef, kCFNumberLongType, i_cdFlags );
+ }
+
+ /* Get the DVD features */
+ flagsNumberRef = ( CFNumberRef )
+ CFDictionaryGetValue ( propertiesDict,
+ CFSTR ( kIOPropertySupportedDVDFeatures ) );
+ if ( flagsNumberRef != 0 ) {
+ CFNumberGetValue ( flagsNumberRef, kCFNumberLongType, i_dvdFlags );
+ }
+
+ return true;
+}
+
+/*!
+ Get disc type associated with the cd object.
+*/
+static discmode_t
+get_discmode_osx (void *p_user_data)
+{
+ _img_private_t *p_env = p_user_data;
+ char str[10];
+ int32_t i_discmode = CDIO_DISC_MODE_ERROR;
+ CFDictionaryRef propertiesDict = 0;
+ CFStringRef data;
+
+ propertiesDict = GetRegistryEntryProperties ( p_env->MediaClass_service );
+
+ if ( propertiesDict == 0 ) return i_discmode;
+
+ data = ( CFStringRef )
+ CFDictionaryGetValue ( propertiesDict, CFSTR ( kIODVDMediaTypeKey ) );
+
+ if( CFStringGetCString( data, str, sizeof(str),
+ kCFStringEncodingASCII ) ) {
+ if (0 == strncmp(str, "DVD+R", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_DVD_PR;
+ else if (0 == strncmp(str, "DVD+RW", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_DVD_PRW;
+ else if (0 == strncmp(str, "DVD-R", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_DVD_R;
+ else if (0 == strncmp(str, "DVD-RW", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_DVD_RW;
+ else if (0 == strncmp(str, "DVD-ROM", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_DVD_ROM;
+ else if (0 == strncmp(str, "DVD-RAM", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_DVD_RAM;
+ else if (0 == strncmp(str, "CD-ROM", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_CD_DATA;
+ else if (0 == strncmp(str, "CDR", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_CD_DATA;
+ else if (0 == strncmp(str, "CDRW", strlen(str)) )
+ i_discmode = CDIO_DISC_MODE_CD_DATA;
+ //?? Handled by below? CFRelease( data );
+ }
+ CFRelease( propertiesDict );
+ if (CDIO_DISC_MODE_CD_DATA == i_discmode) {
+ /* Need to do more classification */
+ return get_discmode_cd_generic(p_user_data);
+ }
+ return i_discmode;
+
+}
+
+static io_service_t
+get_drive_service_osx(const _img_private_t *p_env)
+{
+ io_service_t service;
+ io_iterator_t service_iterator;
+
+ service_iterator = GetDeviceIterator ( kIOCDBlockStorageDeviceClassString );
+
+ if( service_iterator == MACH_PORT_NULL ) return 0;
+
+ service = IOIteratorNext( service_iterator );
+ if( service == 0 ) return 0;
+
+ do
{
- track = pTrackDescriptors[i].point;
+ char psz_service[MAX_SERVICE_NAME];
+ IORegistryEntryGetPath(service, kIOServicePlane, psz_service);
+ psz_service[MAX_SERVICE_NAME-1] = '\0';
+
+ /* FIXME: This is all hoaky. Here we need info from a parent class,
+ psz_service of what we opened above. We are relying on the
+ fact that the name will be a substring of the name we
+ openned with.
+ */
+ if (0 == strncmp(psz_service, p_env->psz_MediaClass_service,
+ strlen(psz_service))) {
+ /* Found our device */
+ IOObjectRelease( service_iterator );
+ return service;
+ }
+
+ IOObjectRelease( service );
+
+ } while( ( service = IOIteratorNext( service_iterator ) ) != 0 );
- if( track > CDIO_CD_MAX_TRACKS || track < CDIO_CD_MIN_TRACK_NO )
- continue;
+ IOObjectRelease( service_iterator );
+ return service;
+}
- i_tracks++;
+static void
+get_drive_cap_osx(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;
+ uint32_t i_cdFlags;
+ uint32_t i_dvdFlags;
+
+ io_service_t service = get_drive_service_osx(p_env);
+
+ if( service == 0 ) goto err_exit;
+
+ /* Found our device */
+ {
+ CFDictionaryRef properties = GetRegistryEntryProperties ( service );
+
+ if (! GetFeaturesFlagsForDrive ( properties, &i_cdFlags,
+ &i_dvdFlags ) ) {
+ IOObjectRelease( service );
+ goto err_exit;
}
+
+ /* Reader */
+
+ if ( 0 != (i_cdFlags & kCDFeaturesAnalogAudioMask) )
+ *p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO;
+
+ if ( 0 != (i_cdFlags & kCDFeaturesWriteOnceMask) )
+ *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_R;
+
+ if ( 0 != (i_cdFlags & kCDFeaturesCDDAStreamAccurateMask) )
+ *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_DA;
+
+ if ( 0 != (i_dvdFlags & kDVDFeaturesReadStructuresMask) )
+ *p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM;
+
+ if ( 0 != (i_cdFlags & kCDFeaturesReWriteableMask) )
+ *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW;
+
+ if ( 0 != (i_dvdFlags & kDVDFeaturesWriteOnceMask) )
+ *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R;
+
+ if ( 0 != (i_dvdFlags & kDVDFeaturesRandomWriteableMask) )
+ *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM;
+
+ if ( 0 != (i_dvdFlags & kDVDFeaturesReWriteableMask) )
+ *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RW;
+
+ /***
+ if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRMask) )
+ *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PR;
+
+ if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRWMask )
+ *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PRW;
+ ***/
+
+ /* FIXME: fill out. For now assume CD-ROM is relatively modern. */
+ *p_misc_cap = (
+ CDIO_DRIVE_CAP_MISC_CLOSE_TRAY
+ | CDIO_DRIVE_CAP_MISC_EJECT
+ | CDIO_DRIVE_CAP_MISC_LOCK
+ | CDIO_DRIVE_CAP_MISC_SELECT_SPEED
+ | CDIO_DRIVE_CAP_MISC_MULTI_SESSION
+ | CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED
+ | CDIO_DRIVE_CAP_MISC_RESET
+ | CDIO_DRIVE_CAP_MCN
+ | CDIO_DRIVE_CAP_ISRC
+ );
+
+ IOObjectRelease( service );
+ }
+
+ return;
+
+ err_exit:
+ *p_misc_cap = *p_write_cap = *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
+ return;
+}
+
+#if 1
+/****************************************************************************
+ * GetDriveDescription - Gets drive description.
+ ****************************************************************************/
+
+static bool
+get_hwinfo_osx ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info)
+{
+ _img_private_t *p_env = (_img_private_t *) p_cdio->env;
+ io_service_t service = get_drive_service_osx(p_env);
+
+ if ( service == 0 ) return false;
+
+ /* Found our device */
+ {
+ CFStringRef vendor = NULL;
+ CFStringRef product = NULL;
+ CFStringRef revision = NULL;
+
+ CFDictionaryRef properties = GetRegistryEntryProperties ( service );
+ CFDictionaryRef deviceDict = ( CFDictionaryRef )
+ CFDictionaryGetValue ( properties,
+ CFSTR ( kIOPropertyDeviceCharacteristicsKey ) );
+
+ if ( deviceDict == 0 ) return false;
+
+ vendor = ( CFStringRef )
+ CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyVendorNameKey ) );
+
+ if ( CFStringGetCString( vendor,
+ (char *) &(hw_info->psz_vendor),
+ sizeof(hw_info->psz_vendor),
+ kCFStringEncodingASCII ) )
+ CFRelease( vendor );
+
+ product = ( CFStringRef )
+ CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyProductNameKey ) );
+
+ if ( CFStringGetCString( product,
+ (char *) &(hw_info->psz_model),
+ sizeof(hw_info->psz_model),
+ kCFStringEncodingASCII ) )
+ CFRelease( product );
+
+ revision = ( CFStringRef )
+ CFDictionaryGetValue ( deviceDict,
+ CFSTR ( kIOPropertyProductRevisionLevelKey ) );
+
+ if ( CFStringGetCString( product,
+ (char *) &(hw_info->psz_revision),
+ sizeof(hw_info->psz_revision),
+ kCFStringEncodingASCII ) )
+ CFRelease( revision );
+ }
+ return true;
+
+}
+#endif
+
+/*!
+ Return the media catalog number MCN.
+
+ Note: string is malloc'd so caller should free() then returned
+ string when done with it.
+
+ */
+static const cdtext_t *
+get_cdtext_osx (void *p_user_data, track_t i_track)
+{
+ return NULL;
+}
+
+static void
+_free_osx (void *p_user_data) {
+ _img_private_t *p_env = p_user_data;
+ if (NULL == p_env) return;
+ cdio_generic_free(p_env);
+ if (NULL != p_env->pp_lba) free((void *) p_env->pp_lba);
+ if (NULL != p_env->pTOC) free((void *) p_env->pTOC);
+ IOObjectRelease( p_env->MediaClass_service );
+
+ if (NULL != p_env->pp_scsiTaskDeviceInterface)
+ ( *(p_env->pp_scsiTaskDeviceInterface) )->
+ Release ( (p_env->pp_scsiTaskDeviceInterface) );
- return( i_tracks );
}
/*!
@@ -128,10 +644,10 @@ _cdio_getNumberOfTracks( CDTOC *pTOC, int i_descriptors )
Returns 0 if no error.
*/
static int
-_cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn,
- bool is_form2, unsigned int nblocks)
+_get_read_mode1_sectors_osx (void *user_data, void *data, lsn_t lsn,
+ bool b_form2, unsigned int nblocks)
{
- _img_private_t *_obj = env;
+ _img_private_t *env = user_data;
dk_cd_read_t cd_read;
memset( &cd_read, 0, sizeof(cd_read) );
@@ -140,7 +656,7 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn,
cd_read.buffer = data;
cd_read.sectorType = kCDSectorTypeMode1;
- if (is_form2) {
+ if (b_form2) {
cd_read.offset = lsn * kCDSectorSizeMode2;
cd_read.bufferLength = kCDSectorSizeMode2 * nblocks;
} else {
@@ -148,9 +664,9 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn,
cd_read.bufferLength = kCDSectorSizeMode1 * nblocks;
}
- if( ioctl( _obj->gen.fd, DKIOCCDREAD, &cd_read ) == -1 )
+ if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 )
{
- cdio_error( "could not read block %d, %s", lsn, strerror(errno) );
+ cdio_info( "could not read block %d, %s", lsn, strerror(errno) );
return -1;
}
return 0;
@@ -163,10 +679,10 @@ _cdio_read_mode1_sectors (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,
- bool is_form2, unsigned int nblocks)
+_get_read_mode2_sectors_osx (void *user_data, void *data, lsn_t lsn,
+ bool b_form2, unsigned int nblocks)
{
- _img_private_t *_obj = env;
+ _img_private_t *env = user_data;
dk_cd_read_t cd_read;
memset( &cd_read, 0, sizeof(cd_read) );
@@ -174,7 +690,7 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn,
cd_read.sectorArea = kCDSectorAreaUser;
cd_read.buffer = data;
- if (is_form2) {
+ if (b_form2) {
cd_read.offset = lsn * kCDSectorSizeMode2Form2;
cd_read.sectorType = kCDSectorTypeMode2Form2;
cd_read.bufferLength = kCDSectorSizeMode2Form2 * nblocks;
@@ -184,9 +700,9 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn,
cd_read.bufferLength = kCDSectorSizeMode2Form1 * nblocks;
}
- if( ioctl( _obj->gen.fd, DKIOCCDREAD, &cd_read ) == -1 )
+ if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 )
{
- cdio_error( "could not read block %d, %s", lsn, strerror(errno) );
+ cdio_info( "could not read block %d, %s", lsn, strerror(errno) );
return -1;
}
return 0;
@@ -198,24 +714,24 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn,
Returns 0 if no error.
*/
static int
-_cdio_read_audio_sectors (void *env, void *data, lsn_t lsn,
- unsigned int nblocks)
+_get_read_audio_sectors_osx (void *user_data, void *data, lsn_t lsn,
+ unsigned int nblocks)
{
- _img_private_t *_obj = env;
+ _img_private_t *env = user_data;
dk_cd_read_t cd_read;
memset( &cd_read, 0, sizeof(cd_read) );
- cd_read.offset = lsn * kCDSectorSizeCDDA;
- cd_read.sectorArea = kCDSectorAreaUser;
- cd_read.sectorType = kCDSectorTypeCDDA;
+ cd_read.offset = lsn * kCDSectorSizeCDDA;
+ cd_read.sectorArea = kCDSectorAreaUser;
+ cd_read.sectorType = kCDSectorTypeCDDA;
- cd_read.buffer = data;
+ cd_read.buffer = data;
cd_read.bufferLength = kCDSectorSizeCDDA * nblocks;
- if( ioctl( _obj->gen.fd, DKIOCCDREAD, &cd_read ) == -1 )
+ if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 )
{
- cdio_error( "could not read block %d", lsn );
+ cdio_info( "could not read block %d", lsn );
return -1;
}
return 0;
@@ -226,10 +742,10 @@ _cdio_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,
- bool is_form2)
+_get_read_mode1_sector_osx (void *user_data, void *data, lsn_t lsn,
+ bool b_form2)
{
- return _cdio_read_mode1_sectors(env, data, lsn, is_form2, 1);
+ return _get_read_mode1_sectors_osx(user_data, data, lsn, b_form2, 1);
}
/*!
@@ -237,35 +753,35 @@ _cdio_read_mode1_sector (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 is_form2)
+_get_read_mode2_sector_osx (void *user_data, void *data, lsn_t lsn,
+ bool b_form2)
{
- return _cdio_read_mode2_sectors(env, data, lsn, is_form2, 1);
+ return _get_read_mode2_sectors_osx(user_data, data, lsn, b_form2, 1);
}
/*!
Set the key "arg" to "value" in source device.
*/
static int
-_cdio_set_arg (void *env, const char key[], const char value[])
+_set_arg_osx (void *user_data, const char key[], const char value[])
{
- _img_private_t *_obj = env;
+ _img_private_t *env = user_data;
if (!strcmp (key, "source"))
{
if (!value)
return -2;
- free (_obj->gen.source_name);
+ free (env->gen.source_name);
- _obj->gen.source_name = strdup (value);
+ env->gen.source_name = strdup (value);
}
else if (!strcmp (key, "access-mode"))
{
if (!strcmp(value, "OSX"))
- _obj->access_mode = _AM_OSX;
+ env->access_mode = _AM_OSX;
else
- cdio_error ("unknown access type: %s. ignored.", value);
+ cdio_warn ("unknown access type: %s. ignored.", value);
}
else
return -1;
@@ -273,168 +789,194 @@ _cdio_set_arg (void *env, const char key[], const char value[])
return 0;
}
+#if 0
+static void TestDevice(_img_private_t *p_env, io_service_t service)
+{
+ SInt32 score;
+ HRESULT herr;
+ kern_return_t err;
+ IOCFPlugInInterface **plugInInterface = NULL;
+ MMCDeviceInterface **mmcInterface = NULL;
+
+ /* Create the IOCFPlugIn interface so we can query it. */
+
+ err = IOCreatePlugInInterfaceForService ( service,
+ kIOMMCDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &plugInInterface,
+ &score );
+ if ( err != noErr ) {
+ printf("IOCreatePlugInInterfaceForService returned %d\n", err);
+ return;
+ }
+
+ /* Query the interface for the MMCDeviceInterface. */
+
+ herr = ( *plugInInterface )->QueryInterface ( plugInInterface,
+ CFUUIDGetUUIDBytes ( kIOMMCDeviceInterfaceID ),
+ ( LPVOID ) &mmcInterface );
+
+ if ( herr != S_OK ) {
+ printf("QueryInterface returned %ld\n", herr);
+ return;
+ }
+
+ p_env->pp_scsiTaskDeviceInterface =
+ ( *mmcInterface )->GetSCSITaskDeviceInterface ( mmcInterface );
+
+ if ( NULL == p_env->pp_scsiTaskDeviceInterface ) {
+ printf("GetSCSITaskDeviceInterface returned NULL\n");
+ return;
+ }
+
+ ( *mmcInterface )->Release ( mmcInterface );
+ IODestroyPlugInInterface ( plugInInterface );
+}
+#endif
+
/*!
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_osx (void *p_user_data)
{
- mach_port_t port;
- char *psz_devname;
- kern_return_t ret;
- io_iterator_t iterator;
- io_registry_entry_t service;
- CFMutableDictionaryRef properties;
+ _img_private_t *p_env = p_user_data;
+ CFDictionaryRef propertiesDict = 0;
CFDataRef data;
-
- _obj->gen.fd = open( _obj->gen.source_name, O_RDONLY | O_NONBLOCK );
- if (-1 == _obj->gen.fd) {
- cdio_error("Failed to open %s: %s", _obj->gen.source_name,
- strerror(errno));
+
+ /* create a CF dictionary containing the TOC */
+ propertiesDict = GetRegistryEntryProperties( p_env->MediaClass_service );
+
+ if ( 0 == propertiesDict ) {
return false;
}
- /* get the device name */
- if( ( psz_devname = strrchr( _obj->gen.source_name, '/') ) != NULL )
- ++psz_devname;
- else
- psz_devname = _obj->gen.source_name;
-
- /* unraw the device name */
- if( *psz_devname == 'r' )
- ++psz_devname;
-
- /* get port for IOKit communication */
- if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS )
- {
- cdio_error( "IOMasterPort: 0x%08x", ret );
- return false;
- }
-
- /* get service iterator for the device */
- if( ( ret = IOServiceGetMatchingServices(
- port, IOBSDNameMatching( port, 0, psz_devname ),
- &iterator ) ) != KERN_SUCCESS )
- {
- cdio_error( "IOServiceGetMatchingServices: 0x%08x", ret );
- return false;
- }
-
- /* first service */
- service = IOIteratorNext( iterator );
- IOObjectRelease( iterator );
-
- /* search for kIOCDMediaClass */
- while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) )
- {
-
- ret = IORegistryEntryGetParentIterator( service, kIOServicePlane,
- &iterator );
- if( ret != KERN_SUCCESS )
- {
- cdio_error( "IORegistryEntryGetParentIterator: 0x%08x", ret );
- IOObjectRelease( service );
- return false;
- }
-
- IOObjectRelease( service );
- service = IOIteratorNext( iterator );
- IOObjectRelease( iterator );
- }
-
- if( service == 0 )
- {
- cdio_error( "search for kIOCDMediaClass came up empty" );
- return false;
- }
-
- /* create a CF dictionary containing the TOC */
- ret = IORegistryEntryCreateCFProperties( service, &properties,
- kCFAllocatorDefault, kNilOptions );
-
- if( ret != KERN_SUCCESS )
- {
- cdio_error( "IORegistryEntryCreateCFProperties: 0x%08x", ret );
- IOObjectRelease( service );
- return false;
- }
-
/* get the TOC from the dictionary */
- data = (CFDataRef) CFDictionaryGetValue( properties,
+ data = (CFDataRef) CFDictionaryGetValue( propertiesDict,
CFSTR(kIOCDMediaTOCKey) );
- if( data != NULL )
- {
- CFRange range;
- CFIndex buf_len;
-
- buf_len = CFDataGetLength( data ) + 1;
- range = CFRangeMake( 0, buf_len );
-
- if( ( _obj->pTOC = (CDTOC *)malloc( buf_len ) ) != NULL ) {
- CFDataGetBytes( data, range, (u_char *) _obj->pTOC );
- } else {
- cdio_error( "Trouble allocating CDROM TOC" );
- return false;
- }
- }
- else
- {
- cdio_error( "CFDictionaryGetValue failed" );
+ if ( data != NULL ) {
+ CFRange range;
+ CFIndex buf_len;
+
+ buf_len = CFDataGetLength( data ) + 1;
+ range = CFRangeMake( 0, buf_len );
+
+ if( ( p_env->pTOC = (CDTOC *)malloc( buf_len ) ) != NULL ) {
+ CFDataGetBytes( data, range, (u_char *) p_env->pTOC );
+ } else {
+ cdio_warn( "Trouble allocating CDROM TOC" );
+ return false;
}
-
- CFRelease( properties );
- IOObjectRelease( service );
+ } else {
+ cdio_warn( "Trouble reading TOC" );
+ return false;
+ }
- _obj->i_descriptors = CDTOCGetDescriptorCount ( _obj->pTOC );
- _obj->num_tracks = _cdio_getNumberOfTracks(_obj->pTOC, _obj->i_descriptors);
+ /* TestDevice(p_env, service); */
+ CFRelease( propertiesDict );
- /* Read in starting sectors */
+ p_env->i_descriptors = CDTOCGetDescriptorCount ( p_env->pTOC );
+
+ /* Read in starting sectors. There may be non-tracks mixed in with
+ the real tracks. So find the first and last track number by
+ scanning. Also find the lead-out track position.
+ */
{
int i, i_leadout = -1;
+
CDTOCDescriptor *pTrackDescriptors;
- track_t track;
- int i_tracks;
- _obj->pp_lba = malloc( (_obj->num_tracks + 1) * sizeof(int) );
- if( _obj->pp_lba == NULL )
+ p_env->pp_lba = malloc( p_env->i_descriptors * sizeof(int) );
+ if( p_env->pp_lba == NULL )
{
- cdio_error("Out of memory in allocating track starting LSNs" );
- free( _obj->pTOC );
+ cdio_warn("Out of memory in allocating track starting LSNs" );
+ free( p_env->pTOC );
return false;
}
- pTrackDescriptors = _obj->pTOC->descriptors;
+ pTrackDescriptors = p_env->pTOC->descriptors;
+
+ p_env->gen.i_first_track = CDIO_CD_MAX_TRACKS+1;
+ p_env->i_last_track = CDIO_CD_MIN_TRACK_NO;
+ p_env->i_first_session = CDIO_CD_MAX_TRACKS+1;
+ p_env->i_last_session = CDIO_CD_MIN_TRACK_NO;
- for( i_tracks = 0, i = 0; i <= _obj->i_descriptors; i++ )
+ for( i = 0; i <= p_env->i_descriptors; i++ )
{
- track = pTrackDescriptors[i].point;
+ track_t i_track = pTrackDescriptors[i].point;
+ session_t i_session = pTrackDescriptors[i].session;
+
+ cdio_debug( "point: %d, tno: %d, session: %d, adr: %d, control:%d, "
+ "address: %d:%d:%d, p: %d:%d:%d",
+ i_track,
+ pTrackDescriptors[i].tno, i_session,
+ pTrackDescriptors[i].adr, pTrackDescriptors[i].control,
+ pTrackDescriptors[i].address.minute,
+ pTrackDescriptors[i].address.second,
+ pTrackDescriptors[i].address.frame,
+ pTrackDescriptors[i].p.minute,
+ pTrackDescriptors[i].p.second,
+ pTrackDescriptors[i].p.frame );
+
+ /* track information has adr = 1 */
+ if ( 0x01 != pTrackDescriptors[i].adr )
+ continue;
- if( track == 0xA2 )
- /* Note leadout should be 0xAA, But OSX seems to use 0xA2. */
+ if( i_track == OSX_CDROM_LEADOUT_TRACK )
i_leadout = i;
-
- if( track > CDIO_CD_MAX_TRACKS || track < CDIO_CD_MIN_TRACK_NO )
+
+ if( i_track > CDIO_CD_MAX_TRACKS || i_track < CDIO_CD_MIN_TRACK_NO )
continue;
+
+ if (p_env->gen.i_first_track > i_track)
+ p_env->gen.i_first_track = i_track;
+
+ if (p_env->i_last_track < i_track)
+ p_env->i_last_track = i_track;
- _obj->pp_lba[i_tracks++] =
+ if (p_env->i_first_session > i_session)
+ p_env->i_first_session = i_session;
+
+ if (p_env->i_last_session < i_session)
+ p_env->i_last_session = i_session;
+ }
+
+ /* Now that we know what the first track number is, we can make sure
+ index positions are ordered starting at 0.
+ */
+ for( i = 0; i <= p_env->i_descriptors; i++ )
+ {
+ track_t i_track = pTrackDescriptors[i].point;
+
+ if( i_track > CDIO_CD_MAX_TRACKS || i_track < CDIO_CD_MIN_TRACK_NO )
+ continue;
+
+ /* Note what OSX calls a LBA we call an LSN. So below re we
+ really have have MSF -> LSN -> LBA.
+ */
+ p_env->pp_lba[i_track - p_env->gen.i_first_track] =
cdio_lsn_to_lba(CDConvertMSFToLBA( pTrackDescriptors[i].p ));
}
if( i_leadout == -1 )
{
- cdio_error( "CD leadout not found" );
- free( _obj->pp_lba );
- free( (void *) _obj->pTOC );
+ cdio_warn( "CD leadout not found" );
+ free( p_env->pp_lba );
+ free( (void *) p_env->pTOC );
return false;
}
- /* set leadout sector */
- _obj->pp_lba[i_tracks] =
+ /* Set leadout sector.
+ Note what OSX calls a LBA we call an LSN. So below re we
+ really have have MSF -> LSN -> LBA.
+ */
+ p_env->pp_lba[TOTAL_TRACKS] =
cdio_lsn_to_lba(CDConvertMSFToLBA( pTrackDescriptors[i_leadout].p ));
+ p_env->gen.i_tracks = TOTAL_TRACKS;
}
- _obj->toc_init = true;
+ p_env->gen.toc_init = true;
return( true );
@@ -442,24 +984,25 @@ _cdio_read_toc (_img_private_t *_obj)
/*!
Return the starting LSN 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 lsn_t
-_cdio_get_track_lba(void *env, track_t track_num)
+get_track_lba_osx(void *p_user_data, track_t i_track)
{
- _img_private_t *_obj = env;
+ _img_private_t *p_env = p_user_data;
- if (!_obj->toc_init) _cdio_read_toc (_obj) ;
+ if (!p_env->gen.toc_init) read_toc_osx (p_env) ;
+ if (!p_env->gen.toc_init) return CDIO_INVALID_LSN;
- if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1;
+ if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->i_last_track+1;
- if (track_num > TOTAL_TRACKS+1 || track_num == 0) {
+ if (i_track > p_env->i_last_track + 1 || i_track < p_env->gen.i_first_track) {
return CDIO_INVALID_LSN;
} else {
- return _obj->pp_lba[track_num-1];
+ return p_env->pp_lba[i_track - p_env->gen.i_first_track];
}
}
@@ -474,18 +1017,18 @@ _cdio_get_track_lba(void *env, track_t track_num)
*/
static int
-_cdio_eject_media (void *env) {
+_eject_media_osx (void *user_data) {
- _img_private_t *_obj = env;
+ _img_private_t *p_env = user_data;
FILE *p_eject;
char *psz_disk;
char sz_cmd[32];
- if( ( psz_disk = (char *)strstr( _obj->gen.source_name, "disk" ) ) != NULL &&
+ if( ( psz_disk = (char *)strstr( p_env->gen.source_name, "disk" ) ) != NULL &&
strlen( psz_disk ) > 4 )
{
-#define EJECT_CMD "/usr/sbin/disktool -e %s 0"
+#define EJECT_CMD "/usr/sbin/hdiutil eject %s"
snprintf( sz_cmd, sizeof(sz_cmd), EJECT_CMD, psz_disk );
#undef EJECT_CMD
@@ -518,23 +1061,23 @@ _cdio_eject_media (void *env) {
Return the size of the CD in logical block address (LBA) units.
*/
static uint32_t
-_cdio_stat_size (void *env)
+_stat_size_osx (void *user_data)
{
- return _cdio_get_track_lba(env, CDIO_CDROM_LEADOUT_TRACK);
+ return get_track_lba_osx(user_data, CDIO_CDROM_LEADOUT_TRACK);
}
/*!
Return the value associated with the key "arg".
*/
static const char *
-_cdio_get_arg (void *env, const char key[])
+_get_arg_osx (void *user_data, const char key[])
{
- _img_private_t *_obj = env;
+ _img_private_t *p_env = user_data;
if (!strcmp (key, "source")) {
- return _obj->gen.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_OSX:
return "OS X";
case _AM_NONE:
@@ -545,101 +1088,67 @@ _cdio_get_arg (void *env, const char key[])
}
/*!
- Return the number 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) ;
-
- {
- track_t track = CDIO_INVALID_TRACK;
- int i;
- CDTOCDescriptor *pTrackDescriptors;
-
- pTrackDescriptors = _obj->pTOC->descriptors;
-
- for( i = 0; i < _obj->i_descriptors; i++ )
- {
- track = pTrackDescriptors[i].point;
-
- if( track > CDIO_CD_MAX_TRACKS || track < CDIO_CD_MIN_TRACK_NO )
- continue;
- return ( track );
- }
- }
-
- return CDIO_INVALID_TRACK;
-}
-
-/*!
Return the media catalog number MCN.
*/
static char *
-_cdio_get_mcn (void *env) {
- _img_private_t *_obj = env;
+get_mcn_osx (const void *user_data) {
+ const _img_private_t *p_env = user_data;
dk_cd_read_mcn_t cd_read;
memset( &cd_read, 0, sizeof(cd_read) );
- if( ioctl( _obj->gen.fd, DKIOCCDREADMCN, &cd_read ) < 0 )
+ if( ioctl( p_env->gen.fd, DKIOCCDREADMCN, &cd_read ) < 0 )
{
- cdio_error( "could not read MCN, %s", strerror(errno) );
+ cdio_debug( "could not read MCN, %s", strerror(errno) );
return NULL;
}
return strdup((char*)cd_read.mcn);
}
-/*!
- Return the number of tracks in the current medium.
- CDIO_INVALID_TRACK is returned on error.
- This is the externally called interface.
-*/
-static track_t
-_cdio_get_num_tracks(void *env)
-{
- _img_private_t *_obj = env;
-
- if (!_obj->toc_init) _cdio_read_toc (_obj) ;
- return( _obj->num_tracks );
-}
-
/*!
Get format of track.
*/
static track_format_t
-_cdio_get_track_format(void *env, track_t track_num)
+get_track_format_osx(void *user_data, track_t i_track)
{
- _img_private_t *_obj = env;
+ _img_private_t *p_env = user_data;
+ dk_cd_read_track_info_t cd_read;
CDTrackInfo a_track;
-
- if (!_obj->toc_init) _cdio_read_toc (_obj) ;
- if (track_num > TOTAL_TRACKS || track_num == 0)
+ if (!p_env->gen.toc_init) read_toc_osx (p_env) ;
+
+ if (i_track > p_env->i_last_track || i_track < p_env->gen.i_first_track)
return TRACK_FORMAT_ERROR;
- dk_cd_read_track_info_t cd_read;
memset( &cd_read, 0, sizeof(cd_read) );
- cd_read.address = track_num;
+ cd_read.address = i_track;
cd_read.addressType = kCDTrackInfoAddressTypeTrackNumber;
cd_read.buffer = &a_track;
cd_read.bufferLength = sizeof(CDTrackInfo);
- if( ioctl( _obj->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 )
+ if( ioctl( p_env->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 )
{
- cdio_error( "could not read trackinfo for track %d", track_num );
- return -1;
+ cdio_warn( "could not read trackinfo for track %d", i_track );
+ return TRACK_FORMAT_ERROR;
}
- cdio_warn( "trackinfo trackMode: %x dataMode: %x", a_track.trackMode, a_track.dataMode );
+ cdio_debug( "%d: trackinfo trackMode: %x dataMode: %x", i_track, a_track.trackMode, a_track.dataMode );
+
+ if (a_track.trackMode == CDIO_CDROM_DATA_TRACK) {
+ if (a_track.dataMode == CDROM_CDI_TRACK) {
+ return TRACK_FORMAT_CDI;
+ } else if (a_track.dataMode == CDROM_XA_TRACK) {
+ return TRACK_FORMAT_XA;
+ } else {
+ return TRACK_FORMAT_DATA;
+ }
+ } else {
+ return TRACK_FORMAT_AUDIO;
+ }
- return TRACK_FORMAT_AUDIO;
}
/*!
@@ -651,25 +1160,34 @@ _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_osx(void *user_data, track_t i_track)
{
+ _img_private_t *p_env = user_data;
+ CDTrackInfo a_track;
-#if 0
- if (!_obj->toc_init) _cdio_read_toc (_obj) ;
-
- if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1;
+ if (!p_env->gen.toc_init) read_toc_osx (p_env) ;
- if (track_num > TOTAL_TRACKS+1 || track_num == 0)
+ if ( i_track > p_env->i_last_track || i_track < p_env->gen.i_first_track )
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);
-#else
- /* FIXME! Figure out how to do. */
- return true;
-#endif
+ else {
+
+ dk_cd_read_track_info_t cd_read;
+
+ memset( &cd_read, 0, sizeof(cd_read) );
+
+ cd_read.address = i_track;
+ cd_read.addressType = kCDTrackInfoAddressTypeTrackNumber;
+
+ cd_read.buffer = &a_track;
+ cd_read.bufferLength = sizeof(CDTrackInfo);
+
+ if( ioctl( p_env->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 ) {
+ cdio_warn( "could not read trackinfo for track %d", i_track );
+ return false;
+ }
+ return ((a_track.trackMode & CDIO_CDROM_DATA_TRACK) != 0);
+ }
}
#endif /* HAVE_DARWIN_CDROM */
@@ -694,13 +1212,13 @@ cdio_get_devices_osx(void)
kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
if( kern_result != KERN_SUCCESS )
{
- return( nil );
+ return( NULL );
}
classes_to_match = IOServiceMatching( kIOCDMediaClass );
if( classes_to_match == NULL )
{
- return( nil );
+ return( NULL );
}
CFDictionarySetValue( classes_to_match, CFSTR(kIOMediaEjectableKey),
@@ -711,7 +1229,7 @@ cdio_get_devices_osx(void)
&media_iterator );
if( kern_result != KERN_SUCCESS )
{
- return( nil );
+ return( NULL );
}
next_media = IOIteratorNext( media_iterator );
@@ -744,7 +1262,7 @@ cdio_get_devices_osx(void)
CFRelease( str_bsd_path );
IOObjectRelease( next_media );
IOObjectRelease( media_iterator );
- cdio_add_device_list(&drives, psz_buf, &num_drives);
+ cdio_add_device_list(&drives, strdup(psz_buf), &num_drives);
}
CFRelease( str_bsd_path );
@@ -776,13 +1294,13 @@ cdio_get_default_device_osx(void)
kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
if( kern_result != KERN_SUCCESS )
{
- return( nil );
+ return( NULL );
}
classes_to_match = IOServiceMatching( kIOCDMediaClass );
if( classes_to_match == NULL )
{
- return( nil );
+ return( NULL );
}
CFDictionarySetValue( classes_to_match, CFSTR(kIOMediaEjectableKey),
@@ -793,7 +1311,7 @@ cdio_get_default_device_osx(void)
&media_iterator );
if( kern_result != KERN_SUCCESS )
{
- return( nil );
+ return( NULL );
}
next_media = IOIteratorNext( media_iterator );
@@ -845,55 +1363,90 @@ cdio_get_default_device_osx(void)
ones to set that up.
*/
CdIo *
-cdio_open_osx (const char *orig_source_name)
+cdio_open_am_osx (const char *psz_source_name, const char *psz_access_mode)
+{
+
+ if (psz_access_mode != NULL)
+ cdio_warn ("there is only one access mode for OS X. Arg %s ignored",
+ psz_access_mode);
+ return cdio_open_osx(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_osx (const char *psz_orig_source)
{
#ifdef HAVE_DARWIN_CDROM
CdIo *ret;
_img_private_t *_data;
- char *source_name;
+ char *psz_source;
cdio_funcs _funcs = {
- .eject_media = _cdio_eject_media,
- .free = _cdio_osx_free,
- .get_arg = _cdio_get_arg,
+ .eject_media = _eject_media_osx,
+ .free = _free_osx,
+ .get_arg = _get_arg_osx,
+ .get_cdtext = get_cdtext_osx,
.get_default_device = cdio_get_default_device_osx,
.get_devices = cdio_get_devices_osx,
- .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_track_lba = _cdio_get_track_lba,
+ .get_discmode = get_discmode_osx,
+ .get_drive_cap = get_drive_cap_osx,
+ .get_first_track_num= get_first_track_num_generic,
+ .get_hwinfo = get_hwinfo_osx,
+ .get_mcn = get_mcn_osx,
+ .get_num_tracks = get_num_tracks_generic,
+ .get_track_format = get_track_format_osx,
+ .get_track_green = get_track_green_osx,
+ .get_track_lba = get_track_lba_osx,
.get_track_msf = NULL,
.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 = _get_read_audio_sectors_osx,
+ .read_mode1_sector = _get_read_mode1_sector_osx,
+ .read_mode1_sectors = _get_read_mode1_sectors_osx,
+ .read_mode2_sector = _get_read_mode2_sector_osx,
+ .read_mode2_sectors = _get_read_mode2_sectors_osx,
+ .read_toc = read_toc_osx,
+ .run_scsi_mmc_cmd = run_scsi_cmd_osx,
+ .set_arg = _set_arg_osx,
+ .stat_size = _stat_size_osx
};
_data = _cdio_malloc (sizeof (_img_private_t));
_data->access_mode = _AM_OSX;
- _data->gen.init = false;
- _data->gen.fd = -1;
-
- 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);
+ _data->MediaClass_service = 0;
+ _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_osx();
+ if (NULL == psz_source) return NULL;
+ _set_arg_osx(_data, "source", psz_source);
+ free(psz_source);
+ } else {
+ if (cdio_is_device_generic(psz_orig_source))
+ _set_arg_osx(_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 a not a device", psz_orig_source);
+#endif
+ return NULL;
+ }
+ }
+
+ ret = cdio_new ((void *)_data, &_funcs);
if (ret == NULL) return NULL;
- if (cdio_generic_init(_data))
+ if (cdio_generic_init(_data) && init_osx(_data))
return ret;
else {
cdio_generic_free (_data);