def _extract_config_h(info_data): """Pull some keyboard information from existing config.h files """ config_c = config_h(info_data['keyboard_folder']) # Pull in data from the json map dotty_info = dotty(info_data) info_config_map = json_load(Path('data/mappings/info_config.json')) for config_key, info_dict in info_config_map.items(): info_key = info_dict['info_key'] key_type = info_dict.get('value_type', 'str') try: if config_key in config_c and info_dict.get('to_json', True): if dotty_info.get(info_key) and info_dict.get('warn_duplicate', True): _log_warning(info_data, '%s in config.h is overwriting %s in info.json' % (config_key, info_key)) if key_type.startswith('array'): if '.' in key_type: key_type, array_type = key_type.split('.', 1) else: array_type = None config_value = config_c[config_key].replace('{', '').replace('}', '').strip() if array_type == 'int': dotty_info[info_key] = list(map(int, config_value.split(','))) else: dotty_info[info_key] = config_value.split(',') elif key_type == 'bool': dotty_info[info_key] = config_c[config_key] in true_values elif key_type == 'hex': dotty_info[info_key] = '0x' + config_c[config_key][2:].upper() elif key_type == 'list': dotty_info[info_key] = config_c[config_key].split() elif key_type == 'int': dotty_info[info_key] = int(config_c[config_key]) else: dotty_info[info_key] = config_c[config_key] except Exception as e: _log_warning(info_data, f'{config_key}->{info_key}: {e}') info_data.update(dotty_info) # Pull data that easily can't be mapped in json _extract_matrix_info(info_data, config_c) _extract_audio(info_data, config_c) _extract_split_main(info_data, config_c) _extract_split_transport(info_data, config_c) _extract_split_right_pins(info_data, config_c) return info_data
def _extract_config_h(info_data): """Pull some keyboard information from existing rules.mk files """ config_c = config_h(info_data['keyboard_folder']) row_pins = config_c.get('MATRIX_ROW_PINS', '').replace('{', '').replace('}', '').strip() col_pins = config_c.get('MATRIX_COL_PINS', '').replace('{', '').replace('}', '').strip() direct_pins = config_c.get('DIRECT_PINS', '').replace(' ', '')[1:-1] info_data['diode_direction'] = config_c.get('DIODE_DIRECTION') info_data['matrix_size'] = { 'rows': compute(config_c.get('MATRIX_ROWS', '0')), 'cols': compute(config_c.get('MATRIX_COLS', '0')), } info_data['matrix_pins'] = {} if row_pins: info_data['matrix_pins']['rows'] = row_pins.split(',') if col_pins: info_data['matrix_pins']['cols'] = col_pins.split(',') if direct_pins: direct_pin_array = [] for row in direct_pins.split('},{'): if row.startswith('{'): row = row[1:] if row.endswith('}'): row = row[:-1] direct_pin_array.append([]) for pin in row.split(','): if pin == 'NO_PIN': pin = None direct_pin_array[-1].append(pin) info_data['matrix_pins']['direct'] = direct_pin_array info_data['usb'] = { 'vid': config_c.get('VENDOR_ID'), 'pid': config_c.get('PRODUCT_ID'), 'device_ver': config_c.get('DEVICE_VER'), 'manufacturer': config_c.get('MANUFACTURER'), 'product': config_c.get('PRODUCT'), 'description': config_c.get('DESCRIPTION'), } return info_data
def _extract_config_h(info_data): """Pull some keyboard information from existing config.h files """ config_c = config_h(info_data['keyboard_folder']) _extract_debounce(info_data, config_c) _extract_diode_direction(info_data, config_c) _extract_indicators(info_data, config_c) _extract_matrix_info(info_data, config_c) _extract_usb_info(info_data, config_c) _extract_led_matrix(info_data, config_c) _extract_rgblight(info_data, config_c) return info_data
def info_json(keyboard): """Generate the info.json data for a specific keyboard. """ cur_dir = Path('keyboards') root_rules_mk = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') if 'DEFAULT_FOLDER' in root_rules_mk: keyboard = root_rules_mk['DEFAULT_FOLDER'] info_data = { 'keyboard_name': str(keyboard), 'keyboard_folder': str(keyboard), 'keymaps': {}, 'layouts': {}, 'parse_errors': [], 'parse_warnings': [], 'maintainer': 'qmk', } # Populate the list of JSON keymaps for keymap in list_keymaps(keyboard, c=False, fullpath=True): info_data['keymaps'][keymap.name] = { 'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json' } # Populate layout data layouts, aliases = _search_keyboard_h(keyboard) if aliases: info_data['layout_aliases'] = aliases for layout_name, layout_json in layouts.items(): if not layout_name.startswith('LAYOUT_kc'): layout_json['c_macro'] = True info_data['layouts'][layout_name] = layout_json # Merge in the data from info.json, config.h, and rules.mk info_data = merge_info_jsons(keyboard, info_data) info_data = _process_defaults(info_data) info_data = _extract_rules_mk(info_data, rules_mk(str(keyboard))) info_data = _extract_config_h(info_data, config_h(str(keyboard))) # Ensure that we have matrix row and column counts info_data = _matrix_size(info_data) # Merge in data from <keyboard.c> info_data = _extract_led_config(info_data, str(keyboard)) # Validate against the jsonschema try: validate(info_data, 'qmk.api.keyboard.v1') except jsonschema.ValidationError as e: json_path = '.'.join([str(p) for p in e.absolute_path]) cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message) exit(1) # Make sure we have at least one layout if not info_data.get('layouts'): _find_missing_layouts(info_data, keyboard) if not info_data.get('layouts'): _log_error( info_data, 'No LAYOUTs defined! Need at least one layout defined in the keyboard.h or info.json.' ) # Filter out any non-existing community layouts for layout in info_data.get('community_layouts', []): if not _valid_community_layout(layout): # Ignore layout from future checks info_data['community_layouts'].remove(layout) _log_error( info_data, 'Claims to support a community layout that does not exist: %s' % (layout)) # Make sure we supply layout macros for the community layouts we claim to support for layout in info_data.get('community_layouts', []): layout_name = 'LAYOUT_' + layout if layout_name not in info_data.get( 'layouts', {}) and layout_name not in info_data.get( 'layout_aliases', {}): _log_error( info_data, 'Claims to support community layout %s but no %s() macro found' % (layout, layout_name)) # Check that the reported matrix size is consistent with the actual matrix size _check_matrix(info_data) return info_data