aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python/qmk/cli
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python/qmk/cli')
-rwxr-xr-xlib/python/qmk/cli/compile.py2
-rw-r--r--lib/python/qmk/cli/docs.py10
-rwxr-xr-xlib/python/qmk/cli/doctor.py67
-rw-r--r--lib/python/qmk/cli/flash.py5
4 files changed, 56 insertions, 28 deletions
diff --git a/lib/python/qmk/cli/compile.py b/lib/python/qmk/cli/compile.py
index 234ffb12c..8e2d0cdbf 100755
--- a/lib/python/qmk/cli/compile.py
+++ b/lib/python/qmk/cli/compile.py
@@ -37,7 +37,7 @@ def compile(cli):
cli.log.info('Creating {fg_cyan}%s{style_reset_all} keymap in {fg_cyan}%s', user_keymap['keymap'], keymap_path)
# Compile the keymap
- command = compile_configurator_json(cli.args.filename)
+ command = compile_configurator_json(user_keymap)
cli.log.info('Wrote keymap to {fg_cyan}%s/%s/keymap.c', keymap_path, user_keymap['keymap'])
diff --git a/lib/python/qmk/cli/docs.py b/lib/python/qmk/cli/docs.py
index b41989139..163c8b801 100644
--- a/lib/python/qmk/cli/docs.py
+++ b/lib/python/qmk/cli/docs.py
@@ -1,21 +1,19 @@
"""Serve QMK documentation locally
"""
import http.server
+import os
from milc import cli
-class DocsHandler(http.server.SimpleHTTPRequestHandler):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, directory='docs', **kwargs)
-
-
@cli.argument('-p', '--port', default=8936, type=int, help='Port number to use.')
@cli.subcommand('Run a local webserver for QMK documentation.')
def docs(cli):
"""Spin up a local HTTPServer instance for the QMK docs.
"""
- with http.server.HTTPServer(('', cli.config.docs.port), DocsHandler) as httpd:
+ os.chdir('docs')
+
+ with http.server.HTTPServer(('', cli.config.docs.port), http.server.SimpleHTTPRequestHandler) as httpd:
cli.log.info("Serving QMK docs at http://localhost:%d/", cli.config.docs.port)
cli.log.info("Press Control+C to exit.")
diff --git a/lib/python/qmk/cli/doctor.py b/lib/python/qmk/cli/doctor.py
index 1010eafb3..6ddc5571b 100755
--- a/lib/python/qmk/cli/doctor.py
+++ b/lib/python/qmk/cli/doctor.py
@@ -2,13 +2,24 @@
Check up for QMK environment.
"""
+import os
import platform
import shutil
import subprocess
+import glob
from milc import cli
+def _udev_rule(vid, pid=None):
+ """ Helper function that return udev rules
+ """
+ if pid:
+ return 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="%s", ATTRS{idProduct}=="%s", MODE:="0666"' % (vid, pid)
+ else:
+ return 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="%s", MODE:="0666"' % vid
+
+
@cli.subcommand('Basic QMK environment checks')
def doctor(cli):
"""Basic QMK environment checks.
@@ -17,7 +28,6 @@ def doctor(cli):
TODO(unclaimed):
* [ ] Compile a trivial program with each compiler
- * [ ] Check for udev entries on linux
"""
cli.log.info('QMK Doctor is checking your environment.')
@@ -39,30 +49,49 @@ def doctor(cli):
ok = False
# Determine our OS and run platform specific tests
- OS = platform.system()
+ OS = platform.system() # noqa (N806), uppercase name is ok in this instance
if OS == "Darwin":
cli.log.info("Detected {fg_cyan}macOS.")
elif OS == "Linux":
cli.log.info("Detected {fg_cyan}Linux.")
- if shutil.which('systemctl'):
- mm_check = subprocess.run(['systemctl', 'list-unit-files'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=10, universal_newlines=True)
- if mm_check.returncode == 0:
- mm = False
- for line in mm_check.stdout.split('\n'):
- if 'ModemManager' in line and 'enabled' in line:
- mm = True
-
- if mm:
- cli.log.warn("{bg_yellow}Detected ModemManager. Please disable it if you are using a Pro-Micro.")
-
- else:
- cli.log.error('{bg_red}Could not run `systemctl list-unit-files`:')
- cli.log.error(mm_check.stderr)
-
- else:
- cli.log.warn("Can't find systemctl to check for ModemManager.")
+ # Checking for udev rules
+ udev_dir = "/etc/udev/rules.d/"
+ # These are the recommended udev rules
+ desired_rules = {
+ 'dfu': {_udev_rule("03eb", "2ff4"), _udev_rule("03eb", "2ffb"), _udev_rule("03eb", "2ff0")},
+ 'tmk': {_udev_rule("feed")},
+ 'input_club': {_udev_rule("1c11")},
+ 'stm32': {_udev_rule("1eaf", "0003"), _udev_rule("0483", "df11")},
+ 'caterina': {'ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"', 'ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"'},
+ }
+
+ if os.path.exists(udev_dir):
+ udev_rules = [rule for rule in glob.iglob(os.path.join(udev_dir, "*.rules")) if os.path.isfile(rule)]
+ # Collect all rules from the config files
+ current_rules = set()
+ for rule in udev_rules:
+ with open(rule, "r") as fd:
+ for line in fd.readlines():
+ line = line.strip()
+ if not line.startswith("#") and len(line):
+ current_rules.add(line)
+
+ # Check if the desired rules are among the currently present rules
+ for bootloader, rules in desired_rules.items():
+ if not rules.issubset(current_rules):
+ # If the rules for catalina are not present, check if ModemManager is running
+ if bootloader == "caterina":
+ if shutil.which("systemctl"):
+ mm_check = subprocess.run(["systemctl", "--quiet", "is-active", "ModemManager.service"], timeout=10)
+ if mm_check.returncode == 0:
+ ok = False
+ cli.log.warn("{bg_yellow}Detected ModemManager without udev rules. Please either disable it or set the appropriate udev rules if you are using a Pro Micro.")
+ else:
+ cli.log.warn("Can't find systemctl to check for ModemManager.")
+ else:
+ cli.log.warn("{bg_yellow}Missing udev rules for '%s' boards. You'll need to use `sudo` in order to flash them.", bootloader)
else:
cli.log.info("Assuming {fg_cyan}Windows.")
diff --git a/lib/python/qmk/cli/flash.py b/lib/python/qmk/cli/flash.py
index 031cb9496..e897174a2 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.
A bootloader must be specified.
"""
import subprocess
+from argparse import FileType
import qmk.path
from milc import cli
@@ -28,7 +29,7 @@ def print_bootloader_help():
@cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.')
-@cli.argument('filename', nargs='?', arg_only=True, help='The configurator export JSON to compile. Use this if you dont want to specify a keymap and keyboard.')
+@cli.argument('filename', nargs='?', arg_only=True, type=FileType('r'), help='The configurator export JSON to compile.')
@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.')
@cli.argument('-kb', '--keyboard', help='The keyboard to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.')
@cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.')
@@ -65,7 +66,7 @@ def flash(cli):
cli.log.info('Creating {fg_cyan}%s{style_reset_all} keymap in {fg_cyan}%s', user_keymap['keymap'], keymap_path)
# Convert the JSON into a C file and write it to disk.
- command = compile_configurator_json(cli.args.filename, cli.args.bootloader)
+ command = compile_configurator_json(user_keymap, cli.args.bootloader)
cli.log.info('Wrote keymap to {fg_cyan}%s/%s/keymap.c', keymap_path, user_keymap['keymap'])