From 1949a54ec952a7cfab1d22c3ae02b59a1be80cd5 Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 28 Aug 2004 09:15:41 +0000 Subject: [PATCH] _cdio_osx.c: add getting hw info. Get some read/write capabilities and disc info. *generic*: split off CD discmode classification so it can be used by OSX cdio: env -> p_env --- lib/_cdio_generic.c | 19 ++- lib/_cdio_osx.c | 312 +++++++++++++++++++++++++++++++------------- lib/cdio.c | 26 ++-- lib/cdio_private.h | 6 +- lib/generic.h | 7 +- 5 files changed, 260 insertions(+), 110 deletions(-) diff --git a/lib/_cdio_generic.c b/lib/_cdio_generic.c index df8418bc..3e4f3b35 100644 --- a/lib/_cdio_generic.c +++ b/lib/_cdio_generic.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_generic.c,v 1.24 2004/08/13 13:04:37 rocky Exp $ + $Id: _cdio_generic.c,v 1.25 2004/08/28 09:15:41 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.24 2004/08/13 13:04:37 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.25 2004/08/28 09:15:41 rocky Exp $"; #include #include @@ -267,8 +267,6 @@ discmode_t get_discmode_generic (void *p_user_data ) { generic_img_private_t *p_env = p_user_data; - track_t i_track; - discmode_t discmode=CDIO_DISC_MODE_NO_INFO; /* See if this is a DVD. */ cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ @@ -287,6 +285,19 @@ get_discmode_generic (void *p_user_data ) } } + return get_discmode_cd_generic(p_user_data); +} + +/*! + Get disc type associated with cd object. +*/ +discmode_t +get_discmode_cd_generic (void *p_user_data ) +{ + generic_img_private_t *p_env = p_user_data; + track_t i_track; + discmode_t discmode=CDIO_DISC_MODE_NO_INFO; + if (!p_env->toc_init) p_env->cdio->op.read_toc (p_user_data); diff --git a/lib/_cdio_osx.c b/lib/_cdio_osx.c index 50ccf400..3960eb49 100644 --- a/lib/_cdio_osx.c +++ b/lib/_cdio_osx.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_osx.c,v 1.60 2004/08/27 02:59:25 rocky Exp $ + $Id: _cdio_osx.c,v 1.61 2004/08/28 09:15:41 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein from vcdimager code: @@ -34,7 +34,7 @@ #include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.60 2004/08/27 02:59:25 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.61 2004/08/28 09:15:41 rocky Exp $"; #include #include @@ -70,9 +70,6 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.60 2004/08/27 02:59:25 rocky #include #include -#include -#include -#include #include #include #include @@ -80,10 +77,13 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.60 2004/08/27 02:59:25 rocky #include #include #include +#include #include #include #include +#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 @@ -98,6 +98,7 @@ typedef enum { _AM_OSX, } access_mode_t; +#define MAX_SERVICE_NAME 1000 typedef struct { /* Things common to all drivers like this. This must be first. */ @@ -115,6 +116,7 @@ typedef struct { lsn_t *pp_lba; CFMutableDictionaryRef dict; io_service_t MediaClass_service; + char psz_MediaClass_service[MAX_SERVICE_NAME]; SCSITaskDeviceInterface **pp_scsiTaskDeviceInterface; } _img_private_t; @@ -192,9 +194,10 @@ init_osx(_img_private_t *p_env) { p_env->MediaClass_service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); - /* search for kIOCDMediaClass */ + /* search for kIOCDMediaClass or kIOCDVDMediaClass */ while( p_env->MediaClass_service && - !IOObjectConformsTo( p_env->MediaClass_service, kIOCDMediaClass ) ) + (!IOObjectConformsTo(p_env->MediaClass_service, kIOCDMediaClass)) && + (!IOObjectConformsTo(p_env->MediaClass_service, kIODVDMediaClass)) ) { ret = IORegistryEntryGetParentIterator( p_env->MediaClass_service, @@ -230,6 +233,9 @@ init_osx(_img_private_t *p_env) { IOObjectRelease( p_env->MediaClass_service ); return false; } + + IORegistryEntryGetPath(p_env->MediaClass_service, kIOServicePlane, + p_env->psz_MediaClass_service); return true; } @@ -329,6 +335,26 @@ run_scsi_cmd_osx( const void *p_user_data, #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. @@ -370,112 +396,218 @@ GetFeaturesFlagsForDrive ( CFDictionaryRef dict, 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", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_PR; + else if (0 == strncmp(str, "DVD+RW", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_PRW; + else if (0 == strncmp(str, "DVD-R", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_R; + else if (0 == strncmp(str, "DVD-ROM", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_ROM; + else if (0 == strncmp(str, "DVD-RAM", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_RAM; + else if (0 == strncmp(str, "CD-ROM", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_CD_DA; + else if (0 == strncmp(str, "CDR", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_CD_DATA; + else if (0 == strncmp(str, "CDRW", sizeof(str)) ) + i_discmode = CDIO_DISC_MODE_CD_DATA; + 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 + { + 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 ); + + IOObjectRelease( service_iterator ); + return service; +} + 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) { -#if 1 - *p_misc_cap = *p_write_cap = *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; - return; -#else const _img_private_t *p_env = p_user_data; uint32_t i_cdFlags; uint32_t i_dvdFlags; - properties = GetRegistryEntryProperties ( ??service ); + io_service_t service = get_drive_service_osx(p_env); + + if( service == 0 ) goto err_exit; - if (! GetFeaturesFlagsForDrive ( properties, &i_cdFlags, &i_dvdFlags ) ) - return; - - /* 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) ) + /* 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; + ***/ - 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; + /* FIXME: fill out */ + *p_misc_cap = 0; - /*** - if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRMask) ) - *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PR; + IOObjectRelease( service ); + } - if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRWMask ) - *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PRW; - ***/ -#endif + return; + err_exit: + *p_misc_cap = *p_write_cap = *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; + return; } -#if ADDED_DRIVE_INFO +#if 1 /**************************************************************************** * GetDriveDescription - Gets drive description. ****************************************************************************/ static bool -GetDriveDescription ( CFMutableDictionaryRef dict, - /*out*/ cdio_hwinfo_t *hw_info) +get_hwinfo_osx ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info) { - - CFDictionaryRef deviceDict = NULL; - CFStringRef vendor = NULL; - CFStringRef product = NULL; - CFStringRef revision = NULL; - - if ( dict != 0 ) return false; - - deviceDict = ( CFDictionaryRef ) - CFDictionaryGetValue ( dict, - CFSTR ( kIOPropertyDeviceCharacteristicsKey ) ); + _img_private_t *p_env = (_img_private_t *) p_cdio->env; + io_service_t service = get_drive_service_osx(p_env); - if ( deviceDict != 0 ) return false; + if ( service == 0 ) return false; - vendor = ( CFStringRef ) - CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyVendorNameKey ) ); - - if( CFStringGetCString( vendor, - (char *) &(hw_info->vendor), - sizeof(hw_info->vendor), - kCFStringEncodingASCII ) ) - CFRelease( vendor ); - - product = ( CFStringRef ) - CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyProductNameKey ) ); - - if( CFStringGetCString( product, - (char *) &(hw_info->model), - sizeof(hw_info->model), - kCFStringEncodingASCII ) ) - CFRelease( product ); - - revision = ( CFStringRef ) - CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyProductRevisionLevelKey ) ); - - if( CFStringGetCString( product, - (char *) &(hw_info->revision), - sizeof(hw_info->revision), - kCFStringEncodingASCII ) ) - CFRelease( revision ); + /* 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->vendor), + sizeof(hw_info->vendor), + kCFStringEncodingASCII ) ) + CFRelease( vendor ); + + product = ( CFStringRef ) + CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyProductNameKey ) ); + + if( CFStringGetCString( product, + (char *) &(hw_info->model), + sizeof(hw_info->model), + kCFStringEncodingASCII ) ) + CFRelease( product ); + + revision = ( CFStringRef ) + CFDictionaryGetValue ( deviceDict, + CFSTR ( kIOPropertyProductRevisionLevelKey ) ); + + if( CFStringGetCString( product, + (char *) &(hw_info->revision), + sizeof(hw_info->revision), + kCFStringEncodingASCII ) ) + CFRelease( revision ); + } return true; } @@ -661,6 +793,7 @@ _set_arg_osx (void *user_data, const char key[], const char value[]) return 0; } +#if 0 static void TestDevice(_img_private_t *p_env, io_service_t service) { SInt32 score; @@ -703,6 +836,7 @@ static void TestDevice(_img_private_t *p_env, io_service_t service) ( *mmcInterface )->Release ( mmcInterface ); IODestroyPlugInInterface ( plugInInterface ); } +#endif /*! Read and cache the CD's Track Table of Contents and track info. @@ -1281,13 +1415,13 @@ cdio_open_osx (const char *psz_orig_source) .eject_media = _eject_media_osx, .free = _free_osx, .get_arg = _get_arg_osx, - .get_cdtext = get_cdtext_generic, + .get_cdtext = get_cdtext_osx, .get_default_device = cdio_get_default_device_osx, .get_devices = cdio_get_devices_osx, - .get_discmode = get_discmode_generic, - .get_cdtext = get_cdtext_osx, + .get_discmode = get_discmode_osx, .get_drive_cap = get_drive_cap_osx, .get_first_track_num= _get_first_track_num_osx, + .get_hwinfo = get_hwinfo_osx, .get_mcn = get_mcn_osx, .get_num_tracks = _get_num_tracks_osx, .get_track_format = get_track_format_osx, diff --git a/lib/cdio.c b/lib/cdio.c index 3bacaed0..33070d3f 100644 --- a/lib/cdio.c +++ b/lib/cdio.c @@ -1,5 +1,5 @@ /* - $Id: cdio.c,v 1.70 2004/08/27 11:23:40 rocky Exp $ + $Id: cdio.c,v 1.71 2004/08/28 09:15:41 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -39,7 +39,7 @@ #include #include "cdio_private.h" -static const char _rcsid[] = "$Id: cdio.c,v 1.70 2004/08/27 11:23:40 rocky Exp $"; +static const char _rcsid[] = "$Id: cdio.c,v 1.71 2004/08/28 09:15:41 rocky Exp $"; const char *track_format2str[6] = @@ -597,10 +597,10 @@ cdio_get_hwinfo (const CdIo *p_cdio, cdio_hwinfo_t *hw_info) then return NULL. */ char * -cdio_get_mcn (const CdIo *cdio) +cdio_get_mcn (const CdIo *p_cdio) { - if (cdio->op.get_mcn) { - return cdio->op.get_mcn (cdio->env); + if (p_cdio->op.get_mcn) { + return p_cdio->op.get_mcn (p_cdio->env); } else { return NULL; } @@ -611,12 +611,12 @@ cdio_get_mcn (const CdIo *cdio) CDIO_INVALID_TRACK is returned on error. */ track_t -cdio_get_num_tracks (const CdIo *cdio) +cdio_get_num_tracks (const CdIo *p_cdio) { - if (cdio == NULL) return CDIO_INVALID_TRACK; + if (p_cdio == NULL) return CDIO_INVALID_TRACK; - if (cdio->op.get_num_tracks) { - return cdio->op.get_num_tracks (cdio->env); + if (p_cdio->op.get_num_tracks) { + return p_cdio->op.get_num_tracks (p_cdio->env); } else { return CDIO_INVALID_TRACK; } @@ -626,12 +626,12 @@ cdio_get_num_tracks (const CdIo *cdio) Get format of track. */ track_format_t -cdio_get_track_format(const CdIo *cdio, track_t track_num) +cdio_get_track_format(const CdIo *p_cdio, track_t i_track) { - cdio_assert (cdio != NULL); + cdio_assert (p_cdio != NULL); - if (cdio->op.get_track_format) { - return cdio->op.get_track_format (cdio->env, track_num); + if (p_cdio->op.get_track_format) { + return p_cdio->op.get_track_format (p_cdio->env, i_track); } else { return TRACK_FORMAT_ERROR; } diff --git a/lib/cdio_private.h b/lib/cdio_private.h index 62a46572..99c3d773 100644 --- a/lib/cdio_private.h +++ b/lib/cdio_private.h @@ -1,5 +1,5 @@ /* - $Id: cdio_private.h,v 1.40 2004/08/27 02:50:13 rocky Exp $ + $Id: cdio_private.h,v 1.41 2004/08/28 09:15:41 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein @@ -98,7 +98,7 @@ extern "C" { /*! Get disc mode associated with cd_obj. */ - discmode_t (*get_discmode) (void *env); + discmode_t (*get_discmode) (void *p_env); /*! Return the what kind of device we've got. @@ -113,7 +113,7 @@ extern "C" { Return the number of of the first track. CDIO_INVALID_TRACK is returned on error. */ - track_t (*get_first_track_num) (void *env); + track_t (*get_first_track_num) (void *p_env); /*! Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. diff --git a/lib/generic.h b/lib/generic.h index 32cda655..ce4cec3c 100644 --- a/lib/generic.h +++ b/lib/generic.h @@ -1,5 +1,5 @@ /* - $Id: generic.h,v 1.1 2004/08/10 11:58:15 rocky Exp $ + $Id: generic.h,v 1.2 2004/08/28 09:15:41 rocky Exp $ Copyright (C) 2004 Rocky Bernstein @@ -149,6 +149,11 @@ extern "C" { */ discmode_t get_discmode_generic (void *p_user_data ); + /*! + Same as above but only handles CD cases + */ + discmode_t get_discmode_cd_generic (void *p_user_data ); + void set_cdtext_field_generic(void *user_data, track_t i_track, track_t i_first_track, cdtext_field_t e_field, const char *psz_value);