Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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