--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bthci/bthci2/CommandsEvents/generator/command.py Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,397 @@
+# Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# Functions for generating CHCICommandBase derived classes.
+# Attempts to fill in provided file templates with values deduced from the
+# command name and command parameters.
+# Template substitutions are:
+# $CLASSNAME: CNameOfCommand, where NameOfCommand is given as parameter.
+# $FILENAME: namofcommand, lower case version of NameOfCommand. Used when substituting filename.
+# $HEADERGUARD: NAMEOFCOMMAND, upper case version of NameOfCommand. Used as header guard define.
+# $PARAMETERS: Type1 aParam1, Type2 aParam2, etc. List of parameters. Used in NewL and constructor definitions and implementations.
+# $MEMBERS: Type1 iParam1; Type2 iParam2; etc. Class member declarations.
+# $NEWL_DEFINITIONS: static $CLASSNAME NewL(); and if parameter count > 0, static $CLASSNAME NewL($PARAMETERS);. NewL definitions.
+# $NEWL_IMPLEMENTATIONS: Implementations of the NewLs.
+# $CONSTRUCTOR_DEFINITION: Constructor definition. A class always has a default constructor.
+# $CONSTRUCTOR_IMPLEMENTATION: Constructor implementation.
+# $DESTRUCTOR_IMPLEMENTATION: Destructor implementation.
+# $WRITE_FRAME: Code to write command data to a CHctlCommandFrame.
+# $COMMANDFRAME: Comments out CHctlCommandFrame parameter of the WriteFrame method of commands that have no data. This to avoid compiler warnings.
+# $MEMBER_ASSIGNMENT: iParam1 = aParam1; For Reset implementation.
+# $ACCESSOR_DEFINITIONS: Type1 Param1(); Parameter getter method definition.
+# $ACCESSOR_IMPLEMENTATION: Type1 $CLASSNAME::Param1() { return iParam1; }. Parameter getter method implementation.
+# $EVENT_MATCH_DEFINITIONS: Definition of the event matching methods
+# $EVENT_MATCH_IMPLEMENTATIONS: Implementations of the event matching methods
+# $EVENT_MATCH_INCLUDES: System includes required by event matching methods
+# $GENERATE_TIME_STAMP: timestamp showing when the generator produced the file
+# $PRAGMA_HW_VOICE_SETTING_ADVICE: Write pragma lines for commands setupsynchronousconnection and writevoicesetting
+#
+#
+
+import re
+import string
+from parameter import makeParameters, makeMembers
+from time import strftime
+from utils import doTimeStampCompareAndWrite
+
+# makes the aParam part of constructor
+def makeConstructorParameters(aParams):
+ ctor_str = ""
+
+ for p in aParams:
+ ctor_str += 'a' + p.getName() + ', '
+
+ return ctor_str[:-2]
+
+# makes member initialization part of constructor
+def makeMemberInitialization(aParams):
+ init_str = ", "
+
+ for p in aParams:
+ init_str += 'i' + p.getName() + '(a' + p.getName() + ')\n\t, '
+
+ return init_str[:-4]
+
+# makes class NewL definition
+def makeNewLDefinitions(aParams, aClass):
+ def_str = ''
+
+ if len(aParams) > 0:
+ def_str += 'IMPORT_C static C' + aClass + '* NewL(' + makeParameters(aParams) +');\n\t'
+
+ return def_str + 'IMPORT_C static C' + aClass +'* NewL();'
+
+def makeNewLImp(aClass, aParamString, aConsParamString):
+ imp_str = ''
+ imp_str += 'EXPORT_C C' + aClass + '* C' + aClass + '::NewL(' + aParamString + ')\n\t{\n\t'
+ imp_str += 'C' + aClass + '* self = new (ELeave) C' + aClass + '(' + aConsParamString + ');\n\t'
+ imp_str += 'CleanupStack::PushL(self);\n\t'
+ imp_str += 'self->CHCICommandBase::BaseConstructL();\n\t'
+ imp_str += 'CleanupStack::Pop(self);\n\t'
+ imp_str += 'return self;\n\t}'
+ return imp_str
+
+# makes class NewL implementation
+def makeNewLImplementations(aParams, aClass):
+ imp_str = ''
+
+ if len(aParams) > 0:
+ imp_str += makeNewLImp(aClass, makeParameters(aParams), makeConstructorParameters(aParams))
+ imp_str += '\n\n'
+
+ imp_str += makeNewLImp(aClass, '', '')
+ return imp_str
+
+# makes class constructor definition
+def makeConstructorDefinitions(aParams, aClass):
+ def_str = ''
+
+ if len(aParams) > 0:
+ def_str += 'C' + aClass + '(' + makeParameters(aParams) + ');\n\t'
+
+ return def_str + 'C' + aClass + '();'
+
+# makes class constructor implementation
+def makeConstructorImplementations(aParams, aClass, aMatchParams):
+ imp_str = ''
+
+ CreditsConsumed = aMatchParams[0]
+ ExpCmdStatus = aMatchParams[1]
+ ExpCmdComplete = aMatchParams[2]
+
+ if len(aParams) > 0:
+ imp_str += 'C' + aClass + 'Command::C' + aClass + 'Command(' + makeParameters(aParams) + ')\n\t: CHCICommandBase(K' + aClass + 'Opcode)\n\t' + makeMemberInitialization(aParams) + '\n\t{\n\t'
+ if int(CreditsConsumed) != 1:
+ imp_str += 'SetCreditsConsumed(' + str(CreditsConsumed) + ');\n\t'
+ if ExpCmdStatus == 'False':
+ imp_str += 'SetExpectsCommandStatusEvent(EFalse);\n\t'
+ if ExpCmdComplete == 'False':
+ imp_str += 'SetExpectsCommandCompleteEvent(EFalse);\n\t'
+ imp_str += '}\n\n'
+
+ imp_str += 'C' + aClass + 'Command::C' + aClass + 'Command()\n\t: CHCICommandBase(K' + aClass + 'Opcode)\n\t{\n\t'
+ if int(CreditsConsumed) != 1:
+ imp_str += 'SetCreditsConsumed(' + str(CreditsConsumed) + ');\n\t'
+ if ExpCmdStatus == 'False':
+ imp_str += 'SetExpectsCommandStatusEvent(EFalse);\n\t'
+ if ExpCmdComplete == 'False':
+ imp_str += 'SetExpectsCommandCompleteEvent(EFalse);\n\t'
+
+ imp_str += '}'
+
+ return imp_str
+
+def makeDestructorImplementation(aParams):
+ imp_str = ''
+
+ # We only need to close arrays
+ for p in aParams:
+ if p.iArray != '':
+ imp_str += 'i' + p.getName() + '.Close();\n\t'
+
+ return imp_str[0:-2]
+
+# makes code that write command data to CHctlCommandFrame
+def makeWriteFrame(aParams):
+
+ ## (the parameter length is now output by the base class)
+ frame_str = ''
+
+ ## Write the functions to set the data for the parameters
+ ## If there are multiple array parameters then they are ordered like an
+ ## array of structures, see BT Spec 2.0 Vol 2 Part E 5.2. The logic below allows
+ ## for multiple such arrays of structures based on sets of consecutive parameters
+ ## sharing the same array bound - however this is not really needed since no current
+ ## event has more than one array.
+ firstOne = True
+ currentArray = None
+ for p in aParams:
+ if not p.iNotInFrame:
+ if not firstOne:
+ frame_str += '\n\t'
+ else:
+ firstOne = False
+ if p.iArray:
+ if currentArray != p.iArray:
+ if currentArray != None:
+ # end the previous array loop (actually, this is never needed)
+ frame_str += '\t}\n\t'
+ currentArray = None
+ # start the new array loop
+ currentArray = p.iArray # remember we're doing this array
+ frame_str += 'for(int i=0;i<i' + p.iArray + ';++i)\n\t\t{\n\t'
+
+ # continue generating the array
+ frame_str += '\taCommandFrame.' + p.iType.iSetter + '(' + p.setterParams('i') + ');'
+ else:
+ if currentArray != None:
+ # finish off the array we were doing (won't actually happen, arrays always come last really)
+ frame_str += '\t}\n\t'
+ frame_str += 'aCommandFrame.' + p.iType.iSetter + '(' + p.setterParams() + ');'
+
+ if currentArray != None:
+ frame_str += '\n\t\t}'
+
+ return frame_str
+
+
+# if we do not have command data comment out parameter to avoid compiler warnings
+def makeCommandFrame(aParams):
+ if len(aParams) > 0:
+ return 'CHctlCommandFrame& aCommandFrame'
+ else:
+ return 'CHctlCommandFrame& /*aCommandFrame*/'
+
+# generates code block of form iParam = aParam;
+def makeMemberAssignment(aParams):
+ ass_str = ''
+
+ for p in aParams:
+ ass_str += p.memberAssignment() + '\n\t'
+
+ return ass_str[:-2]
+
+# make getter definition of form Param()
+def makeAccessorDefinitions(aParams):
+ def_str = ''
+
+ for p in aParams:
+ def_str += p.accessorDef('Command') + '\n\t'
+
+ return def_str[:-2]
+
+# make getter implementation
+def makeAccessorImplementations(aParams, aClass):
+ imp_str = ''
+
+ for p in aParams:
+ imp_str += p.commandAccessorImpl(aClass)
+
+ return imp_str
+
+
+def zsafe_codeEventMatch(aMatchParams, aFirstTime):
+ code_str = ''
+
+ code_str += '\n'
+ for p in aMatchParams[:]:
+ code_str += p + '\n'
+
+ return code_str
+
+#make event match
+def codeEventMatch(aMatchParams, aFirstTime):
+ code_str = ''
+ eventName = aMatchParams[0]
+ concludesCmd = aMatchParams[1]
+ continueMatching = aMatchParams[2]
+
+ if not aFirstTime:
+ code_str += 'else '
+
+ code_str += 'if (aEvent.EventCode() == ' 'E' + eventName +')\n\t\t'
+ code_str += '{\n\t\t'
+
+ if len(aMatchParams) > 3:
+ matchOperands = aMatchParams[3:]
+
+ if eventName == 'CommandCompleteEvent':
+ code_str += 'THCI' + eventName + '& event = THCI' + eventName + '::Cast(aEvent);\n\t\t'
+ else:
+ code_str += 'T' + eventName + '& event = T' + eventName + '::Cast(aEvent);\n\t\t'
+
+ if len(matchOperands) > 1:
+ code_str += 'if ('
+ else:
+ code_str += 'if '
+
+ i = 0
+ while i < len(matchOperands):
+ operands = string.split(matchOperands[i],'_')
+
+ if len(operands) == 1:
+ code_str += '(event.' + operands[0] + '() == ' + operands[0] + '())'
+ else:
+ code_str += '(event.' + operands[0] + '() == ' + operands[1]
+ if len(operands) > 2:
+ code_str += '()' # kludge: trailing _ means we need a function call syntax
+ code_str += ')'
+ i += 1
+ if i < len(matchOperands):
+ code_str += ' && '
+
+ if len(matchOperands) > 1:
+ code_str += ')\n\t\t\t'
+ else:
+ code_str += '\n\t\t\t'
+
+ code_str += '{\n\t\t\t'
+ code_str += 'aMatchesCmd = ETrue;\n\t\t\t'
+ code_str += 'aConcludesCmd = E' + concludesCmd + ';\n\t\t\t'
+ code_str += 'aContinueMatching = E' + continueMatching + ';\n\t\t\t'
+ code_str += '}\n\t\t'
+
+ else:
+ code_str += 'aMatchesCmd = ETrue;\n\t\t'
+ code_str += 'aConcludesCmd = E' + concludesCmd + ';\n\t\t'
+ code_str += 'aContinueMatching = E' + continueMatching + ';\n\t\t'
+
+ code_str += '}\n\t'
+
+ return code_str
+
+#make event matching method definitions
+def makeEventMatchDefinitions(aParams):
+ def_str = ''
+ Creditsconsumed = aParams[0]
+ ExpCmdStatus = aParams[1]
+ ExpCmdComplete = aParams[2]
+
+ if len(aParams) > 3 and 'Match' in aParams: # Always define a match function.
+ def_str += 'virtual void Match(const THCIEventBase& aEvent, TBool& aMatchesCmd, TBool& aConcludesCmd, TBool& aContinueMatching) const;\n\t'
+
+ return def_str
+
+#make event matching method definitions
+def makeEventMatchImplementations(aParams, aClass):
+ imp_str = ''
+ Creditsconsumed = aParams[0]
+ ExpCmdStatus = aParams[1]
+ ExpCmdComplete = aParams[2]
+
+ if len(aParams) > 3 and 'Match' in aParams:
+ imp_str += '/*virtual*/ void ' + 'C' + aClass + 'Command::Match(const THCIEventBase& aEvent, TBool& aMatchesCmd, TBool& aConcludesCmd, TBool& aContinueMatching) const\n\t'
+ imp_str += '{\n\t'
+
+ # Produce matching code specific to command
+ m = aParams.index('Match') + 1
+ firstTime = True
+ while ('Match' in aParams[m:]):
+ nm = m + aParams[m:].index('Match')
+ imp_str += codeEventMatch(aParams[m:nm], firstTime)
+ m = nm + 1
+ firstTime = False
+ else:
+ imp_str += codeEventMatch(aParams[m:], firstTime)
+
+ # Insert general matching code
+ imp_str += '// Command Status Event and default Command Complete Event matching\n\t'
+ imp_str += '// is implemented in the base class. If we haven\'t matched already\n\t'
+ imp_str += '// then we should try the default matching.\n\t'
+ imp_str += 'if (!aMatchesCmd)\n\t\t'
+ imp_str += '{\n\t\t'
+ imp_str += 'CHCICommandBase::Match(aEvent, aMatchesCmd, aConcludesCmd, aContinueMatching);\n\t\t'
+ imp_str += '}\n\t'
+ imp_str += '}\n\t'
+
+ return imp_str
+
+#make event matching method definitions
+def makeEventMatchIncludes(aParams):
+ inc_str = ''
+
+ remParams = aParams[:]
+ while ('Match' in remParams):
+ e = remParams.index('Match') + 1
+ eventName = remParams[e]
+ remParams = remParams[e:]
+
+ if eventName != 'CommandCompleteEvent':
+ inc_str += '#include <bluetooth/hci/' + string.lower(eventName) + '.h>\n'
+
+ return inc_str
+
+# if command is setupsynchronousconnection or writevoicesetting write pragma lines
+def makePragmaHwVoiceSettingAdvice(aCmd):
+ if aCmd == 'WriteVoiceSetting' or aCmd == 'SetupSynchronousConnection':
+ strPragma = '#pragma message("Value of iVoiceSetting member is closely related to hardware used. ")\n'
+ strPragma += '#pragma message("Bits: Input Coding, Input Data, Input Sample Size and Linear_PCM_Bit_pos, should be set...")\n'
+ strPragma += '#pragma message("...according to hardware capabilities, and OR-ed to create appropriate iVoiceSetting value.")'
+ return strPragma
+ return ''
+
+def writeCommand(aCmd, aMatchData, aParams, aHeaderTemplate, aSourceTemplate, aHeaderPath, aSourcePath):
+ # separate by ,
+ matchParams = re.split(r'[^a-zA-Z_0-9\*]+', aMatchData);
+
+ # Make template values
+ c = {'COMMAND': aCmd, # plain command name
+ 'CLASSNAME': 'C' + aCmd + 'Command', #CaCmd
+ 'FILENAME': aCmd.lower() + 'command', # acmd
+ 'HEADERGUARD': aCmd.upper() + 'COMMAND', # ACMD
+ 'PARAMETERS': makeParameters(aParams), # aParam1, aParam2
+ 'MEMBERS': makeMembers(aParams), # iParam1; iParam2
+ 'NEWL_DEFINITIONS': makeNewLDefinitions(aParams, aCmd + 'Command'), # NewL($PARAMETERS)
+ 'NEWL_IMPLEMENTATIONS': makeNewLImplementations(aParams, aCmd + 'Command'),
+ 'CONSTRUCTOR_DEFINITIONS': makeConstructorDefinitions(aParams, aCmd + 'Command'),
+ 'CONSTRUCTOR_IMPLEMENTATIONS': makeConstructorImplementations(aParams, aCmd, matchParams), # Don't add 'Command', aCmd is used to build K...Opcode
+ 'DESTRUCTOR_IMPLEMENTATION': makeDestructorImplementation(aParams),
+ 'WRITE_FRAME': makeWriteFrame(aParams),
+ 'COMMANDFRAME': makeCommandFrame(aParams),
+ 'MEMBER_ASSIGNMENT': makeMemberAssignment(aParams),
+ 'ACCESSOR_DEFINITIONS': makeAccessorDefinitions(aParams),
+ 'ACCESSOR_IMPLEMENTATIONS': makeAccessorImplementations(aParams, 'C' + aCmd + 'Command'),
+ 'EVENT_MATCH_DEFINITIONS': makeEventMatchDefinitions(matchParams),
+ 'EVENT_MATCH_IMPLEMENTATIONS': makeEventMatchImplementations(matchParams, aCmd),
+ 'EVENT_MATCH_INCLUDES': makeEventMatchIncludes(matchParams),
+ 'PRAGMA_HW_VOICE_SETTING_ADVICE': makePragmaHwVoiceSettingAdvice(aCmd),
+ 'GENERATE_TIME_STAMP': strftime("%a, %d %b %Y %H:%M:%S") + ' (time stamp)'} # (time stamp) is needed for preventing unneccesary submissions.
+
+ # Fill in template
+ #file(aHeaderPath + '\\' + c['FILENAME'] + '.h', 'w+').write(aHeaderTemplate.substitute(c))
+ #file(aSourcePath + '\\' + c['FILENAME'] + '.cpp', 'w+').write(aSourceTemplate.substitute(c))
+
+ doTimeStampCompareAndWrite(aHeaderPath + '\\' + c['FILENAME'] + '.h', aHeaderTemplate.substitute(c))
+ doTimeStampCompareAndWrite(aSourcePath + '\\' + c['FILENAME'] + '.cpp', aSourceTemplate.substitute(c))
+
+