/* * AudioDeviceTreeParser.cpp * Apple02Audio * * Created by lcerveau on Thu May 31 2001. * Copyright (c) 2001 __CompanyName__. All rights reserved. * */ #include "AudioHardwareCommon.h" #include "AudioHardwareConstants.h" #include "AudioDeviceTreeParser.h" #include "AudioHardwareOutput.h" #include "AudioHardwareDetect.h" #include "AudioHardwarePower.h" #define super OSObject // aml 5.27.02 #define OVERRIDE_REGISTRY_ZERO_GAIN 1 OSDefineMetaClassAndStructors(AudioDeviceTreeParser, OSObject) // Creation and destruction of the object AudioDeviceTreeParser *AudioDeviceTreeParser::createWithEntryProvider(IOService *provider){ AudioDeviceTreeParser *myAudioDTParser = 0; FAIL_IF(!provider, EXIT); myAudioDTParser = new AudioDeviceTreeParser; if(myAudioDTParser) { if(!(myAudioDTParser->init(provider))){ myAudioDTParser->release(); myAudioDTParser = 0; } } EXIT: return myAudioDTParser; } bool AudioDeviceTreeParser::init(IOService *provider){ soundEntry = 0; if(!super::init()) return(false); soundEntry = provider->childFromPath(kSoundEntryName, gIODTPlane); if(!soundEntry) return false; soundEntry->retain(); return(true); } void AudioDeviceTreeParser::free(){ soundEntry->release(); super::free(); } // Information getter for outputs UInt32 AudioDeviceTreeParser::getNumberOfOutputs(){ OSData *tempData; UInt32 AudioOutputNb = 0; tempData = OSDynamicCast(OSData, soundEntry->getProperty(kNumOutputsPropName)); FAIL_IF(!tempData, BAIL); AudioOutputNb = *(UInt32 *)(tempData->getBytesNoCopy()); FAIL_IF(0 == AudioOutputNb,EXIT); EXIT: return AudioOutputNb; BAIL: AudioOutputNb = 0; goto EXIT; } OSArray *AudioDeviceTreeParser::createOutputsArray(){ OSData *tempData; OSArray* AudioOutputs = 0; UInt32 AudioOutputNb; char * theSoundObjects, *thetempObject; int parser, startidx, stopidx, startwordidx, stopwordidx, length; AudioHardwareOutputInfo myInfo; AudioHardwareOutput *theOutput; int size; // get the output numbers and create the detects array AudioOutputNb = getNumberOfOutputs(); FAIL_IF(0 == AudioOutputNb,EXIT); AudioOutputs = OSArray::withCapacity(AudioOutputNb); FAIL_IF(!AudioOutputs, BAIL); // get all the sound objects and do the parsing tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); size = (int) tempData->getLength(); parser = -1; while(size && parser < size) { // find the end of string ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; // do the detect parsing if it is one stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject, kOutputObjEntryName, stopwordidx-1)) { length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, kDeviceMaskPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.deviceMask, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kDeviceMatchPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.deviceMatch, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kIconIDPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.iconID, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kPortConnectionPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.portConnection, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kPortTypePropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.portType, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kNameIDPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.nameID, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, "param", stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.param, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kModelPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, kOutputPortObjName, 8)) myInfo.outputKind = kOutputPortTypeClassic; else if(!bcmp(thetempObject+startwordidx, kKiheiSpeakerObjName, 8)) myInfo.outputKind = kOutputPortTypeProj5; else if(!bcmp(thetempObject+startwordidx, kWSIntSpeakerObjName, 8)) myInfo.outputKind = kOutputPortTypeProj3; else if(!bcmp(thetempObject+startwordidx, kOutputEQPortObjName, 8)) myInfo.outputKind = kOutputPortTypeEQ; else myInfo.outputKind = kOutputPortTypeUnknown; } ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); } theOutput = AudioHardwareOutput::create(myInfo); AudioOutputs->setObject(theOutput); CLEAN_RELEASE(theOutput); myInfo.deviceMask =0; myInfo.deviceMatch =0; myInfo.iconID =0; myInfo.portConnection =0; myInfo.portType =0; myInfo.nameID =0; myInfo.outputKind = 0; myInfo.param = 0; } } EXIT: return AudioOutputs; BAIL: goto EXIT; } UInt32 AudioDeviceTreeParser::getNumberOfInputs(){ UInt32 result = 0; OSData *tempData; tempData = OSDynamicCast(OSData, soundEntry->getProperty(kNumInputsPropName)); FAIL_IF(!tempData, BAIL); result = *(UInt32 *)(tempData->getBytesNoCopy()); FAIL_IF(0 == result, BAIL); EXIT: return result; BAIL: goto EXIT; } UInt32 AudioDeviceTreeParser::getNumberofInputsWithMuxes(){ UInt32 result; OSData *tempData; char * theSoundObjects, *thetempObject; int parser, startidx, stopidx, stopwordidx, size; result = 0; tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); size = (int) tempData->getLength(); parser = -1; while(size && parser < size) { ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; // do the detect parsing if it is one stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject, kInputObjEntryName, stopwordidx-1)) result++; else if( !bcmp(thetempObject, kMuxObjEntryName, stopwordidx-1)) result++; } EXIT: return result; BAIL: result = 0; goto EXIT; } UInt32 AudioDeviceTreeParser::getNumberOfDetects(){ UInt32 result = 0; OSData *tempData; tempData = OSDynamicCast(OSData, soundEntry->getProperty(kNumDetectsPropName)); FAIL_IF(!tempData, BAIL); result = *(UInt32 *)(tempData->getBytesNoCopy()); FAIL_IF(0 == result, BAIL); EXIT: return result; BAIL: goto EXIT; } UInt32 AudioDeviceTreeParser::getNumberOfFeatures(){ UInt32 result = 0; return result; } SInt16 AudioDeviceTreeParser::getInitOperationType(){ SInt16 result = 0; OSData *tempData; char * theSoundObjects, *thetempObject; int parser, startidx, stopidx, startwordidx, stopwordidx, length; short opkind = 0; int size; // get all the sound objects and do the parsing tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); FailIf (NULL == theSoundObjects, BAIL); size = (int) tempData->getLength(); parser = -1; while(size && parser < size) { // find the end of string ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; // do the detect parsing if there is one stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject, "init", stopwordidx-1)) { length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, "operation", stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(opkind, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, "param", stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); thetempObject[stopwordidx] = '\0'; thetempObject[stopwordidx] = ' '; } else if(!bcmp(thetempObject+startwordidx, "param-size", stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); thetempObject[stopwordidx] = '\0'; thetempObject[stopwordidx] = ' '; } ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); } } } result = opkind; EXIT: return result; BAIL: result = 0; goto EXIT; } // cheap and dirty way to get the phase inversion feature object. // Do it this way until we parse all the features directly bool AudioDeviceTreeParser::getPhaseInversion() { bool result = false; OSData *tempData; char * theSoundObjects, *thetempObject; int parser, startidx, stopidx, startwordidx, stopwordidx, length; int size; // get all the sound objects and do the parsing tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); size = (int) tempData->getLength(); parser = -1; while(size && parser < size) { // find the end of string ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; // do the feature parsing if it is one stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject, "feature", stopwordidx-1)) { length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, "model", stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, "PhaseInversion", 8)) { result = true; // we are done so lets get out of here goto EXIT; } } ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); } } } EXIT: return result; BAIL: goto EXIT; result = 0; } SInt16 AudioDeviceTreeParser::getPowerObjectType(){ SInt16 result = 0; OSData *tempData; char * theSoundObjects, *thetempObject; int parser, startidx, stopidx, startwordidx, stopwordidx, length; int size; // get all the sound objects and do the parsing tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); size = (int) tempData->getLength(); parser = -1; while(size && parser < size) { // find the end of string ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; // do the feature parsing if it is one stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject, "feature", stopwordidx-1)) { length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, "model", stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, "Proj7PowerControl", 8)) result= kProj7PowerObject; else if (!bcmp(thetempObject+startwordidx, "Proj10PowerControl", 8)) result= kProj10PowerObject; else if (!bcmp(thetempObject+startwordidx, "Proj8PowerControl", 8)) result= kProj8PowerObject; else if (!bcmp(thetempObject+startwordidx, "Proj6PowerControl", 8)) result= kProj6PowerObject; else if (!bcmp(thetempObject+startwordidx, "Proj14PowerControl", 8)) result= kProj14PowerObject; else if (!bcmp(thetempObject+startwordidx, "Proj16PowerControl", 8)) result= kProj16PowerObject; } ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); } } } EXIT: return result; BAIL: goto EXIT; result = 0; } UInt32 AudioDeviceTreeParser::getLayoutID(){ UInt32 result = 0; OSData *tempData; tempData = OSDynamicCast(OSData, soundEntry->getProperty(kDeviceIDPropName)); FAIL_IF(!tempData, BAIL); result = *(UInt32 *)(tempData->getBytesNoCopy()); FAIL_IF(0 == result, BAIL); EXIT: return result; BAIL: goto EXIT; } OSArray *AudioDeviceTreeParser::getDSPFeatures(){ return(0); } OSArray *AudioDeviceTreeParser::createInputsArray(){ // this get the inputs, not used because handles everything. return(0); } // // aml 4.29.02, returns true if we have HW input gain by checking the current HW model // bool AudioDeviceTreeParser::getHasHWInputGain(){ bool hasHWInputGain = true; OSData *tempData; tempData = OSDynamicCast(OSData, soundEntry->getProperty(kModelPropName)); FAIL_IF(!tempData, EXIT); if((!bcmp(tempData->getBytesNoCopy(), kDacaModelName, tempData->getLength())) || (!bcmp(tempData->getBytesNoCopy(), kTexasModelName, tempData->getLength())) || (!bcmp(tempData->getBytesNoCopy(), kTexas2ModelName, tempData->getLength()))) { hasHWInputGain = false; } else { hasHWInputGain = true; } // aml XXX testing #if 0 if (!bcmp(tempData->getBytesNoCopy(), kDacaModelName, tempData->getLength())) { IOLog("AudioDeviceTreeParser::getHasHWInputGain - kDacaModelName.\n"); } else if (!bcmp(tempData->getBytesNoCopy(), kTexasModelName, tempData->getLength())) { IOLog("AudioDeviceTreeParser::getHasHWInputGain - kTexasModelName.\n"); } else if (!bcmp(tempData->getBytesNoCopy(), kTexas2ModelName, tempData->getLength())) { IOLog("AudioDeviceTreeParser::getHasHWInputGain - kTexas2ModelName.\n"); } else if (!bcmp(tempData->getBytesNoCopy(), kAWACsModelName, tempData->getLength())) { IOLog("AudioDeviceTreeParser::getHasHWInputGain - kAWACsModelName.\n"); } else if (!bcmp(tempData->getBytesNoCopy(), kScreamerModelName, tempData->getLength())) { IOLog("AudioDeviceTreeParser::getHasHWInputGain - kScreamerModelName.\n"); } else if (!bcmp(tempData->getBytesNoCopy(), kBurgundyModelName, tempData->getLength())) { IOLog("AudioDeviceTreeParser::getHasHWInputGain - kBurgundyModelName.\n"); } IOLog("AudioDeviceTreeParser::getHasHWInputGain - has HW gain = %d.\n", hasHWInputGain); #endif EXIT: return hasHWInputGain; } // // aml 4.26.02, returns a dictionary of types (imic, line, etc.) and their zero dB gain offsets // UInt32 AudioDeviceTreeParser::getInternalMicGainOffset(){ UInt32 zeroGain; zeroGain = 0; #if OVERRIDE_REGISTRY_ZERO_GAIN // override the registry entries with these fixed values. // values come from open firmware files and OS 9 source code. // see AudioHardwareConstants.h for the full list of layouts. switch (getLayoutID()) { case layout101: zeroGain = 0x00090000; // 9.0 dB break; case layoutKihei: zeroGain = 0x001E0000; // 30 dB break; case layoutPismo: zeroGain = 0x00138000; // 19.5 dB break; case layoutMercury: zeroGain = 0x00090000; // 9.0 dB break; case layoutPerigee: zeroGain = 0x001E0000; // 30 dB break; case layoutWallStreet: zeroGain = 0x00090000; // 9.0 dB break; default: zeroGain = 0x0; // 0 dB break; } #else // OVERRIDE_REGISTRY_ZERO_GAIN OSData * tempData; UInt32 portType; char * theSoundObjects; char * thetempObject; int parser; int startidx; int stopidx; int stopwordidx; int startwordidx; int size; int length; UInt32 result; result = 0; tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); size = (int) tempData->getLength(); parser = -1; while(size && parser < size) { ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx); // // Parse for input or mux objects // if(!bcmp(thetempObject, kInputObjEntryName, stopwordidx-1) || !bcmp(thetempObject, kMuxObjEntryName, stopwordidx-1)) { length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { // // reset variables // portType = 0; NEXTENDOFWORD(thetempObject, stopwordidx); // // Parse input objects for input port or mux type (internal mic, external mic, line, etc.) // if(!bcmp(thetempObject+startwordidx, kPortTypePropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx); READWORDASNUMBER(portType, thetempObject, startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx); if (portType == kIntMicSource) { // // next word is the zero gain value // ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx); if(!bcmp(thetempObject+startwordidx, kZeroGainPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx); READWORDASNUMBER(zeroGain, thetempObject, startwordidx, stopwordidx); } } ASSIGNNEXTWORD(thetempObject, startwordidx, stopwordidx); } ASSIGNNEXTWORD(thetempObject, startwordidx, stopwordidx); } } } #endif // OVERRIDE_REGISTRY_ZERO_GAIN return zeroGain; } OSArray *AudioDeviceTreeParser::createInputsArrayWithMuxes(){ // this get the inputs and the muxes there are on OSArray *AudioInputs = 0; OSData *tempData; char * theSoundObjects, *thetempObject; int parser, startidx, stopidx, startwordidx, stopwordidx, length; UInt32 tlength, muxIndex; AudioHardwareInputInfo myInfo; UInt32 AudioInputMuxNb, AudioMuxNb; AudioHardwareMuxInfo myMuxInfo; AudioHardwareInput *theInput; AudioHardwareMux *theMux; bool muxflag = false; int size; muxIndex = 0; // get the output numbers and create the detects array AudioMuxNb = 0; AudioInputMuxNb = getNumberofInputsWithMuxes(); DEBUG2_IOLOG ("Number of inputs with muxes = %ld\n", AudioInputMuxNb); if( 0 != AudioInputMuxNb) AudioInputs = OSArray::withCapacity(AudioInputMuxNb); FAIL_IF(!AudioInputs, BAIL); // get all the sound objects and do the parsing tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); size = (int) tempData->getLength(); parser = -1; myInfo.sndHWPort = 0; myInfo.inputPortType = 0; myInfo.channels = 0; myInfo.isOnMuX = muxflag; while(size && parser < size) { // find the end of string ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; // do the detect parsing if it is one stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject, kInputObjEntryName, stopwordidx-1)) { length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, kPortChannelsPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.channels, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kPortConnectionPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.sndHWPort, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kPortTypePropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.inputPortType, thetempObject, startwordidx, stopwordidx); } ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); } if(myInfo.isOnMuX) { myInfo.theMuxRef = OSDynamicCast(AudioHardwareMux, AudioInputs->getObject(muxIndex)); } else { myInfo.theMuxRef = 0; } theInput = AudioHardwareInput::create(myInfo); AudioInputs->setObject(theInput); CLEAN_RELEASE(theInput); myInfo.sndHWPort = 0; myInfo.inputPortType = 0; myInfo.channels = 0; } else if(!bcmp(thetempObject, kMuxObjEntryName, stopwordidx-1)) { muxflag = true; myInfo.isOnMuX = muxflag; // we know we have 1 mux we should create the array length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, kModelPropName, stopwordidx-startwordidx)) { //model ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, kMuxProgOutName, 6)) myMuxInfo.MuxPortType = kAudioHardwareMuxPO; else if(!bcmp(thetempObject+startwordidx, kMux101ObjName, 6)) myMuxInfo.MuxPortType = kAudioHardwareMux101; else if(!bcmp(thetempObject+startwordidx, kMuxWSObjName, 6)) myMuxInfo.MuxPortType = kAudioHardwareMuxWS; else myMuxInfo.MuxPortType = kAudioHardwareMuxUnknown; } else if(!bcmp(thetempObject+startwordidx, kSourceMapPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); // READWORDASNUMBER(myInfo.sndHWPort, thetempObject, startwordidx, stopwordidx); tlength = sizeof(MuxSourceMap) * 2; thetempObject[stopwordidx] = '\0'; getStringAsHexData((char *) &(thetempObject[startwordidx]),(UInt8 *) &(myMuxInfo.MuxPOsources), &tlength); thetempObject[stopwordidx] = ' '; } else if(!bcmp(thetempObject+startwordidx, kSourceMapCountPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myMuxInfo.MuxPOnumSources, thetempObject, startwordidx, stopwordidx); } ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); } if(kAudioHardwareMuxUnknown != myMuxInfo.MuxPortType) { // we don't add a mux that is unknown if (0 == AudioMuxNb) { // creation of an array of one Mux we should think of more theMux = AudioHardwareMux::create(myMuxInfo); muxIndex = AudioInputs->getCount(); if(theMux) AudioInputs->setObject(theMux); } else { DEBUG_IOLOG("There shouldn't be another mux"); } } } } EXIT: return AudioInputs; BAIL: goto EXIT; } OSArray *AudioDeviceTreeParser::createDetectsArray(){ OSArray* AudioDetects; OSData *tempData; char * theSoundObjects, *thetempObject; int parser, startidx, stopidx, startwordidx, stopwordidx, length; short detectidx; AudioHardwareDetect *theDetect; AudioHardwareDetectInfo myInfo; int size; myInfo.detectKind =0; myInfo.bitMask = 0; myInfo.bitMatch = 0; myInfo.device = 0; // get the detect numbers and create the detects array AudioDetects = OSArray::withCapacity(getNumberOfDetects()); // get the complete Sound objects to parse them tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName)); FAIL_IF(!tempData, BAIL); theSoundObjects = (char *) tempData->getBytesNoCopy(); size = (int) tempData->getLength(); parser = -1; detectidx =0; while(size && parser < size) { // find the end of string ASSIGNSTARTSTRING(startidx, parser); NEXTENDOFSTRING(theSoundObjects, parser); ASSIGNSTOPSTRING(stopidx, parser); thetempObject = theSoundObjects+startidx; // do the detect parsing if it is one stopwordidx = 0; NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject, kDetectObjEntryName, stopwordidx-1)) { length = stopidx-startidx; startwordidx = ++stopwordidx; while(stopwordidx < length) { NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, kBitMaskPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.bitMask, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kBitMatchPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.bitMatch, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kDevicePropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); READWORDASNUMBER(myInfo.device, thetempObject, startwordidx, stopwordidx); } else if(!bcmp(thetempObject+startwordidx, kModelPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); NEXTENDOFWORD(thetempObject, stopwordidx, size); if(!bcmp(thetempObject+startwordidx, kAnyInDetectObjName, 6)) myInfo.detectKind = kAudioHardwareDetectAnyInSense; else if(!bcmp(thetempObject+startwordidx, kInSenseBitsDetectObjName, 6)) myInfo.detectKind = kAudioHardwareDetectInSense; else if(!bcmp(thetempObject+startwordidx, kGPIODetectObjName, 6)) myInfo.detectKind = kAudioHardwareDetectGPIO; else if(!bcmp(thetempObject+startwordidx, kGPIOGenericDetectObjName, 6)) myInfo.detectKind = kAudioHardwareGenericDetectGPIO; else myInfo.detectKind = kAudioHardwareDetectUnknown; } ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx); } theDetect = AudioHardwareDetect::create(detectidx, myInfo); AudioDetects->setObject(theDetect); CLEAN_RELEASE(theDetect); myInfo.detectKind =0; myInfo.bitMask = 0; myInfo.bitMatch = 0; myInfo.device = 0; detectidx++; } } EXIT: return AudioDetects; BAIL: goto EXIT; } UInt8 AudioDeviceTreeParser::convertAsciiToHexData(char ascii) { UInt8 subvalue; subvalue = 0; if((ascii >= '0') && (ascii <= '9')) subvalue = '0'; else if ((ascii >= 'a') && (ascii <= 'f')) subvalue = 'a'- 10; else if ((ascii >= 'A') && (ascii <= 'F')) subvalue = 'A'-10; return ascii-subvalue; } UInt32 AudioDeviceTreeParser::getStringAsNumber(char *string){ SInt32 number, multiplier; char *valueStr; valueStr = string; number = 0; if (('0' == *valueStr) && ('x' == *(valueStr+1))) { // this is an hex number valueStr+=2; while(*valueStr) number = number*16+convertAsciiToHexData(*valueStr++); } else { if ('-' == *valueStr) { multiplier = -1; valueStr++; } else multiplier = 1; while(*valueStr) number = (number *10)+ convertAsciiToHexData(*valueStr++); number *= multiplier; } return number; } bool AudioDeviceTreeParser::getStringAsHexData( char *string, UInt8 *value, UInt32 *size ) { UInt32 length; bool err = true; length = 0; while (*string && (length < *size)) { *value++ = (convertAsciiToHexData(*string++) << 4) |convertAsciiToHexData(*string++); length++; } *size = length; return err; }