forked from mirror/qmk_firmware
Deploy qmk_udev during bootstrap, updated CLI bootstrap docs (#26147)
This commit is contained in:
@@ -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
|
||||
|
||||
126
util/install_udev.sh
Executable file
126
util/install_udev.sh
Executable file
@@ -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