Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbd667e30c | |||
| 32506bf1bb | |||
| 45a231af0c | |||
| 1f7ad8a73e | |||
| 2faca28631 | |||
| d99eed2ed0 | |||
| a5a481e322 | |||
| 21daea7028 | |||
| 51e80c2f52 | |||
| 567ef9637e | |||
| e8818c9d23 | |||
| 2710813c51 | |||
| fb69e6d50a | |||
| 135d9f63a1 | |||
| 695cd7eb4d | |||
| 61ca025afd | |||
| 2bd1630621 | |||
| 34517d01b7 | |||
| 0a4d66e13a | |||
| fe0a3af05f | |||
| 4508b8548f | |||
| 2ea90a0893 | |||
| 9fccc990be | |||
| 6d99eacdf8 | |||
| dbd731585a | |||
| 9d480bd287 | |||
| 709f416e52 | |||
| bcdac9a80e | |||
| 4772e68828 | |||
| 24741c7d2b | |||
| b756421528 | |||
| 3d96bcdc14 | |||
| 6e6b6bcde6 | |||
| 1df06eed72 | |||
| 60a56b6976 | |||
| 1e3605feb3 | |||
| 48ddcefea1 | |||
| 2f6f38cc33 | |||
| c73ae7e97c | |||
| 0475193870 | |||
| 8d9b3b2880 | |||
| 0dbe3dc448 |
@@ -0,0 +1,15 @@
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "pip" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
reviewers:
|
||||
- "qmk/collaborators"
|
||||
@@ -17,27 +17,15 @@ jobs:
|
||||
python-version: [3.7, 3.8, 3.9]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2.3.4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v2.2.2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python3 -m pip install wheel
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Install QMK CLI from source
|
||||
run: |
|
||||
python3 -m pip install -r requirements.txt
|
||||
python3 setup.py sdist bdist_wheel
|
||||
cd ..
|
||||
python3 -m pip install --force-reinstall --no-index --no-deps --prefix=~/.local --find-links qmk_cli/dist qmk
|
||||
|
||||
- name: Run qmk setup -y
|
||||
run: qmk setup -y
|
||||
- name: Run ci_tests
|
||||
run: ./ci_tests -a
|
||||
|
||||
test_cli_win:
|
||||
runs-on: windows-latest
|
||||
@@ -45,7 +33,7 @@ jobs:
|
||||
QMK_HOME: $HOME/qmk_firmware
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2.3.4
|
||||
|
||||
- name: (MSYS2) Setup and install dependencies
|
||||
uses: msys2/setup-msys2@v2
|
||||
@@ -57,7 +45,6 @@ jobs:
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
python3 -m pip install wheel
|
||||
|
||||
- name: (MSYS2) Install QMK CLI from source
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
@@ -65,7 +52,6 @@ jobs:
|
||||
python3 setup.py sdist bdist_wheel
|
||||
cd ..
|
||||
python3 -m pip install --force-reinstall --no-index --no-deps --find-links qmk_cli/dist qmk
|
||||
|
||||
- name: (MSYS2) Run qmk setup -y
|
||||
shell: msys2 {0}
|
||||
run: qmk setup -y
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '22 18 * * 0'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2.3.4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -17,11 +17,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v2.3.4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v2.2.2
|
||||
with:
|
||||
python-version: '3.7'
|
||||
- name: Run ci_tests
|
||||
run: ./ci_tests
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
@@ -40,8 +42,19 @@ jobs:
|
||||
tags: true
|
||||
- name: Build and publish
|
||||
env:
|
||||
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
|
||||
TWINE_USERNAME: qmk
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
|
||||
run: |
|
||||
python setup.py sdist bdist_wheel
|
||||
twine upload dist/*
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v1.10.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
- name: Build and Push to Docker Hub
|
||||
uses: docker/build-push-action@v2.6.1
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: qmkfm/qmk_cli:latest
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
FROM qmkfm/base_container
|
||||
|
||||
# Copy package in
|
||||
ADD dist /tmp/dist
|
||||
|
||||
# Install python packages
|
||||
RUN python3 -m pip uninstall -y qmk || true
|
||||
RUN python3 -m pip install --upgrade pip setuptools wheel nose2 && \
|
||||
python3 -m pip install /tmp/dist/qmk-*.whl && \
|
||||
rm -rf /tmp/dist
|
||||
|
||||
# Set the default location for qmk_firmware
|
||||
ENV QMK_HOME /qmk_firmware
|
||||
@@ -8,10 +8,11 @@ A program to help users work with [QMK Firmware](https://qmk.fm/).
|
||||
* Interact with your qmk_firmware tree from any location
|
||||
* Use `qmk clone` to pull down anyone's `qmk_firmware` fork
|
||||
* Setup your build environment with `qmk setup`
|
||||
* Use `qmk console` to get debugging information from your keyboard(s)
|
||||
* Check that your environment is correctly setup with `qmk doctor`
|
||||
* Integrates with qmk_firmware for additional functionality:
|
||||
* `qmk compile`
|
||||
* `qmk console`
|
||||
* `qmk info`
|
||||
* `qmk flash`
|
||||
* `qmk lint`
|
||||
* ...and many more!
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.0.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
* [Open an Issue](https://github.com/qmk/qmk_cli/issues/new?assignees=&labels=bug&template=bug_report.md&title=%5BBug%5D+)
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
#set -x
|
||||
|
||||
ADVANCED=false
|
||||
TMPDIR=$(mktemp -d)
|
||||
QMK_HOME="$TMPDIR/qmk_firmware"
|
||||
export QMK_HOME
|
||||
|
||||
for arg in $@; do
|
||||
if [ "$arg" = "-a" ]; then
|
||||
ADVANCED=true
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $ADVANCED = true ]; then
|
||||
echo "*** Running in advanced mode with tmp files in $TMPDIR"
|
||||
else
|
||||
echo "*** Running in basic mode with tmp files in $TMPDIR"
|
||||
fi
|
||||
|
||||
# Setup our virtualenv
|
||||
if [ -e .ci_venv ]; then
|
||||
rm -rf .ci_venv
|
||||
fi
|
||||
|
||||
python3 -m venv .ci_venv
|
||||
source .ci_venv/bin/activate
|
||||
|
||||
# Install dependencies
|
||||
python3 -m pip install -U pip wheel
|
||||
python3 -m pip install .
|
||||
python3 -m pip install -r requirements-dev.txt
|
||||
|
||||
# Ensure that qmk works
|
||||
echo "*** Testing 'qmk clone -h'"
|
||||
qmk clone -h
|
||||
echo "*** Testing 'qmk config -a'"
|
||||
qmk config -a
|
||||
echo "*** Testing 'qmk setup -n'"
|
||||
qmk setup -n
|
||||
|
||||
echo
|
||||
echo "*** Basic tests completed successfully!"
|
||||
|
||||
# Run advanced test if requested
|
||||
if [ $ADVANCED = true ]; then
|
||||
echo
|
||||
echo "*** Testing 'qmk setup -y'"
|
||||
qmk setup -y
|
||||
|
||||
echo
|
||||
echo "*** Advanced tests completed successfully!"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
deactivate
|
||||
rm -rf .ci_venv $TMPDIR
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
"""A program to help you work with qmk_firmware."""
|
||||
|
||||
__version__ = '0.0.52'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup.
|
||||
"""
|
||||
from . import clone # noqa
|
||||
from . import console # noqa
|
||||
from . import env # noqa
|
||||
from . import setup # noqa
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
"""Acquire debugging information from usb hid devices
|
||||
|
||||
cli implementation of https://www.pjrc.com/teensy/hid_listen.html
|
||||
"""
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from platform import platform
|
||||
from threading import Thread
|
||||
from time import sleep, strftime
|
||||
|
||||
from milc import cli
|
||||
from milc.questions import yesno
|
||||
|
||||
LOG_COLOR = {
|
||||
'next': 0,
|
||||
'colors': [
|
||||
'{fg_blue}',
|
||||
'{fg_cyan}',
|
||||
'{fg_green}',
|
||||
'{fg_magenta}',
|
||||
'{fg_red}',
|
||||
'{fg_yellow}',
|
||||
],
|
||||
}
|
||||
|
||||
KNOWN_BOOTLOADERS = {
|
||||
# VID , PID
|
||||
('03EB', '2FEF'): 'atmel-dfu: ATmega16U2',
|
||||
('03EB', '2FF0'): 'atmel-dfu: ATmega32U2',
|
||||
('03EB', '2FF3'): 'atmel-dfu: ATmega16U4',
|
||||
('03EB', '2FF4'): 'atmel-dfu: ATmega32U4',
|
||||
('03EB', '2FF9'): 'atmel-dfu: AT90USB64',
|
||||
('03EB', '2FFA'): 'atmel-dfu: AT90USB162',
|
||||
('03EB', '2FFB'): 'atmel-dfu: AT90USB128',
|
||||
('03EB', '6124'): 'Microchip SAM-BA',
|
||||
('0483', 'DF11'): 'stm32-dfu: STM32 BOOTLOADER',
|
||||
('16C0', '05DC'): 'USBasp: USBaspLoader',
|
||||
('16C0', '05DF'): 'bootloadHID: HIDBoot',
|
||||
('16C0', '0478'): 'halfkay: Teensy Halfkay',
|
||||
('1B4F', '9203'): 'caterina: Pro Micro 3.3V',
|
||||
('1B4F', '9205'): 'caterina: Pro Micro 5V',
|
||||
('1B4F', '9207'): 'caterina: LilyPadUSB',
|
||||
('1C11', 'B007'): 'kiibohd: Kiibohd DFU Bootloader',
|
||||
('1EAF', '0003'): 'stm32duino: Maple 003',
|
||||
('1FFB', '0101'): 'caterina: Polou A-Star 32U4 Bootloader',
|
||||
('2341', '0036'): 'caterina: Arduino Leonardo',
|
||||
('2341', '0037'): 'caterina: Arduino Micro',
|
||||
('239A', '000C'): 'caterina: Adafruit Feather 32U4',
|
||||
('239A', '000D'): 'caterina: Adafruit ItsyBitsy 32U4 3v',
|
||||
('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v',
|
||||
('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v',
|
||||
('2A03', '0036'): 'caterina: Arduino Leonardo',
|
||||
('2A03', '0037'): 'caterina: Arduino Micro',
|
||||
('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode'
|
||||
}
|
||||
|
||||
|
||||
def install_deps():
|
||||
"""Install the necessary dependencies for qmk console.
|
||||
"""
|
||||
this_platform = platform().lower()
|
||||
|
||||
if 'darwin' in this_platform or 'macos' in this_platform:
|
||||
command = ['brew', 'install', 'hidapi']
|
||||
elif 'linux' in this_platform:
|
||||
command = ['sudo', 'apt', 'install', '-y', 'libhidapi-hidraw0', 'libusb-dev']
|
||||
elif 'windows' in this_platform:
|
||||
command = ['pacboy', 'sync', '--needed', '--noconfirm', '--disable-download-timeout', 'hidapi:x']
|
||||
else:
|
||||
cli.log.error('Unsupported platform: %s', this_platform)
|
||||
|
||||
if yesno("Would you like to run `%s` to install the necessary package?", ' '.join(command)):
|
||||
cli.run(command, capture_output=False)
|
||||
return True
|
||||
|
||||
|
||||
@lru_cache(maxsize=0)
|
||||
def import_usb_core():
|
||||
"""Attempts to import the usb.core module.
|
||||
"""
|
||||
try:
|
||||
import usb.core
|
||||
return usb.core
|
||||
|
||||
except ImportError as e:
|
||||
cli.log.error('Could not import usb.core: %s', e)
|
||||
|
||||
if install_deps():
|
||||
return import_usb_core()
|
||||
|
||||
raise
|
||||
|
||||
|
||||
def import_hid():
|
||||
"""Attempts to import the hid module.
|
||||
"""
|
||||
try:
|
||||
import hid
|
||||
return hid
|
||||
|
||||
except ImportError as e:
|
||||
cli.log.error('Could not import hid: %s', e)
|
||||
|
||||
if install_deps():
|
||||
return import_hid()
|
||||
|
||||
raise
|
||||
|
||||
|
||||
class MonitorDevice(object):
|
||||
def __init__(self, hid_device, numeric):
|
||||
self.hid = import_hid()
|
||||
self.hid_device = hid_device
|
||||
self.numeric = numeric
|
||||
self.device = self.hid.Device(path=hid_device['path'])
|
||||
self.current_line = ''
|
||||
|
||||
cli.log.info('Console Connected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', hid_device)
|
||||
|
||||
def read(self, size, encoding='ascii', timeout=1):
|
||||
"""Read size bytes from the device.
|
||||
"""
|
||||
return self.device.read(size, timeout).decode(encoding)
|
||||
|
||||
def read_line(self):
|
||||
"""Read from the device's console until we get a \n.
|
||||
"""
|
||||
while '\n' not in self.current_line:
|
||||
self.current_line += self.read(32).replace('\x00', '')
|
||||
|
||||
lines = self.current_line.split('\n', 1)
|
||||
self.current_line = lines[1]
|
||||
|
||||
return lines[0]
|
||||
|
||||
def run_forever(self):
|
||||
while True:
|
||||
try:
|
||||
message = {**self.hid_device, 'text': self.read_line()}
|
||||
identifier = (int2hex(message['vendor_id']), int2hex(message['product_id'])) if self.numeric else (message['manufacturer_string'], message['product_string'])
|
||||
message['identifier'] = ':'.join(identifier)
|
||||
message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else ''
|
||||
|
||||
cli.echo('%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message)
|
||||
|
||||
except self.hid.HIDException:
|
||||
break
|
||||
|
||||
|
||||
class FindDevices(object):
|
||||
def __init__(self, vid, pid, index, numeric):
|
||||
self.hid = import_hid()
|
||||
self.vid = vid
|
||||
self.pid = pid
|
||||
self.index = index
|
||||
self.numeric = numeric
|
||||
|
||||
def run_forever(self):
|
||||
"""Process messages from our queue in a loop.
|
||||
"""
|
||||
live_devices = {}
|
||||
live_bootloaders = {}
|
||||
|
||||
while True:
|
||||
try:
|
||||
for device in list(live_devices):
|
||||
if not live_devices[device]['thread'].is_alive():
|
||||
cli.log.info('Console Disconnected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', live_devices[device])
|
||||
del live_devices[device]
|
||||
|
||||
for device in self.find_devices():
|
||||
if device['path'] not in live_devices:
|
||||
device['color'] = LOG_COLOR['colors'][LOG_COLOR['next']]
|
||||
LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
|
||||
live_devices[device['path']] = device
|
||||
|
||||
try:
|
||||
monitor = MonitorDevice(device, self.numeric)
|
||||
device['thread'] = Thread(target=monitor.run_forever, daemon=True)
|
||||
|
||||
device['thread'].start()
|
||||
except Exception as e:
|
||||
device['e'] = e
|
||||
device['e_name'] = e.__class__.__name__
|
||||
cli.log.error("Could not connect to %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s:%(vendor_id)04X:%(product_id)04X:%(index)d): %(e_name)s: %(e)s", device)
|
||||
if cli.config.general.verbose:
|
||||
cli.log.exception(e)
|
||||
del live_devices[device['path']]
|
||||
|
||||
if cli.args.bootloaders:
|
||||
for device in self.find_bootloaders():
|
||||
if device.address in live_bootloaders:
|
||||
live_bootloaders[device.address]._qmk_found = True
|
||||
else:
|
||||
name = KNOWN_BOOTLOADERS[(int2hex(device.idVendor), int2hex(device.idProduct))]
|
||||
cli.log.info('Bootloader Connected: {style_bright}{fg_magenta}%s', name)
|
||||
device._qmk_found = True
|
||||
live_bootloaders[device.address] = device
|
||||
|
||||
for device in list(live_bootloaders):
|
||||
if live_bootloaders[device]._qmk_found:
|
||||
live_bootloaders[device]._qmk_found = False
|
||||
else:
|
||||
name = KNOWN_BOOTLOADERS[(int2hex(live_bootloaders[device].idVendor), int2hex(live_bootloaders[device].idProduct))]
|
||||
cli.log.info('Bootloader Disconnected: {style_bright}{fg_magenta}%s', name)
|
||||
del live_bootloaders[device]
|
||||
|
||||
sleep(.1)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
|
||||
def is_bootloader(self, hid_device):
|
||||
"""Returns true if the device in question matches a known bootloader vid/pid.
|
||||
"""
|
||||
return (int2hex(hid_device.idVendor), int2hex(hid_device.idProduct)) in KNOWN_BOOTLOADERS
|
||||
|
||||
def is_console_hid(self, hid_device):
|
||||
"""Returns true when the usage page indicates it's a teensy-style console.
|
||||
"""
|
||||
return hid_device['usage_page'] == 0xFF31 and hid_device['usage'] == 0x0074
|
||||
|
||||
def is_filtered_device(self, hid_device):
|
||||
"""Returns True if the device should be included in the list of available consoles.
|
||||
"""
|
||||
return int2hex(hid_device['vendor_id']) == self.vid and int2hex(hid_device['product_id']) == self.pid
|
||||
|
||||
def find_devices_by_report(self, hid_devices):
|
||||
"""Returns a list of available teensy-style consoles by doing a brute-force search.
|
||||
|
||||
Some versions of linux don't report usage and usage_page. In that case we fallback to reading the report (possibly inaccurately) ourselves.
|
||||
"""
|
||||
devices = []
|
||||
|
||||
for device in hid_devices:
|
||||
path = device['path'].decode('utf-8')
|
||||
|
||||
if path.startswith('/dev/hidraw'):
|
||||
number = path[11:]
|
||||
report = Path(f'/sys/class/hidraw/hidraw{number}/device/report_descriptor')
|
||||
|
||||
if report.exists():
|
||||
rp = report.read_bytes()
|
||||
|
||||
if rp[1] == 0x31 and rp[3] == 0x09:
|
||||
devices.append(device)
|
||||
|
||||
return devices
|
||||
|
||||
def find_bootloaders(self):
|
||||
"""Returns a list of available bootloader devices.
|
||||
"""
|
||||
import usb.core
|
||||
|
||||
return list(filter(self.is_bootloader, usb.core.find(find_all=True)))
|
||||
|
||||
def find_devices(self):
|
||||
"""Returns a list of available teensy-style consoles.
|
||||
"""
|
||||
hid_devices = self.hid.enumerate()
|
||||
devices = list(filter(self.is_console_hid, hid_devices))
|
||||
|
||||
if not devices:
|
||||
devices = self.find_devices_by_report(hid_devices)
|
||||
|
||||
if self.vid and self.pid:
|
||||
devices = list(filter(self.is_filtered_device, devices))
|
||||
|
||||
# Add index numbers
|
||||
device_index = {}
|
||||
for device in devices:
|
||||
id = ':'.join((int2hex(device['vendor_id']), int2hex(device['product_id'])))
|
||||
|
||||
if id not in device_index:
|
||||
device_index[id] = 0
|
||||
|
||||
device_index[id] += 1
|
||||
device['index'] = device_index[id]
|
||||
|
||||
return devices
|
||||
|
||||
|
||||
def int2hex(number):
|
||||
"""Returns a string representation of the number as hex.
|
||||
"""
|
||||
return "%04X" % number
|
||||
|
||||
|
||||
def list_devices(device_finder):
|
||||
"""Show the user a nicely formatted list of devices.
|
||||
"""
|
||||
devices = device_finder.find_devices()
|
||||
|
||||
if devices:
|
||||
cli.log.info('Available devices:')
|
||||
for dev in devices:
|
||||
color = LOG_COLOR['colors'][LOG_COLOR['next']]
|
||||
LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
|
||||
cli.log.info("\t%s%s:%s:%d{style_reset_all}\t%s %s", color, int2hex(dev['vendor_id']), int2hex(dev['product_id']), dev['index'], dev['manufacturer_string'], dev['product_string'])
|
||||
|
||||
if cli.args.bootloaders:
|
||||
bootloaders = device_finder.find_bootloaders()
|
||||
|
||||
if bootloaders:
|
||||
cli.log.info('Available Bootloaders:')
|
||||
|
||||
for dev in bootloaders:
|
||||
cli.log.info("\t%s:%s\t%s", int2hex(dev.idVendor), int2hex(dev.idProduct), KNOWN_BOOTLOADERS[(int2hex(dev.idVendor), int2hex(dev.idProduct))])
|
||||
|
||||
|
||||
@cli.argument('--bootloaders', arg_only=True, default=True, action='store_boolean', help='displaying bootloaders.')
|
||||
@cli.argument('-d', '--device', help='Device to select - uses format <pid>:<vid>[:<index>].')
|
||||
@cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available hid_listen devices.')
|
||||
@cli.argument('-n', '--numeric', arg_only=True, action='store_true', help='Show VID/PID instead of names.')
|
||||
@cli.argument('-t', '--timestamp', arg_only=True, action='store_true', help='Print the timestamp for received messages as well.')
|
||||
@cli.argument('-w', '--wait', type=int, default=1, help="How many seconds to wait between checks (Default: 1)")
|
||||
@cli.subcommand('Acquire debugging information from usb hid devices.')
|
||||
def console(cli):
|
||||
"""Acquire debugging information from usb hid devices
|
||||
"""
|
||||
vid = None
|
||||
pid = None
|
||||
index = 1
|
||||
|
||||
if cli.config.console.device:
|
||||
device = cli.config.console.device.split(':')
|
||||
|
||||
if len(device) == 2:
|
||||
vid, pid = device
|
||||
|
||||
elif len(device) == 3:
|
||||
vid, pid, index = device
|
||||
|
||||
if not index.isdigit():
|
||||
cli.log.error('Device index must be a number! Got "%s" instead.', index)
|
||||
exit(1)
|
||||
|
||||
index = int(index)
|
||||
|
||||
if index < 1:
|
||||
cli.log.error('Device index must be greater than 0! Got %s', index)
|
||||
exit(1)
|
||||
|
||||
else:
|
||||
cli.log.error('Invalid format for device, expected "<pid>:<vid>[:<index>]" but got "%s".', cli.config.console.device)
|
||||
cli.print_help()
|
||||
exit(1)
|
||||
|
||||
vid = vid.upper()
|
||||
pid = pid.upper()
|
||||
|
||||
device_finder = FindDevices(vid, pid, index, cli.args.numeric)
|
||||
|
||||
if cli.args.list:
|
||||
return list_devices(device_finder)
|
||||
|
||||
print('Looking for devices...', flush=True)
|
||||
device_finder.run_forever()
|
||||
@@ -83,6 +83,8 @@ def setup(cli):
|
||||
git_upstream(cli.args.home)
|
||||
else:
|
||||
exit(1)
|
||||
else:
|
||||
cli.log.warning('Not cloning qmk_firmware due to user input or --no flag.')
|
||||
|
||||
# Offer to set `user.qmk_home` for them.
|
||||
if str(cli.args.home) != os.environ['QMK_HOME'] and yesno(home_prompt):
|
||||
@@ -91,14 +93,15 @@ def setup(cli):
|
||||
cli.write_config_option('user', 'qmk_home')
|
||||
|
||||
# Run `qmk doctor` to check the rest of the environment out
|
||||
color = '--color' if cli.config.general.color else '--no-color'
|
||||
unicode = '--unicode' if cli.config.general.unicode else '--no-unicode'
|
||||
doctor_command = [Path(sys.argv[0]).as_posix(), color, unicode, 'doctor']
|
||||
if cli.args.home.exists():
|
||||
color = '--color' if cli.config.general.color else '--no-color'
|
||||
unicode = '--unicode' if cli.config.general.unicode else '--no-unicode'
|
||||
doctor_command = [Path(sys.argv[0]).as_posix(), color, unicode, 'doctor']
|
||||
|
||||
if cli.args.no:
|
||||
doctor_command.append('--no')
|
||||
if cli.args.no:
|
||||
doctor_command.append('-n')
|
||||
|
||||
if cli.args.yes:
|
||||
doctor_command.append('--yes')
|
||||
if cli.args.yes:
|
||||
doctor_command.append('-y')
|
||||
|
||||
cli.run(doctor_command, capture_output=False)
|
||||
cli.run(doctor_command, stdin=None, capture_output=False)
|
||||
|
||||
+29
-2
@@ -1,2 +1,29 @@
|
||||
bumpversion
|
||||
twine
|
||||
bleach==4.0.0
|
||||
bump2version==1.0.1
|
||||
bumpversion==0.6.0
|
||||
certifi==2021.5.30
|
||||
cffi==1.14.6
|
||||
chardet==4.0.0
|
||||
colorama==0.4.4
|
||||
cryptography==3.4.7
|
||||
docutils==0.17.1
|
||||
idna==2.10
|
||||
importlib-metadata==4.6.3
|
||||
jeepney==0.7.1
|
||||
keyring==23.0.1
|
||||
packaging==21.0
|
||||
pkginfo==1.7.1
|
||||
pycparser==2.20
|
||||
Pygments==2.9.0
|
||||
pyparsing==2.4.7
|
||||
readme-renderer==29.0
|
||||
requests==2.26.0
|
||||
requests-toolbelt==0.9.1
|
||||
rfc3986==1.5.0
|
||||
SecretStorage==3.3.1
|
||||
six==1.16.0
|
||||
tqdm==4.62.0
|
||||
twine==3.4.2
|
||||
urllib3==1.26.6
|
||||
webencodings==0.5.1
|
||||
zipp==3.5.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 0.0.52
|
||||
current_version = 0.3.0
|
||||
commit = True
|
||||
tag = True
|
||||
tag_name = {new_version}
|
||||
|
||||
@@ -40,15 +40,30 @@ if __name__ == "__main__":
|
||||
],
|
||||
python_requires=metadata['requires-python'],
|
||||
install_requires=[
|
||||
"dotty-dict",
|
||||
"flake8",
|
||||
"hid",
|
||||
"hjson",
|
||||
"jsonschema>=3",
|
||||
"milc>=1.4.0",
|
||||
"nose2",
|
||||
"pygments",
|
||||
"pyusb",
|
||||
"yapf"
|
||||
"appdirs==1.4.4",
|
||||
"argcomplete==1.12.3",
|
||||
"attrs==21.2.0",
|
||||
"colorama==0.4.4",
|
||||
"coverage==5.5",
|
||||
"qmk-dotty-dict==1.3.0.post1",
|
||||
"flake8==3.9.2",
|
||||
"halo==0.0.31",
|
||||
"hid==1.0.4",
|
||||
"hjson==3.0.2",
|
||||
"jsonschema==3.2.0",
|
||||
"log-symbols==0.0.14",
|
||||
"mccabe==0.6.1",
|
||||
"milc==1.5.0",
|
||||
"nose2==0.10.0",
|
||||
"pycodestyle==2.7.0",
|
||||
"pyflakes==2.3.1",
|
||||
"Pygments==2.9.0",
|
||||
"pyrsistent==0.18.0",
|
||||
"pyusb==1.2.1",
|
||||
"setuptools>=45",
|
||||
"six==1.16.0",
|
||||
"spinners==0.0.24",
|
||||
"termcolor==1.1.0",
|
||||
"yapf==0.31.0"
|
||||
]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user