diff options
| author | Erovia <Erovia@users.noreply.github.com> | 2022-08-20 06:39:19 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-20 15:39:19 +1000 |
| commit | 5e2ffe7d8f4187109514147469d7db93e075f6f0 (patch) | |
| tree | 83552a38351b50f6ab175c6abd6070abcc3d78a0 /lib/python/qmk/cli/flash.py | |
| parent | 3bf36e8b04be5af9826fe3241d227efb185a4a31 (diff) | |
CLI: Teaching the CLI to flash binaries (#16584)
Co-authored-by: Ryan <fauxpark@gmail.com>
Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
Co-authored-by: Joel Challis <git@zvecr.com>
Co-authored-by: Nick Brassel <nick@tzarc.org>
Diffstat (limited to 'lib/python/qmk/cli/flash.py')
| -rw-r--r-- | lib/python/qmk/cli/flash.py | 120 |
1 files changed, 69 insertions, 51 deletions
diff --git a/lib/python/qmk/cli/flash.py b/lib/python/qmk/cli/flash.py index ebe739c50e..c39f4b36d4 100644 --- a/lib/python/qmk/cli/flash.py +++ b/lib/python/qmk/cli/flash.py | |||
| @@ -4,6 +4,7 @@ You can compile a keymap already in the repo or using a QMK Configurator export. | |||
| 4 | A bootloader must be specified. | 4 | A bootloader must be specified. |
| 5 | """ | 5 | """ |
| 6 | from subprocess import DEVNULL | 6 | from subprocess import DEVNULL |
| 7 | import sys | ||
| 7 | 8 | ||
| 8 | from argcomplete.completers import FilesCompleter | 9 | from argcomplete.completers import FilesCompleter |
| 9 | from milc import cli | 10 | from milc import cli |
| @@ -12,6 +13,7 @@ import qmk.path | |||
| 12 | from qmk.decorators import automagic_keyboard, automagic_keymap | 13 | from qmk.decorators import automagic_keyboard, automagic_keymap |
| 13 | from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json | 14 | from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json |
| 14 | from qmk.keyboard import keyboard_completer, keyboard_folder | 15 | from qmk.keyboard import keyboard_completer, keyboard_folder |
| 16 | from qmk.flashers import flasher | ||
| 15 | 17 | ||
| 16 | 18 | ||
| 17 | def print_bootloader_help(): | 19 | def print_bootloader_help(): |
| @@ -38,9 +40,10 @@ def print_bootloader_help(): | |||
| 38 | cli.echo('For more info, visit https://docs.qmk.fm/#/flashing') | 40 | cli.echo('For more info, visit https://docs.qmk.fm/#/flashing') |
| 39 | 41 | ||
| 40 | 42 | ||
| 41 | @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='The configurator export JSON to compile.') | 43 | @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='A configurator export JSON to be compiled and flashed or a pre-compiled binary firmware file (bin/hex) to be flashed.') |
| 42 | @cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.') | 44 | @cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.') |
| 43 | @cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.') | 45 | @cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.') |
| 46 | @cli.argument('-m', '--mcu', help='The MCU name. Required for HalfKay, HID, USBAspLoader and ISP flashing.') | ||
| 44 | @cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') | 47 | @cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') |
| 45 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') | 48 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') |
| 46 | @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") | 49 | @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") |
| @@ -53,6 +56,8 @@ def print_bootloader_help(): | |||
| 53 | def flash(cli): | 56 | def flash(cli): |
| 54 | """Compile and or flash QMK Firmware or keyboard/layout | 57 | """Compile and or flash QMK Firmware or keyboard/layout |
| 55 | 58 | ||
| 59 | If a binary firmware is supplied, try to flash that. | ||
| 60 | |||
| 56 | If a Configurator JSON export is supplied this command will create a new keymap. Keymap and Keyboard arguments | 61 | If a Configurator JSON export is supplied this command will create a new keymap. Keymap and Keyboard arguments |
| 57 | will be ignored. | 62 | will be ignored. |
| 58 | 63 | ||
| @@ -60,56 +65,69 @@ def flash(cli): | |||
| 60 | 65 | ||
| 61 | If bootloader is omitted the make system will use the configured bootloader for that keyboard. | 66 | If bootloader is omitted the make system will use the configured bootloader for that keyboard. |
| 62 | """ | 67 | """ |
| 63 | if cli.args.clean and not cli.args.filename and not cli.args.dry_run: | 68 | if cli.args.filename and cli.args.filename.suffix in ['.bin', '.hex']: |
| 64 | if cli.config.flash.keyboard and cli.config.flash.keymap: | 69 | # Try to flash binary firmware |
| 65 | command = create_make_command(cli.config.flash.keyboard, cli.config.flash.keymap, 'clean') | 70 | cli.echo('Flashing binary firmware...\nPlease reset your keyboard into bootloader mode now!\nPress Ctrl-C to exit.\n') |
| 66 | cli.run(command, capture_output=False, stdin=DEVNULL) | 71 | try: |
| 67 | 72 | err, msg = flasher(cli.args.mcu, cli.args.filename) | |
| 68 | # Build the environment vars | 73 | if err: |
| 69 | envs = {} | 74 | cli.log.error(msg) |
| 70 | for env in cli.args.env: | 75 | return False |
| 71 | if '=' in env: | 76 | except KeyboardInterrupt: |
| 72 | key, value = env.split('=', 1) | 77 | cli.log.info('Ctrl-C was pressed, exiting...') |
| 73 | envs[key] = value | 78 | sys.exit(0) |
| 74 | else: | ||
| 75 | cli.log.warning('Invalid environment variable: %s', env) | ||
| 76 | |||
| 77 | # Determine the compile command | ||
| 78 | command = '' | ||
| 79 | |||
| 80 | if cli.args.bootloaders: | ||
| 81 | # Provide usage and list bootloaders | ||
| 82 | cli.echo('usage: qmk flash [-h] [-b] [-n] [-kb KEYBOARD] [-km KEYMAP] [-bl BOOTLOADER] [filename]') | ||
| 83 | print_bootloader_help() | ||
| 84 | return False | ||
| 85 | |||
| 86 | if cli.args.filename: | ||
| 87 | # Handle compiling a configurator JSON | ||
| 88 | user_keymap = parse_configurator_json(cli.args.filename) | ||
| 89 | keymap_path = qmk.path.keymap(user_keymap['keyboard']) | ||
| 90 | command = compile_configurator_json(user_keymap, cli.args.bootloader, parallel=cli.config.flash.parallel, **envs) | ||
| 91 | |||
| 92 | cli.log.info('Wrote keymap to {fg_cyan}%s/%s/keymap.c', keymap_path, user_keymap['keymap']) | ||
| 93 | 79 | ||
| 94 | else: | 80 | else: |
| 95 | if cli.config.flash.keyboard and cli.config.flash.keymap: | 81 | if cli.args.clean and not cli.args.filename and not cli.args.dry_run: |
| 96 | # Generate the make command for a specific keyboard/keymap. | 82 | if cli.config.flash.keyboard and cli.config.flash.keymap: |
| 97 | command = create_make_command(cli.config.flash.keyboard, cli.config.flash.keymap, cli.args.bootloader, parallel=cli.config.flash.parallel, **envs) | 83 | command = create_make_command(cli.config.flash.keyboard, cli.config.flash.keymap, 'clean') |
| 98 | 84 | cli.run(command, capture_output=False, stdin=DEVNULL) | |
| 99 | elif not cli.config.flash.keyboard: | 85 | |
| 100 | cli.log.error('Could not determine keyboard!') | 86 | # Build the environment vars |
| 101 | elif not cli.config.flash.keymap: | 87 | envs = {} |
| 102 | cli.log.error('Could not determine keymap!') | 88 | for env in cli.args.env: |
| 103 | 89 | if '=' in env: | |
| 104 | # Compile the firmware, if we're able to | 90 | key, value = env.split('=', 1) |
| 105 | if command: | 91 | envs[key] = value |
| 106 | cli.log.info('Compiling keymap with {fg_cyan}%s', ' '.join(command)) | 92 | else: |
| 107 | if not cli.args.dry_run: | 93 | cli.log.warning('Invalid environment variable: %s', env) |
| 108 | cli.echo('\n') | 94 | |
| 109 | compile = cli.run(command, capture_output=False, stdin=DEVNULL) | 95 | # Determine the compile command |
| 110 | return compile.returncode | 96 | command = '' |
| 97 | |||
| 98 | if cli.args.bootloaders: | ||
| 99 | # Provide usage and list bootloaders | ||
| 100 | cli.echo('usage: qmk flash [-h] [-b] [-n] [-kb KEYBOARD] [-km KEYMAP] [-bl BOOTLOADER] [filename]') | ||
| 101 | print_bootloader_help() | ||
| 102 | return False | ||
| 103 | |||
| 104 | if cli.args.filename: | ||
| 105 | # Handle compiling a configurator JSON | ||
| 106 | user_keymap = parse_configurator_json(cli.args.filename) | ||
| 107 | keymap_path = qmk.path.keymap(user_keymap['keyboard']) | ||
| 108 | command = compile_configurator_json(user_keymap, cli.args.bootloader, parallel=cli.config.flash.parallel, **envs) | ||
| 109 | |||
| 110 | cli.log.info('Wrote keymap to {fg_cyan}%s/%s/keymap.c', keymap_path, user_keymap['keymap']) | ||
| 111 | 111 | ||
| 112 | else: | 112 | else: |
| 113 | cli.log.error('You must supply a configurator export, both `--keyboard` and `--keymap`, or be in a directory for a keyboard or keymap.') | 113 | if cli.config.flash.keyboard and cli.config.flash.keymap: |
| 114 | cli.echo('usage: qmk flash [-h] [-b] [-n] [-kb KEYBOARD] [-km KEYMAP] [-bl BOOTLOADER] [filename]') | 114 | # Generate the make command for a specific keyboard/keymap. |
| 115 | return False | 115 | command = create_make_command(cli.config.flash.keyboard, cli.config.flash.keymap, cli.args.bootloader, parallel=cli.config.flash.parallel, **envs) |
| 116 | |||
| 117 | elif not cli.config.flash.keyboard: | ||
| 118 | cli.log.error('Could not determine keyboard!') | ||
| 119 | elif not cli.config.flash.keymap: | ||
| 120 | cli.log.error('Could not determine keymap!') | ||
| 121 | |||
| 122 | # Compile the firmware, if we're able to | ||
| 123 | if command: | ||
| 124 | cli.log.info('Compiling keymap with {fg_cyan}%s', ' '.join(command)) | ||
| 125 | if not cli.args.dry_run: | ||
| 126 | cli.echo('\n') | ||
| 127 | compile = cli.run(command, capture_output=False, stdin=DEVNULL) | ||
| 128 | return compile.returncode | ||
| 129 | |||
| 130 | else: | ||
| 131 | cli.log.error('You must supply a configurator export, both `--keyboard` and `--keymap`, or be in a directory for a keyboard or keymap.') | ||
| 132 | cli.echo('usage: qmk flash [-h] [-b] [-n] [-kb KEYBOARD] [-km KEYMAP] [-bl BOOTLOADER] [filename]') | ||
| 133 | return False | ||
