diff options
author | Zach White <skullydazed@gmail.com> | 2021-05-08 20:56:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-08 20:56:07 -0700 |
commit | 7a25dcacffcadf541da5107a35856b66e770bcaf (patch) | |
tree | cdb3ee8542ae68b61708f3cab99bbd921e2b8b76 | |
parent | d0a3bca9ecc6ccdc75218524b97b9cfb8a681baf (diff) | |
download | qmk_firmware-7a25dcacffcadf541da5107a35856b66e770bcaf.tar.gz qmk_firmware-7a25dcacffcadf541da5107a35856b66e770bcaf.zip |
New command: qmk console (#12828)
* stash poc
* stash
* tidy up implementation
* Tidy up slightly for review
* Tidy up slightly for review
* Bodge environment to make tests pass
* Refactor away from asyncio due to windows issues
* Filter devices
* align vid/pid printing
* Add hidapi to the installers
* start preparing for multiple hid_listeners
* udev rules for hid_listen
* refactor to move closer to end state
* very basic implementation of the threaded model
* refactor how vid/pid/index are supplied and parsed
* windows improvements
* read the report directly when usage page isn't available
* add per-device colors, the choice to show names or numbers, and refactor
* add timestamps
* Add support for showing bootloaders
* tweak the color for bootloaders
* Align bootloader disconnect with connect color
* add support for showing all bootloaders
* fix the pyusb check
* tweaks
* fix exception
* hide a stack trace behind -v
* add --no-bootloaders option
* add documentation for qmk console
* Apply suggestions from code review
Co-authored-by: Ryan <fauxpark@gmail.com>
* pyformat
* clean up and flesh out KNOWN_BOOTLOADERS
Co-authored-by: zvecr <git@zvecr.com>
Co-authored-by: Ryan <fauxpark@gmail.com>
-rw-r--r-- | .github/workflows/cli.yml | 2 | ||||
-rwxr-xr-x | bin/qmk | 2 | ||||
-rw-r--r-- | docs/cli_commands.md | 48 | ||||
-rw-r--r-- | lib/python/qmk/cli/__init__.py | 1 | ||||
-rw-r--r-- | lib/python/qmk/cli/console.py | 302 | ||||
-rw-r--r-- | requirements-dev.txt | 2 | ||||
-rwxr-xr-x | util/install/arch.sh | 10 | ||||
-rwxr-xr-x | util/install/debian.sh | 7 | ||||
-rwxr-xr-x | util/install/fedora.sh | 7 | ||||
-rwxr-xr-x | util/install/gentoo.sh | 7 | ||||
-rwxr-xr-x | util/install/msys2.sh | 9 | ||||
-rw-r--r-- | util/udev/50-qmk.rules | 3 |
12 files changed, 378 insertions, 22 deletions
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 28c6bb367..df727518e 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml | |||
@@ -23,6 +23,6 @@ jobs: | |||
23 | with: | 23 | with: |
24 | submodules: recursive | 24 | submodules: recursive |
25 | - name: Install dependencies | 25 | - name: Install dependencies |
26 | run: pip3 install -r requirements.txt | 26 | run: pip3 install -r requirements-dev.txt |
27 | - name: Run tests | 27 | - name: Run tests |
28 | run: bin/qmk pytest | 28 | run: bin/qmk pytest |
@@ -33,6 +33,8 @@ def _check_modules(requirements): | |||
33 | # Not every module is importable by its own name. | 33 | # Not every module is importable by its own name. |
34 | if module['name'] == "pep8-naming": | 34 | if module['name'] == "pep8-naming": |
35 | module['import'] = "pep8ext_naming" | 35 | module['import'] = "pep8ext_naming" |
36 | elif module['name'] == 'pyusb': | ||
37 | module['import'] = 'usb.core' | ||
36 | 38 | ||
37 | if not find_spec(module['import']): | 39 | if not find_spec(module['import']): |
38 | print('Could not find module %s!' % module['name']) | 40 | print('Could not find module %s!' % module['name']) |
diff --git a/docs/cli_commands.md b/docs/cli_commands.md index 05e930607..581342093 100644 --- a/docs/cli_commands.md +++ b/docs/cli_commands.md | |||
@@ -107,6 +107,54 @@ This command lets you configure the behavior of QMK. For the full `qmk config` d | |||
107 | qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN] | 107 | qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN] |
108 | ``` | 108 | ``` |
109 | 109 | ||
110 | ## `qmk console` | ||
111 | |||
112 | This command lets you connect to keyboard consoles to get debugging messages. It only works if your keyboard firmware has been compiled with `CONSOLE_ENABLED=yes`. | ||
113 | |||
114 | **Usage**: | ||
115 | |||
116 | ``` | ||
117 | qmk console [-d <pid>:<vid>[:<index>]] [-l] [-n] [-t] [-w <seconds>] | ||
118 | ``` | ||
119 | |||
120 | **Examples**: | ||
121 | |||
122 | Connect to all available keyboards and show their console messages: | ||
123 | |||
124 | ``` | ||
125 | qmk console | ||
126 | ``` | ||
127 | |||
128 | List all devices: | ||
129 | |||
130 | ``` | ||
131 | qmk console -l | ||
132 | ``` | ||
133 | |||
134 | Show only messages from clueboard/66/rev3 keyboards: | ||
135 | |||
136 | ``` | ||
137 | qmk console -d C1ED:2370 | ||
138 | ``` | ||
139 | |||
140 | Show only messages from the second clueboard/66/rev3: | ||
141 | |||
142 | ``` | ||
143 | qmk console -d C1ED:2370:2 | ||
144 | ``` | ||
145 | |||
146 | Show timestamps and VID:PID instead of names: | ||
147 | |||
148 | ``` | ||
149 | qmk console -n -t | ||
150 | ``` | ||
151 | |||
152 | Disable bootloader messages: | ||
153 | |||
154 | ``` | ||
155 | qmk console --no-bootloaders | ||
156 | ``` | ||
157 | |||
110 | ## `qmk doctor` | 158 | ## `qmk doctor` |
111 | 159 | ||
112 | This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to. | 160 | This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to. |
diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index f7df90811..cfb6e6ea5 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py | |||
@@ -12,6 +12,7 @@ from . import chibios | |||
12 | from . import clean | 12 | from . import clean |
13 | from . import compile | 13 | from . import compile |
14 | from . import config | 14 | from . import config |
15 | from . import console | ||
15 | from . import docs | 16 | from . import docs |
16 | from . import doctor | 17 | from . import doctor |
17 | from . import fileformat | 18 | from . import fileformat |
diff --git a/lib/python/qmk/cli/console.py b/lib/python/qmk/cli/console.py new file mode 100644 index 000000000..45ff0c8be --- /dev/null +++ b/lib/python/qmk/cli/console.py | |||
@@ -0,0 +1,302 @@ | |||
1 | """Acquire debugging information from usb hid devices | ||
2 | |||
3 | cli implementation of https://www.pjrc.com/teensy/hid_listen.html | ||
4 | """ | ||
5 | from pathlib import Path | ||
6 | from threading import Thread | ||
7 | from time import sleep, strftime | ||
8 | |||
9 | import hid | ||
10 | import usb.core | ||
11 | |||
12 | from milc import cli | ||
13 | |||
14 | LOG_COLOR = { | ||
15 | 'next': 0, | ||
16 | 'colors': [ | ||
17 | '{fg_blue}', | ||
18 | '{fg_cyan}', | ||
19 | '{fg_green}', | ||
20 | '{fg_magenta}', | ||
21 | '{fg_red}', | ||
22 | '{fg_yellow}', | ||
23 | ], | ||
24 | } | ||
25 | |||
26 | KNOWN_BOOTLOADERS = { | ||
27 | # VID , PID | ||
28 | ('03EB', '2FEF'): 'atmel-dfu: ATmega16U2', | ||
29 | ('03EB', '2FF0'): 'atmel-dfu: ATmega32U2', | ||
30 | ('03EB', '2FF3'): 'atmel-dfu: ATmega16U4', | ||
31 | ('03EB', '2FF4'): 'atmel-dfu: ATmega32U4', | ||
32 | ('03EB', '2FF9'): 'atmel-dfu: AT90USB64', | ||
33 | ('03EB', '2FFA'): 'atmel-dfu: AT90USB162', | ||
34 | ('03EB', '2FFB'): 'atmel-dfu: AT90USB128', | ||
35 | ('03EB', '6124'): 'Microchip SAM-BA', | ||
36 | ('0483', 'DF11'): 'stm32-dfu: STM32 BOOTLOADER', | ||
37 | ('16C0', '05DC'): 'USBasp: USBaspLoader', | ||
38 | ('16C0', '05DF'): 'bootloadHID: HIDBoot', | ||
39 | ('16C0', '0478'): 'halfkay: Teensy Halfkay', | ||
40 | ('1B4F', '9203'): 'caterina: Pro Micro 3.3V', | ||
41 | ('1B4F', '9205'): 'caterina: Pro Micro 5V', | ||
42 | ('1B4F', '9207'): 'caterina: LilyPadUSB', | ||
43 | ('1C11', 'B007'): 'kiibohd: Kiibohd DFU Bootloader', | ||
44 | ('1EAF', '0003'): 'stm32duino: Maple 003', | ||
45 | ('1FFB', '0101'): 'caterina: Polou A-Star 32U4 Bootloader', | ||
46 | ('2341', '0036'): 'caterina: Arduino Leonardo', | ||
47 | ('2341', '0037'): 'caterina: Arduino Micro', | ||
48 | ('239A', '000C'): 'caterina: Adafruit Feather 32U4', | ||
49 | ('239A', '000D'): 'caterina: Adafruit ItsyBitsy 32U4 3v', | ||
50 | ('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v', | ||
51 | ('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v', | ||
52 | ('2A03', '0036'): 'caterina: Arduino Leonardo', | ||
53 | ('2A03', '0037'): 'caterina: Arduino Micro', | ||
54 | ('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode' | ||
55 | } | ||
56 | |||
57 | |||
58 | class MonitorDevice(object): | ||
59 | def __init__(self, hid_device, numeric): | ||
60 | self.hid_device = hid_device | ||
61 | self.numeric = numeric | ||
62 | self.device = hid.Device(path=hid_device['path']) | ||
63 | self.current_line = '' | ||
64 | |||
65 | 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) | ||
66 | |||
67 | def read(self, size, encoding='ascii', timeout=1): | ||
68 | """Read size bytes from the device. | ||
69 | """ | ||
70 | return self.device.read(size, timeout).decode(encoding) | ||
71 | |||
72 | def read_line(self): | ||
73 | """Read from the device's console until we get a \n. | ||
74 | """ | ||
75 | while '\n' not in self.current_line: | ||
76 | self.current_line += self.read(32).replace('\x00', '') | ||
77 | |||
78 | lines = self.current_line.split('\n', 1) | ||
79 | self.current_line = lines[1] | ||
80 | |||
81 | return lines[0] | ||
82 | |||
83 | def run_forever(self): | ||
84 | while True: | ||
85 | try: | ||
86 | message = {**self.hid_device, 'text': self.read_line()} | ||
87 | identifier = (int2hex(message['vendor_id']), int2hex(message['product_id'])) if self.numeric else (message['manufacturer_string'], message['product_string']) | ||
88 | message['identifier'] = ':'.join(identifier) | ||
89 | message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else '' | ||
90 | |||
91 | cli.echo('%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message) | ||
92 | |||
93 | except hid.HIDException: | ||
94 | break | ||
95 | |||
96 | |||
97 | class FindDevices(object): | ||
98 | def __init__(self, vid, pid, index, numeric): | ||
99 | self.vid = vid | ||
100 | self.pid = pid | ||
101 | self.index = index | ||
102 | self.numeric = numeric | ||
103 | |||
104 | def run_forever(self): | ||
105 | """Process messages from our queue in a loop. | ||
106 | """ | ||
107 | live_devices = {} | ||
108 | live_bootloaders = {} | ||
109 | |||
110 | while True: | ||
111 | try: | ||
112 | for device in list(live_devices): | ||
113 | if not live_devices[device]['thread'].is_alive(): | ||
114 | 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]) | ||
115 | del live_devices[device] | ||
116 | |||
117 | for device in self.find_devices(): | ||
118 | if device['path'] not in live_devices: | ||
119 | device['color'] = LOG_COLOR['colors'][LOG_COLOR['next']] | ||
120 | LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors']) | ||
121 | live_devices[device['path']] = device | ||
122 | |||
123 | try: | ||
124 | monitor = MonitorDevice(device, self.numeric) | ||
125 | device['thread'] = Thread(target=monitor.run_forever, daemon=True) | ||
126 | |||
127 | device['thread'].start() | ||
128 | except Exception as e: | ||
129 | device['e'] = e | ||
130 | device['e_name'] = e.__class__.__name__ | ||
131 | 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) | ||
132 | if cli.config.general.verbose: | ||
133 | cli.log.exception(e) | ||
134 | del live_devices[device['path']] | ||
135 | |||
136 | if cli.args.bootloaders: | ||
137 | for device in self.find_bootloaders(): | ||
138 | if device.address in live_bootloaders: | ||
139 | live_bootloaders[device.address]._qmk_found = True | ||
140 | else: | ||
141 | name = KNOWN_BOOTLOADERS[(int2hex(device.idVendor), int2hex(device.idProduct))] | ||
142 | cli.log.info('Bootloader Connected: {style_bright}{fg_magenta}%s', name) | ||
143 | device._qmk_found = True | ||
144 | live_bootloaders[device.address] = device | ||
145 | |||
146 | for device in list(live_bootloaders): | ||
147 | if live_bootloaders[device]._qmk_found: | ||
148 | live_bootloaders[device]._qmk_found = False | ||
149 | else: | ||
150 | name = KNOWN_BOOTLOADERS[(int2hex(live_bootloaders[device].idVendor), int2hex(live_bootloaders[device].idProduct))] | ||
151 | cli.log.info('Bootloader Disconnected: {style_bright}{fg_magenta}%s', name) | ||
152 | del live_bootloaders[device] | ||
153 | |||
154 | sleep(.1) | ||
155 | |||
156 | except KeyboardInterrupt: | ||
157 | break | ||
158 | |||
159 | def is_bootloader(self, hid_device): | ||
160 | """Returns true if the device in question matches a known bootloader vid/pid. | ||
161 | """ | ||
162 | return (int2hex(hid_device.idVendor), int2hex(hid_device.idProduct)) in KNOWN_BOOTLOADERS | ||
163 | |||
164 | def is_console_hid(self, hid_device): | ||
165 | """Returns true when the usage page indicates it's a teensy-style console. | ||
166 | """ | ||
167 | return hid_device['usage_page'] == 0xFF31 and hid_device['usage'] == 0x0074 | ||
168 | |||
169 | def is_filtered_device(self, hid_device): | ||
170 | """Returns True if the device should be included in the list of available consoles. | ||
171 | """ | ||
172 | return int2hex(hid_device['vendor_id']) == self.vid and int2hex(hid_device['product_id']) == self.pid | ||
173 | |||
174 | def find_devices_by_report(self, hid_devices): | ||
175 | """Returns a list of available teensy-style consoles by doing a brute-force search. | ||
176 | |||
177 | Some versions of linux don't report usage and usage_page. In that case we fallback to reading the report (possibly inaccurately) ourselves. | ||
178 | """ | ||
179 | devices = [] | ||
180 | |||
181 | for device in hid_devices: | ||
182 | path = device['path'].decode('utf-8') | ||
183 | |||
184 | if path.startswith('/dev/hidraw'): | ||
185 | number = path[11:] | ||
186 | report = Path(f'/sys/class/hidraw/hidraw{number}/device/report_descriptor') | ||
187 | |||
188 | if report.exists(): | ||
189 | rp = report.read_bytes() | ||
190 | |||
191 | if rp[1] == 0x31 and rp[3] == 0x09: | ||
192 | devices.append(device) | ||
193 | |||
194 | return devices | ||
195 | |||
196 | def find_bootloaders(self): | ||
197 | """Returns a list of available bootloader devices. | ||
198 | """ | ||
199 | return list(filter(self.is_bootloader, usb.core.find(find_all=True))) | ||
200 | |||
201 | def find_devices(self): | ||
202 | """Returns a list of available teensy-style consoles. | ||
203 | """ | ||
204 | hid_devices = hid.enumerate() | ||
205 | devices = list(filter(self.is_console_hid, hid_devices)) | ||
206 | |||
207 | if not devices: | ||
208 | devices = self.find_devices_by_report(hid_devices) | ||
209 | |||
210 | if self.vid and self.pid: | ||
211 | devices = list(filter(self.is_filtered_device, devices)) | ||
212 | |||
213 | # Add index numbers | ||
214 | device_index = {} | ||
215 | for device in devices: | ||
216 | id = ':'.join((int2hex(device['vendor_id']), int2hex(device['product_id']))) | ||
217 | |||
218 | if id not in device_index: | ||
219 | device_index[id] = 0 | ||
220 | |||
221 | device_index[id] += 1 | ||
222 | device['index'] = device_index[id] | ||
223 | |||
224 | return devices | ||
225 | |||
226 | |||
227 | def int2hex(number): | ||
228 | """Returns a string representation of the number as hex. | ||
229 | """ | ||
230 | return "%04X" % number | ||
231 | |||
232 | |||
233 | def list_devices(device_finder): | ||
234 | """Show the user a nicely formatted list of devices. | ||
235 | """ | ||
236 | devices = device_finder.find_devices() | ||
237 | |||
238 | if devices: | ||
239 | cli.log.info('Available devices:') | ||
240 | for dev in devices: | ||
241 | color = LOG_COLOR['colors'][LOG_COLOR['next']] | ||
242 | LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors']) | ||
243 | 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']) | ||
244 | |||
245 | if cli.args.bootloaders: | ||
246 | bootloaders = device_finder.find_bootloaders() | ||
247 | |||
248 | if bootloaders: | ||
249 | cli.log.info('Available Bootloaders:') | ||
250 | |||
251 | for dev in bootloaders: | ||
252 | cli.log.info("\t%s:%s\t%s", int2hex(dev.idVendor), int2hex(dev.idProduct), KNOWN_BOOTLOADERS[(int2hex(dev.idVendor), int2hex(dev.idProduct))]) | ||
253 | |||
254 | |||
255 | @cli.argument('--bootloaders', arg_only=True, default=True, action='store_boolean', help='displaying bootloaders.') | ||
256 | @cli.argument('-d', '--device', help='Device to select - uses format <pid>:<vid>[:<index>].') | ||
257 | @cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available hid_listen devices.') | ||
258 | @cli.argument('-n', '--numeric', arg_only=True, action='store_true', help='Show VID/PID instead of names.') | ||
259 | @cli.argument('-t', '--timestamp', arg_only=True, action='store_true', help='Print the timestamp for received messages as well.') | ||
260 | @cli.argument('-w', '--wait', type=int, default=1, help="How many seconds to wait between checks (Default: 1)") | ||
261 | @cli.subcommand('Acquire debugging information from usb hid devices.', hidden=False if cli.config.user.developer else True) | ||
262 | def console(cli): | ||
263 | """Acquire debugging information from usb hid devices | ||
264 | """ | ||
265 | vid = None | ||
266 | pid = None | ||
267 | index = 1 | ||
268 | |||
269 | if cli.config.console.device: | ||
270 | device = cli.config.console.device.split(':') | ||
271 | |||
272 | if len(device) == 2: | ||
273 | vid, pid = device | ||
274 | |||
275 | elif len(device) == 3: | ||
276 | vid, pid, index = device | ||
277 | |||
278 | if not index.isdigit(): | ||
279 | cli.log.error('Device index must be a number! Got "%s" instead.', index) | ||
280 | exit(1) | ||
281 | |||
282 | index = int(index) | ||
283 | |||
284 | if index < 1: | ||
285 | cli.log.error('Device index must be greater than 0! Got %s', index) | ||
286 | exit(1) | ||
287 | |||
288 | else: | ||
289 | cli.log.error('Invalid format for device, expected "<pid>:<vid>[:<index>]" but got "%s".', cli.config.console.device) | ||
290 | cli.print_help() | ||
291 | exit(1) | ||
292 | |||
293 | vid = vid.upper() | ||
294 | pid = pid.upper() | ||
295 | |||
296 | device_finder = FindDevices(vid, pid, index, cli.args.numeric) | ||
297 | |||
298 | if cli.args.list: | ||
299 | return list_devices(device_finder) | ||
300 | |||
301 | print('Looking for devices...', flush=True) | ||
302 | device_finder.run_forever() | ||
diff --git a/requirements-dev.txt b/requirements-dev.txt index 1db3b6d73..12d570e70 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt | |||
@@ -4,5 +4,7 @@ | |||
4 | # Python development requirements | 4 | # Python development requirements |
5 | nose2 | 5 | nose2 |
6 | flake8 | 6 | flake8 |
7 | hid | ||
7 | pep8-naming | 8 | pep8-naming |
9 | pyusb | ||
8 | yapf | 10 | yapf |
diff --git a/util/install/arch.sh b/util/install/arch.sh index 7442e2f13..eac4ad64e 100755 --- a/util/install/arch.sh +++ b/util/install/arch.sh | |||
@@ -4,13 +4,13 @@ _qmk_install() { | |||
4 | echo "Installing dependencies" | 4 | echo "Installing dependencies" |
5 | 5 | ||
6 | sudo pacman --needed --noconfirm -S \ | 6 | sudo pacman --needed --noconfirm -S \ |
7 | base-devel clang diffutils gcc git unzip wget zip \ | 7 | base-devel clang diffutils gcc git unzip wget zip python-pip \ |
8 | python-pip \ | 8 | avr-binutils arm-none-eabi-binutils arm-none-eabi-gcc \ |
9 | avr-binutils \ | 9 | arm-none-eabi-newlib avrdude dfu-programmer dfu-util |
10 | arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib \ | ||
11 | avrdude dfu-programmer dfu-util | ||
12 | sudo pacman --needed --noconfirm -U https://archive.archlinux.org/packages/a/avr-gcc/avr-gcc-8.3.0-1-x86_64.pkg.tar.xz | 10 | sudo pacman --needed --noconfirm -U https://archive.archlinux.org/packages/a/avr-gcc/avr-gcc-8.3.0-1-x86_64.pkg.tar.xz |
13 | sudo pacman --needed --noconfirm -S avr-libc # Must be installed after the above, or it will bring in the latest avr-gcc instead | 11 | sudo pacman --needed --noconfirm -S avr-libc # Must be installed after the above, or it will bring in the latest avr-gcc instead |
14 | 12 | ||
13 | sudo pacman --needed --noconfirm -S hidapi # This will fail if the community repo isn't enabled | ||
14 | |||
15 | python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt | 15 | python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt |
16 | } | 16 | } |
diff --git a/util/install/debian.sh b/util/install/debian.sh index 0ae9764a3..ef87c41b5 100755 --- a/util/install/debian.sh +++ b/util/install/debian.sh | |||
@@ -13,10 +13,9 @@ _qmk_install() { | |||
13 | 13 | ||
14 | sudo apt-get -yq install \ | 14 | sudo apt-get -yq install \ |
15 | build-essential clang-format diffutils gcc git unzip wget zip \ | 15 | build-essential clang-format diffutils gcc git unzip wget zip \ |
16 | python3-pip \ | 16 | python3-pip binutils-avr gcc-avr avr-libc binutils-arm-none-eabi \ |
17 | binutils-avr gcc-avr avr-libc \ | 17 | gcc-arm-none-eabi libnewlib-arm-none-eabi avrdude dfu-programmer \ |
18 | binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi \ | 18 | dfu-util teensy-loader-cli libhidapi-hidraw0 |
19 | avrdude dfu-programmer dfu-util teensy-loader-cli libusb-dev | ||
20 | 19 | ||
21 | python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt | 20 | python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt |
22 | } | 21 | } |
diff --git a/util/install/fedora.sh b/util/install/fedora.sh index 44b71b98b..10fc7c8ad 100755 --- a/util/install/fedora.sh +++ b/util/install/fedora.sh | |||
@@ -5,11 +5,10 @@ _qmk_install() { | |||
5 | 5 | ||
6 | # TODO: Check whether devel/headers packages are really needed | 6 | # TODO: Check whether devel/headers packages are really needed |
7 | sudo dnf -y install \ | 7 | sudo dnf -y install \ |
8 | clang diffutils git gcc glibc-headers kernel-devel kernel-headers make unzip wget zip \ | 8 | clang diffutils git gcc glibc-headers kernel-devel kernel-headers \ |
9 | python3 \ | 9 | make unzip wget zip python3 avr-binutils avr-gcc avr-libc \ |
10 | avr-binutils avr-gcc avr-libc \ | ||
11 | arm-none-eabi-binutils-cs arm-none-eabi-gcc-cs arm-none-eabi-newlib \ | 10 | arm-none-eabi-binutils-cs arm-none-eabi-gcc-cs arm-none-eabi-newlib \ |
12 | avrdude dfu-programmer dfu-util libusb-devel | 11 | avrdude dfu-programmer dfu-util hidapi |
13 | 12 | ||
14 | python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt | 13 | python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt |
15 | } | 14 | } |
diff --git a/util/install/gentoo.sh b/util/install/gentoo.sh index 97eb5df07..604d07bf8 100755 --- a/util/install/gentoo.sh +++ b/util/install/gentoo.sh | |||
@@ -22,9 +22,10 @@ _qmk_install() { | |||
22 | echo "sys-devel/gcc multilib" | sudo tee --append /etc/portage/package.use/qmkfirmware >/dev/null | 22 | echo "sys-devel/gcc multilib" | sudo tee --append /etc/portage/package.use/qmkfirmware >/dev/null |
23 | sudo emerge -auN sys-devel/gcc | 23 | sudo emerge -auN sys-devel/gcc |
24 | sudo emerge -au --noreplace \ | 24 | sudo emerge -au --noreplace \ |
25 | app-arch/unzip app-arch/zip net-misc/wget sys-devel/clang sys-devel/crossdev \ | 25 | app-arch/unzip app-arch/zip net-misc/wget sys-devel/clang \ |
26 | \>=dev-lang/python-3.7 \ | 26 | sys-devel/crossdev \>=dev-lang/python-3.7 dev-embedded/avrdude \ |
27 | dev-embedded/avrdude dev-embedded/dfu-programmer app-mobilephone/dfu-util | 27 | dev-embedded/dfu-programmer app-mobilephone/dfu-util sys-apps/hwloc \ |
28 | dev-libs/hidapi | ||
28 | 29 | ||
29 | sudo crossdev -s4 --stable --g \<9 --portage --verbose --target avr | 30 | sudo crossdev -s4 --stable --g \<9 --portage --verbose --target avr |
30 | sudo crossdev -s4 --stable --g \<9 --portage --verbose --target arm-none-eabi | 31 | sudo crossdev -s4 --stable --g \<9 --portage --verbose --target arm-none-eabi |
diff --git a/util/install/msys2.sh b/util/install/msys2.sh index c8598a60f..9b8343aed 100755 --- a/util/install/msys2.sh +++ b/util/install/msys2.sh | |||
@@ -9,11 +9,10 @@ _qmk_install() { | |||
9 | 9 | ||
10 | pacman --needed --noconfirm --disable-download-timeout -S pactoys-git | 10 | pacman --needed --noconfirm --disable-download-timeout -S pactoys-git |
11 | pacboy sync --needed --noconfirm --disable-download-timeout \ | 11 | pacboy sync --needed --noconfirm --disable-download-timeout \ |
12 | base-devel: toolchain:x clang:x git: unzip: \ | 12 | base-devel: toolchain:x clang:x git: unzip: python3-pip:x \ |
13 | python3-pip:x \ | 13 | avr-binutils:x avr-gcc:x avr-libc:x arm-none-eabi-binutils:x \ |
14 | avr-binutils:x avr-gcc:x avr-libc:x \ | 14 | arm-none-eabi-gcc:x arm-none-eabi-newlib:x avrdude:x bootloadhid:x \ |
15 | arm-none-eabi-binutils:x arm-none-eabi-gcc:x arm-none-eabi-newlib:x \ | 15 | dfu-programmer:x dfu-util:x teensy-loader-cli:x hidapi:x |
16 | avrdude:x bootloadhid:x dfu-programmer:x dfu-util:x teensy-loader-cli:x | ||
17 | 16 | ||
18 | _qmk_install_drivers | 17 | _qmk_install_drivers |
19 | 18 | ||
diff --git a/util/udev/50-qmk.rules b/util/udev/50-qmk.rules index acaa7dcc5..679fe4ced 100644 --- a/util/udev/50-qmk.rules +++ b/util/udev/50-qmk.rules | |||
@@ -60,3 +60,6 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="239a", ATTRS{idProduct}=="000e", TAG+="uacc | |||
60 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0036", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" | 60 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0036", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" |
61 | ### Micro | 61 | ### Micro |
62 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0037", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" | 62 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0037", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1" |
63 | |||
64 | # hid_listen | ||
65 | KERNEL=="hidraw*", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl" | ||