[plain text]
#include "AppleUSBAudioDevice.h"
#define super IOAudioDevice
OSDefineMetaClassAndStructors (AppleUSBAudioDevice, super)
bool AppleUSBAudioDevice::init (OSDictionary * properties) {
bool resultCode;
debug2IOLog ("+AppleUSBAudioDevice[%p]::init ()\n", this);
resultCode = FALSE;
FailIf (FALSE == super::init (properties), Exit);
resultCode = TRUE;
Exit:
debug2IOLog ("-AppleUSBAudioDevice[%p]::init ()\n", this);
return resultCode;
}
void AppleUSBAudioDevice::free () {
debug2IOLog ("+AppleUSBAudioDevice[%p]::free ()\n", this);
if (interfaceLock) {
IORecursiveLockFree (interfaceLock);
interfaceLock = NULL;
}
if (usbAudio) {
usbAudio->release ();
usbAudio = NULL;
}
super::free ();
debug2IOLog ("-AppleUSBAudioDevice[%p]::free ()\n", this);
}
bool AppleUSBAudioDevice::requestTerminate (IOService * provider, IOOptionBits options) {
debug4IOLog ("+AppleUSBAudioDevice[%p]::requestTerminate (%p, %x)\n", this, provider, options);
debug4IOLog ("-AppleUSBAudioDevice[%p]::requestTerminate (%p, %x)\n", this, provider, options);
return TRUE; }
bool AppleUSBAudioDevice::ControlsStreamNumber (UInt8 streamNumber) {
UInt8 * streamNumbers;
UInt8 numStreams;
UInt8 index;
bool doesControl;
doesControl = FALSE;
if (usbAudio) {
usbAudio->GetControlledStreamNumbers (&streamNumbers, &numStreams);
for (index = 0; index < numStreams; index++) {
debug3IOLog ("Checking stream %d against controled stream %d\n", streamNumber, streamNumbers[index]);
if (streamNumber == streamNumbers[index]) {
doesControl = TRUE;
break; }
}
}
return doesControl;
}
bool AppleUSBAudioDevice::start (IOService * provider) {
bool result;
debug3IOLog ("+ AppleUSBAudioDevice[%p]::start (%p)\n", this, provider);
result = FALSE;
controlInterface = OSDynamicCast (IOUSBInterface, provider);
FailIf (FALSE == controlInterface->open (this), Exit);
mInitHardwareThread = thread_call_allocate ((thread_call_func_t)AppleUSBAudioDevice::initHardwareThread, (thread_call_param_t)this);
FailIf (NULL == mInitHardwareThread, Exit);
debug3IOLog ("- AppleUSBAudioDevice[%p]::start (%p)\n", this, provider);
result = super::start (provider);
Exit:
return result;
}
bool AppleUSBAudioDevice::initHardware (IOService * provider) {
bool result;
result = FALSE;
FailIf (NULL == mInitHardwareThread, Exit);
thread_call_enter1 (mInitHardwareThread, (void *)provider);
result = TRUE;
Exit:
return result;
}
void AppleUSBAudioDevice::initHardwareThread (AppleUSBAudioDevice * aua, void * provider) {
IOCommandGate * cg;
IOReturn result;
FailIf (NULL == aua, Exit);
cg = aua->getCommandGate ();
if (cg) {
result = cg->runAction (aua->initHardwareThreadAction, provider);
}
Exit:
return;
}
IOReturn AppleUSBAudioDevice::initHardwareThreadAction (OSObject * owner, void * provider, void * arg2, void * arg3, void * arg4) {
AppleUSBAudioDevice * aua;
IOReturn result;
result = kIOReturnError;
aua = (AppleUSBAudioDevice *)owner;
FailIf (NULL == aua, Exit);
result = aua->protectedInitHardware ((IOService *)provider);
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::protectedInitHardware (IOService * provider) {
char string[kStringBufferSize];
UInt8 stringIndex;
IOReturn err;
Boolean resultCode;
UInt8 * streamNumbers;
UInt8 numStreams;
debug3IOLog ("+AppleUSBAudioDevice[%p]::start (%p)\n", this, provider);
resultCode = FALSE;
debug2IOLog ("There are %d configurations on this device\n", controlInterface->GetDevice()->GetNumConfigurations ());
debug2IOLog ("Our control interface number is %d\n", controlInterface->GetInterfaceNumber ());
usbAudio = USBAudioConfigObject::create (controlInterface->GetDevice()->GetFullConfigurationDescriptor (0), controlInterface->GetInterfaceNumber ());
FailIf (NULL == usbAudio, Exit);
usbAudio->GetControlledStreamNumbers (&streamNumbers, &numStreams);
debug2IOLog ("Num streams controlled = %d\n", numStreams);
debug2IOLog ("GetNumStreamInterfaces = %d\n", usbAudio->GetNumStreamInterfaces ());
FailIf (0 == numStreams, Exit);
FailIf (usbAudio->GetNumOutputTerminals (0, 0) == 1 && usbAudio->GetIndexedOutputTerminalType (0, 0, 0) == OUTPUT_LOW_FREQUENCY_EFFECTS_SPEAKER, Exit);
err = kIOReturnError;
string[0] = 0;
stringIndex = controlInterface->GetInterfaceStringIndex ();
if (0 != stringIndex) {
err = controlInterface->GetDevice()->GetStringDescriptor (stringIndex, string, kStringBufferSize);
} else {
stringIndex = controlInterface->GetDevice()->GetProductStringIndex ();
if (0 != stringIndex) {
err = controlInterface->GetDevice()->GetStringDescriptor (stringIndex, string, kStringBufferSize);
}
}
if (0 == string[0] || kIOReturnSuccess != err) {
strcpy (string, "Unknown USB Audio Device");
}
setDeviceName (string);
err = kIOReturnError;
string[0] = 0;
stringIndex = controlInterface->GetDevice()->GetManufacturerStringIndex ();
if (0 != stringIndex) {
err = controlInterface->GetDevice()->GetStringDescriptor (stringIndex, string, kStringBufferSize);
}
if (0 == string[0] || kIOReturnSuccess != err) {
strcpy (string, "Unknown Manufacturer");
}
setManufacturerName (string);
setDeviceTransportType (kIOAudioDeviceTransportTypeUSB);
interfaceLock = IORecursiveLockAlloc ();
FailIf (NULL == interfaceLock, Exit);
resultCode = super::initHardware (provider);
Exit:
debug3IOLog ("-AppleUSBAudioDevice[%p]::start (%p)\n", this, provider);
return TRUE;
}
IOReturn AppleUSBAudioDevice::performPowerStateChange (IOAudioDevicePowerState oldPowerState, IOAudioDevicePowerState newPowerState, UInt32 *microSecsUntilComplete) {
IOReturn result;
debug4IOLog ("+AppleUSBAudioDevice::performPowerStateChange (%d, %d, %p)\n", oldPowerState, newPowerState, microSecsUntilComplete);
result = super::performPowerStateChange (oldPowerState, newPowerState, microSecsUntilComplete);
if (oldPowerState == kIOAudioDeviceSleep) {
debugIOLog ("Waking from sleep - flushing controls to the device.\n");
flushAudioControls ();
}
return result;
}
void AppleUSBAudioDevice::stop (IOService *provider) {
bool shouldStop;
debug5IOLog ("+AppleUSBAudioDevice[%p]::stop (%p) - audioEngines = %p - rc=%d\n", this, provider, audioEngines, getRetainCount());
shouldStop = TRUE;
if (shouldStop) {
performStop (provider);
}
debug2IOLog("-AppleUSBAudioDevice[%p]::stop ()\n", this);
}
Boolean AppleUSBAudioDevice::ShouldUpdatePRAM (void) {
const IORegistryPlane * usbPlane;
IORegistryEntry * usbRegEntry;
OSObject * obj;
OSNumber * number;
UInt16 productID;
UInt16 vendorID;
Boolean speakersGood;
Boolean connectionGood;
Boolean result;
result = FALSE;
speakersGood = FALSE;
connectionGood = FALSE;
vendorID = controlInterface->GetDevice()->GetVendorID ();
debug2IOLog ("+ ShouldUpdatePRAM\nspeaker's vendorID = 0x%x\n", vendorID);
if (kIOUSBVendorIDAppleComputer == vendorID || kIOUSBVendorIDHaronKardon == vendorID || kIOUSBVendorMicronas == vendorID) {
speakersGood = TRUE;
}
debug2IOLog ("speakersGood = %d\n", speakersGood);
if (TRUE == speakersGood) {
usbPlane = getPlane (kIOUSBPlane);
FailIf (NULL == usbPlane, Exit);
usbRegEntry = controlInterface->GetDevice()->getParentEntry (usbPlane);
FailIf (NULL == usbRegEntry, Exit);
obj = usbRegEntry->getProperty (kUSBVendorID);
number = OSDynamicCast (OSNumber, obj);
FailIf (NULL == number, Exit);
vendorID = number->unsigned32BitValue ();
debug2IOLog ("hub's vendorID = 0x%x\n", vendorID);
if (kIOUSBVendorIDAppleComputer == vendorID) {
obj = usbRegEntry->getProperty (kUSBDevicePropertyLocationID);
number = OSDynamicCast (OSNumber, obj);
FailIf (NULL == number, Exit);
if (OSDynamicCast (IOUSBRootHubDevice, usbRegEntry)) {
connectionGood = TRUE;
debugIOLog ("Directly connected to the root hub\n");
} else {
obj = usbRegEntry->getProperty (kUSBProductID);
number = OSDynamicCast (OSNumber, obj);
FailIf (NULL == number, Exit);
productID = number->unsigned32BitValue ();
debug2IOLog ("hub's productID = 0x%x\n", productID);
if (kStudioDisplay15CRT == productID || kStudioDisplay17CRT == productID || kCinemaDisplay == productID || kStudioDisplay17FP == productID) {
connectionGood = TRUE;
debugIOLog ("Connected to a capable monitor\n");
}
}
}
}
debug2IOLog ("connectionGood = %d\n", connectionGood);
if (TRUE == connectionGood && FALSE == FindSoundNode ()) {
result = TRUE;
}
Exit:
debug2IOLog ("- ShouldUpdatePRAM result = %d\n", result);
return result;
}
Boolean AppleUSBAudioDevice::FindSoundNode (void) {
const IORegistryPlane * dtPlane;
IORegistryEntry * regEntry;
IORegistryIterator * iterator;
Boolean found;
Boolean done;
const char * name;
found = FALSE;
dtPlane = IORegistryEntry::getPlane (kIODeviceTreePlane);
FailIf (NULL == dtPlane, Exit);
iterator = IORegistryIterator::iterateOver (dtPlane, kIORegistryIterateRecursively);
FailIf (NULL == iterator, Exit);
done = FALSE;
regEntry = iterator->getNextObject ();
while (NULL != regEntry && FALSE == done) {
name = regEntry->getName ();
if (0 == strcmp (name, "mac-io")) {
iterator->release (); iterator = IORegistryIterator::iterateOver (regEntry, dtPlane);
done = TRUE;
}
regEntry = iterator->getNextObject ();
}
regEntry = iterator->getNextObject ();
while (NULL != regEntry && FALSE == found) {
name = regEntry->getName ();
if (0 == strcmp (name, "sound")) {
found = TRUE;
}
regEntry = iterator->getNextObject ();
}
iterator->release ();
Exit:
return found;
}
void AppleUSBAudioDevice::performStop (IOService *provider) {
debug3IOLog("+AppleUSBAudioDevice[%p]::performStop (%p)\n", this, provider);
super::stop (provider);
if (controlInterface) {
controlInterface->close (this);
controlInterface = NULL;
}
debug3IOLog ("-AppleUSBAudioDevice[%p]::performStop (%p)\n", this, provider);
}
bool AppleUSBAudioDevice::terminate (IOOptionBits options) {
bool shouldTerminate;
bool result;
shouldTerminate = TRUE;
result = TRUE;
debug3IOLog ("+AppleUSBAudioDevice[%p]::terminate () - rc=%d\n", this, getRetainCount ());
if (shouldTerminate) {
result = super::terminate (options);
}
debug3IOLog ("-AppleUSBAudioDevice[%p]::terminate () - rc=%d\n", this, getRetainCount ());
return result;
}
bool AppleUSBAudioDevice::finalize (IOOptionBits options) {
bool result;
debug4IOLog ("+AppleUSBAudioDevice[%p]::finalize (%p) - rc=%d\n", this, options, getRetainCount ());
result = super::finalize (options);
debug4IOLog ("-AppleUSBAudioDevice[%p]::finalize (%p) - rc=%d\n", this, options, getRetainCount ());
return result;
}
IOReturn AppleUSBAudioDevice::message (UInt32 type, IOService * provider, void * arg) {
debug5IOLog ("+AppleUSBAudioDevice[%p]::message (0x%x, %p) - rc=%d\n", this, type, provider, getRetainCount ());
switch (type) {
case kIOMessageServiceIsTerminated:
case kIOMessageServiceIsRequestingClose:
if (controlInterface != NULL && controlInterface == provider) {
controlInterface->close (this);
controlInterface = NULL;
}
default:
;
}
debug5IOLog ("-AppleUSBAudioDevice[%p]::message (0x%x, %p) - rc=%d\n", this, type, provider, getRetainCount ());
return kIOReturnSuccess;
}
IOReturn AppleUSBAudioDevice::createControlsForInterface (IOAudioEngine *audioEngine, UInt8 interfaceNum, UInt8 altInterfaceNum) {
AppleUSBAudioEngine * usbAudioEngine;
UInt8 channelNum;
AppleUSBAudioLevelControl * speakerControl;
AppleUSBAudioLevelControl * micControl;
AppleUSBAudioLevelControl * pramControl;
AppleUSBAudioMuteControl * muteControl;
IOReturn result;
UInt16 terminalType;
UInt8 numTerminals;
UInt8 featureUnitID;
UInt8 terminalIndex;
UInt8 controlInterfaceNum;
Boolean shouldUpdatePRAM;
debug4IOLog ("+AppleUSBAudioDevice[%p]::createControlsForInterface %d %d\n", this, interfaceNum, altInterfaceNum);
result = kIOReturnError;
terminatingDriver = FALSE;
FailIf (NULL == controlInterface, Exit);
usbAudioEngine = OSDynamicCast (AppleUSBAudioEngine, audioEngine);
FailIf (NULL == usbAudioEngine, Exit);
controlInterfaceNum = controlInterface->GetInterfaceNumber ();
if (usbAudioEngine->getDirection () == kIOAudioStreamDirectionOutput) {
featureUnitID = 0;
numTerminals = usbAudio->GetNumOutputTerminals (controlInterfaceNum, 0);
debug2IOLog ("num output terminals = %d\n", numTerminals);
for (terminalIndex = 0; terminalIndex < numTerminals; terminalIndex++) {
debug2IOLog ("terminalIndex = 0x%X\n", terminalIndex);
terminalType = usbAudio->GetIndexedOutputTerminalType (controlInterfaceNum, 0, terminalIndex);
debug2IOLog ("terminalType = 0x%X\n", terminalType);
if (terminalType != 0x0101) { featureUnitID = usbAudio->GetFeatureUnitIDConnectedToOutputTerminal (controlInterfaceNum, 0, usbAudio->GetIndexedOutputTerminalID (controlInterfaceNum, 0, terminalIndex));
debug2IOLog ("featureUnitID = %d\n", featureUnitID);
break; }
}
FailWithAction (0 == featureUnitID, result = kIOReturnSuccess, Exit); controlInterface->SetAlternateInterface (this, kRootAlternateSetting);
shouldUpdatePRAM = ShouldUpdatePRAM ();
if (shouldUpdatePRAM) {
pramControl = AppleUSBAudioLevelControl::create (featureUnitID,
controlInterfaceNum,
0xff,
1,
shouldUpdatePRAM,
(USBDeviceRequest)&deviceRequest,
this,
kIOAudioLevelControlSubTypeVolume,
kIOAudioControlUsageOutput);
if (NULL != pramControl) {
audioEngine->addDefaultAudioControl (pramControl);
pramControl->release ();
}
}
for (channelNum = 0; channelNum <= usbAudio->GetNumChannels (interfaceNum, altInterfaceNum); channelNum++) {
if (usbAudio->ChannelHasVolumeControl (controlInterfaceNum, 0, featureUnitID, channelNum)) {
speakerControl = AppleUSBAudioLevelControl::create (featureUnitID,
controlInterfaceNum,
VOLUME_CONTROL,
channelNum,
shouldUpdatePRAM,
(USBDeviceRequest)&deviceRequest,
this,
kIOAudioLevelControlSubTypeVolume,
kIOAudioControlUsageOutput);
if (NULL != speakerControl) {
audioEngine->addDefaultAudioControl (speakerControl);
speakerControl->release ();
} else {
debug2IOLog ("++AppleUSBAudioDevice::createControlsForInterface () - error creating volume control for channelNum %d\n", channelNum);
}
}
}
muteControl = NULL;
for (channelNum = 0; channelNum <= usbAudio->GetNumChannels (interfaceNum, altInterfaceNum); channelNum++) {
if (usbAudio->ChannelHasMuteControl (controlInterfaceNum, 0, featureUnitID, channelNum)) {
muteControl = AppleUSBAudioMuteControl::create (featureUnitID,
controlInterfaceNum,
channelNum,
(USBDeviceRequest)&deviceRequest,
this,
kIOAudioControlUsageOutput);
if (NULL != muteControl) {
audioEngine->addDefaultAudioControl (muteControl);
muteControl->release ();
} else {
debug2IOLog ("++AppleUSBAudioDevice::createControlsForInterface () - error creating mute control for channelNum %d\n", channelNum);
}
}
}
} else {
featureUnitID = 0;
numTerminals = usbAudio->GetNumOutputTerminals (controlInterfaceNum, 0);
debug2IOLog ("num output terminals = %d\n", numTerminals);
for (terminalIndex = 0; terminalIndex < numTerminals; terminalIndex++) {
debug2IOLog ("terminalIndex = 0x%X\n", terminalIndex);
terminalType = usbAudio->GetIndexedOutputTerminalType (controlInterfaceNum, 0, terminalIndex);
debug2IOLog ("terminalType = 0x%X\n", terminalType);
if (terminalType == 0x0101) { featureUnitID = usbAudio->GetFeatureUnitIDConnectedToOutputTerminal (controlInterfaceNum, 0, usbAudio->GetIndexedOutputTerminalID (controlInterfaceNum, 0, terminalIndex));
debug2IOLog ("featureUnitID = %d\n", featureUnitID);
break; }
}
FailWithAction (0 == featureUnitID, result = kIOReturnSuccess, Exit); controlInterface->SetAlternateInterface (this, kRootAlternateSetting);
debug2IOLog ("There are %d controls\n", usbAudio->GetNumChannels (interfaceNum, altInterfaceNum));
for (channelNum = 0; channelNum <= usbAudio->GetNumChannels (interfaceNum, altInterfaceNum); channelNum++) {
if (usbAudio->ChannelHasVolumeControl (controlInterfaceNum, 0, featureUnitID, channelNum)) {
micControl = AppleUSBAudioLevelControl::create (featureUnitID,
controlInterfaceNum,
VOLUME_CONTROL,
channelNum,
FALSE,
(USBDeviceRequest)&deviceRequest,
this,
kIOAudioLevelControlSubTypeVolume,
kIOAudioControlUsageInput);
if (NULL != micControl) {
audioEngine->addDefaultAudioControl (micControl);
micControl->release ();
} else {
debug2IOLog ("++AppleUSBAudioDevice::createControlsForInterface () - error creating volume control for channelNum %d\n", channelNum);
}
} else {
debug2IOLog ("channel %d doesn't have a volume control\n", channelNum);
}
}
muteControl = NULL;
for (channelNum = 0; channelNum <= usbAudio->GetNumChannels (interfaceNum, altInterfaceNum); channelNum++) {
if (usbAudio->ChannelHasMuteControl (controlInterfaceNum, 0, featureUnitID, channelNum)) {
muteControl = AppleUSBAudioMuteControl::create (featureUnitID,
controlInterfaceNum,
channelNum,
(USBDeviceRequest)&deviceRequest,
this,
kIOAudioControlUsageInput);
if (NULL != muteControl) {
audioEngine->addDefaultAudioControl (muteControl);
muteControl->release ();
} else {
debug2IOLog ("++AppleUSBAudioDevice::createControlsForInterface () - error creating mute control for channelNum %d\n", channelNum);
}
}
}
}
Exit:
return result;
}
IOReturn AppleUSBAudioDevice::activateAudioEngine (IOAudioEngine *audioEngine, bool shouldStartAudioEngine, UInt8 interfaceNum, UInt8 altInterfaceNum) {
IOReturn result;
debug5IOLog ("+AppleUSBAudioDevice[%p]::activateAudioEngine (%p, %d) - rc=%d\n", this, audioEngine, shouldStartAudioEngine, getRetainCount());
result = super::activateAudioEngine (audioEngine, shouldStartAudioEngine);
debug4IOLog ("-AppleUSBAudioDevice[%p]::activateAudioEngine (%p) - rc=%d\n", this, audioEngine, getRetainCount ());
return result;
}
IOReturn AppleUSBAudioDevice::deviceRequest (IOUSBDevRequest *request, AppleUSBAudioDevice * self, IOUSBCompletion *completion) {
IOReturn result;
debug4IOLog ("+AppleUSBAudioDevice[%p]::deviceRequest (%p, %p)\n", self, request, completion);
result = kIOReturnSuccess;
if (self->controlInterface && FALSE == self->terminatingDriver) {
FailIf (NULL == self->interfaceLock, Exit);
IORecursiveLockLock (self->interfaceLock);
result = self->controlInterface->DeviceRequest (request, completion);
IORecursiveLockUnlock (self->interfaceLock);
}
debug4IOLog ("-AppleUSBAudioDevice[%p]::deviceRequest (%p, %p)\n", self, request, completion);
Exit:
return result;
}
bool AppleUSBAudioDevice::willTerminate (IOService * provider, IOOptionBits options) {
debug3IOLog ("+AppleUSBAudioDevice[%p]::willTerminate (%p)\n", this, provider);
if (controlInterface == provider) {
terminatingDriver = TRUE;
}
debug2IOLog ("-AppleUSBAudioDevice[%p]::willTerminate\n", this);
return super::willTerminate (provider, options);
}
#ifdef DEBUG
void AppleUSBAudioDevice::retain() const
{
super::retain();
}
void AppleUSBAudioDevice::release() const
{
super::release();
}
#endif
Generated by GNU enscript 1.6.4.