Skip to content

Commit 7b72b6d

Browse files
add debugApp script to capture app PRINTF output over USB CDC
1 parent 1fdec31 commit 7b72b6d

File tree

3 files changed

+124
-1
lines changed

3 files changed

+124
-1
lines changed

doc/source/script_reference.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ checkGenuine.py
1111
:func: get_argparser
1212
:prog: python -m ledgerblue.checkGenuine
1313

14+
.. _debugApp.py:
15+
16+
debugApp.py
17+
-----------
18+
19+
.. argparse::
20+
:module: ledgerblue.debugApp
21+
:func: get_argparser
22+
:prog: python -m ledgerblue.debugApp
23+
1424
.. _deleteApp.py:
1525

1626
deleteApp.py

ledgerblue/debugApp.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
"""
2+
*******************************************************************************
3+
* Ledger Blue
4+
* (c) 2016 Ledger
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
********************************************************************************
18+
"""
19+
20+
import argparse
21+
import sys
22+
23+
import serial
24+
import serial.tools.list_ports
25+
26+
LEDGER_VENDOR_ID = 0x2C97
27+
28+
29+
def get_argparser():
30+
parser = argparse.ArgumentParser(
31+
description="Listen to debug output from a Ledger app compiled with DEBUG_OVER_USB."
32+
)
33+
parser.add_argument(
34+
"--port", "-p",
35+
help="Serial port to use (e.g. COM3 on Windows, /dev/ttyACM0 on Linux). Auto-detected if omitted.",
36+
type=str,
37+
default=None,
38+
)
39+
parser.add_argument(
40+
"--baudrate", "-b",
41+
help="Baud rate for the serial connection (default: 115200).",
42+
type=int,
43+
default=115200,
44+
)
45+
parser.add_argument(
46+
"--output", "-o",
47+
help="Write debug output to a file in addition to stdout.",
48+
type=str,
49+
default=None,
50+
)
51+
return parser
52+
53+
54+
def find_ledger_cdc_port(port=None):
55+
"""Find the Ledger device's CDC (virtual serial) port.
56+
57+
When DEBUG_OVER_USB is enabled in a Ledger app, the device exposes
58+
an additional USB CDC interface that sends PRINTF debug output.
59+
"""
60+
if port:
61+
return port
62+
63+
for p in serial.tools.list_ports.comports():
64+
if p.vid == LEDGER_VENDOR_ID:
65+
return p.device
66+
67+
return None
68+
69+
70+
if __name__ == '__main__':
71+
args = get_argparser().parse_args()
72+
73+
cdc_port = find_ledger_cdc_port(args.port)
74+
if cdc_port is None:
75+
print(
76+
"No Ledger CDC debug port found.\n"
77+
"Make sure your Ledger app was compiled with DEBUG_OVER_USB=1\n"
78+
"and that the device is connected and the app is running.\n"
79+
"You can also specify the port manually with --port."
80+
)
81+
sys.exit(1)
82+
83+
print("Listening on {} (baudrate={}) ...".format(cdc_port, args.baudrate))
84+
print("Press Ctrl+C to stop.\n")
85+
86+
output_file = None
87+
if args.output:
88+
try:
89+
output_file = open(args.output, "a", encoding="utf-8")
90+
except OSError:
91+
print("Unable to open file {} for writing.".format(args.output))
92+
sys.exit(1)
93+
94+
try:
95+
with serial.Serial(cdc_port, args.baudrate, timeout=1) as ser:
96+
while True:
97+
data = ser.readline()
98+
if data:
99+
text = data.decode("utf-8", errors="replace")
100+
sys.stdout.write(text)
101+
sys.stdout.flush()
102+
if output_file:
103+
output_file.write(text)
104+
output_file.flush()
105+
except serial.SerialException as e:
106+
print("Serial error: {}".format(e))
107+
sys.exit(1)
108+
except KeyboardInterrupt:
109+
print("\nStopped.")
110+
finally:
111+
if output_file:
112+
output_file.close()

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ dependencies = [
4343
"nfcpy>=1.0.4",
4444
"bleak>=0.20.1",
4545
"pycryptodome>=3.18.0",
46-
"python-gnupg>=0.5.0"
46+
"python-gnupg>=0.5.0",
47+
"pyserial>=3.5"
4748
]
4849

4950
[tool.setuptools]

0 commit comments

Comments
 (0)