AppleOnboardAudio.cpp [plain text]
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOMessage.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/IOTimerEventSource.h>
#include "AppleOnboardAudio.h"
OSDefineMetaClassAndAbstractStructors(AppleOnboardAudio, IOAudioDevice)
#define super IOAudioDevice
#pragma mark +UNIX LIKE FUNCTIONS
bool AppleOnboardAudio::init(OSDictionary *properties)
{
OSDictionary *AOAprop;
DEBUG_IOLOG("+ AppleOnboardAudio::init\n");
if (!super::init(properties)) return false;
outMute =0;
playthruToggle =0;
outVolLeft =0;
outVolRight =0;
inGainLeft =0;
inGainRight =0;
inputSelector = 0;
gIsMute = false;
gIsPlayThroughActive = false;
gVolLeft =0;
gVolRight =0;
gGainLeft = 0;
gGainRight = 0;
gIsModemSoundActive = false;
gHasModemSound = false;
gLastInputSourceBeforeModem =0;
gExpertMode = false;
AudioDetects = 0;
AudioOutputs = 0;
AudioInputs = 0;
AudioSoftDSPFeatures = 0;
driverDMAEngine = 0;
currentDevices = 0xFFFF;
theAudioPowerObject = 0;
theAudioDeviceTreeParser = 0;
if ( AOAprop = OSDynamicCast(OSDictionary, properties->getObject("AOAAttributes"))) {
gHasModemSound =
(kOSBooleanTrue == OSDynamicCast(OSBoolean, AOAprop->getObject("analogModem")));
}
CLOG("- AppleOnboardAudio::init\n");
return true;
}
void AppleOnboardAudio::free()
{
DEBUG_IOLOG("+ AppleOnboardAudio::free\n");
if(driverDMAEngine)
driverDMAEngine->release();
CLEAN_RELEASE(outMute);
CLEAN_RELEASE(playthruToggle);
CLEAN_RELEASE(outVolLeft);
CLEAN_RELEASE(outVolRight);
CLEAN_RELEASE(inGainLeft);
CLEAN_RELEASE(inGainRight);
CLEAN_RELEASE(inputSelector);
CLEAN_RELEASE(theAudioPowerObject);
CLEAN_RELEASE(AudioDetects);
CLEAN_RELEASE(AudioOutputs);
CLEAN_RELEASE(AudioInputs);
CLEAN_RELEASE(theAudioDeviceTreeParser);
publishResource ("setModemSound", NULL);
super::free();
DEBUG_IOLOG("- AppleOnboardAudio::free, (void)\n");
}
IOService* AppleOnboardAudio::probe(IOService* provider, SInt32* score)
{
DEBUG_IOLOG("+ AppleOnboardAudio::probe\n");
super::probe(provider, score);
DEBUG_IOLOG("- AppleOnboardAudio::probe\n");
return (0);
}
OSArray *AppleOnboardAudio::getDetectArray(){
return(AudioDetects);
}
bool AppleOnboardAudio::getMuteState(){
return(gIsMute);
}
void AppleOnboardAudio::setMuteState(bool newMuteState){
outMute->setValue(newMuteState);
}
#pragma mark +PORT HANDLER FUNCTIONS
IOReturn AppleOnboardAudio::configureAudioOutputs(IOService *provider) {
IOReturn result = kIOReturnSuccess;
AudioHardwareOutput *theOutput;
UInt16 idx;
DEBUG_IOLOG("+ AppleOnboardAudio::configureAudioOutputs\n");
if(!theAudioDeviceTreeParser)
goto BAIL;
AudioOutputs = theAudioDeviceTreeParser->createOutputsArray();
if(!AudioOutputs)
goto BAIL;
for(idx = 0; idx < AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast(AudioHardwareOutput, AudioOutputs->getObject(idx));
if( theOutput) theOutput->attachAudioPluginRef((AppleOnboardAudio *) this);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::configureAudioOutputs, %d\n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::configureAudioDetects(IOService *provider) {
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::configureAudioDetects\n");
if(!theAudioDeviceTreeParser)
goto BAIL;
AudioDetects = theAudioDeviceTreeParser->createDetectsArray();
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::configureAudioDetects, %d \n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::configureAudioInputs(IOService *provider) {
IOReturn result = kIOReturnSuccess;
UInt16 idx;
AudioHardwareInput *theInput;
AudioHardwareMux *theMux;
DEBUG_IOLOG("+ AppleOnboardAudio::configureAudioDetects\n");
FailIf (NULL == theAudioDeviceTreeParser, BAIL);
AudioInputs = theAudioDeviceTreeParser->createInputsArrayWithMuxes();
FailIf (NULL == AudioInputs, BAIL);
for(idx = 0; idx < AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if (NULL != theInput) {
theInput->attachAudioPluginRef((AppleOnboardAudio *) this);
} else {
theMux = OSDynamicCast(AudioHardwareMux, AudioInputs->getObject(idx));
if (NULL != theMux) {
theMux->attachAudioPluginRef((AppleOnboardAudio *) this);
} else {
DEBUG_IOLOG ("!!!It's not an input and it's not a mux!!!\n");
}
}
}
EXIT:
DEBUG2_IOLOG("- %d = AppleOnboardAudio::configureAudioDetects\n", result);
return (result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::parseAndActivateInit(IOService *provider){
IOReturn result = kIOReturnSuccess;
SInt16 initType = 0;
DEBUG_IOLOG("+ AppleOnboardAudio::parseAndActivateInit\n");
if(!theAudioDeviceTreeParser)
goto BAIL;
initType = theAudioDeviceTreeParser->getInitOperationType();
if(2 == initType)
sndHWSetProgOutput(kSndHWProgOutput0);
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::parseAndActivateInit, %d\n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
UInt32 AppleOnboardAudio::getCurrentDevices(){
return(currentDevices);
}
void AppleOnboardAudio::setCurrentDevices(UInt32 devices){
UInt32 odevice;
if(devices != currentDevices) {
odevice = currentDevices;
currentDevices = devices;
changedDeviceHandler(odevice);
}
debug2IOLog ("currentDevices = %ld\n", currentDevices);
debug2IOLog ("fCPUNeedsPhaseInversion = %d\n", fCPUNeedsPhaseInversion);
if (fCPUNeedsPhaseInversion)
{
bool state;
if (currentDevices == 0 || currentDevices & kSndHWInternalSpeaker) state = true;
else
state = false;
driverDMAEngine->setPhaseInversion(state);
}
}
void AppleOnboardAudio::changedDeviceHandler(UInt32 olddevices){
UInt16 i;
AudioHardwareOutput *theOutput;
if(AudioOutputs) {
for(i = 0; i< AudioOutputs->getCount(); i++) {
theOutput = OSDynamicCast(AudioHardwareOutput, AudioOutputs->getObject(i));
if( theOutput) theOutput->deviceIntService(currentDevices);
}
}
}
#pragma mark +IOAUDIO INIT
bool AppleOnboardAudio::initHardware (IOService *provider){
IOWorkLoop *workLoop;
bool result;
DEBUG_IOLOG("+ AppleOnboardAudio::initHardware\n");
result = FALSE;
if (!super::initHardware (provider)) {
goto EXIT;
}
ourPowerState = kIOAudioDeviceActive;
ScheduleIdle ();
sndHWInitialize (provider);
theAudioDeviceTreeParser = AudioDeviceTreeParser::createWithEntryProvider (provider);
setManufacturerName ("Apple");
setDeviceName ("Built-in audio controller");
parseAndActivateInit (provider);
configureAudioDetects (provider);
configureAudioOutputs (provider);
configureAudioInputs (provider);
configurePowerObject (provider);
configureDMAEngines (provider);
createDefaultsPorts ();
if (kIOReturnSuccess != activateAudioEngine (driverDMAEngine)){
driverDMAEngine->release ();
goto EXIT;
}
workLoop = getWorkLoop ();
FailIf (NULL == workLoop, EXIT);
idleTimer = IOTimerEventSource::timerEventSource (this, IdleSleepHandlerTimer);
FailIf (NULL == idleTimer, EXIT);
workLoop->addEventSource (idleTimer);
sndHWPostDMAEngineInit (provider);
gExpertMode = TRUE; if (NULL != outVolLeft) {
outVolLeft->setValue (PRAMToVolumeValue ());
}
if (NULL != outVolRight) {
outVolRight->setValue (PRAMToVolumeValue ());
}
flushAudioControls ();
gExpertMode = FALSE;
publishResource ("setModemSound", this);
registerPrioritySleepWakeInterest (&sysPowerDownHandler, this, 0);
registerService ();
result = TRUE;
EXIT:
DEBUG_IOLOG ("- AppleOnboardAudio::initHardware\n");
return (result);
}
IOReturn AppleOnboardAudio::configureDMAEngines(IOService *provider){
IOReturn result;
bool hasInput;
result = kIOReturnError;
FailIf (NULL == theAudioDeviceTreeParser, EXIT);
if (theAudioDeviceTreeParser->getNumberOfInputs () > 0)
hasInput = true;
else
hasInput = false;
driverDMAEngine = new AppleDBDMAAudioDMAEngine;
FailIf (NULL == driverDMAEngine, EXIT);
fCPUNeedsPhaseInversion = theAudioDeviceTreeParser->getPhaseInversion ();
driverDMAEngine->setPhaseInversion (false);
if (!driverDMAEngine->init (NULL, provider, hasInput)) {
driverDMAEngine->release ();
goto EXIT;
}
result = kIOReturnSuccess;
EXIT:
return result;
}
IOReturn AppleOnboardAudio::createDefaultsPorts() {
IOAudioPort *outputPort = 0;
IOAudioPort *inputPort = 0;
IOReturn result;
OSDictionary *AOAprop = 0, *theRange = 0;
OSNumber *theNumber;
OSData *theData;
SInt32 OutminLin, OutmaxLin, InminLin, InmaxLin;
IOFixed OutminDB, OutmaxDB, InminDB, InmaxDB;
UInt32 idx;
DEBUG_IOLOG("+ AppleOnboardAudio::createDefaultsPorts\n");
result = kIOReturnSuccess;
FailIf (NULL == driverDMAEngine, BAIL);
FailIf (NULL == (AOAprop = OSDynamicCast(OSDictionary, this->getProperty("AOAAttributes"))), BAIL);
if (NULL != (theRange= OSDynamicCast(OSDictionary, AOAprop->getObject("RangeOut")))) {
outputPort = IOAudioPort::withAttributes(kIOAudioPortTypeOutput, "Main Output port");
if (NULL != outputPort) {
theNumber = OSDynamicCast(OSNumber, theRange->getObject("minLin"));
OutminLin = (SInt32) theNumber->unsigned32BitValue();
theNumber = OSDynamicCast(OSNumber, theRange->getObject("maxLin"));
OutmaxLin = (SInt32) theNumber->unsigned32BitValue();
theData = OSDynamicCast(OSData, theRange->getObject("minLog"));
OutminDB = *((IOFixed*) theData->getBytesNoCopy());
theData = OSDynamicCast(OSData, theRange->getObject("maxLog"));
OutmaxDB = *((IOFixed*) theData->getBytesNoCopy());
fMaxVolume = OutmaxLin;
fMinVolume = OutminLin;
outVolLeft = IOAudioLevelControl::createVolumeControl(OutmaxLin, OutminLin, OutmaxLin, OutminDB, OutmaxDB,
kIOAudioControlChannelIDDefaultLeft,
kIOAudioControlChannelNameLeft,
kOutVolLeft,
kIOAudioControlUsageOutput);
if (NULL != outVolLeft) {
driverDMAEngine->addDefaultAudioControl(outVolLeft);
outVolLeft->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)volumeChangeHandler, this);
}
outVolRight = IOAudioLevelControl::createVolumeControl(OutmaxLin, OutminLin, OutmaxLin, OutminDB, OutmaxDB,
kIOAudioControlChannelIDDefaultRight,
kIOAudioControlChannelNameRight,
kOutVolRight,
kIOAudioControlUsageOutput);
if (NULL != outVolRight) {
driverDMAEngine->addDefaultAudioControl(outVolRight);
outVolRight->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)volumeChangeHandler, this);
}
outMute = IOAudioToggleControl::createMuteControl(false,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kOutMute,
kIOAudioControlUsageOutput);
if (NULL != outMute) {
driverDMAEngine->addDefaultAudioControl(outMute);
outMute->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)outputMuteChangeHandler, this);
}
attachAudioPort(outputPort, driverDMAEngine, 0);
outputPort->release();
}
}
if ((theAudioDeviceTreeParser->getNumberOfInputs() > 0)) {
if (NULL != (theRange= OSDynamicCast(OSDictionary, AOAprop->getObject("RangeIn")))) {
inputPort = IOAudioPort::withAttributes(kIOAudioPortTypeInput, "Main Input Port");
if (NULL != inputPort) {
theNumber = OSDynamicCast(OSNumber, theRange->getObject("minLin"));
InminLin = (SInt32) theNumber->unsigned32BitValue();
theNumber = OSDynamicCast(OSNumber, theRange->getObject("maxLin"));
InmaxLin = (SInt32) theNumber->unsigned32BitValue();
theData = OSDynamicCast(OSData, theRange->getObject("minLog"));
InminDB = *((IOFixed*) theData->getBytesNoCopy());
theData = OSDynamicCast(OSData, theRange->getObject("maxLog"));
InmaxDB = *((IOFixed*) theData->getBytesNoCopy());
inGainLeft = IOAudioLevelControl::createVolumeControl((InmaxLin-InminLin)/2, InminLin, InmaxLin, InminDB, InmaxDB,
kIOAudioControlChannelIDDefaultLeft,
kIOAudioControlChannelNameLeft,
kInGainLeft,
kIOAudioControlUsageInput);
if (NULL != inGainLeft) {
driverDMAEngine->addDefaultAudioControl(inGainLeft);
inGainLeft->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)gainLeftChangeHandler, this);
}
inGainRight = IOAudioLevelControl::createVolumeControl((InmaxLin-InminLin)/2, InminLin, InmaxLin, InminDB, InmaxDB,
kIOAudioControlChannelIDDefaultRight,
kIOAudioControlChannelNameRight,
kInGainRight,
kIOAudioControlUsageInput);
if (NULL != inGainRight) {
driverDMAEngine->addDefaultAudioControl(inGainRight);
inGainRight->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)gainRightChangeHandler, this);
}
attachAudioPort(inputPort, 0, driverDMAEngine);
inputPort->release();
}
}
if(AudioInputs) {
AudioHardwareInput *theInput;
UInt32 inputType;
inputSelector = NULL;
for(idx = 0; idx < AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if(theInput) {
inputType = theInput->getInputPortType();
DEBUG2_IOLOG ("Creating input selector of type %4s\n", (char*)&inputType);
if (NULL == inputSelector && 'none' != inputType) {
inputSelector = IOAudioSelectorControl::createInputSelector(inputType,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kInputSelector);
if (NULL != inputSelector) {
driverDMAEngine->addDefaultAudioControl(inputSelector);
inputSelector->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)inputSelectorChangeHandler, this);
}
}
if (NULL != inputSelector) {
DEBUG2_IOLOG ("Calling addAvailableSelection with type %4s\n", (char*)&inputType);
switch(inputType) {
case 'imic' :
inputSelector->addAvailableSelection('imic', "Internal microphone");
break;
case 'emic' :
inputSelector->addAvailableSelection('emic', "External microphone/Line In");
break;
case 'sinj' :
inputSelector->addAvailableSelection('sinj', "Sound Input");
break;
case 'line' :
inputSelector->addAvailableSelection('line', "Line In");
break;
case 'zvpc' :
inputSelector->addAvailableSelection('zvpc', "Zoomed Video");
break;
default:
break;
}
}
}
}
}
if (NULL != outputPort) {
playthruToggle = IOAudioToggleControl::createMuteControl(true,
kIOAudioControlChannelIDAll,
kIOAudioControlChannelNameAll,
kPassThruToggle,
kIOAudioControlUsagePassThru);
if (NULL != playthruToggle) {
driverDMAEngine->addDefaultAudioControl(playthruToggle);
playthruToggle->setValueChangeHandler((IOAudioControl::IntValueChangeHandler)passThruChangeHandler, this);
}
}
}
EXIT:
DEBUG2_IOLOG("- %d = AppleOnboardAudio::createDefaultsPorts\n", result);
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
#pragma mark +IOAUDIO CONTROL HANDLERS
IORegistryEntry * AppleOnboardAudio::FindEntryByNameAndProperty (const IORegistryEntry * start, const char * name, const char * key, UInt32 value) {
OSIterator *iterator;
IORegistryEntry *theEntry;
IORegistryEntry *tmpReg;
OSNumber *tmpNumber;
theEntry = NULL;
iterator = NULL;
FAIL_IF (NULL == start, Exit);
iterator = start->getChildIterator (gIOServicePlane);
FAIL_IF (NULL == iterator, Exit);
while (NULL == theEntry && (tmpReg = OSDynamicCast (IORegistryEntry, iterator->getNextObject ())) != NULL) {
if (strcmp (tmpReg->getName (), name) == 0) {
tmpNumber = OSDynamicCast (OSNumber, tmpReg->getProperty (key));
if (NULL != tmpNumber && tmpNumber->unsigned32BitValue () == value) {
theEntry = tmpReg;
theEntry->retain();
}
}
}
Exit:
if (NULL != iterator) {
iterator->release ();
}
return theEntry;
}
IOReturn AppleOnboardAudio::volumeChangeHandler (IOService *target, IOAudioControl *volumeControl, SInt32 oldValue, SInt32 newValue) {
AppleOnboardAudio * audioDevice;
IOCommandGate * cg;
IOReturn result;
result = kIOReturnError;
audioDevice = OSDynamicCast (AppleOnboardAudio, target);
FailIf (NULL == audioDevice, Exit);
cg = audioDevice->getCommandGate ();
if (NULL != cg) {
result = cg->runAction (volumeChangeAction, (void *)volumeControl, (void *)oldValue, (void *)newValue);
}
Exit:
return result;
}
IOReturn AppleOnboardAudio::volumeChangeAction (OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) {
IOReturn result = kIOReturnError;
AppleOnboardAudio * audioDevice;
IOAudioLevelControl * levelControl;
audioDevice = OSDynamicCast (AppleOnboardAudio, owner);
FailIf (NULL == audioDevice, Exit);
levelControl = OSDynamicCast (IOAudioLevelControl, (IOAudioControl *)arg1);
FailIf (NULL == levelControl, Exit);
switch (levelControl->getSubType ()) {
case kIOAudioLevelControlSubTypeVolume:
switch (levelControl->getChannelID ()) {
case kIOAudioControlChannelIDDefaultLeft:
result = volumeLeftChangeHandler ((IOService *)owner, (IOAudioControl *)arg1, (SInt32)arg2, (SInt32)arg3);
break;
case kIOAudioControlChannelIDDefaultRight:
result = volumeRightChangeHandler ((IOService *)owner, (IOAudioControl *)arg1, (SInt32)arg2, (SInt32)arg3);
break;
}
break;
case kIOAudioToggleControlSubTypeMute:
result = outputMuteChangeHandler ((IOService *)owner, (IOAudioControl *)arg1, (SInt32)arg2, (SInt32)arg3);
break;
default:
result = kIOReturnBadArgument;
}
Exit:
return result;
}
IOReturn AppleOnboardAudio::volumeLeftChangeHandler(IOService *target, IOAudioControl *volumeControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio * audioDevice;
IOAudioLevelControl * levelControl;
DEBUG_IOLOG("+ AppleOnboardAudio::volumeLeftChangeHandler\n");
audioDevice = OSDynamicCast (AppleOnboardAudio, target);
if(!audioDevice)
goto BAIL;
levelControl = OSDynamicCast (IOAudioLevelControl, volumeControl);
FailIf (NULL == levelControl, EXIT);
result = audioDevice->volumeLeftChanged(volumeControl, oldValue, newValue);
if (newValue == levelControl->getMinValue () && (NULL == audioDevice->outVolRight || (NULL != audioDevice->outVolRight && audioDevice->outVolRight->getMinValue () == audioDevice->outVolRight->getIntValue ()))) {
OSNumber * muteState;
muteState = OSNumber::withNumber (1, 32);
audioDevice->outMute->hardwareValueChanged (muteState);
} else if (oldValue == levelControl->getMinValue () && FALSE == audioDevice->gIsMute) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)0, 32);
audioDevice->outMute->hardwareValueChanged (muteState);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::volumeLeftChangeHandler, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::volumeLeftChanged(IOAudioControl *volumeControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AudioHardwareOutput *theOutput;
UInt16 idx;
SInt32 newiSubVolume;
IOAudioLevelControl * iSubLeftVolume;
IORegistryEntry * start;
DEBUG_IOLOG("+ AppleOnboardAudio::volumeLeftChanged\n");
if(!AudioOutputs)
goto BAIL;
gVolLeft = newValue;
for(idx = 0; idx< AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast(AudioHardwareOutput, AudioOutputs->getObject(idx));
if( theOutput) theOutput->setVolume(newValue, gVolRight);
}
if (NULL != driverDMAEngine->iSubBufferMemory) {
start = childFromPath ("AppleDBDMAAudioDMAEngine", gIOServicePlane);
FAIL_IF (NULL == start, Exit);
iSubLeftVolume = (IOAudioLevelControl *)FindEntryByNameAndProperty (start, "AppleUSBAudioLevelControl", kIOAudioControlSubTypeKey, 'subL');
start->release ();
if (NULL != iSubLeftVolume) {
newiSubVolume = ((newValue * kiSubMaxVolume) / ((IOAudioLevelControl *)volumeControl)->getMaxValue ()) * kiSubVolumePercent / 100;
iSubLeftVolume->setValue (newiSubVolume);
iSubLeftVolume->release();
}
}
Exit:
debug2IOLog ( "AppleOnboardAudio::volumeLeftChanged say's gExpertMode = %d\n", (unsigned int)gExpertMode );
if(!gExpertMode) { debug3IOLog ( "AppleOnboardAudio::volumeLeftChanged invokes WritePRAMVol( %d, %d)\n", (unsigned int)gVolLeft, (unsigned int)gVolRight );
WritePRAMVol(gVolLeft,gVolRight);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::volumeLeftChanged, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::volumeRightChangeHandler(IOService *target, IOAudioControl *volumeControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio * audioDevice;
IOAudioLevelControl * levelControl;
DEBUG_IOLOG("+ AppleOnboardAudio::volumeRightChangeHandler\n");
audioDevice = OSDynamicCast (AppleOnboardAudio, target);
if(!audioDevice)
goto BAIL;
levelControl = OSDynamicCast (IOAudioLevelControl, volumeControl);
FailIf (NULL == levelControl, EXIT);
result = audioDevice->volumeRightChanged(volumeControl, oldValue, newValue);
if (newValue == levelControl->getMinValue () && (NULL == audioDevice->outVolLeft || (NULL != audioDevice->outVolLeft && audioDevice->outVolLeft->getMinValue () == audioDevice->outVolLeft->getIntValue ()))) {
OSNumber * muteState;
muteState = OSNumber::withNumber (1, 32);
audioDevice->outMute->hardwareValueChanged (muteState);
} else if (oldValue == levelControl->getMinValue () && FALSE == audioDevice->gIsMute) {
OSNumber * muteState;
muteState = OSNumber::withNumber ((long long unsigned int)0, 32);
audioDevice->outMute->hardwareValueChanged (muteState);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::volumeRightChangeHandler, result = %d\n", kIOReturnSuccess);
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::volumeRightChanged(IOAudioControl *volumeControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AudioHardwareOutput *theOutput;
UInt16 idx;
SInt32 newiSubVolume;
IOAudioLevelControl * iSubRightVolume;
IORegistryEntry * start;
DEBUG_IOLOG("+ AppleOnboardAudio::volumeRightChanged\n");
if(!AudioOutputs)
goto BAIL;
gVolRight = newValue;
for(idx = 0; idx< AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast(AudioHardwareOutput, AudioOutputs->getObject(idx));
if( theOutput) theOutput->setVolume(gVolLeft, newValue);
}
if (NULL != driverDMAEngine->iSubBufferMemory) {
start = childFromPath ("AppleDBDMAAudioDMAEngine", gIOServicePlane);
FAIL_IF (NULL == start, Exit);
iSubRightVolume = (IOAudioLevelControl *)FindEntryByNameAndProperty (start, "AppleUSBAudioLevelControl", kIOAudioControlSubTypeKey, 'subR');
start->release ();
if (NULL != iSubRightVolume) {
newiSubVolume = ((newValue * kiSubMaxVolume) / ((IOAudioLevelControl *)volumeControl)->getMaxValue ()) * kiSubVolumePercent / 100;
iSubRightVolume->setValue (newiSubVolume);
iSubRightVolume->release();
}
}
Exit:
debug2IOLog ( "AppleOnboardAudio::volumeRightChanged say's gExpertMode = %d\n", (unsigned int)gExpertMode );
if(!gExpertMode) { debug3IOLog ( "AppleOnboardAudio::volumeRightChanged invokes WritePRAMVol( %d, %d)\n", (unsigned int)gVolLeft, (unsigned int)gVolRight );
WritePRAMVol(gVolLeft,gVolRight);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::volumeRightChanged, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::outputMuteChangeHandler(IOService *target, IOAudioControl *muteControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("+ AppleOnboardAudio::outputMuteChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice)
goto BAIL;
result = audioDevice->outputMuteChanged(muteControl, oldValue, newValue);
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::outputMuteChangeHandler, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::outputMuteChanged(IOAudioControl *muteControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
UInt32 idx;
AudioHardwareOutput * theOutput;
IOAudioToggleControl * iSubMute;
IORegistryEntry * start;
DEBUG_IOLOG("+ AppleOnboardAudio::outputMuteChanged\n");
if(!AudioOutputs)
goto BAIL;
gIsMute = newValue;
for(idx = 0; idx< AudioOutputs->getCount(); idx++) {
theOutput = OSDynamicCast(AudioHardwareOutput, AudioOutputs->getObject(idx));
if( theOutput) theOutput->setMute(newValue);
}
debug2IOLog ( "AppleOnboardAudio::outputMuteChanged say's gExpertMode = %d\n", (unsigned int)gExpertMode );
if(!gExpertMode) {
if (newValue) {
debugIOLog( "AppleOnboardAudio::outputMuteChanged invokes WritePRAMVol(0,0)\n" );
WritePRAMVol(0,0);
} else {
debug3IOLog ( "AppleOnboardAudio::outputMuteChanged invokes WritePRAMVol( %d, %d)\n", (unsigned int)gVolLeft, (unsigned int)gVolRight );
WritePRAMVol(gVolLeft,gVolRight);
}
}
start = childFromPath ("AppleDBDMAAudioDMAEngine", gIOServicePlane);
FAIL_IF (NULL == start, EXIT);
iSubMute = (IOAudioToggleControl *)FindEntryByNameAndProperty (start, "AppleUSBAudioMuteControl", kIOAudioControlSubTypeKey, 'subM');
start->release ();
if ( NULL != iSubMute ) {
iSubMute->setValue (newValue);
iSubMute->release();
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::outputMuteChanged, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::gainLeftChangeHandler(IOService *target, IOAudioControl *gainControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("_ AppleOnboardAudio::gainLeftChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice)
goto BAIL;
result = audioDevice->gainLeftChanged(gainControl, oldValue, newValue);
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::gainLeftChangeHandler, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::gainLeftChanged(IOAudioControl *gainControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
UInt32 idx;
AudioHardwareInput *theInput;
DEBUG_IOLOG("+ AppleOnboardAudio::gainLeftChanged\n");
if(!AudioInputs)
goto BAIL;
gGainLeft = newValue;
for(idx = 0; idx< AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if( theInput) theInput->setInputGain(newValue, gGainRight);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::gainLeftChanged, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::gainRightChangeHandler(IOService *target, IOAudioControl *gainControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("+ AppleOnboardAudio::gainRightChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice)
goto BAIL;
result = audioDevice->gainRightChanged(gainControl, oldValue, newValue);
EXIT:
DEBUG_IOLOG("- AppleOnboardAudio::gainRightChangeHandler\n");
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::gainRightChanged(IOAudioControl *gainControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
UInt32 idx;
AudioHardwareInput *theInput;
DEBUG_IOLOG("+ AppleOnboardAudio::gainRightChanged\n");
if(!AudioInputs)
goto BAIL;
gGainRight = newValue;
for(idx = 0; idx< AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if( theInput) theInput->setInputGain(gGainLeft, newValue);
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::gainRightChanged, %d\n", (result == kIOReturnSuccess));
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::passThruChangeHandler(IOService *target, IOAudioControl *passThruControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("+ AppleOnboardAudio::passThruChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice) goto BAIL;
result = audioDevice->passThruChanged(passThruControl, oldValue, newValue);
EXIT:
DEBUG_IOLOG("- AppleOnboardAudio::passThruChangeHandler\n");
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::passThruChanged(IOAudioControl *passThruControl, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::passThruChanged\n");
gIsPlayThroughActive = newValue;
sndHWSetPlayThrough(!newValue);
DEBUG_IOLOG("- AppleOnboardAudio::passThruChanged\n");
return result;
}
IOReturn AppleOnboardAudio::inputSelectorChangeHandler(IOService *target, IOAudioControl *inputSelector, SInt32 oldValue, SInt32 newValue){
IOReturn result = kIOReturnSuccess;
AppleOnboardAudio *audioDevice;
DEBUG_IOLOG("+ AppleOnboardAudio::inputSelectorChangeHandler\n");
audioDevice = (AppleOnboardAudio *)target;
if(!audioDevice) goto BAIL;
result = audioDevice->inputSelectorChanged(inputSelector, oldValue, newValue);
EXIT:
DEBUG_IOLOG("- AppleOnboardAudio::inputSelectorChangeHandler\n");
return result;
BAIL:
result = kIOReturnError;
goto EXIT;
}
IOReturn AppleOnboardAudio::inputSelectorChanged(IOAudioControl *inputSelector, SInt32 oldValue, SInt32 newValue){
AudioHardwareInput *theInput;
UInt32 idx;
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::inputSelectorChanged\n");
if(AudioInputs) {
for(idx = 0; idx< AudioInputs->getCount(); idx++) {
theInput = OSDynamicCast(AudioHardwareInput, AudioInputs->getObject(idx));
if( theInput) theInput->forceActivation(newValue);
}
}
DEBUG_IOLOG("- AppleOnboardAudio::inputSelectorChanged\n");
return result;
}
#pragma mark +POWER MANAGEMENT
IOReturn AppleOnboardAudio::configurePowerObject(IOService *provider){
IOReturn result = kIOReturnSuccess;
DEBUG_IOLOG("+ AppleOnboardAudio::configurePowerObject\n");
switch (theAudioDeviceTreeParser->getPowerObjectType()) {
case kProj6PowerObject:
theAudioPowerObject = AudioProj6PowerObject::createAudioProj6PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj7PowerObject:
theAudioPowerObject = AudioProj7PowerObject::createAudioProj7PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj8PowerObject:
theAudioPowerObject = AudioProj8PowerObject::createAudioProj8PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj10PowerObject:
theAudioPowerObject = AudioProj10PowerObject::createAudioProj10PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj14PowerObject:
theAudioPowerObject = AudioProj14PowerObject::createAudioProj14PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kProj16PowerObject:
theAudioPowerObject = AudioProj16PowerObject::createAudioProj16PowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
case kBasePowerObject:
default: theAudioPowerObject = AudioPowerObject::createAudioPowerObject(this);
if(!theAudioPowerObject) goto BAIL;
break;
}
EXIT:
DEBUG2_IOLOG("- AppleOnboardAudio::configurePowerObject result = %d\n", (result == kIOReturnSuccess));
return(result);
BAIL:
result = kIOReturnError;
goto EXIT;
}
void AppleOnboardAudio::IdleSleepHandlerTimer (OSObject *owner, IOTimerEventSource *sender) {
AppleOnboardAudio * appleOnboardAudio;
appleOnboardAudio = OSDynamicCast (AppleOnboardAudio, owner);
FailIf (NULL == appleOnboardAudio, Exit);
if (kIOAudioDeviceIdle == appleOnboardAudio->fNewPowerState) {
if (NULL != appleOnboardAudio->theAudioPowerObject) {
appleOnboardAudio->theAudioPowerObject->setIdlePowerState ();
appleOnboardAudio->ourPowerState = kIOAudioDeviceIdle;
}
}
Exit:
return;
}
void AppleOnboardAudio::ScheduleIdle (void) {
AbsoluteTime fireTime;
UInt64 nanos;
if (NULL != idleTimer) {
clock_get_uptime (&fireTime);
absolutetime_to_nanoseconds (fireTime, &nanos);
nanos += kPowerDownDelayTime;
nanoseconds_to_absolutetime (nanos, &fireTime);
idleTimer->wakeAtTime (fireTime); }
return;
}
IOReturn AppleOnboardAudio::performPowerStateChange(IOAudioDevicePowerState oldPowerState,
IOAudioDevicePowerState newPowerState,
UInt32 *microsecondsUntilComplete)
{
IOReturn result;
debug3IOLog ("+ AppleOnboardAudio::performPowerStateChange (%d, %d)\n", oldPowerState, newPowerState);
result = kIOReturnSuccess;
if (NULL != theAudioPowerObject) {
if (kIOAudioDeviceSleep == oldPowerState) {
*microsecondsUntilComplete = theAudioPowerObject->GetTimeToChangePowerState (ourPowerState, kIOAudioDeviceActive);
}
*microsecondsUntilComplete += theAudioPowerObject->GetTimeToChangePowerState (ourPowerState, newPowerState);
}
result = super::performPowerStateChange (oldPowerState, newPowerState, microsecondsUntilComplete);
if (NULL != theAudioPowerObject) {
if (kIOAudioDeviceSleep == oldPowerState) {
ourPowerState = kIOAudioDeviceActive;
theAudioPowerObject->setHardwarePowerOn ();
}
fNewPowerState = newPowerState;
if (newPowerState != ourPowerState) {
if (kIOAudioDeviceIdle == newPowerState) {
if (TRUE == theAudioPowerObject->wantsIdleCalls ()) {
ScheduleIdle ();
}
} else {
ourPowerState = newPowerState;
switch (ourPowerState) {
case kIOAudioDeviceSleep:
theAudioPowerObject->setHardwarePowerOff ();
break;
case kIOAudioDeviceActive:
theAudioPowerObject->setHardwarePowerOn ();
break;
default:
;
}
}
}
}
debugIOLog ("- AppleOnboardAudio::performPowerStateChange\n");
return result;
}
IOReturn AppleOnboardAudio::sysPowerDownHandler (void * target, void * refCon, UInt32 messageType, IOService * provider, void * messageArgument, vm_size_t argSize) {
AppleOnboardAudio * appleOnboardAudio;
IOReturn result;
result = kIOReturnUnsupported;
appleOnboardAudio = OSDynamicCast (AppleOnboardAudio, (OSObject *)target);
FailIf (NULL == appleOnboardAudio, Exit);
switch (messageType) {
case kIOMessageSystemWillPowerOff:
case kIOMessageSystemWillRestart:
if (NULL != appleOnboardAudio->theAudioPowerObject) {
appleOnboardAudio->theAudioPowerObject->setIdlePowerState ();
}
result = kIOReturnSuccess;
break;
default:
break;
}
Exit:
return result;
}
#pragma mark +MODEM SOUND
IOReturn AppleOnboardAudio::setModemSound (bool state){
AudioHardwareInput * theInput;
UInt32 idx;
debugIOLog ("+ AppleOnboardAudio::setModemSound\n");
theInput = NULL;
if (gIsModemSoundActive == state)
goto EXIT;
if (FALSE != state) { if (NULL != AudioInputs) {
for (idx = 0; idx < AudioInputs->getCount (); idx++) {
theInput = OSDynamicCast (AudioHardwareInput, AudioInputs->getObject (idx));
if (NULL != theInput) {
theInput->forceActivation ('modm');
theInput->setInputGain (0,0);
}
}
}
sndHWSetPlayThrough (true);
} else {
sndHWSetPlayThrough (!gIsPlayThroughActive);
if (NULL != AudioInputs) {
for (idx = 0; idx < AudioInputs->getCount (); idx++) {
theInput = OSDynamicCast (AudioHardwareInput, AudioInputs->getObject (idx));
if (NULL != theInput){
theInput->forceActivation (inputSelector->getIntValue ());
theInput->setInputGain (gGainLeft, gGainRight);
}
}
}
}
gIsModemSoundActive = state;
EXIT:
debugIOLog ("- AppleOnboardAudio::setModemSound\n");
return kIOReturnSuccess;
}
IOReturn AppleOnboardAudio::callPlatformFunction( const OSSymbol * functionName, bool waitForFunction,void *param1, void *param2, void *param3, void *param4 ) {
debugIOLog ("+ AppleOnboardAudio::callPlatformFunction\n");
if (functionName->isEqualTo ("setModemSound")) {
return (setModemSound ((bool)param1));
}
debugIOLog ("- AppleOnboardAudio::callPlatformFunction\n");
return (super::callPlatformFunction (functionName, waitForFunction,param1, param2, param3, param4));
}
#pragma mark +PRAM VOLUME
UInt8 AppleOnboardAudio::VolumeToPRAMValue (UInt32 inLeftVol, UInt32 inRightVol) {
UInt32 pramVolume; UInt32 averageVolume; UInt32 volumeRange;
UInt32 volumeSteps;
UInt32 leftVol;
UInt32 rightVol;
debug3IOLog ( "AppleOnboardAudio::VolumeToPRAMValue ( 0x%X, 0x%X )\n", (unsigned int)inLeftVol, (unsigned int)inRightVol );
pramVolume = 0; if ( ( 0 != inLeftVol ) || ( 0 != inRightVol ) ) { leftVol = inLeftVol;
rightVol = inRightVol;
if (NULL != outVolLeft) {
leftVol -= outVolLeft->getMinValue ();
debug2IOLog ( "AppleOnboardAudio::VolumeToPRAMValue leftVol = 0x%X\n", (unsigned int)leftVol );
}
if (NULL != outVolRight) {
rightVol -= outVolRight->getMinValue ();
debug2IOLog ( "AppleOnboardAudio::VolumeToPRAMValue rightVol = 0x%X\n", (unsigned int)rightVol );
}
if (NULL != outVolLeft) {
volumeRange = (outVolLeft->getMaxValue () - outVolLeft->getMinValue () + 1);
debug2IOLog ( "AppleOnboardAudio::VolumeToPRAMValue outVolLeft volumeRange = 0x%X\n", (unsigned int)volumeRange );
} else if (NULL != outVolRight) {
volumeRange = (outVolRight->getMaxValue () - outVolRight->getMinValue () + 1);
debug2IOLog ( "AppleOnboardAudio::VolumeToPRAMValue outVolRight volumeRange = 0x%X\n", (unsigned int)volumeRange );
} else {
volumeRange = kMaximumPRAMVolume;
debug2IOLog ( "AppleOnboardAudio::VolumeToPRAMValue volumeRange = 0x%X\n", (unsigned int)volumeRange );
}
averageVolume = (leftVol + rightVol) >> 1; debug2IOLog ( "AppleOnboardAudio::VolumeToPRAMValue averageVolume = 0x%X\n", (unsigned int)volumeRange );
volumeSteps = volumeRange / kMaximumPRAMVolume; pramVolume = averageVolume / volumeSteps;
if ((pramVolume == 0) && (leftVol != 0 || rightVol !=0 )) {
pramVolume = 1;
}
}
debug2IOLog ( "AppleOnboardAudio::VolumeToPRAMValue returns 0x%X\n", (unsigned int)pramVolume );
return (pramVolume & 0x07);
}
UInt32 AppleOnboardAudio::PRAMToVolumeValue (void) {
UInt32 volumeRange;
UInt32 volumeSteps;
if (NULL != outVolLeft) {
volumeRange = (outVolLeft->getMaxValue () - outVolLeft->getMinValue () + 1);
} else if (NULL != outVolRight) {
volumeRange = (outVolRight->getMaxValue () - outVolRight->getMinValue () + 1);
} else {
volumeRange = kMaximumPRAMVolume;
}
volumeSteps = volumeRange / kMaximumPRAMVolume;
return (volumeSteps * ReadPRAMVol ());
}
void AppleOnboardAudio::WritePRAMVol (UInt32 leftVol, UInt32 rightVol) {
UInt8 pramVolume;
UInt8 curPRAMVol;
IODTPlatformExpert * platform;
IOReturn err;
platform = OSDynamicCast(IODTPlatformExpert,getPlatform());
debug3IOLog("AppleOnboardAudio::WritePRAMVol leftVol=%lu, rightVol=%lu\n",leftVol, rightVol);
if (platform) {
debug2IOLog ( "AppleOnboardAudio::WritePRAMVol platform 0x%X\n", (unsigned int)platform );
pramVolume = VolumeToPRAMValue(leftVol,rightVol);
curPRAMVol = pramVolume ^ 0xFF;
debug3IOLog ( "AppleOnboardAudio::WritePRAMVol target pramVolume = 0x%X, curPRAMVol = 0x%X\n", pramVolume, curPRAMVol );
err = platform->readXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
if ( kIOReturnSuccess == err ) {
debug2IOLog ( "AppleOnboardAudio::WritePRAMVol curPRAMVol = 0x%X before write\n", (curPRAMVol & 0x07) );
if (pramVolume != (curPRAMVol & 0x07)) {
curPRAMVol = (curPRAMVol & 0xF8) | pramVolume;
debug2IOLog("AppleOnboardAudio::WritePRAMVol curPRAMVol = 0x%x\n",curPRAMVol);
err = platform->writeXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol,(IOByteCount) 1);
if ( kIOReturnSuccess != err ) {
debug5IOLog ( "0x%X = platform->writeXPRAM( 0x%X, & 0x%X, 1 ), value = 0x%X\n", err, (unsigned int)kPRamVolumeAddr, (unsigned int)&curPRAMVol, (unsigned int)curPRAMVol );
} else {
err = platform->readXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
if ( kIOReturnSuccess == err ) {
if ( ( 0x07 & curPRAMVol ) != pramVolume ) {
debug3IOLog ( "PRAM Read after Write did not compare: Write = 0x%X, Read = 0x%X\n", (unsigned int)pramVolume, (unsigned int)curPRAMVol );
} else {
debugIOLog ( "PRAM verified after write!\n" );
}
} else {
debugIOLog ( "Could not readXPRAM to verify write!\n" );
}
}
} else {
debugIOLog ( "PRAM write request is to current value: no I/O\n" );
}
} else {
debug2IOLog ( "Could not readXPRAM prior to write! Error 0x%X\n", err );
}
} else {
debugIOLog ( "AppleOnboardAudio::WritePRAMVol say's no platform\n" );
}
}
UInt8 AppleOnboardAudio::ReadPRAMVol (void) {
UInt8 curPRAMVol;
IODTPlatformExpert * platform;
curPRAMVol = 0;
platform = OSDynamicCast(IODTPlatformExpert,getPlatform());
if (platform) {
platform->readXPRAM((IOByteCount)kPRamVolumeAddr, &curPRAMVol, (IOByteCount)1);
curPRAMVol &= 0x07;
}
return curPRAMVol;
}
IOReturn AppleOnboardAudio::newUserClient( task_t inOwningTask,
void * inSecurityID,
UInt32 inType,
IOUserClient ** outHandler )
{
#pragma unused( inType )
IOReturn err;
IOUserClient * userClientPtr;
bool result;
IOLog( "[AppleOnboardAudio] creating user client for task 0x%08lX\n", ( UInt32 ) inOwningTask );
err = kIOReturnNoMemory;
userClientPtr = AppleOnboardAudioUserClient::Create( this, inOwningTask );
if( !userClientPtr ) goto exit;
err = kIOReturnError;
result = userClientPtr->attach( this );
if( !result ) goto exit;
result = userClientPtr->start( this );
if( !result ) goto exit;
*outHandler = userClientPtr;
err = kIOReturnSuccess;
exit:
IOLog( "[AppleOnboardAudio] newUserClient done (err=%d)\n", err );
if( err != kIOReturnSuccess )
{
if( userClientPtr )
{
userClientPtr->detach( this );
userClientPtr->release();
}
}
return( err );
}
#if 0
#pragma mark -
#endif
const IOExternalMethod AppleOnboardAudioUserClient::sMethods[] =
{
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioRead, kIOUCScalarIScalarO, 1, 1 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioWrite, kIOUCScalarIScalarO, 2, 0 },
{
NULL, ( IOMethod ) &AppleOnboardAudioUserClient::gpioGetActiveState, kIOUCScalarIScalarO, 1, 1 },
};
const IOItemCount AppleOnboardAudioUserClient::sMethodCount = sizeof( AppleOnboardAudioUserClient::sMethods ) /
sizeof( AppleOnboardAudioUserClient::sMethods[ 0 ] );
OSDefineMetaClassAndStructors( AppleOnboardAudioUserClient, IOUserClient )
AppleOnboardAudioUserClient * AppleOnboardAudioUserClient::Create( AppleOnboardAudio *inDriver, task_t inTask )
{
AppleOnboardAudioUserClient * userClient;
userClient = new AppleOnboardAudioUserClient;
if( !userClient )
{
IOLog( "[AppleOnboardAudio] create user client object failed\n" );
goto exit;
}
if( !userClient->initWithDriver( inDriver, inTask ) )
{
IOLog( "[AppleOnboardAudio] initWithDriver failed\n" );
userClient->release();
userClient = NULL;
goto exit;
}
IOLog( "[AppleOnboardAudio] User client created for task 0x%08lX\n", ( UInt32 ) inTask );
exit:
return( userClient );
}
bool AppleOnboardAudioUserClient::initWithDriver( AppleOnboardAudio *inDriver, task_t inTask )
{
bool result;
IOLog( "[AppleOnboardAudio] initWithDriver\n" );
result = false;
if( !initWithTask( inTask, NULL, 0 ) )
{
IOLog( "[AppleOnboardAudio] initWithTask failed\n" );
goto exit;
}
if( !inDriver )
{
IOLog( "[AppleOnboardAudio] initWithDriver failed (null input driver)\n" );
goto exit;
}
mDriver = inDriver;
mClientTask = inTask;
result = true;
exit:
return( result );
}
void AppleOnboardAudioUserClient::free( void )
{
IOLog( "[AppleOnboardAudio] free\n" );
IOUserClient::free();
}
IOReturn AppleOnboardAudioUserClient::clientClose( void )
{
IOLog( "[AppleOnboardAudio] clientClose\n" );
if( !isInactive() )
{
mDriver = NULL;
}
return( kIOReturnSuccess );
}
IOReturn AppleOnboardAudioUserClient::clientDied( void )
{
IOLog( "[AppleOnboardAudio] clientDied\n" );
return( clientClose() );
}
IOExternalMethod * AppleOnboardAudioUserClient::getTargetAndMethodForIndex( IOService **outTarget, UInt32 inIndex )
{
IOExternalMethod * methodPtr;
methodPtr = NULL;
if( inIndex <= sMethodCount )
{
*outTarget = this;
methodPtr = ( IOExternalMethod * ) &sMethods[ inIndex ];
}
else
{
IOLog( "[AppleOnboardAudio] getTargetAndMethodForIndex - bad index (index=%lu)\n", inIndex );
}
return( methodPtr );
}
IOReturn AppleOnboardAudioUserClient::gpioRead (UInt32 selector, UInt8 * gpioState)
{
IOReturn err;
#ifdef DEBUGMODE
IOLog ("gpioRead (selector=%4s, gpioState=0x%p)\n", (char *)&selector, gpioState);
#endif
err = kIOReturnNotReadable;
FailIf (NULL == mDriver, Exit);
*gpioState = mDriver->readGPIO (selector);
#ifdef DEBUGMODE
IOLog ("gpioRead gpioState=0x%x\n", *gpioState);
#endif
err = kIOReturnSuccess;
Exit:
return (err);
}
IOReturn AppleOnboardAudioUserClient::gpioWrite (UInt32 selector, UInt8 value)
{
IOReturn err;
#ifdef DEBUGMODE
IOLog ( "gpioWrite (selector=%4s, value=0x%x)\n", (char *)&selector, value);
#endif
err = kIOReturnNotReadable;
FailIf (NULL == mDriver, Exit);
mDriver->writeGPIO (selector, value);
err = kIOReturnSuccess;
Exit:
return (err);
}
IOReturn AppleOnboardAudioUserClient::gpioGetActiveState (UInt32 selector, UInt8 * gpioActiveState)
{
IOReturn err;
#ifdef DEBUGMODE
IOLog ("gpioGetActiveState (selector=%4s, gpioActiveState=0x%p)\n", (char *)&selector, gpioActiveState);
#endif
err = kIOReturnNotReadable;
FailIf (NULL == mDriver, Exit);
*gpioActiveState = mDriver->getGPIOActiveState (selector);
#ifdef DEBUGMODE
IOLog ("gpioGetActiveState gpioState=0x%x\n", *gpioActiveState);
#endif
err = kIOReturnSuccess;
Exit:
return (err);
}
#if 0
enum
{
kgpioReadIndex = 0,
kgpioWriteIndex = 1
};
static IOReturn SetupUserClient( void );
static void TearDownUserClient( void );
static mach_port_t gMasterPort = 0;
static io_object_t gDriverObject = 0;
static io_connect_t gDataPort = 0;
static IOReturn SetupUserClient( void )
{
IOReturn err;
CFDictionaryRef matchingDictionary;
io_iterator_t serviceIter;
err = kIOReturnSuccess;
matchingDictionary = NULL;
serviceIter = NULL;
if( gDataPort )
{
goto exit;
}
err = IOMasterPort( NULL, &gMasterPort );
if( err != kIOReturnSuccess ) goto exit;
err = kIOReturnNotFound;
matchingDictionary = IOServiceNameMatching( "AppleTexasAudio" );
if( !matchingDictionary ) goto exit;
err = IOServiceGetMatchingServices( gMasterPort, matchingDictionary, &serviceIter );
if( err != kIOReturnSuccess ) goto exit;
matchingDictionary = NULL;
err = kIOReturnNotFound;
gDriverObject = IOIteratorNext( serviceIter );
if( !gDriverObject ) goto exit;
err = IOServiceOpen( gDriverObject, mach_task_self(), 0, &gDataPort );
if( err != kIOReturnSuccess ) goto exit;
exit:
if( serviceIter )
{
IOObjectRelease( serviceIter );
}
if( matchingDictionary )
{
CFRelease( matchingDictionary );
}
if( err != kIOReturnSuccess )
{
TearDownUserClient();
}
return( err );
}
static void TearDownUserClient( void )
{
if( gDataPort )
{
IOServiceClose( gDataPort );
gDataPort = 0;
}
if( gDriverObject )
{
IOObjectRelease( gDriverObject );
gDriverObject = NULL;
}
if( gMasterPort )
{
mach_port_deallocate( mach_task_self(), gMasterPort );
gMasterPort = 0;
}
}
#if 0
#pragma mark -
#endif
OSStatus gpioRead( UInt32 selector, UInt8 * gpioState )
{
OSStatus err;
err = SetupUserClient();
if( err != noErr ) goto exit;
err = IOConnectMethodScalarIScalarO( gDataPort, kgpioReadIndex, 1, 1, selector, gpioState );
if( err != noErr ) goto exit;
exit:
return( err );
}
OSStatus gpioWrite( UInt32 selector, UInt8 value )
{
OSStatus err;
err = SetupUserClient();
if( err != noErr ) goto exit;
err = IOConnectMethodScalarIScalarO( gDataPort, kgpioWriteIndex, 2, 0, selector, gpioState );
if( err != noErr ) goto exit;
exit:
return( err );
}
OSStatus gpioGetAddress( UInt32 selector, UInt8 ** gpioAddress )
{
OSStatus err;
err = SetupUserClient();
if( err != noErr ) goto exit;
err = IOConnectMethodScalarIScalarO( gDataPort, kgpiogetAddressIndex, 2, selector, gpioAddress );
if( err != noErr ) goto exit;
exit:
return( err );
}
#endif