mirror of
https://github.com/jmwtsn/qmk_firmware.git
synced 2026-06-03 19:53:31 -03:00
Deploy qmk_udev during bootstrap, updated CLI bootstrap docs (#26147)
This commit is contained in:
+6
-35
@@ -4,47 +4,18 @@
|
||||
|
||||
The QMK CLI (command line interface) makes building and working with QMK keyboards easier. We have provided a number of commands to simplify and streamline tasks such as obtaining and compiling the QMK firmware, creating keymaps, and more.
|
||||
|
||||
### Requirements {#requirements}
|
||||
### Installation {#installation}
|
||||
|
||||
QMK requires Python 3.9 or greater. We try to keep the number of requirements small but you will also need to install the packages listed in [`requirements.txt`](https://github.com/qmk/qmk_firmware/blob/master/requirements.txt). These are installed automatically when you install the QMK CLI.
|
||||
|
||||
### Install Using Homebrew (macOS, some Linux) {#install-using-homebrew}
|
||||
|
||||
If you have installed [Homebrew](https://brew.sh) you can tap and install QMK:
|
||||
The recommended way to install the QMK CLI and all necessary dependencies (toolchains, flashing utilities, udev rules on Linux) is to use the bootstrapper script:
|
||||
|
||||
```
|
||||
brew install qmk/qmk/qmk
|
||||
export QMK_HOME='~/qmk_firmware' # Optional, set the location for `qmk_firmware`
|
||||
qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build environment
|
||||
curl -fsSL https://install.qmk.fm | sh
|
||||
```
|
||||
|
||||
### Install Using uv {#install-using-uv}
|
||||
|
||||
If you have installed [uv](https://docs.astral.sh/uv/), the QMK CLI can be installed and managed as a uv tool:
|
||||
For more options, run:
|
||||
|
||||
```
|
||||
uv tool install qmk
|
||||
export QMK_HOME='~/qmk_firmware' # Optional, set the location for `qmk_firmware`
|
||||
qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build environment
|
||||
curl -fsSL https://install.qmk.fm | sh -s -- --help
|
||||
```
|
||||
|
||||
This installation can be updated via `uv tool upgrade qmk`. See [Upgrading tools](https://docs.astral.sh/uv/guides/tools/#upgrading-tools) for more information.
|
||||
|
||||
### Install Using pip {#install-using-easy_install-or-pip}
|
||||
|
||||
If your system is not listed above you can install QMK manually. First ensure that you have Python 3.9 (or later) installed and have installed pip. Then install QMK with this command:
|
||||
|
||||
```
|
||||
python3 -m pip install qmk
|
||||
export QMK_HOME='~/qmk_firmware' # Optional, set the location for `qmk_firmware`
|
||||
qmk setup # This will clone `qmk/qmk_firmware` and optionally set up your build environment
|
||||
```
|
||||
|
||||
### Packaging For Other Operating Systems {#packaging-for-other-operating-systems}
|
||||
|
||||
We are looking for people to create and maintain a `qmk` package for more operating systems. If you would like to create a package for your OS please follow these guidelines:
|
||||
|
||||
* Follow best practices for your OS when they conflict with these guidelines
|
||||
* Document why in a comment when you do deviate
|
||||
* Install using a virtualenv
|
||||
* Instruct the user to set the environment variable `QMK_HOME` to have the firmware source checked out somewhere other than `~/qmk_firmware`.
|
||||
For detailed setup instructions, see [Setting Up Your QMK Environment](newbs_getting_started#set-up-your-environment).
|
||||
|
||||
@@ -12,11 +12,11 @@ If you intend to maintain keyboards and/or contribute to QMK, you can enable the
|
||||
|
||||
`qmk config user.developer=True`
|
||||
|
||||
This will allow you to see all available subcommands.
|
||||
**Note:** You will have to install additional requirements:
|
||||
```
|
||||
python3 -m pip install -r requirements-dev.txt
|
||||
```
|
||||
This will allow you to see all available subcommands.
|
||||
|
||||
::: tip
|
||||
If you installed QMK using the bootstrapper (`curl -fsSL https://install.qmk.fm | sh`), the development requirements are already installed.
|
||||
:::
|
||||
|
||||
# Subcommands
|
||||
|
||||
|
||||
+2
-5
@@ -19,13 +19,10 @@ Note that running `make` with `sudo` is generally ***not*** a good idea, and you
|
||||
|
||||
### Linux `udev` Rules {#linux-udev-rules}
|
||||
|
||||
On Linux, you'll need proper privileges to communicate with the bootloader device. You can either use `sudo` when flashing firmware (not recommended), or place [this file](https://github.com/qmk/qmk_firmware/tree/master/util/udev/50-qmk.rules) into `/etc/udev/rules.d/`.
|
||||
|
||||
Once added, run the following:
|
||||
On Linux, you'll need proper privileges to communicate with the bootloader device. You can either use `sudo` when flashing firmware (not recommended), or install the udev rules from the [qmk_udev](https://github.com/qmk/qmk_udev) repository by running:
|
||||
|
||||
```
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger
|
||||
util/install_udev.sh
|
||||
```
|
||||
|
||||
**Note:** With older versions of ModemManager (< 1.12), filtering only works when not in strict mode. The following commands can update that setting:
|
||||
|
||||
+2
-2
@@ -217,8 +217,8 @@ To generate this bootloader, use the `bootloader` target, eg. `make planck/rev4:
|
||||
|
||||
Compatible flashers:
|
||||
|
||||
* TBD
|
||||
* Currently, you need to either use the [Python script](https://github.com/qmk/lufa/tree/master/Bootloaders/HID/HostLoaderApp_python), or compile [`hid_bootloader_cli`](https://github.com/qmk/lufa/tree/master/Bootloaders/HID/HostLoaderApp), from the LUFA repo. Homebrew may (will) have support for this directly (via `brew install qmk/qmk/hid_bootloader_cli`).
|
||||
* [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases) (recommended GUI)
|
||||
* [hid_bootloader_cli](https://github.com/qmk/lufa/tree/master/Bootloaders/HID/HostLoaderApp) / `:qmk-hid` target in QMK (recommended command line)
|
||||
|
||||
Flashing sequence:
|
||||
|
||||
|
||||
@@ -1,62 +1,23 @@
|
||||
"""OS-specific functions for: Linux
|
||||
"""
|
||||
import platform
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from milc import cli
|
||||
|
||||
from qmk.constants import QMK_FIRMWARE, BOOTLOADER_VIDS_PIDS
|
||||
from qmk.constants import QMK_FIRMWARE
|
||||
from .check import CheckStatus, release_info
|
||||
|
||||
QMK_UDEV_INSTALL_SCRIPT = 'util/install_udev.sh'
|
||||
|
||||
|
||||
def _is_wsl():
|
||||
return 'microsoft' in platform.uname().release.lower()
|
||||
|
||||
|
||||
def _udev_rule(vid, pid=None, *args):
|
||||
""" Helper function that return udev rules
|
||||
"""
|
||||
rule = ""
|
||||
if pid:
|
||||
rule = 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="%s", ATTRS{idProduct}=="%s", TAG+="uaccess"' % (
|
||||
vid,
|
||||
pid,
|
||||
)
|
||||
else:
|
||||
rule = 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="%s", TAG+="uaccess"' % vid
|
||||
if args:
|
||||
rule = ', '.join([rule, *args])
|
||||
return rule
|
||||
|
||||
|
||||
def _generate_desired_rules(bootloader_vids_pids):
|
||||
rules = dict()
|
||||
for bl in bootloader_vids_pids.keys():
|
||||
rules[bl] = set()
|
||||
for vid_pid in bootloader_vids_pids[bl]:
|
||||
if bl == 'caterina' or bl == 'md-boot':
|
||||
rules[bl].add(_udev_rule(vid_pid[0], vid_pid[1], 'ENV{ID_MM_DEVICE_IGNORE}="1"'))
|
||||
else:
|
||||
rules[bl].add(_udev_rule(vid_pid[0], vid_pid[1]))
|
||||
return rules
|
||||
|
||||
|
||||
def _deprecated_udev_rule(vid, pid=None):
|
||||
""" Helper function that return udev rules
|
||||
|
||||
Note: these are no longer the recommended rules, this is just used to check for them
|
||||
"""
|
||||
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
|
||||
|
||||
|
||||
def check_udev_rules():
|
||||
"""Make sure the udev rules look good.
|
||||
"""
|
||||
rc = CheckStatus.OK
|
||||
udev_dirs = [
|
||||
Path("/usr/lib/udev/rules.d/"),
|
||||
Path("/usr/local/lib/udev/rules.d/"),
|
||||
@@ -64,24 +25,15 @@ def check_udev_rules():
|
||||
Path("/etc/udev/rules.d/"),
|
||||
]
|
||||
|
||||
desired_rules = _generate_desired_rules(BOOTLOADER_VIDS_PIDS)
|
||||
if not any(udev_dir.exists() for udev_dir in udev_dirs):
|
||||
cli.log.warning("{fg_yellow}Can't find udev rules directories, skipping udev rule checking...")
|
||||
cli.log.debug("Checked directories: %s", ', '.join(str(udev_dir) for udev_dir in udev_dirs))
|
||||
return CheckStatus.WARNING
|
||||
|
||||
# These rules are no longer recommended, only use them to check for their presence.
|
||||
deprecated_rules = {
|
||||
'atmel-dfu': {_deprecated_udev_rule("03eb", "2ff4"), _deprecated_udev_rule("03eb", "2ffb"), _deprecated_udev_rule("03eb", "2ff0")},
|
||||
'kiibohd': {_deprecated_udev_rule("1c11")},
|
||||
'stm32': {_deprecated_udev_rule("1eaf", "0003"), _deprecated_udev_rule("0483", "df11")},
|
||||
'bootloadhid': {_deprecated_udev_rule("16c0", "05df")},
|
||||
'caterina': {'ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"', 'ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"'},
|
||||
'tmk': {_deprecated_udev_rule("feed")}
|
||||
}
|
||||
|
||||
if any(udev_dir.exists() for udev_dir in udev_dirs):
|
||||
udev_rules = [rule_file for udev_dir in udev_dirs for rule_file in udev_dir.glob('*.rules')]
|
||||
current_rules = set()
|
||||
|
||||
# Collect all rules from the config files
|
||||
for rule_file in udev_rules:
|
||||
# Collect all non-comment lines from QMK-related rules files
|
||||
current_rules = set()
|
||||
for udev_dir in udev_dirs:
|
||||
for rule_file in udev_dir.glob('*qmk*'):
|
||||
try:
|
||||
for line in rule_file.read_text(encoding='utf-8').split('\n'):
|
||||
line = line.strip()
|
||||
@@ -90,45 +42,17 @@ def check_udev_rules():
|
||||
except (PermissionError, FileNotFoundError):
|
||||
cli.log.debug("Failed to read: %s", rule_file)
|
||||
|
||||
# Check if the desired rules are among the currently present rules
|
||||
for bootloader, rules in desired_rules.items():
|
||||
if not rules.issubset(current_rules):
|
||||
deprecated_rule = deprecated_rules.get(bootloader)
|
||||
if deprecated_rule and deprecated_rule.issubset(current_rules):
|
||||
cli.log.warning("{fg_yellow}Found old, deprecated udev rules for '%s' boards. The new rules on https://docs.qmk.fm/#/faq_build?id=linux-udev-rules offer better security with the same functionality.", bootloader)
|
||||
else:
|
||||
# For caterina, check if ModemManager is running
|
||||
if bootloader == "caterina" and check_modem_manager():
|
||||
cli.log.warning("{fg_yellow}Detected ModemManager without the necessary udev rules. Please either disable it or set the appropriate udev rules if you are using a Pro Micro.")
|
||||
if not current_rules:
|
||||
cli.log.warning("{fg_yellow}Missing udev rules for QMK boards. Please run '%s' to install the rules", QMK_UDEV_INSTALL_SCRIPT)
|
||||
return CheckStatus.WARNING
|
||||
|
||||
rc = CheckStatus.WARNING
|
||||
cli.log.warning("{fg_yellow}Missing or outdated udev rules for '%s' boards. Run 'sudo cp %s/util/udev/50-qmk.rules /etc/udev/rules.d/'.", bootloader, QMK_FIRMWARE)
|
||||
# Check for the qmk_udev ID_QMK marker
|
||||
if any('ID_QMK' in rule for rule in current_rules):
|
||||
return CheckStatus.OK
|
||||
|
||||
else:
|
||||
cli.log.warning("{fg_yellow}Can't find udev rules, skipping udev rule checking...")
|
||||
cli.log.debug("Checked directories: %s", ', '.join(str(udev_dir) for udev_dir in udev_dirs))
|
||||
|
||||
return rc
|
||||
|
||||
|
||||
def check_systemd():
|
||||
"""Check if it's a systemd system
|
||||
"""
|
||||
return bool(shutil.which("systemctl"))
|
||||
|
||||
|
||||
def check_modem_manager():
|
||||
"""Returns True if ModemManager is running.
|
||||
|
||||
"""
|
||||
if check_systemd():
|
||||
mm_check = cli.run(["systemctl", "--quiet", "is-active", "ModemManager.service"], timeout=10)
|
||||
if mm_check.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
"""(TODO): Add check for non-systemd systems
|
||||
"""
|
||||
return False
|
||||
# Legacy rules found (TAG+="uaccess" without ID_QMK)
|
||||
cli.log.warning("{fg_yellow}Found legacy udev rules. Please run '%s' to install the latest rules", QMK_UDEV_INSTALL_SCRIPT)
|
||||
return CheckStatus.WARNING
|
||||
|
||||
|
||||
def os_test_linux():
|
||||
|
||||
+41
-19
@@ -357,7 +357,7 @@ __EOT__
|
||||
|
||||
install_uv() {
|
||||
# Install `uv` (or update as necessary)
|
||||
download_url https://astral.sh/uv/install.sh - | TMPDIR="$(windows_ish_path "${TMPDIR:-}")" UV_INSTALL_DIR="$(windows_ish_path "${UV_INSTALL_DIR:-}")" sh
|
||||
download_url https://astral.sh/uv/install.sh - | TMPDIR="$(posix_ish_path "${TMPDIR:-}")" UV_INSTALL_DIR="$(windows_ish_path "${UV_INSTALL_DIR:-}")" sh
|
||||
}
|
||||
|
||||
setup_paths() {
|
||||
@@ -464,27 +464,49 @@ __EOT__
|
||||
}
|
||||
|
||||
install_linux_udev_rules() {
|
||||
# Download the udev rules to the toolchains location
|
||||
echo "Downloading QMK udev rules file..." >&2
|
||||
local qmk_rules_target_file="$QMK_DISTRIB_DIR/50-qmk.rules"
|
||||
download_url "https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/util/udev/50-qmk.rules" "$qmk_rules_target_file"
|
||||
# Get the latest qmk_udev release
|
||||
local latest_udev_release=$(github_api_call repos/qmk/qmk_udev/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||
if [ -z "$latest_udev_release" ]; then
|
||||
echo "Could not determine latest qmk_udev release." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Using qmk_udev release: $latest_udev_release" >&2
|
||||
|
||||
# Install the udev rules -- path list is aligned with qmk doctor's linux.py
|
||||
local udev_rules_paths="
|
||||
/usr/lib/udev/rules.d
|
||||
/usr/local/lib/udev/rules.d
|
||||
/run/udev/rules.d
|
||||
/etc/udev/rules.d
|
||||
"
|
||||
for udev_rules_dir in $udev_rules_paths; do
|
||||
if [ -d "$udev_rules_dir" ]; then
|
||||
echo "Installing udev rules to $udev_rules_dir/50-qmk.rules ..." >&2
|
||||
$(nsudo) mv "$qmk_rules_target_file" "$udev_rules_dir"
|
||||
$(nsudo) chown 0:0 "$udev_rules_dir/50-qmk.rules"
|
||||
$(nsudo) chmod 644 "$udev_rules_dir/50-qmk.rules"
|
||||
break
|
||||
# Download the udev rules file
|
||||
local qmk_rules_file="$QMK_DISTRIB_DIR/50-qmk.rules"
|
||||
local release_base="https://github.com/qmk/qmk_udev/releases/download/$latest_udev_release"
|
||||
download_url "$release_base/50-qmk.rules" "$qmk_rules_file"
|
||||
|
||||
# Download the architecture-appropriate qmk_id binary
|
||||
local arch="$(fn_arch)"
|
||||
local qmk_id_file="$QMK_DISTRIB_DIR/qmk_id"
|
||||
download_url "$release_base/qmk_id-linux${arch}" "$qmk_id_file"
|
||||
|
||||
# Remove existing QMK udev rules and qmk_id helpers from all standard locations
|
||||
echo "Removing existing QMK udev rules and helpers..." >&2
|
||||
for dir in /etc/udev/rules.d /run/udev/rules.d /usr/lib/udev/rules.d /usr/local/lib/udev/rules.d /lib/udev/rules.d; do
|
||||
if [ -d "$dir" ]; then
|
||||
for f in "$dir"/*-qmk.rules; do
|
||||
[ -e "$f" ] && echo "Removing $f" >&2 && $(nsudo) rm -f "$f"
|
||||
done
|
||||
fi
|
||||
done
|
||||
for dir in /usr/lib/udev /usr/local/lib/udev /lib/udev; do
|
||||
[ -e "$dir/qmk_id" ] && echo "Removing $dir/qmk_id" >&2 && $(nsudo) rm -f "$dir/qmk_id"
|
||||
done
|
||||
|
||||
# Install qmk_id binary
|
||||
echo "Installing /usr/lib/udev/qmk_id ..." >&2
|
||||
$(nsudo) install -d -m 0755 /usr/lib/udev
|
||||
$(nsudo) install -m 0755 "$qmk_id_file" /usr/lib/udev/qmk_id
|
||||
|
||||
# Install udev rules
|
||||
echo "Installing /etc/udev/rules.d/50-qmk.rules ..." >&2
|
||||
$(nsudo) install -d -m 0755 /etc/udev/rules.d
|
||||
$(nsudo) install -m 0644 "$qmk_rules_file" /etc/udev/rules.d/50-qmk.rules
|
||||
|
||||
# Clean up downloaded files
|
||||
rm -f "$qmk_rules_file" "$qmk_id_file" || true
|
||||
|
||||
# Reload udev rules
|
||||
if command -v udevadm >/dev/null 2>&1; then
|
||||
|
||||
Executable
+126
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env sh
|
||||
# Copyright 2025 Nick Brassel (@tzarc)
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
################################################################################
|
||||
# Installs the latest QMK udev rules and qmk_id helper from
|
||||
# https://github.com/qmk/qmk_udev
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
|
||||
nsudo() {
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
if [ -n "$(command -v sudo 2>/dev/null || true)" ]; then
|
||||
echo "sudo"
|
||||
elif [ -n "$(command -v doas 2>/dev/null || true)" ]; then
|
||||
echo "doas"
|
||||
else
|
||||
echo "Please install 'sudo' or 'doas' to continue." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
true
|
||||
}
|
||||
|
||||
download_url() {
|
||||
local url=$1
|
||||
local filename=${2:-$(basename "$url")}
|
||||
if [ -n "$(command -v curl 2>/dev/null || true)" ]; then
|
||||
curl -LSf -o "$filename" "$url"
|
||||
elif [ -n "$(command -v wget 2>/dev/null || true)" ]; then
|
||||
wget "-O$filename" "$url"
|
||||
else
|
||||
echo "Please install 'curl' or 'wget' to continue." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
github_api_call() {
|
||||
local url="$1"
|
||||
local token="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
|
||||
if [ -n "${token:-}" ]; then
|
||||
if [ -n "$(command -v curl 2>/dev/null || true)" ]; then
|
||||
curl -fsSL -H "Authorization: token $token" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/$url"
|
||||
elif [ -n "$(command -v wget 2>/dev/null || true)" ]; then
|
||||
wget -q --header="Authorization: token $token" --header="Accept: application/vnd.github.v3+json" "https://api.github.com/$url" -O -
|
||||
fi
|
||||
else
|
||||
download_url "https://api.github.com/$url" -
|
||||
fi
|
||||
}
|
||||
|
||||
fn_arch() {
|
||||
local arch_name=$(uname -m | tr 'A-Z' 'a-z')
|
||||
case "$arch_name" in
|
||||
*arm64* | *aarch64*)
|
||||
echo ARM64
|
||||
;;
|
||||
*riscv64*)
|
||||
echo RV64
|
||||
;;
|
||||
*x86_64* | *x64*)
|
||||
echo X64
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: $arch_name" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ "$(uname -s 2>/dev/null || true)" != "Linux" ]; then
|
||||
echo "This script is only intended for Linux." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a temporary directory for downloads
|
||||
tmpdir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
# Get the latest qmk_udev release
|
||||
echo "Fetching latest qmk_udev release..." >&2
|
||||
latest_release=$(github_api_call repos/qmk/qmk_udev/releases/latest | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||
if [ -z "$latest_release" ]; then
|
||||
echo "Could not determine latest qmk_udev release." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Using qmk_udev release: $latest_release" >&2
|
||||
|
||||
release_base="https://github.com/qmk/qmk_udev/releases/download/$latest_release"
|
||||
|
||||
# Download the udev rules file and architecture-appropriate qmk_id binary
|
||||
download_url "$release_base/50-qmk.rules" "$tmpdir/50-qmk.rules"
|
||||
download_url "$release_base/qmk_id-linux$(fn_arch)" "$tmpdir/qmk_id"
|
||||
|
||||
# Remove existing QMK udev rules and qmk_id helpers from all standard locations
|
||||
echo "Removing existing QMK udev rules and helpers..." >&2
|
||||
for dir in /etc/udev/rules.d /run/udev/rules.d /usr/lib/udev/rules.d /usr/local/lib/udev/rules.d /lib/udev/rules.d; do
|
||||
if [ -d "$dir" ]; then
|
||||
for f in "$dir"/*-qmk.rules; do
|
||||
[ -e "$f" ] && echo "Removing $f" >&2 && $(nsudo) rm -f "$f"
|
||||
done
|
||||
fi
|
||||
done
|
||||
for dir in /usr/lib/udev /usr/local/lib/udev /lib/udev; do
|
||||
[ -e "$dir/qmk_id" ] && echo "Removing $dir/qmk_id" >&2 && $(nsudo) rm -f "$dir/qmk_id"
|
||||
done
|
||||
|
||||
# Install qmk_id binary and udev rules
|
||||
echo "Installing /usr/lib/udev/qmk_id ..." >&2
|
||||
$(nsudo) install -d -m 0755 /usr/lib/udev
|
||||
$(nsudo) install -m 0755 "$tmpdir/qmk_id" /usr/lib/udev/qmk_id
|
||||
echo "Installing /etc/udev/rules.d/50-qmk.rules ..." >&2
|
||||
$(nsudo) install -d -m 0755 /etc/udev/rules.d
|
||||
$(nsudo) install -m 0644 "$tmpdir/50-qmk.rules" /etc/udev/rules.d/50-qmk.rules
|
||||
|
||||
# Reload udev rules
|
||||
if command -v udevadm >/dev/null 2>&1; then
|
||||
echo "Reloading udev rules..." >&2
|
||||
$(nsudo) udevadm control --reload-rules || true
|
||||
$(nsudo) udevadm trigger || true
|
||||
else
|
||||
echo "udevadm not found, skipping udev rules reload." >&2
|
||||
fi
|
||||
|
||||
echo "Done." >&2
|
||||
@@ -1,89 +0,0 @@
|
||||
# Atmel DFU
|
||||
### ATmega16U2
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2fef", TAG+="uaccess"
|
||||
### ATmega32U2
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff0", TAG+="uaccess"
|
||||
### ATmega16U4
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff3", TAG+="uaccess"
|
||||
### ATmega32U4
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", TAG+="uaccess"
|
||||
### AT90USB64
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff9", TAG+="uaccess"
|
||||
### AT90USB162
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffa", TAG+="uaccess"
|
||||
### AT90USB128
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffb", TAG+="uaccess"
|
||||
|
||||
# Input Club
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c11", ATTRS{idProduct}=="b007", TAG+="uaccess"
|
||||
|
||||
# STM32duino
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1eaf", ATTRS{idProduct}=="0003", TAG+="uaccess"
|
||||
# STM32 DFU
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", TAG+="uaccess"
|
||||
|
||||
# BootloadHID
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", TAG+="uaccess"
|
||||
|
||||
# USBAspLoader
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05dc", TAG+="uaccess"
|
||||
|
||||
# USBtinyISP
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1782", ATTRS{idProduct}=="0c9f", TAG+="uaccess"
|
||||
|
||||
# ModemManager should ignore the following devices
|
||||
# Atmel SAM-BA (Massdrop)
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="6124", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
|
||||
# Caterina (Pro Micro)
|
||||
## pid.codes shared PID
|
||||
### Keyboardio Atreus 2 Bootloader
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="2302", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
## Spark Fun Electronics
|
||||
### Pro Micro 3V3/8MHz
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9203", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
### Pro Micro 5V/16MHz
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9205", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
### LilyPad 3V3/8MHz (and some Pro Micro clones)
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9207", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
## Pololu Electronics
|
||||
### A-Star 32U4
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1ffb", ATTRS{idProduct}=="0101", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
## Arduino SA
|
||||
### Leonardo
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0036", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
### Micro
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0037", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
## Adafruit Industries LLC
|
||||
### Feather 32U4
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="000c", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
### ItsyBitsy 32U4 3V3/8MHz
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="000d", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
### ItsyBitsy 32U4 5V/16MHz
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="000e", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
## dog hunter AG
|
||||
### Leonardo
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0036", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
### Micro
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0037", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
|
||||
# hid_listen
|
||||
KERNEL=="hidraw*", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl"
|
||||
|
||||
# hid bootloaders
|
||||
## QMK HID
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2067", TAG+="uaccess"
|
||||
## PJRC's HalfKay
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0478", TAG+="uaccess"
|
||||
|
||||
# APM32 DFU
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="314b", ATTRS{idProduct}=="0106", TAG+="uaccess"
|
||||
|
||||
# GD32V DFU
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="28e9", ATTRS{idProduct}=="0189", TAG+="uaccess"
|
||||
|
||||
# WB32 DFU
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="342d", ATTRS{idProduct}=="dfa0", TAG+="uaccess"
|
||||
|
||||
# AT32 DFU
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2e3c", ATTRS{idProduct}=="df11", TAG+="uaccess"
|
||||
Reference in New Issue
Block a user