1
0

Compare commits

...

18 Commits

Author SHA1 Message Date
Joel Challis
ed80e21858 Resolve 'using serial compilation of 2 LTRANS jobs' warning (#26113) 2026-03-30 15:25:29 +11:00
Joel Challis
9d24bc8a33 Fix userspace detection in Makefile (#26117) 2026-03-30 11:24:32 +08:00
QMK Bot
c7fde3d8cc [CI] Format code according to conventions (#26108)
Format code according to conventions
2026-03-27 03:56:53 +00:00
Sebastian Morgenstern
0fdb5df94d Added new pttbutton keyboard (#25952) 2026-03-27 03:15:28 +00:00
Joel Challis
bd500ae092 Detect PRs bypassing DD changes (#26094) 2026-03-20 06:27:49 +11:00
Peter Cock
fec01edaa4 Explain how to use STORE_SETUPS and PRINT_SETUPS (#26070)
* Explain how to use STORE_SETUPS and PRINT_SETUPS

I found the instructions a little terse, but managed.

This also adds a note about PRINT_SETUPS reporting random numbers if STORE_SETUPS hasn't been used.

* Remove line breaks

Existing docs seem to use a mix of hard line breaks at sentence
ends, or 80 chars-ish, versus no line breaks in paragraphs.

* Suggestion during review

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>

---------

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>
2026-03-19 11:40:49 +08:00
Peter Cock
7619e991cf QMK avoids raw line breaks within paragraphs in Markdown (#26080)
* QMK avoids raw line breaks within paragraphs in Markdown

Mentioned in passing during a few of my recent documentation pull requests, eg #26070.

* Suggestion during review

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>

---------

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>
2026-03-19 10:16:35 +08:00
Dasky
627ad33233 Fix pointing device driver typo (#26091)
fix typo
2026-03-18 18:50:33 -07:00
フィルターペーパー
2cbcd76ef0 License violations updates. (#26076) 2026-03-16 03:12:18 +00:00
Joel Challis
322e673bcb Remove use of andstor/file-existence-action (#26078) 2026-03-16 03:12:04 +00:00
dependabot[bot]
4be8880177 Bump geekyeggo/delete-artifact from 5 to 6 (#26077)
Bumps [geekyeggo/delete-artifact](https://github.com/geekyeggo/delete-artifact) from 5 to 6.
- [Release notes](https://github.com/geekyeggo/delete-artifact/releases)
- [Changelog](https://github.com/GeekyEggo/delete-artifact/blob/main/CHANGELOG.md)
- [Commits](https://github.com/geekyeggo/delete-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: geekyeggo/delete-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 02:23:53 +00:00
Jalal El Mansouri
709628dfb2 Honor BUILD_DIR in mass_compile.py (#25586) 2026-03-15 22:07:43 +11:00
Joel Challis
e5faeea94d Unit tests should not run when docs change (#26068) 2026-03-14 15:31:07 +00:00
vuvoth
7ec819eb22 docs: remove hardware link in Ferris Sweep README (#26069)
remove hardware link in Ferris Sweep readme

Corrected wording for Ferris sweep hardware description.
2026-03-14 07:30:14 -06:00
Brandon
7785e87029 Add nulldesignco/v1/nullpad (#26057) 2026-03-13 23:17:29 +00:00
Peter Cock
afb5335bf3 Switch missing default handler in OS detection docs (#26064)
Switch was missing default handler: control reaches end of non-void function

This warning gets treated as an error on Github Actions
2026-03-13 22:59:54 +00:00
Nick Brassel
9fd72b352b Extra bootstrap release package filtering. (#26039) 2026-03-12 21:05:24 +11:00
Joel Challis
7fe0c9c746 [CI] Build unit tests in parallel (#26058) 2026-03-11 16:43:02 +00:00
20 changed files with 319 additions and 28 deletions

View File

@@ -123,14 +123,7 @@ jobs:
SOURCE_DIR: .
DEST_DIR: ${{ inputs.branch || github.ref_name }}/latest
- name: Check if failure marker file exists
id: check_failure_marker
uses: andstor/file-existence-action@v3
with:
files: ./.failed
- name: Fail build if needed
if: steps.check_failure_marker.outputs.files_exists == 'true'
run: |
# Exit with failure if the compilation stage failed
exit 1
[ ! -e .failed ] || exit 1

View File

@@ -166,7 +166,7 @@ jobs:
truncate --size='<960K' $GITHUB_STEP_SUMMARY || true
- name: Delete temporary build artifacts
uses: geekyeggo/delete-artifact@v5
uses: geekyeggo/delete-artifact@v6
with:
name: |
firmware-${{ inputs.keymap }}-*

View File

@@ -8,6 +8,9 @@ on:
paths:
- 'data/constants/**'
- 'lib/python/**'
- 'quantum/rgblight/rgblight_breathe_table.h'
- 'quantum/keycodes.h'
- 'quantum/keymap_extras/**'
jobs:
regen:

View File

@@ -11,6 +11,7 @@ on:
pull_request:
paths:
- 'builddefs/**'
- '!builddefs/docsgen/**'
- 'quantum/**'
- 'platforms/**'
- 'tmk_core/**'
@@ -34,4 +35,4 @@ jobs:
run: pip3 install -r requirements-dev.txt
- name: Run tests
run: qmk test-c
run: qmk test-c -j $(nproc)

View File

@@ -38,14 +38,16 @@ $(info QMK Firmware $(QMK_VERSION))
endif
endif
# Try to determine userspace from qmk config, if set.
ifeq ($(QMK_USERSPACE),)
QMK_USERSPACE = $(shell qmk config -ro user.overlay_dir | cut -d= -f2 | sed -e 's@^None$$@@g')
endif
# Determine which qmk cli to use
QMK_BIN := qmk
# Try to determine userspace from qmk config, if set. Handle direct query on qmk_cli>=1.1.7
# falling back to legacy method of only supporting user.overlay_dir config
export override QMK_USERSPACE := $(shell \
$(QMK_BIN) env | grep -q QMK_USERSPACE \
&& $(QMK_BIN) env QMK_USERSPACE \
|| $(QMK_BIN) config -ro user.overlay_dir | cut -d= -f2 | sed -e 's@^None$$@@g')
# avoid 'Entering|Leaving directory' messages
MAKEFLAGS += --no-print-directory

View File

@@ -58,7 +58,7 @@ endif
#---------------- C Compiler Options ----------------
ifeq ($(strip $(LTO_ENABLE)), yes)
CDEFS += -flto
CDEFS += -flto=auto
CDEFS += -DLTO_ENABLE
endif

View File

@@ -14,6 +14,10 @@ Example:
This page covers my super cool feature. You can use this feature to make coffee, squeeze fresh oj, and have an egg mcmuffin and hashbrowns delivered from your local macca's by drone.
```
# Paragraphs
Do not use hard line breaks within the raw Markdown for each paragraph. These are optional in Markdown, and have no effect on the rendered output. This means each raw paragraph will be a single long line in your editor (best viewed with line wrapping enabled).
# Headings
Your page should generally have multiple "H1" headings. Only H1 and H2 headings will included in the Table of Contents, so plan them out appropriately. Excess width should be avoided in H1 and H2 headings to prevent the Table of Contents from getting too wide.

View File

@@ -136,12 +136,19 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
print_stored_setups();
}
return false;
default:
return true; // Process all other keycodes normally
}
}
```
Then please open an issue on Github with this information and tell what OS was not detected correctly and if you have any intermediate devices between keyboard and your computer.
Add both `STORE_SETUPS` and `PRINT_SETUPS` to your keyboard's keymap. Connect the keyboard to the device where the OS was not recognised, and press the `STORE_SETUPS` key to capture and store the fingerprint. On your development computer, run one of the suggested [console debugging tools](/faq_debug#debugging-tools), connect the keyboard, and press the `PRINT_SETUPS` key. The console should display multiple lines of data from the most recent `STORE_SETUPS` run.
Open an issue on GitHub and paste the console output into the issue. Also tell us which OS (including the version, if possible) was not detected correctly and whether any intermediate devices, such as a USB hub, were used between the keyboard and the target device.
::: tip
If `STORE_SETUPS` has not been used previously, `PRINT_SETUPS` will report whatever values are already present in the controller's EEPROM. These may appear as random numbers.
:::
## Credits

View File

@@ -33,11 +33,13 @@ If you own a board from one of the following vendors already, consider asking th
| iLovBee | Official 30-day copyright source code request issued Sep 11 2024 due to deception on PR, no response received. Ambiguity on PRs -- marketing says wireless, PR author said wired-only, then included wireless code anyway. Seemingly intentionally deceptive. |
| KiiBOOM | Seems to use the same OEM as Epomaker, same problems. |
| kprepublic | Makes no attempt to release source code, all boards in QMK are reverse-engineered, created, and supported by the community. New board variants magically appear without telling customers they're incompatible with existing QMK versions, in some cases bricking boards or requiring ISP flashing. |
| Lofree | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| Luminkey | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| Meletrix | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| mmd / Smartmmd / i-game.tech | Ambiguity on PRs -- marketing says wireless, PR author said wired-only, then included wireless code anyway. Seemingly intentionally deceptive. |
| MyKeyClub | Community-supported JRIS75, vendor was contacted by community members and refused to cooperate. |
| owlab | Selling wired based on QMK without sources, just `via.json` provided. Ambiguous as to whether or not wireless firmware is based on QMK, given that their configuration tool looks very similar to VIA. |
| PMO Lab | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| pressplayid | Selling wired and tri-mode boards based on QMK without sources, just `via.json` provided |
| qwertykeys | Selling wired and tri-mode boards based on QMK without sources, just `via.json` provided. |
| Redragon | Selling tri-mode boards based on QMK without sources, attempted upstreaming crippled firmware without wireless. |

View File

@@ -23,7 +23,7 @@
#include "gpio.h"
#include "pointing_device_internal.h"
const pointing_device_driver_t pmw3320_pointing_device_drivera = {
const pointing_device_driver_t pmw3320_pointing_device_driver = {
.init = pmw3320_init,
.get_report = pmw3320_get_report,
.set_cpi = pmw3320_set_cpi,

View File

@@ -8,8 +8,7 @@ A split 34 keys column staggered keyboard named and decorated after the rustlang
* Hardware Supported:
* Ferris 0.1 (With atmega32u4 chip. Comes in 4 variants: base, low, high and compact)
* Ferris 0.2 (With stm32f072 chip. Comes in 4 variants: bling, mini, high and compact)
* Ferris sweep (With pro-micro. Comes in a couple of PCB edge cuts shapes, but with identical pinout)
* Hardware Availability: [Cuddly Keyboards](https://cuddlykeyboards.com)
* Ferris sweep (With pro-micro. Comes in a couple of PCB edge cut shapes, but with an identical pinout)
Make examples for this keyboard (after setting up your build environment):

View File

@@ -0,0 +1,28 @@
{
"manufacturer": "Sebastian Morgenstern",
"keyboard_name": "pttbutton",
"maintainer": "morningstar1",
"bootloader": "stm32-dfu",
"diode_direction": "COL2ROW",
"features": {
"extrakey": true
},
"matrix_pins": {
"cols": ["B0"],
"rows": ["A0"]
},
"processor": "STM32F042",
"url": "https://github.com/morningstar1/pttbutton",
"usb": {
"device_version": "1.0.0",
"vid": "0x736D",
"pid": "0xAFFE"
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0}
]
}
}
}

View File

@@ -0,0 +1,10 @@
// Copyright 2026 SEbastian Morgenstern
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_F14
)
};

View File

@@ -0,0 +1,42 @@
/* Copyright 2026 Sebastian Morgenstern
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "quantum.h"
#include "hal.h"
void board_init(void) {
// Remap PA11->PA9 and PA12->PA10 for USB
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
}
void keyboard_pre_init_kb(void) {
// Immediately set the LED pin as an output and set it ON
gpio_set_pin_output(A15);
gpio_write_pin_high(A15);
keyboard_pre_init_user();
}
void keyboard_post_init_kb(void) {
// Blink the LED so we know everything is running OK
// Finish with LED OFF
gpio_write_pin_low(A15);
wait_ms(100);
gpio_write_pin_high(A15);
wait_ms(100);
gpio_write_pin_low(A15);
keyboard_post_init_user();
}

View File

@@ -0,0 +1,25 @@
# pttbutton
![pttbutton](https://github.com/morningstar1/PTTButton/blob/main/image/PTTButton.png?raw=true)
A simple one button keyboard with a USB Hub. Primary intention is to use it as a Push To Talk (PTT) button.
* Keyboard Maintainer: [Sebastian Morgenstern](https://github.com/morningstar1)
* Hardware Supported: [PTTButton V1.0](https://github.com/morningstar1/PTTButton)
* Hardware Availability: please contact me <sebastian.morgenstern@gmail.com>
Make example for this keyboard (after setting up your build environment):
make morningstar1/pttbutton:default
Flashing example for this keyboard:
make morningstar1/pttbutton:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in one way:
* **Physical reset button**: Briefly press the small button on the PCB

View File

@@ -0,0 +1,126 @@
{
"manufacturer": "nulldesignco",
"keyboard_name": "nullpad",
"maintainer": "quark-works",
"bootloader": "rp2040",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgb_matrix": true
},
"matrix_pins": {
"cols": ["GP27", "GP28", "GP8", "GP10"],
"rows": ["GP12", "GP25", "GP11", "GP26", "GP9", "GP21"]
},
"processor": "RP2040",
"rgb_matrix": {
"animations": {
"alphas_mods": true,
"band_pinwheel_sat": true,
"band_pinwheel_val": true,
"band_sat": true,
"band_spiral_sat": true,
"band_spiral_val": true,
"band_val": true,
"breathing": true,
"cycle_all": true,
"cycle_left_right": true,
"cycle_out_in": true,
"cycle_out_in_dual": true,
"cycle_pinwheel": true,
"cycle_spiral": true,
"cycle_up_down": true,
"digital_rain": true,
"dual_beacon": true,
"flower_blooming": true,
"gradient_left_right": true,
"gradient_up_down": true,
"hue_breathing": true,
"hue_pendulum": true,
"hue_wave": true,
"jellybean_raindrops": true,
"multisplash": true,
"pixel_flow": true,
"pixel_fractal": true,
"pixel_rain": true,
"rainbow_beacon": true,
"rainbow_moving_chevron": true,
"rainbow_pinwheels": true,
"raindrops": true,
"riverflow": true,
"solid_multisplash": true,
"solid_reactive": true,
"solid_reactive_cross": true,
"solid_reactive_multicross": true,
"solid_reactive_multinexus": true,
"solid_reactive_multiwide": true,
"solid_reactive_nexus": true,
"solid_reactive_simple": true,
"solid_reactive_wide": true,
"solid_splash": true,
"splash": true,
"starlight": true,
"starlight_dual_hue": true,
"starlight_dual_sat": true,
"typing_heatmap": true
},
"driver": "ws2812",
"layout": [
{"matrix": [5, 1], "x": 37, "y": 0, "flags": 4},
{"matrix": [3, 0], "x": 0, "y": 16, "flags": 4},
{"matrix": [3, 1], "x": 75, "y": 16, "flags": 4},
{"matrix": [3, 2], "x": 150, "y": 16, "flags": 4},
{"matrix": [4, 2], "x": 150, "y": 0, "flags": 4},
{"matrix": [4, 3], "x": 224, "y": 8, "flags": 4},
{"matrix": [2, 2], "x": 150, "y": 32, "flags": 4},
{"matrix": [2, 1], "x": 75, "y": 32, "flags": 4},
{"matrix": [2, 0], "x": 0, "y": 32, "flags": 4},
{"matrix": [1, 0], "x": 0, "y": 48, "flags": 4},
{"matrix": [1, 1], "x": 75, "y": 48, "flags": 4},
{"matrix": [1, 2], "x": 150, "y": 48, "flags": 4},
{"matrix": [2, 3], "x": 224, "y": 40, "flags": 4},
{"matrix": [0, 3], "x": 224, "y": 64, "flags": 4},
{"matrix": [0, 2], "x": 150, "y": 64, "flags": 4},
{"matrix": [0, 1], "x": 75, "y": 64, "flags": 4},
{"matrix": [0, 0], "x": 0, "y": 64, "flags": 4}
],
"sleep": true
},
"url": "https://nulldesignco.com/",
"usb": {
"device_version": "1.0.0",
"pid": "0x0011",
"vid": "0x6E6C"
},
"ws2812": {
"driver": "vendor",
"pin": "GP18"
},
"community_layouts": ["numpad_5x4"],
"layouts": {
"LAYOUT_numpad_5x4": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1},
{"matrix": [1, 1], "x": 1, "y": 1},
{"matrix": [1, 2], "x": 2, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2},
{"matrix": [2, 1], "x": 1, "y": 2},
{"matrix": [2, 2], "x": 2, "y": 2},
{"matrix": [2, 3], "x": 3, "y": 1, "h": 2},
{"matrix": [3, 0], "x": 0, "y": 3},
{"matrix": [3, 1], "x": 1, "y": 3},
{"matrix": [3, 2], "x": 2, "y": 3},
{"matrix": [5, 1], "x": 0, "y": 4, "w": 2},
{"matrix": [4, 2], "x": 2, "y": 4},
{"matrix": [4, 3], "x": 3, "y": 3, "h": 2}
]
}
}
}

View File

@@ -0,0 +1,22 @@
// Copyright 2025 quark-works
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_numpad_5x4(
KC_NUM, KC_PSLS, KC_PAST, KC_PMNS,
KC_P7, KC_P8, KC_P9,
KC_P4, KC_P5, KC_P6, KC_PPLS,
KC_P1, KC_P2, KC_P3,
KC_P0, KC_PDOT, KC_PENT
)
};
bool rgb_matrix_indicators_user(void) {
if (host_keyboard_led_state().num_lock) {
rgb_matrix_set_color(16, 255, 0, 0);
}
return false;
}

View File

@@ -0,0 +1,27 @@
# nullpad v1
![sp](https://i.imgur.com/069rfPe.png)
Numpad tray mount PCB with RGB per key.
* Keyboard Maintainer: [Quark](https://github.com/quark-works)
* Hardware Supported: PCB
* Hardware Availability: https://nulldesignco.com/
Make example for this keyboard (after setting up your build environment):
make nulldesignco/nullpad/v1:default
Flashing example for this keyboard:
make nulldesignco/nullpad/v1:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (top left key or NumLock) and plug in the keyboard
* **Physical boot button**: Hold the button labeled as "BOOT" on the back of the board while you connect the keyboard to your computer.
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -23,7 +23,7 @@ def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool,
os.environ.setdefault('SKIP_SCHEMA_VALIDATION', '1')
make_cmd = find_make()
builddir = Path(QMK_FIRMWARE) / '.build'
builddir = Path(env.get("BUILD_DIR")) if env.get("BUILD_DIR") is not None else Path(QMK_FIRMWARE) / '.build'
makefile = builddir / 'parallel_kb_builds.mk'
if dry_run:
@@ -71,8 +71,8 @@ print_failures: all_targets
command = target.compile_command(**env)
command[0] = '+@$(MAKE)' # Override the make so that we can use jobserver to handle parallelism
extra_args = '_'.join([f"{k}_{v}" for k, v in target.extra_args.items()])
build_log = f"{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
failed_log = f"{QMK_FIRMWARE}/.build/failed.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
build_log = f"{builddir}/build.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
failed_log = f"{builddir}/failed.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
target_suffix = ''
if len(extra_args) > 0:
build_log += f".{extra_args}"
@@ -101,9 +101,9 @@ all_targets: {target_filename}{target_suffix}_binary
# yapf: disable
f.write(
f"""\
@rm -rf "{QMK_FIRMWARE}/.build/{target_filename}.elf" 2>/dev/null || true
@rm -rf "{QMK_FIRMWARE}/.build/{target_filename}.map" 2>/dev/null || true
@rm -rf "{QMK_FIRMWARE}/.build/obj_{target_filename}" || true
@rm -rf "{builddir}/{target_filename}.elf" 2>/dev/null || true
@rm -rf "{builddir}/{target_filename}.map" 2>/dev/null || true
@rm -rf "{builddir}/obj_{target_filename}" || true
"""# noqa
)
# yapf: enable

View File

@@ -418,7 +418,7 @@ __EOT__
# Get the latest toolchain release from https://github.com/qmk/qmk_toolchains
local latest_toolchains_release=$(github_api_call repos/qmk/qmk_toolchains/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
# Download the specific release asset with a matching keyword
local toolchain_url=$(github_api_call repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep $(fn_os)$(fn_arch))
local toolchain_url=$(github_api_call repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_toolchains-.*$(fn_os)$(fn_arch)")
if [ -z "$toolchain_url" ]; then
echo "No toolchain found for this OS/Arch combination." >&2
exit 1
@@ -445,7 +445,7 @@ __EOT__
# Get the latest flashing tools release from https://github.com/qmk/qmk_flashutils
local latest_flashutils_release=$(github_api_call repos/qmk/qmk_flashutils/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
# Download the specific release asset with a matching keyword
local flashutils_url=$(github_api_call repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep "$osarchvariant")
local flashutils_url=$(github_api_call repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_flashutils-.*$osarchvariant")
if [ -z "$flashutils_url" ]; then
echo "No flashing tools found for this OS/Arch combination." >&2
exit 1