AudioDeviceTreeParser.cpp [plain text]
#include "AudioHardwareCommon.h"
#include "AudioHardwareConstants.h"
#include "AudioDeviceTreeParser.h"
#include "AudioHardwareOutput.h"
#include "AudioHardwareDetect.h"
#include "AudioHardwarePower.h"
#define super OSObject
OSDefineMetaClassAndStructors(AudioDeviceTreeParser, OSObject)
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();
}
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;
AudioOutputNb = getNumberOfOutputs();
FAIL_IF(0 == AudioOutputNb,EXIT);
AudioOutputs = OSArray::withCapacity(AudioOutputNb);
FAIL_IF(!AudioOutputs, BAIL);
tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName));
FAIL_IF(!tempData, BAIL);
theSoundObjects = (char *) tempData->getBytesNoCopy();
size = (int) tempData->getCapacity();
parser = -1;
while(parser < size) {
ASSIGNSTARTSTRING(startidx, parser);
NEXTENDOFSTRING(theSoundObjects, parser);
ASSIGNSTOPSTRING(stopidx, parser);
thetempObject = theSoundObjects+startidx;
stopwordidx = 0;
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject, kOutputObjEntryName, stopwordidx-1)) {
length = stopidx-startidx;
startwordidx = ++stopwordidx;
while(stopwordidx < length) {
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, kDeviceMaskPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.deviceMask, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kDeviceMatchPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.deviceMatch, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kIconIDPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.iconID, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kPortConnectionPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.portConnection, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kPortTypePropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.portType, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kNameIDPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.nameID, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, "param", stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.param, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kModelPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
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
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->getCapacity();
parser = -1;
while(parser < size) {
ASSIGNSTARTSTRING(startidx, parser);
NEXTENDOFSTRING(theSoundObjects, parser);
ASSIGNSTOPSTRING(stopidx, parser);
thetempObject = theSoundObjects+startidx;
stopwordidx = 0;
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject, "input", 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;
tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName));
FAIL_IF(!tempData, BAIL);
theSoundObjects = (char *) tempData->getBytesNoCopy();
size = (int) tempData->getCapacity();
parser = -1;
while(parser < size) {
ASSIGNSTARTSTRING(startidx, parser);
NEXTENDOFSTRING(theSoundObjects, parser);
ASSIGNSTOPSTRING(stopidx, parser);
thetempObject = theSoundObjects+startidx;
stopwordidx = 0;
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject, "init", stopwordidx-1)) {
length = stopidx-startidx;
startwordidx = ++stopwordidx;
while(stopwordidx < length) {
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, "operation", stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(opkind, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, "param", stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
thetempObject[stopwordidx] = '\0';
thetempObject[stopwordidx] = ' ';
} else if(!bcmp(thetempObject+startwordidx, "param-size", stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
thetempObject[stopwordidx] = '\0';
thetempObject[stopwordidx] = ' ';
}
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
}
}
}
result = opkind;
EXIT:
return result;
BAIL:
result = 0;
goto EXIT;
}
SInt16 AudioDeviceTreeParser::getPowerObjectType(){
SInt16 result = 0;
OSData *tempData;
char * theSoundObjects, *thetempObject;
int parser, startidx, stopidx, startwordidx, stopwordidx, length;
int size;
tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName));
FAIL_IF(!tempData, BAIL);
theSoundObjects = (char *) tempData->getBytesNoCopy();
size = (int) tempData->getCapacity();
parser = -1;
while(parser < size) {
ASSIGNSTARTSTRING(startidx, parser);
NEXTENDOFSTRING(theSoundObjects, parser);
ASSIGNSTOPSTRING(stopidx, parser);
thetempObject = theSoundObjects+startidx;
stopwordidx = 0;
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject, "feature", stopwordidx-1)) {
length = stopidx-startidx;
startwordidx = ++stopwordidx;
while(stopwordidx < length) {
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, "model", stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, "Proj7PowerControl", 8))
result= kProj7PowerObject;
else if (!bcmp(thetempObject+startwordidx, "Proj10PowerControl", 8))
result= kProj10PowerObject;
else if (!bcmp(thetempObject+startwordidx, "Proj6PowerControl", 8))
result= kProj6PowerObject;
}
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(){
return(0);
}
OSArray *AudioDeviceTreeParser::createInputsArrayWithMuxes(){
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;
AudioMuxNb = 0;
AudioInputMuxNb = getNumberofInputsWithMuxes();
if( 0 != AudioInputMuxNb)
AudioInputs = OSArray::withCapacity(AudioInputMuxNb);
FAIL_IF(!AudioInputs, BAIL);
tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName));
FAIL_IF(!tempData, BAIL);
theSoundObjects = (char *) tempData->getBytesNoCopy();
size = (int) tempData->getCapacity();
parser = -1;
myInfo.sndHWPort = 0; myInfo.inputPortType = 0;
myInfo.channels = 0; myInfo.isOnMuX = muxflag;
while(parser < size) {
ASSIGNSTARTSTRING(startidx, parser);
NEXTENDOFSTRING(theSoundObjects, parser);
ASSIGNSTOPSTRING(stopidx, parser);
thetempObject = theSoundObjects+startidx;
stopwordidx = 0;
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject, kInputObjEntryName, stopwordidx-1)) {
length = stopidx-startidx;
startwordidx = ++stopwordidx;
while(stopwordidx < length) {
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, kPortChannelsPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.channels, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kPortConnectionPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.sndHWPort, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kPortTypePropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
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;
length = stopidx-startidx;
startwordidx = ++stopwordidx;
while(stopwordidx < length) {
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, kModelPropName, stopwordidx-startwordidx)) { ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
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);
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);
READWORDASNUMBER(myMuxInfo.MuxPOnumSources, thetempObject, startwordidx, stopwordidx);
}
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
}
if(kAudioHardwareMuxUnknown != myMuxInfo.MuxPortType) {
if (0 == AudioMuxNb) { 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;
AudioDetects = OSArray::withCapacity(getNumberOfDetects());
tempData = OSDynamicCast(OSData, soundEntry->getProperty(kSoundObjectsPropName));
FAIL_IF(!tempData, BAIL);
theSoundObjects = (char *) tempData->getBytesNoCopy();
size = (int) tempData->getCapacity();
parser = -1; detectidx =0;
while(parser < size) {
ASSIGNSTARTSTRING(startidx, parser);
NEXTENDOFSTRING(theSoundObjects, parser);
ASSIGNSTOPSTRING(stopidx, parser);
thetempObject = theSoundObjects+startidx;
stopwordidx = 0;
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject, kDetectObjEntryName, stopwordidx-1)) {
length = stopidx-startidx;
startwordidx = ++stopwordidx;
while(stopwordidx < length) {
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, kBitMaskPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.bitMask, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kBitMatchPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.bitMatch, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kDevicePropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
READWORDASNUMBER(myInfo.device, thetempObject, startwordidx, stopwordidx);
} else if(!bcmp(thetempObject+startwordidx, kModelPropName, stopwordidx-startwordidx)) {
ASSIGNNEXTWORD(thetempObject,startwordidx, stopwordidx);
NEXTENDOFWORD(thetempObject, stopwordidx);
if(!bcmp(thetempObject+startwordidx, kAnyInDetectObjName, 6))
myInfo.detectKind = kAudioHardwareDetectAnyInSense;
else if(!bcmp(thetempObject+startwordidx, kInSenseBitsDetectObjName, 6))
myInfo.detectKind = kAudioHardwareDetectInSense;
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))) { 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;
}