diff options
Diffstat (limited to 'lib/python/qmk/info.py')
-rw-r--r-- | lib/python/qmk/info.py | 82 |
1 files changed, 57 insertions, 25 deletions
diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py index 1cf12190d..39af88f79 100644 --- a/lib/python/qmk/info.py +++ b/lib/python/qmk/info.py | |||
@@ -26,13 +26,12 @@ led_matrix_properties = { | |||
26 | } | 26 | } |
27 | 27 | ||
28 | rgblight_properties = { | 28 | rgblight_properties = { |
29 | 'led_count': 'RGBLED_NUM', | 29 | 'led_count': ('RGBLED_NUM', int), |
30 | 'pin': 'RGB_DI_PIN', | 30 | 'pin': ('RGB_DI_PIN', str), |
31 | 'split_count': 'RGBLED_SPLIT', | 31 | 'max_brightness': ('RGBLIGHT_LIMIT_VAL', int), |
32 | 'max_brightness': 'RGBLIGHT_LIMIT_VAL', | 32 | 'hue_steps': ('RGBLIGHT_HUE_STEP', int), |
33 | 'hue_steps': 'RGBLIGHT_HUE_STEP', | 33 | 'saturation_steps': ('RGBLIGHT_SAT_STEP', int), |
34 | 'saturation_steps': 'RGBLIGHT_SAT_STEP', | 34 | 'brightness_steps': ('RGBLIGHT_VAL_STEP', int) |
35 | 'brightness_steps': 'RGBLIGHT_VAL_STEP' | ||
36 | } | 35 | } |
37 | 36 | ||
38 | rgblight_toggles = { | 37 | rgblight_toggles = { |
@@ -54,6 +53,8 @@ rgblight_animations = { | |||
54 | 'twinkle': 'RGBLIGHT_EFFECT_TWINKLE' | 53 | 'twinkle': 'RGBLIGHT_EFFECT_TWINKLE' |
55 | } | 54 | } |
56 | 55 | ||
56 | usb_properties = {'vid': 'VENDOR_ID', 'pid': 'PRODUCT_ID', 'device_ver': 'DEVICE_VER'} | ||
57 | |||
57 | true_values = ['1', 'on', 'yes'] | 58 | true_values = ['1', 'on', 'yes'] |
58 | false_values = ['0', 'off', 'no'] | 59 | false_values = ['0', 'off', 'no'] |
59 | 60 | ||
@@ -97,7 +98,8 @@ def info_json(keyboard): | |||
97 | keyboard_api_validate(info_data) | 98 | keyboard_api_validate(info_data) |
98 | 99 | ||
99 | except jsonschema.ValidationError as e: | 100 | except jsonschema.ValidationError as e: |
100 | cli.log.error('Invalid info.json data: %s', e.message) | 101 | json_path = '.'.join([str(p) for p in e.absolute_path]) |
102 | cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message) | ||
101 | print(dir(e)) | 103 | print(dir(e)) |
102 | exit() | 104 | exit() |
103 | 105 | ||
@@ -198,6 +200,9 @@ def _extract_indicators(info_data, config_c): | |||
198 | if json_key in info_data.get('indicators', []) and config_key in config_c: | 200 | if json_key in info_data.get('indicators', []) and config_key in config_c: |
199 | _log_warning(info_data, f'Indicator {json_key} is specified in both info.json and config.h, the config.h value wins.') | 201 | _log_warning(info_data, f'Indicator {json_key} is specified in both info.json and config.h, the config.h value wins.') |
200 | 202 | ||
203 | if 'indicators' not in info_data: | ||
204 | info_data['indicators'] = {} | ||
205 | |||
201 | if config_key in config_c: | 206 | if config_key in config_c: |
202 | if 'indicators' not in info_data: | 207 | if 'indicators' not in info_data: |
203 | info_data['indicators'] = {} | 208 | info_data['indicators'] = {} |
@@ -226,10 +231,23 @@ def _extract_community_layouts(info_data, rules): | |||
226 | def _extract_features(info_data, rules): | 231 | def _extract_features(info_data, rules): |
227 | """Find all the features enabled in rules.mk. | 232 | """Find all the features enabled in rules.mk. |
228 | """ | 233 | """ |
234 | # Special handling for bootmagic which also supports a "lite" mode. | ||
235 | if rules.get('BOOTMAGIC_ENABLE') == 'lite': | ||
236 | rules['BOOTMAGIC_LITE_ENABLE'] = 'on' | ||
237 | del(rules['BOOTMAGIC_ENABLE']) | ||
238 | if rules.get('BOOTMAGIC_ENABLE') == 'full': | ||
239 | rules['BOOTMAGIC_ENABLE'] = 'on' | ||
240 | |||
241 | # Skip non-boolean features we haven't implemented special handling for | ||
242 | for feature in 'HAPTIC_ENABLE', 'QWIIC_ENABLE': | ||
243 | if rules.get(feature): | ||
244 | del(rules[feature]) | ||
245 | |||
246 | # Process the rest of the rules as booleans | ||
229 | for key, value in rules.items(): | 247 | for key, value in rules.items(): |
230 | if key.endswith('_ENABLE'): | 248 | if key.endswith('_ENABLE'): |
231 | key = '_'.join(key.split('_')[:-1]).lower() | 249 | key = '_'.join(key.split('_')[:-1]).lower() |
232 | value = True if value in true_values else False if value in false_values else value | 250 | value = True if value.lower() in true_values else False if value.lower() in false_values else value |
233 | 251 | ||
234 | if 'config_h_features' not in info_data: | 252 | if 'config_h_features' not in info_data: |
235 | info_data['config_h_features'] = {} | 253 | info_data['config_h_features'] = {} |
@@ -280,12 +298,21 @@ def _extract_rgblight(info_data, config_c): | |||
280 | rgblight = info_data.get('rgblight', {}) | 298 | rgblight = info_data.get('rgblight', {}) |
281 | animations = rgblight.get('animations', {}) | 299 | animations = rgblight.get('animations', {}) |
282 | 300 | ||
283 | for json_key, config_key in rgblight_properties.items(): | 301 | if 'RGBLED_SPLIT' in config_c: |
302 | raw_split = config_c.get('RGBLED_SPLIT', '').replace('{', '').replace('}', '').strip() | ||
303 | rgblight['split_count'] = [int(i) for i in raw_split.split(',')] | ||
304 | |||
305 | for json_key, config_key_type in rgblight_properties.items(): | ||
306 | config_key, config_type = config_key_type | ||
307 | |||
284 | if config_key in config_c: | 308 | if config_key in config_c: |
285 | if json_key in rgblight: | 309 | if json_key in rgblight: |
286 | _log_warning(info_data, 'RGB Light: %s is specified in both info.json and config.h, the config.h value wins.' % (json_key,)) | 310 | _log_warning(info_data, 'RGB Light: %s is specified in both info.json and config.h, the config.h value wins.' % (json_key,)) |
287 | 311 | ||
288 | rgblight[json_key] = config_c[config_key] | 312 | try: |
313 | rgblight[json_key] = config_type(config_c[config_key]) | ||
314 | except ValueError as e: | ||
315 | cli.log.error('%s: config.h: Could not convert "%s" to %s: %s', info_data['keyboard_folder'], config_c[config_key], config_type.__name__, e) | ||
289 | 316 | ||
290 | for json_key, config_key in rgblight_toggles.items(): | 317 | for json_key, config_key in rgblight_toggles.items(): |
291 | if config_key in config_c: | 318 | if config_key in config_c: |
@@ -332,11 +359,16 @@ def _extract_matrix_info(info_data, config_c): | |||
332 | 359 | ||
333 | info_data['matrix_pins'] = {} | 360 | info_data['matrix_pins'] = {} |
334 | 361 | ||
362 | # FIXME(skullydazed/anyone): Should really check every pin, not just the first | ||
335 | if row_pins: | 363 | if row_pins: |
336 | info_data['matrix_pins']['rows'] = row_pins.split(',') | 364 | row_pins = [pin.strip() for pin in row_pins.split(',') if pin] |
365 | if row_pins[0][0] in 'ABCDEFGHIJK' and row_pins[0][1].isdigit(): | ||
366 | info_data['matrix_pins']['rows'] = row_pins | ||
337 | 367 | ||
338 | if col_pins: | 368 | if col_pins: |
339 | info_data['matrix_pins']['cols'] = col_pins.split(',') | 369 | col_pins = [pin.strip() for pin in col_pins.split(',') if pin] |
370 | if col_pins[0][0] in 'ABCDEFGHIJK' and col_pins[0][1].isdigit(): | ||
371 | info_data['matrix_pins']['cols'] = col_pins | ||
340 | 372 | ||
341 | if direct_pins: | 373 | if direct_pins: |
342 | if 'matrix_pins' in info_data: | 374 | if 'matrix_pins' in info_data: |
@@ -345,6 +377,9 @@ def _extract_matrix_info(info_data, config_c): | |||
345 | info_data['matrix_pins'] = {} | 377 | info_data['matrix_pins'] = {} |
346 | direct_pin_array = [] | 378 | direct_pin_array = [] |
347 | 379 | ||
380 | while direct_pins[-1] != '}': | ||
381 | direct_pins = direct_pins[:-1] | ||
382 | |||
348 | for row in direct_pins.split('},{'): | 383 | for row in direct_pins.split('},{'): |
349 | if row.startswith('{'): | 384 | if row.startswith('{'): |
350 | row = row[1:] | 385 | row = row[1:] |
@@ -368,8 +403,6 @@ def _extract_matrix_info(info_data, config_c): | |||
368 | def _extract_usb_info(info_data, config_c): | 403 | def _extract_usb_info(info_data, config_c): |
369 | """Populate the USB information. | 404 | """Populate the USB information. |
370 | """ | 405 | """ |
371 | usb_properties = {'vid': 'VENDOR_ID', 'pid': 'PRODUCT_ID', 'device_ver': 'DEVICE_VER'} | ||
372 | |||
373 | if 'usb' not in info_data: | 406 | if 'usb' not in info_data: |
374 | info_data['usb'] = {} | 407 | info_data['usb'] = {} |
375 | 408 | ||
@@ -378,10 +411,7 @@ def _extract_usb_info(info_data, config_c): | |||
378 | if info_name in info_data['usb']: | 411 | if info_name in info_data['usb']: |
379 | _log_warning(info_data, '%s in config.h is overwriting usb.%s in info.json' % (config_name, info_name)) | 412 | _log_warning(info_data, '%s in config.h is overwriting usb.%s in info.json' % (config_name, info_name)) |
380 | 413 | ||
381 | info_data['usb'][info_name] = config_c[config_name] | 414 | info_data['usb'][info_name] = '0x' + config_c[config_name][2:].upper() |
382 | |||
383 | elif info_name not in info_data['usb']: | ||
384 | _log_error(info_data, '%s not specified in config.h, and %s not specified in info.json. One is required.' % (config_name, info_name)) | ||
385 | 415 | ||
386 | return info_data | 416 | return info_data |
387 | 417 | ||
@@ -519,8 +549,9 @@ def arm_processor_rules(info_data, rules): | |||
519 | info_data['processor'] = 'unknown' | 549 | info_data['processor'] = 'unknown' |
520 | 550 | ||
521 | if 'BOOTLOADER' in rules: | 551 | if 'BOOTLOADER' in rules: |
522 | if 'bootloader' in info_data: | 552 | # FIXME(skullydazed/anyone): need to remove the massive amounts of duplication first |
523 | _log_warning(info_data, 'Bootloader is specified in both info.json and rules.mk, the rules.mk value wins.') | 553 | # if 'bootloader' in info_data: |
554 | # _log_warning(info_data, 'Bootloader is specified in both info.json and rules.mk, the rules.mk value wins.') | ||
524 | 555 | ||
525 | info_data['bootloader'] = rules['BOOTLOADER'] | 556 | info_data['bootloader'] = rules['BOOTLOADER'] |
526 | 557 | ||
@@ -558,8 +589,9 @@ def avr_processor_rules(info_data, rules): | |||
558 | info_data['processor'] = 'unknown' | 589 | info_data['processor'] = 'unknown' |
559 | 590 | ||
560 | if 'BOOTLOADER' in rules: | 591 | if 'BOOTLOADER' in rules: |
561 | if 'bootloader' in info_data: | 592 | # FIXME(skullydazed/anyone): need to remove the massive amounts of duplication first |
562 | _log_warning(info_data, 'Bootloader is specified in both info.json and rules.mk, the rules.mk value wins.') | 593 | # if 'bootloader' in info_data: |
594 | # _log_warning(info_data, 'Bootloader is specified in both info.json and rules.mk, the rules.mk value wins.') | ||
563 | 595 | ||
564 | info_data['bootloader'] = rules['BOOTLOADER'] | 596 | info_data['bootloader'] = rules['BOOTLOADER'] |
565 | else: | 597 | else: |
@@ -593,8 +625,8 @@ def merge_info_jsons(keyboard, info_data): | |||
593 | keyboard_validate(new_info_data) | 625 | keyboard_validate(new_info_data) |
594 | 626 | ||
595 | except jsonschema.ValidationError as e: | 627 | except jsonschema.ValidationError as e: |
596 | cli.log.error('Invalid info.json data: %s', e.message) | 628 | json_path = '.'.join([str(p) for p in e.absolute_path]) |
597 | cli.log.error('Not including file %s', info_file) | 629 | cli.log.error('Invalid info.json data: %s: %s: %s', info_file, json_path, e.message) |
598 | continue | 630 | continue |
599 | 631 | ||
600 | if not isinstance(new_info_data, dict): | 632 | if not isinstance(new_info_data, dict): |