#include <libkern/c++/OSString.h>
#include <libkern/c++/OSDictionary.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/storage/IOBlockStorageDriver.h>
#include "SCSITaskLib.h"
#include "SCSITaskLibPriv.h"
#include "IOSCSIPeripheralDeviceType05.h"
#include "IODVDServices.h"
#define SCSI_DVD_SERVICES_DEBUGGING_LEVEL 0
#if ( SCSI_DVD_SERVICES_DEBUGGING_LEVEL >= 1 )
#define PANIC_NOW(x) IOPanic x
#else
#define PANIC_NOW(x)
#endif
#if ( SCSI_DVD_SERVICES_DEBUGGING_LEVEL >= 2 )
#define ERROR_LOG(x) IOLog x
#else
#define ERROR_LOG(x)
#endif
#if ( SCSI_DVD_SERVICES_DEBUGGING_LEVEL >= 3 )
#define STATUS_LOG(x) IOLog x
#else
#define STATUS_LOG(x)
#endif
#if (_DVD_USE_DATA_CACHING_)
#define _CACHE_BLOCK_COUNT_ 5
#define _CACHE_BLOCK_SIZE_ 2352
#if ( 0 )
#define CACHE_LOG(x) IOLog x
#else
#define CACHE_LOG(x)
#endif
#endif
#define kNumberRetries 4
struct BlockServicesClientData
{
IODVDServices * owner;
IOStorageCompletion completionData;
IOMemoryDescriptor * clientBuffer;
UInt32 clientStartingBlock;
UInt32 clientRequestedBlockCount;
bool clientReadCDCall;
CDSectorArea clientSectorArea;
CDSectorType clientSectorType;
UInt32 retriesLeft;
#if (_DVD_USE_DATA_CACHING_)
UInt8 * transferSegBuffer;
IOMemoryDescriptor * transferSegDesc;
UInt32 transferStart;
UInt32 transferCount;
#endif
};
typedef struct BlockServicesClientData BlockServicesClientData;
#define super IODVDBlockStorageDevice
OSDefineMetaClassAndStructors ( IODVDServices, IODVDBlockStorageDevice );
bool
IODVDServices::start ( IOService * provider )
{
OSNumber * cdFeatures = NULL;
OSNumber * dvdFeatures = NULL;
UInt32 cdFeaturesFlags = 0;
UInt32 dvdFeaturesFlags = 0;
STATUS_LOG ( ( "%s: ::start\n", getName ( ) ) );
fProvider = OSDynamicCast ( IOSCSIPeripheralDeviceType05, provider );
if ( fProvider == NULL )
{
ERROR_LOG ( ( "IODVDServices: start; wrong provider type!\n" ) );
return false;
}
if ( !super::start ( fProvider ) )
return false;
cdFeatures = ( OSNumber * ) fProvider->getProperty ( kIOPropertySupportedCDFeatures );
dvdFeatures = ( OSNumber * ) fProvider->getProperty ( kIOPropertySupportedDVDFeatures );
cdFeaturesFlags = ( kCDFeaturesWriteOnceMask |
kCDFeaturesReWriteableMask ) & cdFeatures->unsigned32BitValue ( );
dvdFeaturesFlags = ( kDVDFeaturesWriteOnceMask |
kDVDFeaturesReWriteableMask |
kDVDFeaturesRandomWriteableMask ) & dvdFeatures->unsigned32BitValue ( );
STATUS_LOG ( ( "cdFeaturesFlags = %ld\n", cdFeaturesFlags ) );
STATUS_LOG ( ( "dvdFeaturesFlags = %ld\n", dvdFeaturesFlags ) );
if ( ( cdFeaturesFlags != 0 ) || ( dvdFeaturesFlags != 0 ) )
{
if ( !setProperty ( kIOMatchCategoryKey, kSCSITaskUserClientIniterKey ) )
goto failure;
}
#if (_DVD_USE_DATA_CACHING_)
fDataCacheStorage = ( UInt8 * ) IOMalloc ( _CACHE_BLOCK_COUNT_ * _CACHE_BLOCK_SIZE_ );
fDataCacheStartBlock = 0;
fDataCacheBlockCount = 0;
fDataCacheLock = IOSimpleLockAlloc ( );
if ( fDataCacheLock == NULL )
{
PANIC_NOW ( ( "IODVDServices::start Allocate fDataCacheLock failed." ) );
}
#endif
setProperty ( kIOPropertyProtocolCharacteristicsKey, fProvider->GetProtocolCharacteristicsDictionary ( ) );
setProperty ( kIOPropertyDeviceCharacteristicsKey, fProvider->GetDeviceCharacteristicsDictionary ( ) );
registerService ( );
return true;
failure:
super::stop ( fProvider );
return false;
}
bool
IODVDServices::open ( IOService * client, IOOptionBits options, IOStorageAccess access )
{
return super::open ( client, options, ( void * ) access );
}
void
IODVDServices::free ( void )
{
#if (_DVD_USE_DATA_CACHING_)
if ( fDataCacheStorage != NULL )
{
IOFree ( fDataCacheStorage, ( _CACHE_BLOCK_COUNT_ * _CACHE_BLOCK_SIZE_ ) );
}
fDataCacheStartBlock = 0;
fDataCacheBlockCount = 0;
if ( fDataCacheLock != NULL )
{
IOSimpleLockFree ( fDataCacheLock );
fDataCacheLock = NULL;
}
#endif
super::free ( );
}
IOReturn
IODVDServices::message ( UInt32 type,
IOService * nub,
void * arg )
{
IOReturn status = kIOReturnSuccess;
ERROR_LOG ( ( "IODVDServices::message called\n" ) );
switch ( type )
{
case kIOMessageMediaStateHasChanged:
{
ERROR_LOG ( ( "type = kIOMessageMediaStateHasChanged, nub = %p\n", nub ) );
status = messageClients ( type, arg, sizeof ( IOMediaState ) );
ERROR_LOG ( ( "status = %ld\n", ( UInt32 ) status ) );
}
break;
default:
{
status = super::message ( type, nub, arg );
}
break;
}
return status;
}
IOReturn
IODVDServices::setProperties ( OSObject * properties )
{
IOReturn status = kIOReturnSuccess;
OSDictionary * dict = OSDynamicCast ( OSDictionary, properties );
UInt8 trayState = 0xFF;
STATUS_LOG ( ( "IODVDServices: setProperties called\n" ) );
if ( dict == NULL )
{
return kIOReturnBadArgument;
}
if ( dict->getObject ( "TrayState" ) != NULL )
{
STATUS_LOG ( ( "IODVDServices: setProperties TrayState\n" ) );
status = fProvider->GetTrayState ( &trayState );
STATUS_LOG ( ( "GetTrayState returned status = 0x%08x, trayState = %d\n",
status, trayState ) );
if ( status == kIOReturnSuccess )
{
status = fProvider->SetTrayState ( !trayState );
STATUS_LOG ( ( "SetTrayState returned status = 0x%08x\n",
status ) );
}
}
else
{
status = kIOReturnBadArgument;
}
STATUS_LOG ( ( "IODVDServices: leave setProperties\n" ) );
return status;
}
void
IODVDServices::AsyncReadWriteComplete ( void * clientData,
IOReturn status,
UInt64 actualByteCount )
{
IODVDServices * owner;
IOStorageCompletion returnData;
BlockServicesClientData * bsClientData;
bool commandComplete = true;
bsClientData = ( BlockServicesClientData * ) clientData;
returnData = bsClientData->completionData;
owner = bsClientData->owner;
if ((( status != kIOReturnNotAttached ) && ( status != kIOReturnOffline ) &&
( status != kIOReturnSuccess )) && ( bsClientData->retriesLeft > 0 ))
{
IOReturn requestStatus;
STATUS_LOG(("IODVDServices: AsyncReadWriteComplete; retry command\n"));
bsClientData->retriesLeft--;
if ( bsClientData->clientReadCDCall == true )
{
#if (_DVD_USE_DATA_CACHING_)
requestStatus = owner->fProvider->AsyncReadCD(
bsClientData->transferSegDesc,
bsClientData->transferStart,
bsClientData->transferCount,
bsClientData->clientSectorArea,
bsClientData->clientSectorType,
clientData );
#else
requestStatus = owner->fProvider->AsyncReadCD(
bsClientData->clientBuffer,
bsClientData->clientStartingBlock,
bsClientData->clientRequestedBlockCount,
bsClientData->clientSectorArea,
bsClientData->clientSectorType,
clientData );
#endif
}
else
{
requestStatus = owner->fProvider->AsyncReadWrite(
bsClientData->clientBuffer,
bsClientData->clientStartingBlock,
bsClientData->clientRequestedBlockCount,
clientData );
}
if ( requestStatus != kIOReturnSuccess )
{
commandComplete = true;
}
else
{
commandComplete = false;
}
}
if ( commandComplete == true )
{
#if (_DVD_USE_DATA_CACHING_)
if ( bsClientData->transferSegBuffer != NULL )
{
if ( status == kIOReturnSuccess )
{
( bsClientData->clientBuffer )->writeBytes ( ( ( bsClientData->clientRequestedBlockCount - bsClientData->transferCount ) * _CACHE_BLOCK_SIZE_ ),
bsClientData->transferSegBuffer, ( bsClientData->transferCount * _CACHE_BLOCK_SIZE_ ) );
actualByteCount = ( bsClientData->clientRequestedBlockCount * _CACHE_BLOCK_SIZE_ );
}
( bsClientData->transferSegDesc )->release ( );
IOFree ( bsClientData->transferSegBuffer, ( bsClientData->clientRequestedBlockCount * _CACHE_BLOCK_SIZE_ ) );
}
if ( status == kIOReturnSuccess )
{
if (( bsClientData->clientReadCDCall == true ) && ( bsClientData->clientSectorType == kCDSectorTypeCDDA ))
{
IOSimpleLockLock ( owner->fDataCacheLock );
if ( bsClientData->clientRequestedBlockCount >= _CACHE_BLOCK_COUNT_ )
{
UInt32 offset;
offset = ( ( bsClientData->clientRequestedBlockCount - _CACHE_BLOCK_COUNT_ ) * _CACHE_BLOCK_SIZE_ );
( bsClientData->clientBuffer )->readBytes ( offset, owner->fDataCacheStorage,
( _CACHE_BLOCK_COUNT_ * _CACHE_BLOCK_SIZE_ ) );
owner->fDataCacheStartBlock = bsClientData->clientStartingBlock + ( bsClientData->clientRequestedBlockCount - _CACHE_BLOCK_COUNT_ );
owner->fDataCacheBlockCount = _CACHE_BLOCK_COUNT_;
}
IOSimpleLockUnlock ( owner->fDataCacheLock );
}
}
#endif
IOFree ( clientData, sizeof ( BlockServicesClientData ) );
owner->fProvider->release ( );
owner->release ( );
IOStorage::complete ( returnData, status, actualByteCount );
}
}
IOReturn
IODVDServices::doAsyncReadCD ( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks,
CDSectorArea sectorArea,
CDSectorType sectorType,
IOStorageCompletion completion )
{
BlockServicesClientData * clientData;
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
#if (_DVD_USE_DATA_CACHING_)
if ( sectorType == kCDSectorTypeCDDA )
{
IOSimpleLockLock ( fDataCacheLock );
if ( fDataCacheBlockCount != 0 )
{
if ( ( nblks <= fDataCacheBlockCount ) && ( block >= fDataCacheStartBlock ) &&
( block + nblks <= fDataCacheStartBlock + fDataCacheBlockCount) )
{
UInt32 startByte = ( block - fDataCacheStartBlock ) * _CACHE_BLOCK_SIZE_;
buffer->writeBytes ( 0, &fDataCacheStorage[startByte], ( nblks * _CACHE_BLOCK_SIZE_ ) );
IOSimpleLockUnlock ( fDataCacheLock );
IOStorage::complete ( completion, kIOReturnSuccess, ( nblks * _CACHE_BLOCK_SIZE_ ) );
return kIOReturnSuccess;
}
}
IOSimpleLockUnlock ( fDataCacheLock );
}
#endif
clientData = ( BlockServicesClientData * ) IOMalloc ( sizeof ( BlockServicesClientData ) );
if ( clientData == NULL )
{
ERROR_LOG ( ( "IODVDServices: doAsyncReadCD; clientData malloc failed!\n" ) );
return kIOReturnNoResources;
}
retain ( );
fProvider->retain ( );
STATUS_LOG ( ( "IODVDServices: doAsyncReadCD; save completion data!\n" ) );
clientData->owner = this;
clientData->completionData = completion;
clientData->clientBuffer = buffer;
clientData->clientStartingBlock = block;
clientData->clientRequestedBlockCount = nblks;
clientData->clientReadCDCall = true;
clientData->clientSectorArea = sectorArea;
clientData->clientSectorType = sectorType;
clientData->retriesLeft = kNumberRetries;
fProvider->CheckPowerState ( );
#if (_DVD_USE_DATA_CACHING_)
if ( sectorType == kCDSectorTypeCDDA )
{
clientData->transferSegBuffer = ( UInt8 * ) IOMalloc ( nblks * _CACHE_BLOCK_SIZE_ );
if ( clientData->transferSegBuffer != NULL )
{
IOSimpleLockLock ( fDataCacheLock );
if ( ( fDataCacheBlockCount != 0 ) && ( block > fDataCacheStartBlock ) && ( nblks > fDataCacheBlockCount ) && ( block < ( fDataCacheStartBlock + fDataCacheBlockCount ) ) ) {
UInt32 offsetBlk;
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, block = %ld\n", block ) );
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, nblks = %ld\n", nblks ) );
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, fDataCacheStartBlock = %ld\n", fDataCacheStartBlock ) );
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, fDataCacheBlockCount = %ld\n", fDataCacheBlockCount ) );
offsetBlk = ( block - fDataCacheStartBlock );
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, offsetBlk = %ld\n", offsetBlk ) );
clientData->transferCount = nblks - ( fDataCacheBlockCount - offsetBlk );
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, clientData->transferCount = %ld\n", clientData->transferCount ) );
clientData->transferStart = block + ( fDataCacheBlockCount - offsetBlk );
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, clientData->transferStart = %ld\n", clientData->transferStart ) );
clientData->transferSegDesc = IOMemoryDescriptor::withAddress ( clientData->transferSegBuffer,
clientData->transferCount * _CACHE_BLOCK_SIZE_,
kIODirectionIn );
if ( clientData->transferSegDesc != NULL )
{
buffer->writeBytes ( 0, &fDataCacheStorage[offsetBlk * _CACHE_BLOCK_SIZE_], ( ( fDataCacheBlockCount - offsetBlk ) * _CACHE_BLOCK_SIZE_ ) );
IOSimpleLockUnlock ( fDataCacheLock );
return fProvider->AsyncReadCD ( clientData->transferSegDesc,
clientData->transferStart,
clientData->transferCount,
sectorArea,
sectorType,
( void * ) clientData );
}
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, transferSegDesc = NULL\n" ) );
}
CACHE_LOG ( ( "IODVDServices::doAsyncReadCD called, transferSegBuffer = NULL\n" ) );
IOSimpleLockUnlock ( fDataCacheLock );
}
if ( clientData->transferSegBuffer != NULL )
{
IOFree ( clientData->transferSegBuffer, ( nblks * _CACHE_BLOCK_SIZE_ ) );
}
}
clientData->transferSegBuffer = NULL;
clientData->transferSegDesc = NULL;
clientData->transferStart = 0;
clientData->transferCount = 0;
#endif
return fProvider->AsyncReadCD ( buffer,
block,
nblks,
sectorArea,
sectorType,
( void * ) clientData );
}
IOReturn
IODVDServices::doAsyncReadWrite ( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks,
IOStorageCompletion completion )
{
BlockServicesClientData * clientData;
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
clientData = ( BlockServicesClientData * ) IOMalloc ( sizeof ( BlockServicesClientData ) );
if ( clientData == NULL )
{
ERROR_LOG ( ( "IODVDServices: doAsyncReadWrite; clientData malloc failed!\n" ) );
return false;
}
retain ( );
fProvider->retain ( );
STATUS_LOG ( ( "IODVDServices: doAsyncReadWrite; save completion data!\n" ) );
clientData->owner = this;
clientData->completionData = completion;
clientData->clientBuffer = buffer;
clientData->clientStartingBlock = block;
clientData->clientRequestedBlockCount = nblks;
clientData->clientReadCDCall = false;
clientData->retriesLeft = kNumberRetries;
fProvider->CheckPowerState ( );
#if (_DVD_USE_DATA_CACHING_)
clientData->transferSegBuffer = NULL;
clientData->transferSegDesc = NULL;
clientData->transferStart = 0;
clientData->transferCount = 0;
#endif
return fProvider->AsyncReadWrite ( buffer, block, nblks, ( void * ) clientData );
}
IOReturn
IODVDServices::doSyncReadWrite ( IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks )
{
IOReturn result;
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
retain ( );
fProvider->retain ( );
fProvider->CheckPowerState ( );
result = fProvider->SyncReadWrite ( buffer, block, nblks );
fProvider->release ( );
release ( );
return result;
}
IOReturn
IODVDServices::doFormatMedia ( UInt64 byteCapacity )
{
IOReturn result;
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
retain ( );
fProvider->retain ( );
fProvider->CheckPowerState ( );
result = fProvider->FormatMedia ( byteCapacity );
fProvider->release ( );
release ( );
return result;
}
UInt32
IODVDServices::doGetFormatCapacities ( UInt64 * capacities,
UInt32 capacitiesMaxCount ) const
{
IOReturn result;
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
retain ( );
fProvider->retain ( );
fProvider->CheckPowerState ( );
result = fProvider->GetFormatCapacities ( capacities, capacitiesMaxCount );
fProvider->release ( );
release ( );
return result;
}
IOReturn
IODVDServices::doEjectMedia ( void )
{
IOReturn result;
#if (_DVD_USE_DATA_CACHING_)
fDataCacheStartBlock = 0;
fDataCacheBlockCount = 0;
#endif
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
retain ( );
fProvider->retain ( );
fProvider->CheckPowerState ( );
result = fProvider->EjectTheMedia ( );
fProvider->release ( );
release ( );
return result;
}
IOReturn
IODVDServices::doLockUnlockMedia ( bool doLock )
{
IOReturn result;
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
retain ( );
fProvider->retain ( );
fProvider->CheckPowerState ( );
result = fProvider->LockUnlockMedia ( doLock );
fProvider->release ( );
release ( );
return result;
}
char *
IODVDServices::getVendorString ( void )
{
return fProvider->GetVendorString ( );
}
char *
IODVDServices::getProductString ( void )
{
return fProvider->GetProductString ( );
}
char *
IODVDServices::getRevisionString ( void )
{
return fProvider->GetRevisionString ( );
}
char *
IODVDServices::getAdditionalDeviceInfoString ( void )
{
STATUS_LOG ( ( "%s::%s called\n", getName ( ), __FUNCTION__ ) );
return ( "No Additional Device Info" );
}
IOReturn
IODVDServices::reportBlockSize ( UInt64 * blockSize )
{
return fProvider->ReportBlockSize ( blockSize );
}
IOReturn
IODVDServices::reportEjectability ( bool * isEjectable )
{
return fProvider->ReportEjectability ( isEjectable );
}
IOReturn
IODVDServices::reportLockability ( bool * isLockable )
{
return fProvider->ReportLockability ( isLockable );
}
IOReturn
IODVDServices::reportMediaState ( bool * mediaPresent,
bool * changed )
{
return fProvider->ReportMediaState ( mediaPresent, changed );
}
IOReturn
IODVDServices::reportPollRequirements ( bool * pollIsRequired,
bool * pollIsExpensive )
{
return fProvider->ReportPollRequirements ( pollIsRequired, pollIsExpensive );
}
IOReturn
IODVDServices::reportMaxReadTransfer ( UInt64 blockSize,
UInt64 * max )
{
return fProvider->ReportMaxReadTransfer ( blockSize, max );
}
IOReturn
IODVDServices::reportMaxValidBlock ( UInt64 * maxBlock )
{
return fProvider->ReportMaxValidBlock ( maxBlock );
}
IOReturn
IODVDServices::reportRemovability ( bool * isRemovable )
{
return fProvider->ReportRemovability ( isRemovable );
}
IOReturn
IODVDServices::readISRC ( UInt8 track, CDISRC isrc )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->ReadISRC ( track, isrc );
}
IOReturn
IODVDServices::readMCN ( CDMCN mcn )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->ReadMCN ( mcn );
}
IOReturn
IODVDServices::readTOC ( IOMemoryDescriptor * buffer )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->ReadTOC ( buffer );
}
IOReturn
IODVDServices::audioPause ( bool pause )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->AudioPause ( pause );
}
IOReturn
IODVDServices::audioPlay ( CDMSF timeStart, CDMSF timeStop )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->AudioPlay ( timeStart, timeStop );
}
IOReturn
IODVDServices::audioScan ( CDMSF timeStart, bool reverse )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->AudioScan ( timeStart, reverse );
}
IOReturn
IODVDServices::audioStop ( void )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->AudioStop ( );
}
IOReturn
IODVDServices::getAudioStatus ( CDAudioStatus * status )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->GetAudioStatus ( status );
}
IOReturn
IODVDServices::getAudioVolume ( UInt8 * leftVolume,
UInt8 * rightVolume )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->GetAudioVolume ( leftVolume, rightVolume );
}
IOReturn
IODVDServices::setAudioVolume ( UInt8 leftVolume, UInt8 rightVolume )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->SetAudioVolume ( leftVolume, rightVolume );
}
IOReturn
IODVDServices::doSynchronizeCache ( void )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->SynchronizeCache ( );
}
IOReturn
IODVDServices::reportMaxWriteTransfer ( UInt64 blockSize,
UInt64 * max )
{
return fProvider->ReportMaxWriteTransfer ( blockSize, max );
}
IOReturn
IODVDServices::reportWriteProtection ( bool * isWriteProtected )
{
return fProvider->ReportWriteProtection ( isWriteProtected );
}
UInt32
IODVDServices::getMediaType ( void )
{
return fProvider->GetMediaType ( );
}
IOReturn
IODVDServices::getSpeed ( UInt16 * kilobytesPerSecond )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->GetMediaAccessSpeed ( kilobytesPerSecond );
}
IOReturn
IODVDServices::setSpeed ( UInt16 kilobytesPerSecond )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->SetMediaAccessSpeed ( kilobytesPerSecond );
}
IOReturn
IODVDServices::readDVDStructure ( IOMemoryDescriptor * buffer,
const UInt8 structureFormat,
const UInt32 logicalBlockAddress,
const UInt8 layer,
const UInt8 agid )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->ReadDVDStructure ( buffer,
( UInt32 ) buffer->getLength ( ),
structureFormat,
logicalBlockAddress,
layer,
agid );
}
IOReturn
IODVDServices::reportKey ( IOMemoryDescriptor * buffer,
const DVDKeyClass keyClass,
const UInt32 lba,
const UInt8 agid,
const DVDKeyFormat keyFormat )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->ReportKey ( buffer,
keyClass,
lba,
agid,
keyFormat );
}
IOReturn
IODVDServices::sendKey ( IOMemoryDescriptor * buffer,
const DVDKeyClass keyClass,
const UInt8 agid,
const DVDKeyFormat keyFormat )
{
if ( isInactive ( ) != false )
{
return kIOReturnNotAttached;
}
fProvider->CheckPowerState ( );
return fProvider->SendKey ( buffer,
keyClass,
agid,
keyFormat );
}
#pragma mark -
#pragma mark UserClientSupport
bool
IODVDServices::handleOpen ( IOService * client, IOOptionBits options, void * access )
{
if ( ( options & kIOSCSITaskUserClientAccessMask ) == 0 )
{
return super::handleOpen ( client, options, access );
}
if ( fClients == NULL )
fClients = OSSet::withCapacity ( 1 );
if ( fClients == NULL )
return false;
fClients->setObject ( client );
return true;
}
void
IODVDServices::handleClose ( IOService * client, IOOptionBits options )
{
if ( ( options & kIOSCSITaskUserClientAccessMask ) == 0 )
super::handleClose ( client, options );
else
{
fClients->removeObject ( client );
}
}
bool
IODVDServices::handleIsOpen ( const IOService * client ) const
{
if ( client == NULL )
{
if ( ( fClients != NULL ) && ( fClients->getCount ( ) > 0 ) )
return true;
return super::handleIsOpen ( client );
}
if ( ( fClients != NULL ) && ( fClients->containsObject ( client ) ) )
return true;
return super::handleIsOpen ( client );
}
OSMetaClassDefineReservedUnused( IODVDServices, 1 );
OSMetaClassDefineReservedUnused( IODVDServices, 2 );
OSMetaClassDefineReservedUnused( IODVDServices, 3 );
OSMetaClassDefineReservedUnused( IODVDServices, 4 );
OSMetaClassDefineReservedUnused( IODVDServices, 5 );
OSMetaClassDefineReservedUnused( IODVDServices, 6 );
OSMetaClassDefineReservedUnused( IODVDServices, 7 );
OSMetaClassDefineReservedUnused( IODVDServices, 8 );