aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZach White <skullydazed@gmail.com>2021-08-28 18:27:57 -0700
committerGitHub <noreply@github.com>2021-08-29 11:27:57 +1000
commitf155865804da332ac544e6a6bca0ca9035d3e818 (patch)
treeb2786ec3176fce4fff8af90de9bee174d2201e43
parent1ac3b3e9b6e794669db91d6d14c90b420b56bc26 (diff)
downloadqmk_firmware-f155865804da332ac544e6a6bca0ca9035d3e818.tar.gz
qmk_firmware-f155865804da332ac544e6a6bca0ca9035d3e818.zip
remove qmk console, which is now part of the global cli (#14206)
-rw-r--r--docs/cli_commands.md48
-rw-r--r--lib/python/qmk/cli/__init__.py1
-rw-r--r--lib/python/qmk/cli/console.py303
3 files changed, 0 insertions, 352 deletions
diff --git a/docs/cli_commands.md b/docs/cli_commands.md
index 8fa7ad41d..06568afb4 100644
--- a/docs/cli_commands.md
+++ b/docs/cli_commands.md
@@ -118,54 +118,6 @@ This command lets you configure the behavior of QMK. For the full `qmk config` d
118qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN] 118qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN]
119``` 119```
120 120
121## `qmk console`
122
123This command lets you connect to keyboard consoles to get debugging messages. It only works if your keyboard firmware has been compiled with `CONSOLE_ENABLE=yes`.
124
125**Usage**:
126
127```
128qmk console [-d <pid>:<vid>[:<index>]] [-l] [-n] [-t] [-w <seconds>]
129```
130
131**Examples**:
132
133Connect to all available keyboards and show their console messages:
134
135```
136qmk console
137```
138
139List all devices:
140
141```
142qmk console -l
143```
144
145Show only messages from clueboard/66/rev3 keyboards:
146
147```
148qmk console -d C1ED:2370
149```
150
151Show only messages from the second clueboard/66/rev3:
152
153```
154qmk console -d C1ED:2370:2
155```
156
157Show timestamps and VID:PID instead of names:
158
159```
160qmk console -n -t
161```
162
163Disable bootloader messages:
164
165```
166qmk console --no-bootloaders
167```
168
169## `qmk doctor` 121## `qmk doctor`
170 122
171This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to. 123This 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 b22f1c0d2..318adf378 100644
--- a/lib/python/qmk/cli/__init__.py
+++ b/lib/python/qmk/cli/__init__.py
@@ -35,7 +35,6 @@ subcommands = [
35 'qmk.cli.chibios.confmigrate', 35 'qmk.cli.chibios.confmigrate',
36 'qmk.cli.clean', 36 'qmk.cli.clean',
37 'qmk.cli.compile', 37 'qmk.cli.compile',
38 'qmk.cli.console',
39 'qmk.cli.docs', 38 'qmk.cli.docs',
40 'qmk.cli.doctor', 39 'qmk.cli.doctor',
41 'qmk.cli.fileformat', 40 'qmk.cli.fileformat',
diff --git a/lib/python/qmk/cli/console.py b/lib/python/qmk/cli/console.py
deleted file mode 100644
index 3c508160e..000000000
--- a/lib/python/qmk/cli/console.py
+++ /dev/null
@@ -1,303 +0,0 @@
1"""Acquire debugging information from usb hid devices
2
3cli implementation of https://www.pjrc.com/teensy/hid_listen.html
4"""
5from pathlib import Path
6from threading import Thread
7from time import sleep, strftime
8
9import hid
10import usb.core
11
12from milc import cli
13
14LOG_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
26KNOWN_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 ('2A03', '0036'): 'caterina: Arduino Leonardo',
52 ('2A03', '0037'): 'caterina: Arduino Micro',
53 ('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode',
54 ('03EB', '2067'): 'qmk-hid: HID Bootloader',
55 ('03EB', '2045'): 'lufa-ms: LUFA Mass Storage Bootloader'
56}
57
58
59class MonitorDevice(object):
60 def __init__(self, hid_device, numeric):
61 self.hid_device = hid_device
62 self.numeric = numeric
63 self.device = hid.Device(path=hid_device['path'])
64 self.current_line = ''
65
66 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)
67
68 def read(self, size, encoding='ascii', timeout=1):
69 """Read size bytes from the device.
70 """
71 return self.device.read(size, timeout).decode(encoding)
72
73 def read_line(self):
74 """Read from the device's console until we get a \n.
75 """
76 while '\n' not in self.current_line:
77 self.current_line += self.read(32).replace('\x00', '')
78
79 lines = self.current_line.split('\n', 1)
80 self.current_line = lines[1]
81
82 return lines[0]
83
84 def run_forever(self):
85 while True:
86 try:
87 message = {**self.hid_device, 'text': self.read_line()}
88 identifier = (int2hex(message['vendor_id']), int2hex(message['product_id'])) if self.numeric else (message['manufacturer_string'], message['product_string'])
89 message['identifier'] = ':'.join(identifier)
90 message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else ''
91
92 cli.echo('%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message)
93
94 except hid.HIDException:
95 break
96
97
98class FindDevices(object):
99 def __init__(self, vid, pid, index, numeric):
100 self.vid = vid
101 self.pid = pid
102 self.index = index
103 self.numeric = numeric
104
105 def run_forever(self):
106 """Process messages from our queue in a loop.
107 """
108 live_devices = {}
109 live_bootloaders = {}
110
111 while True:
112 try:
113 for device in list(live_devices):
114 if not live_devices[device]['thread'].is_alive():
115 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])
116 del live_devices[device]
117
118 for device in self.find_devices():
119 if device['path'] not in live_devices:
120 device['color'] = LOG_COLOR['colors'][LOG_COLOR['next']]
121 LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
122 live_devices[device['path']] = device
123
124 try:
125 monitor = MonitorDevice(device, self.numeric)
126 device['thread'] = Thread(target=monitor.run_forever, daemon=True)
127
128 device['thread'].start()
129 except Exception as e:
130 device['e'] = e
131 device['e_name'] = e.__class__.__name__
132 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)
133 if cli.config.general.verbose:
134 cli.log.exception(e)
135 del live_devices[device['path']]
136
137 if cli.args.bootloaders:
138 for device in self.find_bootloaders():
139 if device.address in live_bootloaders:
140 live_bootloaders[device.address]._qmk_found = True
141 else:
142 name = KNOWN_BOOTLOADERS[(int2hex(device.idVendor), int2hex(device.idProduct))]
143 cli.log.info('Bootloader Connected: {style_bright}{fg_magenta}%s', name)
144 device._qmk_found = True
145 live_bootloaders[device.address] = device
146
147 for device in list(live_bootloaders):
148 if live_bootloaders[device]._qmk_found:
149 live_bootloaders[device]._qmk_found = False
150 else:
151 name = KNOWN_BOOTLOADERS[(int2hex(live_bootloaders[device].idVendor), int2hex(live_bootloaders[device].idProduct))]
152 cli.log.info('Bootloader Disconnected: {style_bright}{fg_magenta}%s', name)
153 del live_bootloaders[device]
154
155 sleep(.1)
156
157 except KeyboardInterrupt:
158 break
159
160 def is_bootloader(self, hid_device):
161 """Returns true if the device in question matches a known bootloader vid/pid.
162 """
163 return (int2hex(hid_device.idVendor), int2hex(hid_device.idProduct)) in KNOWN_BOOTLOADERS
164
165 def is_console_hid(self, hid_device):
166 """Returns true when the usage page indicates it's a teensy-style console.
167 """
168 return hid_device['usage_page'] == 0xFF31 and hid_device['usage'] == 0x0074
169
170 def is_filtered_device(self, hid_device):
171 """Returns True if the device should be included in the list of available consoles.
172 """
173 return int2hex(hid_device['vendor_id']) == self.vid and int2hex(hid_device['product_id']) == self.pid
174
175 def find_devices_by_report(self, hid_devices):
176 """Returns a list of available teensy-style consoles by doing a brute-force search.
177
178 Some versions of linux don't report usage and usage_page. In that case we fallback to reading the report (possibly inaccurately) ourselves.
179 """
180 devices = []
181
182 for device in hid_devices:
183 path = device['path'].decode('utf-8')
184
185 if path.startswith('/dev/hidraw'):
186 number = path[11:]
187 report = Path(f'/sys/class/hidraw/hidraw{number}/device/report_descriptor')
188
189 if report.exists():
190 rp = report.read_bytes()
191
192 if rp[1] == 0x31 and rp[3] == 0x09:
193 devices.append(device)
194
195 return devices
196
197 def find_bootloaders(self):
198 """Returns a list of available bootloader devices.
199 """
200 return list(filter(self.is_bootloader, usb.core.find(find_all=True)))
201
202 def find_devices(self):
203 """Returns a list of available teensy-style consoles.
204 """
205 hid_devices = hid.enumerate()
206 devices = list(filter(self.is_console_hid, hid_devices))
207
208 if not devices:
209 devices = self.find_devices_by_report(hid_devices)
210
211 if self.vid and self.pid:
212 devices = list(filter(self.is_filtered_device, devices))
213
214 # Add index numbers
215 device_index = {}
216 for device in devices:
217 id = ':'.join((int2hex(device['vendor_id']), int2hex(device['product_id'])))
218
219 if id not in device_index:
220 device_index[id] = 0
221
222 device_index[id] += 1
223 device['index'] = device_index[id]
224
225 return devices
226
227
228def int2hex(number):
229 """Returns a string representation of the number as hex.
230 """
231 return "%04X" % number
232
233
234def list_devices(device_finder):
235 """Show the user a nicely formatted list of devices.
236 """
237 devices = device_finder.find_devices()
238
239 if devices:
240 cli.log.info('Available devices:')
241 for dev in devices:
242 color = LOG_COLOR['colors'][LOG_COLOR['next']]
243 LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
244 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'])
245
246 if cli.args.bootloaders:
247 bootloaders = device_finder.find_bootloaders()
248
249 if bootloaders:
250 cli.log.info('Available Bootloaders:')
251
252 for dev in bootloaders:
253 cli.log.info("\t%s:%s\t%s", int2hex(dev.idVendor), int2hex(dev.idProduct), KNOWN_BOOTLOADERS[(int2hex(dev.idVendor), int2hex(dev.idProduct))])
254
255
256@cli.argument('--bootloaders', arg_only=True, default=True, action='store_boolean', help='displaying bootloaders.')
257@cli.argument('-d', '--device', help='Device to select - uses format <pid>:<vid>[:<index>].')
258@cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available hid_listen devices.')
259@cli.argument('-n', '--numeric', arg_only=True, action='store_true', help='Show VID/PID instead of names.')
260@cli.argument('-t', '--timestamp', arg_only=True, action='store_true', help='Print the timestamp for received messages as well.')
261@cli.argument('-w', '--wait', type=int, default=1, help="How many seconds to wait between checks (Default: 1)")
262@cli.subcommand('Acquire debugging information from usb hid devices.', hidden=False if cli.config.user.developer else True)
263def console(cli):
264 """Acquire debugging information from usb hid devices
265 """
266 vid = None
267 pid = None
268 index = 1
269
270 if cli.config.console.device:
271 device = cli.config.console.device.split(':')
272
273 if len(device) == 2:
274 vid, pid = device
275
276 elif len(device) == 3:
277 vid, pid, index = device
278
279 if not index.isdigit():
280 cli.log.error('Device index must be a number! Got "%s" instead.', index)
281 exit(1)
282
283 index = int(index)
284
285 if index < 1:
286 cli.log.error('Device index must be greater than 0! Got %s', index)
287 exit(1)
288
289 else:
290 cli.log.error('Invalid format for device, expected "<pid>:<vid>[:<index>]" but got "%s".', cli.config.console.device)
291 cli.print_help()
292 exit(1)
293
294 vid = vid.upper()
295 pid = pid.upper()
296
297 device_finder = FindDevices(vid, pid, index, cli.args.numeric)
298
299 if cli.args.list:
300 return list_devices(device_finder)
301
302 print('Looking for devices...', flush=True)
303 device_finder.run_forever()