diff options
-rw-r--r-- | docs/faq_build.md | 135 | ||||
-rw-r--r-- | docs/faq_debug.md | 14 | ||||
-rwxr-xr-x | lib/python/qmk/cli/doctor.py | 57 |
3 files changed, 98 insertions, 108 deletions
diff --git a/docs/faq_build.md b/docs/faq_build.md index e2d0f9b27..131844a2b 100644 --- a/docs/faq_build.md +++ b/docs/faq_build.md | |||
@@ -13,63 +13,74 @@ An example of using `sudo`, when your controller is ATMega32u4: | |||
13 | 13 | ||
14 | or just: | 14 | or just: |
15 | 15 | ||
16 | $ sudo make <keyboard>:<keymap>:dfu | 16 | $ sudo make <keyboard>:<keymap>:flash |
17 | 17 | ||
18 | Note that running `make` with `sudo` is generally ***not*** a good idea, and you should use one of the former methods, if possible. | 18 | Note that running `make` with `sudo` is generally ***not*** a good idea, and you should use one of the former methods, if possible. |
19 | 19 | ||
20 | ### Linux `udev` Rules | 20 | ### Linux `udev` Rules |
21 | On Linux, you'll need proper privileges to access the MCU. You can either use | ||
22 | `sudo` when flashing firmware, or place these files in `/etc/udev/rules.d/`. Once added run the following: | ||
23 | ```console | ||
24 | sudo udevadm control --reload-rules | ||
25 | sudo udevadm trigger | ||
26 | ``` | ||
27 | 21 | ||
28 | **/etc/udev/rules.d/50-atmel-dfu.rules:** | 22 | On Linux, you'll need proper privileges to communicate with the bootloader device. You can either use `sudo` when flashing firmware, or place this file in `/etc/udev/rules.d/`: |
29 | ``` | 23 | |
30 | # Atmel ATMega32U4 | 24 | **/etc/udev/rules.d/50-qmk.rules:** |
31 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", TAG+="uaccess", RUN{builtin}+="uaccess" | ||
32 | # Atmel USBKEY AT90USB1287 | ||
33 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffb", TAG+="uaccess", RUN{builtin}+="uaccess" | ||
34 | # Atmel ATMega32U2 | ||
35 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff0", TAG+="uaccess", RUN{builtin}+="uaccess" | ||
36 | ``` | 25 | ``` |
26 | # Atmel DFU | ||
27 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03EB", ATTRS{idProduct}=="2FEF", TAG+="uaccess", RUN{builtin}+="uaccess" # ATmega16U2 | ||
28 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03EB", ATTRS{idProduct}=="2FF0", TAG+="uaccess", RUN{builtin}+="uaccess" # ATmega32U2 | ||
29 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03EB", ATTRS{idProduct}=="2FF3", TAG+="uaccess", RUN{builtin}+="uaccess" # ATmega16U4 | ||
30 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03EB", ATTRS{idProduct}=="2FF4", TAG+="uaccess", RUN{builtin}+="uaccess" # ATmega32U4 | ||
31 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03EB", ATTRS{idProduct}=="2FF9", TAG+="uaccess", RUN{builtin}+="uaccess" # AT90USB64 | ||
32 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03EB", ATTRS{idProduct}=="2FFB", TAG+="uaccess", RUN{builtin}+="uaccess" # AT90USB128 | ||
37 | 33 | ||
38 | **/etc/udev/rules.d/54-input-club-keyboard.rules:** | 34 | # Input Club |
35 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1C11", ATTRS{idProduct}=="B007", TAG+="uaccess", RUN{builtin}+="uaccess" | ||
39 | 36 | ||
40 | ``` | 37 | # STM32duino |
41 | # Input Club keyboard bootloader | 38 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1EAF", ATTRS{idProduct}=="0003", TAG+="uaccess", RUN{builtin}+="uaccess" |
42 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1c11", ATTRS{idProduct}=="b007", TAG+="uaccess", RUN{builtin}+="uaccess" | 39 | # STM32 DFU |
43 | ``` | 40 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="DF11", TAG+="uaccess", RUN{builtin}+="uaccess" |
44 | 41 | ||
45 | **/etc/udev/rules.d/55-caterina.rules:** | 42 | # BootloadHID |
46 | ``` | 43 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="16C0", ATTRS{idProduct}=="05DF", TAG+="uaccess", RUN{builtin}+="uaccess" |
47 | # ModemManager should ignore the following devices | ||
48 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0036", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" | ||
49 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0036", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" | ||
50 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9205", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" | ||
51 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b4f", ATTRS{idProduct}=="9203", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" | ||
52 | ``` | ||
53 | 44 | ||
54 | **Note:** With older (before 1.12) ModemManager, filtering only works when not in strict mode, the following commands can update that settings: | 45 | # USBAspLoader |
55 | ```console | 46 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="16C0", ATTRS{idProduct}=="05DC", TAG+="uaccess", RUN{builtin}+="uaccess" |
56 | printf '[Service]\nExecStart=\nExecStart=/usr/sbin/ModemManager --filter-policy=default' | sudo tee /etc/systemd/system/ModemManager.service.d/policy.conf | 47 | |
57 | sudo systemctl daemon-reload | 48 | # ModemManager should ignore the following devices |
58 | sudo systemctl restart ModemManager | 49 | # Atmel SAM-BA (Massdrop) |
59 | ``` | 50 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="03EB", ATTRS{idProduct}=="6124", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" |
51 | |||
52 | # Caterina (Pro Micro) | ||
53 | # Spark Fun Electronics | ||
54 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1B4F", ATTRS{idProduct}=="9203", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # Pro Micro 3V3/8MHz | ||
55 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1B4F", ATTRS{idProduct}=="9205", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # Pro Micro 5V/16MHz | ||
56 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1B4F", ATTRS{idProduct}=="9207", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # LilyPad 3V3/8MHz (and some Pro Micro clones) | ||
57 | # Pololu Electronics | ||
58 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1FFB", ATTRS{idProduct}=="0101", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # A-Star 32U4 | ||
59 | # Arduino SA | ||
60 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0036", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # Leonardo | ||
61 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0037", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # Micro | ||
62 | # Adafruit Industries LLC | ||
63 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="239A", ATTRS{idProduct}=="000C", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # Feather 32U4 | ||
64 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="239A", ATTRS{idProduct}=="000D", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # ItsyBitsy 32U4 3V3/8MHz | ||
65 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="239A", ATTRS{idProduct}=="000E", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # ItsyBitsy 32U4 5V/16MHz | ||
66 | # dog hunter AG | ||
67 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2A03", ATTRS{idProduct}=="0036", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # Leonardo | ||
68 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2A03", ATTRS{idProduct}=="0037", TAG+="uaccess", RUN{builtin}+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" # Micro | ||
69 | ``` | ||
70 | |||
71 | Once added, run the following: | ||
60 | 72 | ||
61 | **/etc/udev/rules.d/56-dfu-util.rules:** | ||
62 | ``` | 73 | ``` |
63 | # stm32duino | 74 | sudo udevadm control --reload-rules |
64 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1eaf", ATTRS{idProduct}=="0003", TAG+="uaccess", RUN{builtin}+="uaccess" | 75 | sudo udevadm trigger |
65 | # Generic stm32 | ||
66 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", TAG+="uaccess", RUN{builtin}+="uaccess" | ||
67 | ``` | 76 | ``` |
68 | 77 | ||
69 | **/etc/udev/rules.d/57-bootloadhid.rules:** | 78 | **Note:** With older versions of ModemManager (< 1.12), filtering only works when not in strict mode. The following commands can update that setting: |
79 | |||
70 | ``` | 80 | ``` |
71 | # bootloadHID | 81 | printf '[Service]\nExecStart=\nExecStart=/usr/sbin/ModemManager --filter-policy=default' | sudo tee /etc/systemd/system/ModemManager.service.d/policy.conf |
72 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", TAG+="uaccess", RUN{builtin}+="uaccess" | 82 | sudo systemctl daemon-reload |
83 | sudo systemctl restart ModemManager | ||
73 | ``` | 84 | ``` |
74 | 85 | ||
75 | ### Serial device is not detected in bootloader mode on Linux | 86 | ### Serial device is not detected in bootloader mode on Linux |
@@ -96,46 +107,6 @@ You can buy a really unique VID:PID here. I don't think you need this for person | |||
96 | - http://www.obdev.at/products/vusb/license.html | 107 | - http://www.obdev.at/products/vusb/license.html |
97 | - http://www.mcselec.com/index.php?page=shop.product_details&flypage=shop.flypage&product_id=92&option=com_phpshop&Itemid=1 | 108 | - http://www.mcselec.com/index.php?page=shop.product_details&flypage=shop.flypage&product_id=92&option=com_phpshop&Itemid=1 |
98 | 109 | ||
99 | ## BOOTLOADER_SIZE for AVR | ||
100 | Note that Teensy2.0++ bootloader size is 2048byte. Some Makefiles may have wrong comment. | ||
101 | |||
102 | ``` | ||
103 | # Boot Section Size in *bytes* | ||
104 | # Teensy halfKay 512 | ||
105 | # Teensy++ halfKay 2048 | ||
106 | # Atmel DFU loader 4096 (TMK Alt Controller) | ||
107 | # LUFA bootloader 4096 | ||
108 | # USBaspLoader 2048 | ||
109 | OPT_DEFS += -DBOOTLOADER_SIZE=2048 | ||
110 | ``` | ||
111 | |||
112 | ## `avr-gcc: internal compiler error: Abort trap: 6 (program cc1)` on MacOS | ||
113 | |||
114 | This is an issue with updating on brew, causing symlinks that avr-gcc depend on getting mangled. | ||
115 | |||
116 | The solution is to remove and reinstall all affected modules. | ||
117 | |||
118 | ``` | ||
119 | brew rm avr-gcc avr-gcc@8 dfu-programmer dfu-util gcc-arm-none-eabi arm-gcc-bin@8 avrdude qmk | ||
120 | brew install qmk/qmk/qmk | ||
121 | brew link --force avr-gcc@8 | ||
122 | brew link --force arm-gcc-bin@8 | ||
123 | ``` | ||
124 | |||
125 | ### `avr-gcc` and LUFA | ||
126 | |||
127 | If you updated your `avr-gcc` and you see errors involving LUFA, for example: | ||
128 | |||
129 | `lib/lufa/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h:380:5: error: 'const' attribute on function returning 'void'` | ||
130 | |||
131 | For now, you need to rollback `avr-gcc` to 8 in Homebrew. | ||
132 | |||
133 | ``` | ||
134 | brew uninstall --force avr-gcc | ||
135 | brew install avr-gcc@8 | ||
136 | brew link --force avr-gcc@8 | ||
137 | ``` | ||
138 | |||
139 | ### I just flashed my keyboard and it does nothing/keypresses don't register - it's also ARM (rev6 planck, clueboard 60, hs60v2, etc...) (Feb 2019) | 110 | ### I just flashed my keyboard and it does nothing/keypresses don't register - it's also ARM (rev6 planck, clueboard 60, hs60v2, etc...) (Feb 2019) |
140 | Due to how EEPROM works on ARM based chips, saved settings may no longer be valid. This affects the default layers, and *may*, under certain circumstances we are still figuring out, make the keyboard unusable. Resetting the EEPROM will correct this. | 111 | Due to how EEPROM works on ARM based chips, saved settings may no longer be valid. This affects the default layers, and *may*, under certain circumstances we are still figuring out, make the keyboard unusable. Resetting the EEPROM will correct this. |
141 | 112 | ||
diff --git a/docs/faq_debug.md b/docs/faq_debug.md index 08c84fe4f..7d5473678 100644 --- a/docs/faq_debug.md +++ b/docs/faq_debug.md | |||
@@ -31,20 +31,6 @@ Check: | |||
31 | - try using 'print' function instead of debug print. See **common/print.h**. | 31 | - try using 'print' function instead of debug print. See **common/print.h**. |
32 | - disconnect other devices with console function. See [Issue #97](https://github.com/tmk/tmk_keyboard/issues/97). | 32 | - disconnect other devices with console function. See [Issue #97](https://github.com/tmk/tmk_keyboard/issues/97). |
33 | 33 | ||
34 | ## Linux or UNIX Like System Requires Super User Privilege | ||
35 | Just use 'sudo' to execute *hid_listen* with privilege. | ||
36 | ``` | ||
37 | $ sudo hid_listen | ||
38 | ``` | ||
39 | |||
40 | Or add an *udev rule* for TMK devices with placing a file in rules directory. The directory may vary on each system. | ||
41 | |||
42 | File: /etc/udev/rules.d/52-tmk-keyboard.rules(in case of Ubuntu) | ||
43 | ``` | ||
44 | # tmk keyboard products https://github.com/tmk/tmk_keyboard | ||
45 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="feed", MODE:="0666" | ||
46 | ``` | ||
47 | |||
48 | *** | 34 | *** |
49 | 35 | ||
50 | # Miscellaneous | 36 | # Miscellaneous |
diff --git a/lib/python/qmk/cli/doctor.py b/lib/python/qmk/cli/doctor.py index 920615396..bad864f72 100755 --- a/lib/python/qmk/cli/doctor.py +++ b/lib/python/qmk/cli/doctor.py | |||
@@ -150,25 +150,58 @@ def check_udev_rules(): | |||
150 | ok = True | 150 | ok = True |
151 | udev_dir = Path("/etc/udev/rules.d/") | 151 | udev_dir = Path("/etc/udev/rules.d/") |
152 | desired_rules = { | 152 | desired_rules = { |
153 | 'dfu': {_udev_rule("03eb", "2ff4"), _udev_rule("03eb", "2ffb"), _udev_rule("03eb", "2ff0")}, | 153 | 'atmel-dfu': { |
154 | 'input_club': {_udev_rule("1c11", "b007")}, | 154 | _udev_rule("03EB", "2FEF"), # ATmega16U2 |
155 | 'stm32': {_udev_rule("1eaf", "0003"), _udev_rule("0483", "df11")}, | 155 | _udev_rule("03EB", "2FF0"), # ATmega32U2 |
156 | 'bootloadhid': {_udev_rule("16c0", "05df")}, | 156 | _udev_rule("03EB", "2FF3"), # ATmega16U4 |
157 | _udev_rule("03EB", "2FF4"), # ATmega32U4 | ||
158 | _udev_rule("03EB", "2FF9"), # AT90USB64 | ||
159 | _udev_rule("03EB", "2FFB") # AT90USB128 | ||
160 | }, | ||
161 | 'kiibohd': { | ||
162 | _udev_rule("1C11", "B007") | ||
163 | }, | ||
164 | 'stm32': { | ||
165 | _udev_rule("1EAF", "0003"), # STM32duino | ||
166 | _udev_rule("0483", "DF11") # STM32 DFU | ||
167 | }, | ||
168 | 'bootloadhid': { | ||
169 | _udev_rule("16C0", "05DF") | ||
170 | }, | ||
171 | 'usbasploader': { | ||
172 | _udev_rule("16C0", "05DC") | ||
173 | }, | ||
174 | 'massdrop': { | ||
175 | _udev_rule("03EB", "6124") | ||
176 | }, | ||
157 | 'caterina': { | 177 | 'caterina': { |
158 | _udev_rule("2341", "0036", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), | 178 | # Spark Fun Electronics |
159 | _udev_rule("1b4f", "9205", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), | 179 | _udev_rule("1B4F", "9203", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # Pro Micro 3V3/8MHz |
160 | _udev_rule("1b4f", "9203", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), | 180 | _udev_rule("1B4F", "9205", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # Pro Micro 5V/16MHz |
161 | _udev_rule("2a03", "0036", 'ENV{ID_MM_DEVICE_IGNORE}="1"') | 181 | _udev_rule("1B4F", "9207", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # LilyPad 3V3/8MHz (and some Pro Micro clones) |
182 | # Pololu Electronics | ||
183 | _udev_rule("1FFB", "0101", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # A-Star 32U4 | ||
184 | # Arduino SA | ||
185 | _udev_rule("2341", "0036", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # Leonardo | ||
186 | _udev_rule("2341", "0037", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # Micro | ||
187 | # Adafruit Industries LLC | ||
188 | _udev_rule("239A", "000C", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # Feather 32U4 | ||
189 | _udev_rule("239A", "000D", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # ItsyBitsy 32U4 3V3/8MHz | ||
190 | _udev_rule("239A", "000E", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # ItsyBitsy 32U4 5V/16MHz | ||
191 | # dog hunter AG | ||
192 | _udev_rule("2A03", "0036", 'ENV{ID_MM_DEVICE_IGNORE}="1"'), # Leonardo | ||
193 | _udev_rule("2A03", "0037", 'ENV{ID_MM_DEVICE_IGNORE}="1"') # Micro | ||
162 | } | 194 | } |
163 | } | 195 | } |
164 | 196 | ||
165 | # These rules are no longer recommended, only use them to check for their presence. | 197 | # These rules are no longer recommended, only use them to check for their presence. |
166 | deprecated_rules = { | 198 | deprecated_rules = { |
167 | 'dfu': {_deprecated_udev_rule("03eb", "2ff4"), _deprecated_udev_rule("03eb", "2ffb"), _deprecated_udev_rule("03eb", "2ff0")}, | 199 | 'atmel-dfu': {_deprecated_udev_rule("03eb", "2ff4"), _deprecated_udev_rule("03eb", "2ffb"), _deprecated_udev_rule("03eb", "2ff0")}, |
168 | 'input_club': {_deprecated_udev_rule("1c11")}, | 200 | 'kiibohd': {_deprecated_udev_rule("1c11")}, |
169 | 'stm32': {_deprecated_udev_rule("1eaf", "0003"), _deprecated_udev_rule("0483", "df11")}, | 201 | 'stm32': {_deprecated_udev_rule("1eaf", "0003"), _deprecated_udev_rule("0483", "df11")}, |
170 | 'bootloadhid': {_deprecated_udev_rule("16c0", "05df")}, | 202 | 'bootloadhid': {_deprecated_udev_rule("16c0", "05df")}, |
171 | 'caterina': {'ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"', 'ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"'} | 203 | 'caterina': {'ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"', 'ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"'}, |
204 | 'tmk': {_deprecated_udev_rule("feed")} | ||
172 | } | 205 | } |
173 | 206 | ||
174 | if udev_dir.exists(): | 207 | if udev_dir.exists(): |
@@ -194,7 +227,7 @@ def check_udev_rules(): | |||
194 | if deprecated_rule and deprecated_rule.issubset(current_rules): | 227 | if deprecated_rule and deprecated_rule.issubset(current_rules): |
195 | cli.log.warn("{bg_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) | 228 | cli.log.warn("{bg_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) |
196 | else: | 229 | else: |
197 | cli.log.warn("{bg_yellow}Missing udev rules for '%s' boards. You'll need to use `sudo` in order to flash them.", bootloader) | 230 | cli.log.warn("{bg_yellow}Missing udev rules for '%s' boards. See https://docs.qmk.fm/#/faq_build?id=linux-udev-rules for more details.", bootloader) |
198 | 231 | ||
199 | return ok | 232 | return ok |
200 | 233 | ||