📄 _cdio_osx.c
字号:
&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 boolget_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) );}/*! Reads nblocks of mode2 form2 sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_get_read_mode1_sectors_osx (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks){ _img_private_t *env = user_data; dk_cd_read_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); cd_read.sectorArea = kCDSectorAreaUser; cd_read.buffer = data; cd_read.sectorType = kCDSectorTypeMode1; if (b_form2) { cd_read.offset = lsn * kCDSectorSizeMode2; cd_read.bufferLength = kCDSectorSizeMode2 * nblocks; } else { cd_read.offset = lsn * kCDSectorSizeMode1; cd_read.bufferLength = kCDSectorSizeMode1 * nblocks; } if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) { cdio_info( "could not read block %d, %s", lsn, strerror(errno) ); return -1; } return 0;} /*! Reads nblocks of mode2 form2 sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_get_read_mode2_sectors_osx (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks){ _img_private_t *env = user_data; dk_cd_read_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); cd_read.sectorArea = kCDSectorAreaUser; cd_read.buffer = data; if (b_form2) { cd_read.offset = lsn * kCDSectorSizeMode2Form2; cd_read.sectorType = kCDSectorTypeMode2Form2; cd_read.bufferLength = kCDSectorSizeMode2Form2 * nblocks; } else { cd_read.offset = lsn * kCDSectorSizeMode2Form1; cd_read.sectorType = kCDSectorTypeMode2Form1; cd_read.bufferLength = kCDSectorSizeMode2Form1 * nblocks; } if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) { cdio_info( "could not read block %d, %s", lsn, strerror(errno) ); return -1; } return 0;} /*! Reads a single audio sector from CD device into data starting from lsn. Returns 0 if no error. */static int_get_read_audio_sectors_osx (void *user_data, void *data, lsn_t lsn, unsigned int nblocks){ _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.buffer = data; cd_read.bufferLength = kCDSectorSizeCDDA * nblocks; if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) { cdio_info( "could not read block %d", lsn ); return -1; } return 0;}/*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. */static int_get_read_mode1_sector_osx (void *user_data, void *data, lsn_t lsn, bool b_form2){ return _get_read_mode1_sectors_osx(user_data, data, lsn, b_form2, 1);}/*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. */static int_get_read_mode2_sector_osx (void *user_data, void *data, lsn_t lsn, bool b_form2){ return _get_read_mode2_sectors_osx(user_data, data, lsn, b_form2, 1);}/*! Set the key "arg" to "value" in source device.*/static int_set_arg_osx (void *user_data, const char key[], const char value[]){ _img_private_t *env = user_data; if (!strcmp (key, "source")) { if (!value) return -2; free (env->gen.source_name); env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { if (!strcmp(value, "OSX")) env->access_mode = _AM_OSX; else cdio_warn ("unknown access type: %s. ignored.", value); } else return -1; return 0;}#if 0static 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 boolread_toc_osx (void *p_user_data) { _img_private_t *p_env = p_user_data; CFDictionaryRef propertiesDict = 0; CFDataRef data; /* create a CF dictionary containing the TOC */ propertiesDict = GetRegistryEntryProperties( p_env->MediaClass_service ); if ( 0 == propertiesDict ) { return false; } /* get the TOC from the dictionary */ 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( ( 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; } } else { cdio_warn( "Trouble reading TOC" ); return false; } /* TestDevice(p_env, service); */ CFRelease( propertiesDict ); 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; p_env->pp_lba = malloc( p_env->i_descriptors * sizeof(int) ); if( p_env->pp_lba == NULL ) { cdio_warn("Out of memory in allocating track starting LSNs" ); free( p_env->pTOC ); return false; } 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 = 0; i <= p_env->i_descriptors; i++ ) { 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( i_track == OSX_CDROM_LEADOUT_TRACK ) i_leadout = i; 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; 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_warn( "CD leadout not found" ); free( p_env->pp_lba ); free( (void *) p_env->pTOC ); return false; } /* 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; } p_env->gen.toc_init = true; return( true );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -