# Modifying Python Path, which is dumb, but the only way to import up one directory...
sys.path.append( os.path.expanduser('..') )
+from kll_lib.backends import *
from kll_lib.containers import *
+from kll_lib.hid_dict import *
-### Decorators ###
-
- ## Print Decorator Variables
-ERROR = '\033[5;1;31mERROR\033[0m:'
-WARNING = '\033[5;1;33mWARNING\033[0m:'
-
+### Classes ###
+class Backend( BackendBase ):
+ # Default templates and output files
+ templatePaths = ["templates/kiibohdKeymap.h", "templates/kiibohdDefs.h"]
+ outputPaths = ["generatedKeymap.h", "kll_defs.h"]
-### Classes ###
+ requiredCapabilities = {
+ 'CONS' : 'consCtrlOut',
+ 'NONE' : 'noneOut',
+ 'SYS' : 'sysCtrlOut',
+ 'USB' : 'usbKeyOut',
+ }
-class Backend:
- # Initializes backend
- # Looks for template file and builds list of fill tags
- def __init__( self, templatePath, definesTemplatePath ):
- # Does template exist?
- if not os.path.isfile( templatePath ):
- print ( "{0} '{1}' does not exist...".format( ERROR, templatePath ) )
- sys.exit( 1 )
-
- self.definesTemplatePath = definesTemplatePath
- self.templatePath = templatePath
- self.fill_dict = dict()
-
- # Generate list of fill tags
- self.tagList = []
- with open( templatePath, 'r' ) as openFile:
- for line in openFile:
- match = re.findall( '<\|([^|>]+)\|>', line )
- for item in match:
- self.tagList.append( item )
- with open( definesTemplatePath, 'r' ) as openFile:
- for line in openFile:
- match = re.findall( '<\|([^|>]+)\|>', line )
- for item in match:
- self.tagList.append( item )
-
-
- # USB Code Capability Name
- def usbCodeCapability( self ):
- return "usbKeyOut";
+ # Capability Lookup
+ def capabilityLookup( self, type ):
+ return self.requiredCapabilities[ type ];
# TODO
# Iterate through defines and lookup the variables
for define in variables.defines.keys():
if define in variables.overallVariables.keys():
- self.fill_dict['Defines'] += "\n#define {0} {1}".format( variables.defines[ define ], variables.overallVariables[ define ] )
+ self.fill_dict['Defines'] += "\n#define {0} {1}".format( variables.defines[ define ], variables.overallVariables[ define ].replace( '\n', ' \\\n' ) )
else:
print( "{0} '{1}' not defined...".format( WARNING, define ) )
# Needed for USB behaviour, otherwise, repeated keys will not work
if sequence > 0:
# <single element>, <usbCodeSend capability>, <USB Code 0x00>
- self.fill_dict['ResultMacros'] += "1, {0}, 0x00, ".format( capabilities.getIndex( self.usbCodeCapability() ) )
+ self.fill_dict['ResultMacros'] += "1, {0}, 0x00, ".format( capabilities.getIndex( self.capabilityLookup('USB') ) )
# For each combo in the sequence, add the length of the combo
self.fill_dict['ResultMacros'] += "{0}, ".format( len( macros.resultsIndexSorted[ result ][ sequence ] ) )
# Add each of the arguments of the capability
for arg in range( 0, len( resultItem[1] ) ):
+ # Special cases
+ if isinstance( resultItem[1][ arg ], str ):
+ # If this is a CONSUMER_ element, needs to be split into 2 elements
+ if re.match( '^CONSUMER_', resultItem[1][ arg ] ):
+ tag = resultItem[1][ arg ].split( '_', 1 )[1]
+ if '_' in tag:
+ tag = tag.replace( '_', '' )
+ lookupNum = kll_hid_lookup_dictionary['ConsCode'][ tag ][1]
+ byteForm = lookupNum.to_bytes( 2, byteorder='little' ) # XXX Yes, little endian from how the uC structs work
+ self.fill_dict['ResultMacros'] += "{0}, {1}, ".format( *byteForm )
+ continue
+
+ # None, fall-through disable
+ elif resultItem[0] is self.capabilityLookup('NONE'):
+ continue
+
self.fill_dict['ResultMacros'] += "{0}, ".format( resultItem[1][ arg ] )
# If sequence is longer than 1, append a sequence spacer at the end of the sequence
# Required by USB to end at sequence without holding the key down
if len( macros.resultsIndexSorted[ result ] ) > 1:
# <single element>, <usbCodeSend capability>, <USB Code 0x00>
- self.fill_dict['ResultMacros'] += "1, {0}, 0x00, ".format( capabilities.getIndex( self.usbCodeCapability() ) )
+ self.fill_dict['ResultMacros'] += "1, {0}, 0x00, ".format( capabilities.getIndex( self.capabilityLookup('USB') ) )
# Add list ending 0 and end of list
self.fill_dict['ResultMacros'] += "0 };\n"
# Add the trigger macro scan code guide
# See kiibohd controller Macros/PartialMap/kll.h for exact formatting details
- for sequence in range( 0, len( macros.triggersIndexSorted[ trigger ][ 0 ] ) ):
+ for sequence in range( 0, len( macros.triggersIndexSorted[ trigger ][0] ) ):
# For each combo in the sequence, add the length of the combo
self.fill_dict['TriggerMacros'] += "{0}, ".format( len( macros.triggersIndexSorted[ trigger ][0][ sequence ] ) )
# For each combo, add the key type, key state and scan code
- for combo in range( 0, len( macros.triggersIndexSorted[ trigger ][ 0 ][ sequence ] ) ):
- triggerItem = macros.triggersIndexSorted[ trigger ][ 0 ][ sequence ][ combo ]
+ for combo in range( 0, len( macros.triggersIndexSorted[ trigger ][0][ sequence ] ) ):
+ triggerItemId = macros.triggersIndexSorted[ trigger ][0][ sequence ][ combo ]
+
+ # Lookup triggerItem in ScanCodeStore
+ triggerItemObj = macros.scanCodeStore[ triggerItemId ]
+ triggerItem = triggerItemObj.offset( macros.interconnectOffset )
# TODO Add support for Analog keys
# TODO Add support for LED states
self.fill_dict['MaxScanCode'] = "#define MaxScanCode 0x{0:X}".format( macros.overallMaxScanCode )
+ ## Interconnect ScanCode Offset List ##
+ self.fill_dict['ScanCodeInterconnectOffsetList'] = "const uint8_t InterconnectOffsetList[] = {\n"
+ for offset in range( 0, len( macros.interconnectOffset ) ):
+ self.fill_dict['ScanCodeInterconnectOffsetList'] += "\t0x{0:02X},\n".format( macros.interconnectOffset[ offset ] )
+ self.fill_dict['ScanCodeInterconnectOffsetList'] += "};"
+
+
+ ## Max Interconnect Nodes ##
+ self.fill_dict['InterconnectNodeMax'] = "#define InterconnectNodeMax 0x{0:X}\n".format( len( macros.interconnectOffset ) )
+
+
## Default Layer and Default Layer Scan Map ##
self.fill_dict['DefaultLayerTriggerList'] = ""
self.fill_dict['DefaultLayerScanMap'] = "const nat_ptr_t *default_scanMap[] = {\n"
# Iterate over triggerList and generate a C trigger array for the default map and default map array
- for triggerList in range( macros.firstScanCode[ 0 ], len( macros.triggerList[ 0 ] ) ):
+ for triggerList in range( macros.firstScanCode[0], len( macros.triggerList[0] ) ):
# Generate ScanCode index and triggerList length
- self.fill_dict['DefaultLayerTriggerList'] += "Define_TL( default, 0x{0:02X} ) = {{ {1}".format( triggerList, len( macros.triggerList[ 0 ][ triggerList ] ) )
+ self.fill_dict['DefaultLayerTriggerList'] += "Define_TL( default, 0x{0:02X} ) = {{ {1}".format( triggerList, len( macros.triggerList[0][ triggerList ] ) )
# Add scanCode trigger list to Default Layer Scan Map
self.fill_dict['DefaultLayerScanMap'] += "default_tl_0x{0:02X}, ".format( triggerList )
# Add each item of the trigger list
- for trigger in macros.triggerList[ 0 ][ triggerList ]:
- self.fill_dict['DefaultLayerTriggerList'] += ", {0}".format( trigger )
+ for triggerItem in macros.triggerList[0][ triggerList ]:
+ self.fill_dict['DefaultLayerTriggerList'] += ", {0}".format( triggerItem )
self.fill_dict['DefaultLayerTriggerList'] += " };\n"
self.fill_dict['DefaultLayerTriggerList'] = self.fill_dict['DefaultLayerTriggerList'][:-1] # Remove last newline
## Layer State ##
self.fill_dict['LayerState'] = "uint8_t LayerState[ LayerNum ];"
-
- # Generates the output keymap with fill tags filled
- def generate( self, outputPath, definesOutputPath ):
- # Process each line of the template, outputting to the target path
- with open( outputPath, 'w' ) as outputFile:
- with open( self.templatePath, 'r' ) as templateFile:
- for line in templateFile:
- # TODO Support multiple replacements per line
- # TODO Support replacement with other text inline
- match = re.findall( '<\|([^|>]+)\|>', line )
-
- # If match, replace with processed variable
- if match:
- outputFile.write( self.fill_dict[ match[ 0 ] ] )
- outputFile.write("\n")
-
- # Otherwise, just append template to output file
- else:
- outputFile.write( line )
-
- # Process each line of the defines template, outputting to the target path
- with open( definesOutputPath, 'w' ) as outputFile:
- with open( self.definesTemplatePath, 'r' ) as templateFile:
- for line in templateFile:
- # TODO Support multiple replacements per line
- # TODO Support replacement with other text inline
- match = re.findall( '<\|([^|>]+)\|>', line )
-
- # If match, replace with processed variable
- if match:
- outputFile.write( self.fill_dict[ match[ 0 ] ] )
- outputFile.write("\n")
-
- # Otherwise, just append template to output file
- else:
- outputFile.write( line )
-