#include "AOAHALPlugin.h"
#include <CoreFoundation/CoreFoundation.h>
#include <syslog.h>
io_registry_entry_t gControlReference;
io_registry_entry_t mHeadphoneExclusiveControl;
io_connect_t gConnectionReference;
io_object_t ioAudioEngine;
io_object_t ioAudioDevice;
static void convertDecTo4cc (UInt32 input, char * output);
OSStatus AudioDriverPlugInOpen (AudioDriverPlugInHostInfo * inHostInfo) {
OSStatus theResult;
CFNumberRef theValue;
UInt32 theIntVal;
io_iterator_t theIterator;
kern_return_t theKernelError;
theResult = noErr;
ioAudioEngine = inHostInfo->mIOAudioEngine;
ioAudioDevice = inHostInfo->mIOAudioDevice;
theKernelError = IORegistryEntryCreateIterator (inHostInfo->mIOAudioDevice, kIOServicePlane, kIORegistryIterateRecursively, &theIterator);
if (KERN_SUCCESS == theKernelError) {
gControlReference = IOIteratorNext (theIterator);
while (gControlReference != 0) {
if (IOObjectConformsTo (gControlReference, "IOAudioToggleControl")) {
theValue = IORegistryEntryCreateCFProperty (gControlReference, CFSTR ("IOAudioControlSubType"), kCFAllocatorDefault, 0);
if (theValue) {
CFNumberGetValue (theValue, kCFNumberSInt32Type, (void *)&theIntVal);
CFRelease (theValue);
}
if (theIntVal != 'hpex') {
gControlReference = IOIteratorNext (theIterator);
} else {
mHeadphoneExclusiveControl = gControlReference;
break; }
} else {
gControlReference = IOIteratorNext (theIterator);
}
}
}
if (theIterator)
IOObjectRelease (theIterator);
return theResult;
}
OSStatus AudioDriverPlugInClose (AudioDeviceID inDevice) {
if (gConnectionReference)
IOServiceClose (gConnectionReference);
if (gControlReference)
IOObjectRelease (gControlReference);
return 0;
}
OSStatus AudioDriverPlugInDeviceGetPropertyInfo (AudioDeviceID inDevice, UInt32 inLine, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 * outSize, Boolean * outWritable) {
char theProp[5];
OSStatus theResult;
CFDictionaryRef theDict;
CFNumberRef theNumber;
convertDecTo4cc (inPropertyID, theProp);
theResult = kAudioHardwareUnknownPropertyError;
switch (inPropertyID) {
case kAOAPropertyPowerState:
if (outWritable) *outWritable = FALSE;
if (outSize) *outSize = sizeof (UInt32);
theResult = noErr;
break;
case kAOAPropertySelectionsReference:
theDict = IORegistryEntryCreateCFProperty (ioAudioEngine, CFSTR ("MappingDictionary"), kCFAllocatorDefault, 0);
if (theDict) {
CFRelease (theDict);
if (outWritable) *outWritable = FALSE;
if (outSize) *outSize = sizeof (UInt32);
theResult = noErr;
}
break;
case kAOAPropertyAvailableInputsBitmap:
theNumber = IORegistryEntryCreateCFProperty (ioAudioEngine, CFSTR ("InputsBitmap"), kCFAllocatorDefault, 0);
if (theNumber) {
CFRelease (theNumber);
if (outWritable) *outWritable = FALSE;
if (outSize) *outSize = sizeof (UInt32);
theResult = noErr;
}
break;
case kAOAPropertyAvailableOutputsBitmap:
theNumber = IORegistryEntryCreateCFProperty (ioAudioEngine, CFSTR ("OutputsBitmap"), kCFAllocatorDefault, 0);
if (theNumber) {
CFRelease (theNumber);
if (outWritable) *outWritable = FALSE;
if (outSize) *outSize = sizeof (UInt32);
theResult = noErr;
}
break;
default:
break;
}
return theResult;
}
OSStatus GetIntPropertyData (io_registry_entry_t theEntry, CFStringRef theKey, void * outPropertyData) {
CFNumberRef theValue;
OSStatus theResult;
SInt32 theIntVal;
theResult = kAudioHardwareBadDeviceError;
theValue = IORegistryEntryCreateCFProperty (theEntry, theKey, kCFAllocatorDefault, 0);
if (theValue) {
CFNumberGetValue (theValue, kCFNumberSInt32Type, (void *)&theIntVal);
if (outPropertyData) *(UInt32 *)outPropertyData = theIntVal;
CFRelease (theValue);
theResult = noErr;
}
return theResult;
}
OSStatus AudioDriverPlugInDeviceGetProperty (AudioDeviceID inDevice, UInt32 inLine, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 * ioPropertyDataSize, void * outPropertyData) {
char theProp[5];
OSStatus theResult;
CFDictionaryRef theDict;
CFNumberRef theNumber;
CFStringRef entryname;
theResult = kAudioHardwareUnknownPropertyError;
convertDecTo4cc (inPropertyID, theProp);
switch (inPropertyID) {
case kAOAPropertyPowerState:
theResult = GetIntPropertyData (ioAudioDevice, CFSTR ("IOAudioPowerState"), outPropertyData);
if (!theResult) {
if (ioPropertyDataSize) *ioPropertyDataSize = sizeof (UInt32);
}
break;
case kAOAPropertySelectionsReference:
theDict = IORegistryEntryCreateCFProperty (ioAudioEngine, CFSTR ("MappingDictionary"), kCFAllocatorDefault, 0);
if (theDict) {
if (outPropertyData) *(CFDictionaryRef *)outPropertyData = theDict;
else CFRelease (theDict);
if (ioPropertyDataSize) *ioPropertyDataSize = sizeof (UInt32);
}
theResult = noErr;
break;
case kAOAPropertyAvailableInputsBitmap:
case kAOAPropertyAvailableOutputsBitmap:
entryname = ( inPropertyID == kAOAPropertyAvailableInputsBitmap) ? CFSTR ("InputsBitmap") : CFSTR ("OutputsBitmap");
theNumber = IORegistryEntryCreateCFProperty (ioAudioEngine, entryname, kCFAllocatorDefault, 0);
if (theNumber) {
if (outPropertyData)
{
if ( CFNumberGetValue( theNumber, kCFNumberSInt32Type, outPropertyData ))
{
if (ioPropertyDataSize) *ioPropertyDataSize = sizeof (UInt32);
theResult = noErr;
}
else
{
theResult = kAudioHardwareBadPropertySizeError;
}
}
else
{
theResult = noErr;
}
CFRelease (theNumber);
}
break;
default:
break;
}
return theResult;
}
OSStatus AudioDriverPlugInDeviceSetProperty (AudioDeviceID inDevice, const AudioTimeStamp * inWhen, UInt32 inLine, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void * inPropertyData) {
char theProp[5];
OSStatus theResult;
convertDecTo4cc (inPropertyID, theProp);
theResult = kAudioHardwareUnknownPropertyError;
switch (inPropertyID) {
case kAOAPropertyPowerState:
case kAOAPropertySelectionsReference:
case kAOAPropertyAvailableInputsBitmap:
case kAOAPropertyAvailableOutputsBitmap:
theResult = kAudioHardwareIllegalOperationError;
break;
default:
break;
}
return theResult;
}
OSStatus AudioDriverPlugInStreamGetPropertyInfo (AudioDeviceID inDevice, io_object_t inIOAudioStream, UInt32 inChannel, AudioDevicePropertyID inPropertyID, UInt32 * outSize, Boolean * outWritable) {
char theProp[5];
OSStatus theResult;
convertDecTo4cc (inPropertyID, theProp);
theResult = kAudioHardwareUnknownPropertyError;
return theResult;
}
OSStatus AudioDriverPlugInStreamGetProperty (AudioDeviceID inDevice, io_object_t inIOAudioStream, UInt32 inChannel, AudioDevicePropertyID inPropertyID, UInt32 * ioPropertyDataSize, void * outPropertyData) {
char theProp[5];
OSStatus theResult;
convertDecTo4cc (inPropertyID, theProp);
theResult = kAudioHardwareUnknownPropertyError;
return theResult;
}
OSStatus AudioDriverPlugInStreamSetProperty (AudioDeviceID inDevice, io_object_t inIOAudioStream, const AudioTimeStamp * inWhen, UInt32 inChannel, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void * inPropertyData) {
char theProp[5];
OSStatus theResult;
convertDecTo4cc (inPropertyID, theProp);
theResult = kAudioHardwareUnknownPropertyError;
return theResult;
}
static void convertDecTo4cc (UInt32 input, char * output) {
UInt32 mask;
UInt32 val32;
UInt8 theChar;
short idx;
mask = 0xFF000000;
for (idx = 0; idx < 4; idx++) {
val32 = (input & (mask >> 8 * idx));
theChar = (UInt8)(val32 >> 8 * (3 - idx));
output[idx] = theChar;
}
output[idx]='\0';
}