oep-client-python 0.0.31__py3-none-any.whl → 0.0.32__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oep_client/__init__.py +1 -1
- oep_client/__main__.py +158 -321
- oep_client/arm.py +63 -17
- oep_client/capture.py +209 -208
- oep_client/catalog.py +59 -33
- oep_client/ch32_flash.py +2 -2
- oep_client/config.py +437 -472
- oep_client/conformance.py +1083 -0
- oep_client/conformance_allocator.py +88 -0
- oep_client/conformance_allocator_sample.py +16 -0
- oep_client/conformance_analog.py +142 -0
- oep_client/conformance_analog_payload.py +84 -0
- oep_client/conformance_analog_sample.py +15 -0
- oep_client/conformance_arm_adi.py +141 -0
- oep_client/conformance_arm_adi_blocks.py +87 -0
- oep_client/conformance_arm_adi_sample.py +14 -0
- oep_client/conformance_attach.py +198 -0
- oep_client/conformance_attach_sample.py +16 -0
- oep_client/conformance_block_sample.py +12 -0
- oep_client/conformance_blocks.py +132 -0
- oep_client/conformance_capture_group.py +276 -0
- oep_client/conformance_capture_group_geometry.py +76 -0
- oep_client/conformance_capture_group_sample.py +17 -0
- oep_client/conformance_capture_metadata.py +42 -0
- oep_client/conformance_capture_serial.py +103 -0
- oep_client/conformance_capture_serial_sample.py +61 -0
- oep_client/conformance_capture_timeline.py +261 -0
- oep_client/conformance_capture_timeline_lifecycle.py +175 -0
- oep_client/conformance_capture_timeline_sample.py +15 -0
- oep_client/conformance_clock.py +82 -0
- oep_client/conformance_clock_sample.py +13 -0
- oep_client/conformance_config.py +139 -0
- oep_client/conformance_config_execution.py +84 -0
- oep_client/conformance_config_execution_sample.py +13 -0
- oep_client/conformance_config_fallback.py +72 -0
- oep_client/conformance_config_fallback_sample.py +25 -0
- oep_client/conformance_config_paging.py +87 -0
- oep_client/conformance_config_paging_sample.py +29 -0
- oep_client/conformance_config_power_loss.py +89 -0
- oep_client/conformance_config_power_loss_sample.py +15 -0
- oep_client/conformance_config_sample.py +13 -0
- oep_client/conformance_config_storage.py +79 -0
- oep_client/conformance_config_storage_sample.py +15 -0
- oep_client/conformance_core_fixed_fields.py +100 -0
- oep_client/conformance_core_smoke.py +193 -0
- oep_client/conformance_corr.py +111 -0
- oep_client/conformance_cut.py +83 -0
- oep_client/conformance_cut_sample.py +10 -0
- oep_client/conformance_data.py +315 -0
- oep_client/conformance_data_sample.py +15 -0
- oep_client/conformance_debug.py +177 -0
- oep_client/conformance_debug_sample.py +12 -0
- oep_client/conformance_dependencies.py +261 -0
- oep_client/conformance_dependency_sample.py +17 -0
- oep_client/conformance_discovery.py +135 -0
- oep_client/conformance_dmseq.py +226 -0
- oep_client/conformance_dmseq_sample.py +9 -0
- oep_client/conformance_dmseq_target.py +137 -0
- oep_client/conformance_dmseq_target_sample.py +21 -0
- oep_client/conformance_execution_order.py +101 -0
- oep_client/conformance_execution_order_sample.py +9 -0
- oep_client/conformance_exhausted.py +112 -0
- oep_client/conformance_exhausted_sample.py +59 -0
- oep_client/conformance_fixture_metadata.py +56 -0
- oep_client/conformance_gpio.py +97 -0
- oep_client/conformance_gpio_lifecycle.py +69 -0
- oep_client/conformance_gpio_lifecycle_sample.py +8 -0
- oep_client/conformance_gpio_sample.py +12 -0
- oep_client/conformance_host_core.py +152 -0
- oep_client/conformance_host_core_sample.py +65 -0
- oep_client/conformance_host_deadline.py +96 -0
- oep_client/conformance_host_deadline_sample.py +89 -0
- oep_client/conformance_host_notifications.py +161 -0
- oep_client/conformance_host_notifications_sample.py +39 -0
- oep_client/conformance_host_request_sample.py +27 -0
- oep_client/conformance_host_requests.py +157 -0
- oep_client/conformance_host_resend.py +61 -0
- oep_client/conformance_host_resend_sample.py +66 -0
- oep_client/conformance_host_tlv.py +119 -0
- oep_client/conformance_host_tlv_sample.py +22 -0
- oep_client/conformance_host_values.py +95 -0
- oep_client/conformance_host_values_sample.py +36 -0
- oep_client/conformance_host_wait.py +70 -0
- oep_client/conformance_host_wait_sample.py +65 -0
- oep_client/conformance_i2c.py +141 -0
- oep_client/conformance_i2c_sample.py +14 -0
- oep_client/conformance_interface_smoke.py +79 -0
- oep_client/conformance_interfaces.py +111 -0
- oep_client/conformance_lease.py +168 -0
- oep_client/conformance_lease_sample.py +32 -0
- oep_client/conformance_link_routes.py +111 -0
- oep_client/conformance_link_routes_sample.py +15 -0
- oep_client/conformance_link_transfer_sample.py +24 -0
- oep_client/conformance_link_transfers.py +110 -0
- oep_client/conformance_logic.py +182 -0
- oep_client/conformance_logic_sample.py +14 -0
- oep_client/conformance_mailbox.py +156 -0
- oep_client/conformance_mailbox_sample.py +11 -0
- oep_client/conformance_notification_retention.py +44 -0
- oep_client/conformance_notification_retention_sample.py +41 -0
- oep_client/conformance_notification_sequence.py +214 -0
- oep_client/conformance_notification_sequence_sample.py +11 -0
- oep_client/conformance_oep_declarations.py +98 -0
- oep_client/conformance_oep_smoke.py +202 -0
- oep_client/conformance_outcome_sample.py +12 -0
- oep_client/conformance_outcomes.py +147 -0
- oep_client/conformance_pipeline.py +147 -0
- oep_client/conformance_pipeline_sample.py +9 -0
- oep_client/conformance_port_speed.py +208 -0
- oep_client/conformance_port_speed_execution.py +99 -0
- oep_client/conformance_port_speed_execution_sample.py +6 -0
- oep_client/conformance_port_speed_lifecycle.py +88 -0
- oep_client/conformance_port_speed_sample.py +17 -0
- oep_client/conformance_probe_input.py +84 -0
- oep_client/conformance_probe_input_sample.py +29 -0
- oep_client/conformance_recovery.py +131 -0
- oep_client/conformance_recovery_race_sample.py +133 -0
- oep_client/conformance_recovery_races.py +158 -0
- oep_client/conformance_recovery_sample.py +86 -0
- oep_client/conformance_refusal_order.py +73 -0
- oep_client/conformance_refusal_order_sample.py +33 -0
- oep_client/conformance_registered_ops.py +96 -0
- oep_client/conformance_replay_pressure.py +184 -0
- oep_client/conformance_reset.py +114 -0
- oep_client/conformance_reset_sample.py +8 -0
- oep_client/conformance_resource_sample.py +40 -0
- oep_client/conformance_resources.py +261 -0
- oep_client/conformance_response_race.py +76 -0
- oep_client/conformance_response_race_sample.py +57 -0
- oep_client/conformance_restart.py +81 -0
- oep_client/conformance_restart_sample.py +25 -0
- oep_client/conformance_retention.py +391 -0
- oep_client/conformance_retention_lifecycle.py +135 -0
- oep_client/conformance_retention_lifecycle_sample.py +11 -0
- oep_client/conformance_retention_sample.py +7 -0
- oep_client/conformance_retry.py +78 -0
- oep_client/conformance_retry_sample.py +10 -0
- oep_client/conformance_route_sample.py +66 -0
- oep_client/conformance_routes.py +263 -0
- oep_client/conformance_run.py +120 -0
- oep_client/conformance_run_sample.py +9 -0
- oep_client/conformance_scan.py +122 -0
- oep_client/conformance_scan_options.py +128 -0
- oep_client/conformance_scan_options_sample.py +9 -0
- oep_client/conformance_scan_sample.py +10 -0
- oep_client/conformance_selected_metadata.py +43 -0
- oep_client/conformance_serial.py +118 -0
- oep_client/conformance_session_loss.py +94 -0
- oep_client/conformance_session_loss_sample.py +62 -0
- oep_client/conformance_session_smoke.py +149 -0
- oep_client/conformance_spi.py +161 -0
- oep_client/conformance_spi_sample.py +16 -0
- oep_client/conformance_step.py +100 -0
- oep_client/conformance_step_sample.py +9 -0
- oep_client/conformance_stream.py +238 -0
- oep_client/conformance_stream_sample.py +14 -0
- oep_client/conformance_subscription_sample.py +25 -0
- oep_client/conformance_subscriptions.py +294 -0
- oep_client/conformance_tcp.py +94 -0
- oep_client/conformance_tcp_peers.py +206 -0
- oep_client/conformance_tcp_recovery.py +109 -0
- oep_client/conformance_tcp_recovery_sample.py +168 -0
- oep_client/conformance_tlv_requests.py +127 -0
- oep_client/conformance_uart.py +141 -0
- oep_client/conformance_uart_sample.py +15 -0
- oep_client/conformance_uart_stream.py +37 -0
- oep_client/conformance_uart_stream_sample.py +11 -0
- oep_client/conformance_usb.py +162 -0
- oep_client/conformance_usb_cases.py +103 -0
- oep_client/conformance_usb_model.py +43 -0
- oep_client/conformance_wire_options.py +145 -0
- oep_client/conformance_wire_options_sample.py +11 -0
- oep_client/conformance_writer_lease.py +77 -0
- oep_client/conformance_writer_lease_sample.py +9 -0
- oep_client/console.py +51 -46
- oep_client/core.py +72 -48
- oep_client/dump.py +9 -8
- oep_client/endpoint.py +1285 -1383
- oep_client/fixture.py +31 -103
- oep_client/hardware.py +587 -0
- oep_client/hid_stream.py +74 -12
- oep_client/host.py +178 -78
- oep_client/interfaces.py +67 -52
- oep_client/kept_session.py +36 -11
- oep_client/link.py +244 -99
- oep_client/linktest.py +14 -6
- oep_client/message.py +22 -17
- oep_client/names.py +12 -26
- oep_client/pins.py +70 -63
- oep_client/pytest_conformance.py +60 -0
- oep_client/registry.py +60 -59
- oep_client/riscv.py +287 -145
- oep_client/uiapduino.py +2 -0
- oep_client/usb_stream.py +5 -3
- oep_client/virtual_allocator_model.py +33 -0
- oep_client/virtual_analog_model.py +193 -0
- oep_client/virtual_arm_adi_model.py +139 -0
- oep_client/virtual_attach_model.py +146 -0
- oep_client/virtual_bench.py +131 -115
- oep_client/virtual_bench_capture.py +409 -249
- oep_client/virtual_bench_serial.py +60 -22
- oep_client/virtual_bench_serve.py +31 -99
- oep_client/virtual_bench_usb.py +94 -0
- oep_client/virtual_block_model.py +80 -0
- oep_client/virtual_capture_group_geometry_model.py +43 -0
- oep_client/virtual_capture_group_model.py +245 -0
- oep_client/virtual_capture_metadata_model.py +24 -0
- oep_client/virtual_capture_timeline_model.py +390 -0
- oep_client/virtual_clock_model.py +42 -0
- oep_client/virtual_config_execution_model.py +68 -0
- oep_client/virtual_config_model.py +176 -0
- oep_client/virtual_config_paging_model.py +12 -0
- oep_client/virtual_config_power_loss_model.py +77 -0
- oep_client/virtual_config_storage_model.py +20 -0
- oep_client/virtual_core.py +229 -0
- oep_client/virtual_cut_model.py +83 -0
- oep_client/virtual_data_model.py +97 -0
- oep_client/virtual_debug_model.py +149 -0
- oep_client/virtual_declaration_model.py +39 -0
- oep_client/virtual_dependency_model.py +109 -0
- oep_client/virtual_dmseq_model.py +66 -0
- oep_client/virtual_dmseq_target_model.py +66 -0
- oep_client/virtual_fixture_metadata_model.py +22 -0
- oep_client/virtual_gpio_lifecycle_model.py +15 -0
- oep_client/virtual_gpio_model.py +99 -0
- oep_client/virtual_i2c_model.py +134 -0
- oep_client/virtual_link_routes_model.py +42 -0
- oep_client/virtual_link_transfer_model.py +62 -0
- oep_client/virtual_logic_model.py +199 -0
- oep_client/virtual_mailbox_model.py +55 -0
- oep_client/virtual_names.py +29 -0
- oep_client/virtual_notification_model.py +81 -0
- oep_client/virtual_oep_declaration_model.py +55 -0
- oep_client/virtual_outcome_model.py +78 -0
- oep_client/virtual_pipeline_model.py +94 -0
- oep_client/virtual_port_speed_execution_model.py +36 -0
- oep_client/virtual_port_speed_model.py +148 -0
- oep_client/virtual_registered_ops_model.py +48 -0
- oep_client/virtual_reset_model.py +68 -0
- oep_client/virtual_resource_model.py +86 -0
- oep_client/virtual_restart_model.py +77 -0
- oep_client/virtual_retention_model.py +44 -0
- oep_client/virtual_retry_model.py +92 -0
- oep_client/virtual_route_model.py +187 -0
- oep_client/virtual_run_model.py +84 -0
- oep_client/virtual_scan_model.py +75 -0
- oep_client/virtual_scan_options_model.py +83 -0
- oep_client/virtual_selected_metadata_model.py +17 -0
- oep_client/virtual_spi_model.py +154 -0
- oep_client/virtual_step_model.py +60 -0
- oep_client/virtual_stream_model.py +99 -0
- oep_client/virtual_tlv_request_model.py +74 -0
- oep_client/virtual_uart_model.py +135 -0
- oep_client/virtual_wire_options_model.py +125 -0
- oep_client/virtual_writer_lease_model.py +33 -0
- {oep_client_python-0.0.31.dist-info → oep_client_python-0.0.32.dist-info}/METADATA +149 -192
- oep_client_python-0.0.32.dist-info/RECORD +268 -0
- oep_client_python-0.0.32.dist-info/entry_points.txt +4 -0
- oep_client/multirate.py +0 -254
- oep_client_python-0.0.31.dist-info/RECORD +0 -43
- oep_client_python-0.0.31.dist-info/entry_points.txt +0 -2
- {oep_client_python-0.0.31.dist-info → oep_client_python-0.0.32.dist-info}/WHEEL +0 -0
- {oep_client_python-0.0.31.dist-info → oep_client_python-0.0.32.dist-info}/licenses/LICENSE +0 -0
oep_client/__init__.py
CHANGED
oep_client/__main__.py
CHANGED
|
@@ -2,18 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
oep dump --port /run/board-identify/by-id/<probe> oep dump --virtual p4-x035 --prefix oep.target --json
|
|
4
4
|
oep config show <probe> (the settings and what the probe declares; lock-free)
|
|
5
|
-
oep config state <probe> (the
|
|
6
|
-
oep config
|
|
7
|
-
oep config
|
|
8
|
-
oep config
|
|
9
|
-
oep config uart <probe> oep.fixture.uart#1 115200 --format 8N1
|
|
10
|
-
oep config disable <probe> 3 4 (channels the probe never uses or touches; remove disable CH re-enables)
|
|
11
|
-
oep config remove <probe> bind 1 oep config save <probe> oep config erase <probe>
|
|
12
|
-
oep config wifi <probe> --index 0 --ssid LAB --pass-prompt [--save] (a network the probe joins, probe.config §1.4;
|
|
13
|
-
the passphrase is asked without echo or read from --pass-env VAR, never
|
|
14
|
-
printed; without either the entry keeps its passphrase)
|
|
15
|
-
oep config wifi <probe> --from-env [--save] (OEP_WIFI_SSID_<n> / OEP_WIFI_PASS_<n>, n = the index)
|
|
16
|
-
oep config wifi-unset <probe> --index 0 [--save]
|
|
5
|
+
oep config state <probe> (the storage state; lock-free)
|
|
6
|
+
oep config label <probe> 23 nrst oep config idle <probe> 20 pull-up
|
|
7
|
+
oep config disable <probe> 3 4 (channels the probe never drives or sets up; remove disable CH re-enables)
|
|
8
|
+
oep config remove <probe> idle 20 oep config save <probe> oep config erase <probe>
|
|
17
9
|
oep find [--timeout 2] [--json] [--no-verify] (probes announcing _oep._tcp by DNS-SD over mDNS: unit_id, host,
|
|
18
10
|
port, IP; each verified first by confirm + describe's unit_id, host guide
|
|
19
11
|
§4.1 - one that fails is dropped with a warning)
|
|
@@ -22,8 +14,8 @@
|
|
|
22
14
|
500000 - a faster rate only when named, after its 1 s verify each way)
|
|
23
15
|
oep linktest <probe> --rates now,921600 --patterns in,out,duplex --inflight 1,2 --sizes 128,496 --frames 300
|
|
24
16
|
oep pins <probe> --power 5 --wire swio (find the target's debug pins and reset line: classify the channels, scan,
|
|
25
|
-
identify, hold-low + attach under reset; prints
|
|
26
|
-
oep clock <probe> [-n 8] [--json] (fn 0's clock, core §7.
|
|
17
|
+
identify, hold-low + attach under reset; prints the labels, --save writes them)
|
|
18
|
+
oep clock <probe> [-n 8] [--json] (fn 0's clock, core §7.6: the probe's uptime_ns and boot_id against this
|
|
27
19
|
host's time - the reading with the shortest round trip of n)
|
|
28
20
|
oep restart <probe> [--reopen-s S] (oep.probe.restart: the probe restarts; waits until it is back, its new boot_id)
|
|
29
21
|
|
|
@@ -37,7 +29,9 @@ from __future__ import annotations
|
|
|
37
29
|
import argparse
|
|
38
30
|
import sys
|
|
39
31
|
|
|
32
|
+
import getpass
|
|
40
33
|
import json
|
|
34
|
+
import os
|
|
41
35
|
import struct
|
|
42
36
|
|
|
43
37
|
from . import catalog, config, core, dump, virtual_bench, host, link
|
|
@@ -63,7 +57,7 @@ def main(argv=None) -> int:
|
|
|
63
57
|
parser = argparse.ArgumentParser(prog="oep", description="Open Embedded Probe: what a probe offers, its settings")
|
|
64
58
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
65
59
|
_config_parser(sub)
|
|
66
|
-
sp = sub.add_parser("speed", help="port_speed (oep-if-link §3
|
|
60
|
+
sp = sub.add_parser("speed", help="port_speed (oep-if-link §3; this client's procedure): try faster rates on a UART bridge, "
|
|
67
61
|
"print the report")
|
|
68
62
|
sp.add_argument("probe", help="the probe's serial port (a UART bridge this host opens)")
|
|
69
63
|
sp.add_argument("rates", nargs="?", default="", help="the candidates, comma-separated, in order of preference "
|
|
@@ -102,19 +96,19 @@ def main(argv=None) -> int:
|
|
|
102
96
|
lt.add_argument("--low-latency", choices=("on", "off"), default="on", help="the serial driver's low-latency mode")
|
|
103
97
|
lt.add_argument("--json", action="store_true", help="one JSON object per cell")
|
|
104
98
|
pn = sub.add_parser("pins", help="find where a target is wired: classify the channels, scan the wire, find the "
|
|
105
|
-
"reset line, suggest
|
|
99
|
+
"reset line, suggest labels (writes nothing without --save)")
|
|
106
100
|
pn.add_argument("probe", help="a probe: a serial port, tcp://HOST:PORT or usb[:VID:PID[:SERIAL]]")
|
|
107
101
|
pn.add_argument("--power", type=int, help="the gpio channel that powers the target: switched off, then on, to "
|
|
108
102
|
"see which channels follow it (never touched without this)")
|
|
109
103
|
pn.add_argument("--exclude", default="", help="channels never to read, scan or hold, comma-separated")
|
|
110
104
|
pn.add_argument("--wire", choices=("swio", "rvswd", "swd"), default="swio")
|
|
111
|
-
pn.add_argument("--steps", default="classify,hold,scan,identify,reset,
|
|
112
|
-
help="the steps to run, comma-separated (default all: classify, hold, scan, identify, reset,
|
|
113
|
-
pn.add_argument("--save", action="store_true", help="write the suggested
|
|
114
|
-
pn.add_argument("--
|
|
115
|
-
|
|
105
|
+
pn.add_argument("--steps", default="classify,hold,scan,identify,reset,labels",
|
|
106
|
+
help="the steps to run, comma-separated (default all: classify, hold, scan, identify, reset, labels)")
|
|
107
|
+
pn.add_argument("--save", action="store_true", help="write the suggested labels (config set, then save)")
|
|
108
|
+
pn.add_argument("--name", help="the host's connection profile name: labels <name>.nrst / <name>.power_hi (a probe "
|
|
109
|
+
"serving several targets; default: nrst / power_hi)")
|
|
116
110
|
pn.add_argument("--json", action="store_true", help="the report as JSON (the steps' lines go to stderr)")
|
|
117
|
-
ck = sub.add_parser("clock", help="the probe's clock (fn 0 clock, core §7.
|
|
111
|
+
ck = sub.add_parser("clock", help="the probe's clock (fn 0 clock, core §7.6) against this host's: lock-free")
|
|
118
112
|
ck.add_argument("probe", help="a probe: a serial port, tcp://HOST:PORT or usb[:VID:PID[:SERIAL]]")
|
|
119
113
|
ck.add_argument("-n", type=int, default=8, help="readings; the one with the shortest round trip is kept (default 8)")
|
|
120
114
|
ck.add_argument("--json", action="store_true")
|
|
@@ -246,7 +240,7 @@ def _pins_cmd(args) -> int:
|
|
|
246
240
|
try:
|
|
247
241
|
core.take(hst, 10000, owner="oep pins")
|
|
248
242
|
finder = pins.PinFinder(hst, wire=args.wire, power=args.power, exclude=exclude, say=say, probe=args.probe,
|
|
249
|
-
save=args.save,
|
|
243
|
+
save=args.save, name=args.name)
|
|
250
244
|
report = finder.run(steps=tuple(s for s in args.steps.split(",") if s))
|
|
251
245
|
say(f"done in {report.elapsed_s:.1f} s")
|
|
252
246
|
if args.json:
|
|
@@ -260,7 +254,7 @@ def _pins_cmd(args) -> int:
|
|
|
260
254
|
return 2
|
|
261
255
|
finally:
|
|
262
256
|
hst.link.close()
|
|
263
|
-
return 0 if report.
|
|
257
|
+
return 0 if report.resolution == 'unique-candidate' else 1
|
|
264
258
|
|
|
265
259
|
|
|
266
260
|
# ---- oep linktest -------------------------------------------------------------------------------------------------
|
|
@@ -340,40 +334,16 @@ def _speed(args) -> int:
|
|
|
340
334
|
# ---- oep config ----------------------------------------------------------------------------------------------------
|
|
341
335
|
|
|
342
336
|
def _config_parser(sub) -> None:
|
|
343
|
-
c = sub.add_parser("config", help="the probe's settings (oep.probe.config):
|
|
337
|
+
c = sub.add_parser("config", help="the probe's settings (oep.probe.config): labels, idle, disable, pass-throughs, "
|
|
338
|
+
"Wi-Fi / IPv4, its own settings, save")
|
|
344
339
|
cs = c.add_subparsers(dest="action", required=True)
|
|
345
|
-
show = cs.add_parser("show", help="the settings, what the probe declares, and the
|
|
340
|
+
show = cs.add_parser("show", help="the settings, what the probe declares, and the storage state")
|
|
346
341
|
show.add_argument("probe")
|
|
347
342
|
show.add_argument("--json", action="store_true")
|
|
348
|
-
state = cs.add_parser("state", help="the
|
|
343
|
+
state = cs.add_parser("state", help="the storage state (op state, lock-free)")
|
|
349
344
|
state.add_argument("probe")
|
|
350
345
|
state.add_argument("--json", action="store_true")
|
|
351
|
-
|
|
352
|
-
slot.add_argument("probe")
|
|
353
|
-
slot.add_argument("--slot", type=int, default=0, help="the slot number (default 0)")
|
|
354
|
-
slot.add_argument("--name", required=True, help="1-32 of a-z 0-9 - _ (the oep://<probe>/<name> address)")
|
|
355
|
-
slot.add_argument("--wire", help="rvswd or swio (or an fn); default: the probe's only wire")
|
|
356
|
-
slot.add_argument("--pins", help="swdio,swclk (one pin on swio); default: the wire's only pin set")
|
|
357
|
-
slot.add_argument("--attach", choices=sorted(config.ATTACH), default="host")
|
|
358
|
-
slot.add_argument("--retry", type=float, default=0, help="at-boot: try again every N s while absent (0: never)")
|
|
359
|
-
slot.add_argument("--mechanism", choices=sorted(config.MECHANISM), default="dmseq",
|
|
360
|
-
help="the console's mechanism, or none (no console on this slot)")
|
|
361
|
-
slot.add_argument("--max-speed", type=int, default=0,
|
|
362
|
-
help="the line's ceiling in Hz for the probe's own attach (0: none); the target's, e.g. 1000000")
|
|
363
|
-
slot.add_argument("--idle-clock", choices=sorted(config.IDLE_CLOCK), default="high",
|
|
364
|
-
help="rvswd: SWCLK while the line rests (the target's: low on CH32L103 / V203)")
|
|
365
|
-
slot.add_argument("--save", action="store_true", help="save after the change")
|
|
366
|
-
bind = cs.add_parser("bind", help="the one stream a serial port carries (set it again to change it)")
|
|
367
|
-
bind.add_argument("probe")
|
|
368
|
-
bind.add_argument("--port", type=int, required=True, help="the serial port (its transport index, see show)")
|
|
369
|
-
bind.add_argument("--stream", required=True, help="slot:NAME, slot:N or uart:FN")
|
|
370
|
-
bind.add_argument("--save", action="store_true")
|
|
371
|
-
plan = cs.add_parser("plan", help="the pins an interface keeps (its whole plan, kept as a setting)")
|
|
372
|
-
plan.add_argument("probe")
|
|
373
|
-
plan.add_argument("fn", help="an fn, or name#instance (the list instance, 0 = the first; #0 may be left out, core §7.2)")
|
|
374
|
-
plan.add_argument("roles", nargs="+", help="ROLE=CHANNEL, ROLE a number or the interface's role name (rx, tx, line...)")
|
|
375
|
-
plan.add_argument("--save", action="store_true")
|
|
376
|
-
label = cs.add_parser("label", help="name a channel (a setting, read with config get)")
|
|
346
|
+
label = cs.add_parser("label", help="name a channel (a setting, read with config show)")
|
|
377
347
|
label.add_argument("probe")
|
|
378
348
|
label.add_argument("channel", type=int)
|
|
379
349
|
label.add_argument("text")
|
|
@@ -382,119 +352,73 @@ def _config_parser(sub) -> None:
|
|
|
382
352
|
idle.add_argument("probe")
|
|
383
353
|
idle.add_argument("channel", type=int)
|
|
384
354
|
idle.add_argument("mode", choices=sorted(config.IDLE))
|
|
385
|
-
drive = idle.add_mutually_exclusive_group()
|
|
386
|
-
drive.add_argument("--drive-ma", type=int, help="output modes: the strongest drive level of about this many mA or "
|
|
387
|
-
"less, picked here from the gpio's describe drive_levels")
|
|
388
|
-
drive.add_argument("--drive-level", type=int, help="output modes: a drive level number of this probe")
|
|
389
355
|
idle.add_argument("--save", action="store_true")
|
|
390
|
-
dis = cs.add_parser("disable", help="channels the probe never
|
|
356
|
+
dis = cs.add_parser("disable", help="channels the probe never drives or sets up (not on this board)")
|
|
391
357
|
dis.add_argument("probe")
|
|
392
358
|
dis.add_argument("channels", type=int, nargs="+")
|
|
393
359
|
dis.add_argument("--save", action="store_true")
|
|
394
|
-
|
|
395
|
-
uart.add_argument("probe")
|
|
396
|
-
uart.add_argument("fn", help="an fn, or name#instance of the oep.fixture.uart")
|
|
397
|
-
uart.add_argument("baud", type=int)
|
|
398
|
-
uart.add_argument("--format", default="8N1", help="data bits, parity, stop bits: 8N1 (default), 8E1, 7O2 ...")
|
|
399
|
-
uart.add_argument("--save", action="store_true")
|
|
400
|
-
rm = cs.add_parser("remove", help="remove one item (unset): slot N, bind PORT, plan FN, label CH, idle CH, uart FN, disable CH")
|
|
360
|
+
rm = cs.add_parser("remove", help="remove one item (unset): label CH, idle CH, disable CH")
|
|
401
361
|
rm.add_argument("probe")
|
|
402
|
-
rm.add_argument("kind",
|
|
403
|
-
rm.add_argument("
|
|
362
|
+
rm.add_argument("kind", help="the item's name: label, idle, disable, passthrough, wifi, ... or a probe's own")
|
|
363
|
+
rm.add_argument("channel", type=int)
|
|
404
364
|
rm.add_argument("--save", action="store_true")
|
|
405
|
-
wifi = cs.add_parser("wifi", help="a Wi-Fi network the probe
|
|
365
|
+
wifi = cs.add_parser("wifi", help="a Wi-Fi network the probe tries, by entry (the passphrase asked, never shown)")
|
|
406
366
|
wifi.add_argument("probe")
|
|
407
|
-
wifi.add_argument("
|
|
408
|
-
wifi.add_argument("
|
|
367
|
+
wifi.add_argument("entry", type=int)
|
|
368
|
+
wifi.add_argument("ssid")
|
|
409
369
|
pw = wifi.add_mutually_exclusive_group()
|
|
410
|
-
pw.add_argument("--
|
|
411
|
-
pw.add_argument("--
|
|
412
|
-
pw.add_argument("--
|
|
413
|
-
pw.add_argument("--from-env", action="store_true", help="every entry from OEP_WIFI_SSID_<n> / OEP_WIFI_PASS_<n> "
|
|
414
|
-
"(n = the index; no PASS: open); entries whose SSID and passphrase presence already match are not "
|
|
415
|
-
"sent again (a passphrase cannot be compared: --force sends them)")
|
|
416
|
-
wifi.add_argument("--force", action="store_true", help="--from-env: send every entry, passphrases included")
|
|
370
|
+
pw.add_argument("--open", action="store_true", help="a network without a passphrase")
|
|
371
|
+
pw.add_argument("--keep", action="store_true", help="keep the entry's passphrase (pass_len 0xFF)")
|
|
372
|
+
pw.add_argument("--passphrase-env", metavar="VAR", help="take the passphrase from this environment variable")
|
|
417
373
|
wifi.add_argument("--save", action="store_true")
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
374
|
+
ip = cs.add_parser("ipv4", help="how a netif gets its IPv4 address: dhcp, or a.b.c.d/prefix")
|
|
375
|
+
ip.add_argument("probe")
|
|
376
|
+
ip.add_argument("address", help="dhcp, or a.b.c.d/prefix")
|
|
377
|
+
ip.add_argument("--netif", default="wifi", help="the netif's name (describe's netif list; default wifi)")
|
|
378
|
+
ip.add_argument("--gateway")
|
|
379
|
+
ip.add_argument("--dns")
|
|
380
|
+
ip.add_argument("--save", action="store_true")
|
|
381
|
+
net = cs.add_parser("network", help="the network now: the TCP port, each netif's state and address (lock-free)")
|
|
382
|
+
net.add_argument("probe")
|
|
383
|
+
net.add_argument("--json", action="store_true")
|
|
384
|
+
pt = cs.add_parser("passthrough", help="a serial port carries a fixture UART's receive outside the OEP frames")
|
|
385
|
+
pt.add_argument("probe")
|
|
386
|
+
pt.add_argument("port", type=int, help="fn 0's transport index of a serial port")
|
|
387
|
+
pt.add_argument("uart", help="the fixture UART: fn number or name#instance")
|
|
388
|
+
pt.add_argument("rx", type=int, help="the RX channel")
|
|
389
|
+
pt.add_argument("--baud", type=int, default=115200)
|
|
390
|
+
pt.add_argument("--format", type=int, default=0)
|
|
391
|
+
pt.add_argument("--save", action="store_true")
|
|
392
|
+
cp = cs.add_parser("console-passthrough", help="a serial port carries the target's debug console outside the frames")
|
|
393
|
+
cp.add_argument("probe")
|
|
394
|
+
cp.add_argument("port", type=int, help="fn 0's transport index of a serial port")
|
|
395
|
+
cp.add_argument("wire", help="the wire: fn number or name#instance (oep.wire.rvswd / oep.wire.swio)")
|
|
396
|
+
cp.add_argument("swdio", type=int)
|
|
397
|
+
cp.add_argument("swclk", type=int, nargs="?", default=0xFFFF)
|
|
398
|
+
cp.add_argument("--console", required=True, help="the console: fn number or name#instance")
|
|
399
|
+
cp.add_argument("--mechanism", required=True, help="the console's mechanism by name (sdi, dmdata, dmseq, ...)")
|
|
400
|
+
cp.add_argument("--max-speed", type=int, default=1_000_000)
|
|
401
|
+
cp.add_argument("--save", action="store_true")
|
|
402
|
+
own = cs.add_parser("set", help="a probe's own setting by its name (reverse-DNS), its form from describe")
|
|
403
|
+
own.add_argument("probe")
|
|
404
|
+
own.add_argument("name")
|
|
405
|
+
own.add_argument("value", help="text, a number (u32), 0 / 1 (bool), a.b.c.d (ipv4) or hex (bytes)")
|
|
406
|
+
own.add_argument("--key", type=int, default=0)
|
|
407
|
+
own.add_argument("--save", action="store_true")
|
|
422
408
|
for name in ("save", "erase"):
|
|
423
409
|
cs.add_parser(name, help=f"{name} the stored settings").add_argument("probe")
|
|
424
410
|
|
|
425
411
|
|
|
426
|
-
def _pins(hst, fn: int, text: str | None, wire: str) -> tuple[int, int]:
|
|
427
|
-
if text:
|
|
428
|
-
parts = [int(x, 0) for x in text.split(",")]
|
|
429
|
-
return (parts[0], parts[1] if len(parts) > 1 else 0xFFFF)
|
|
430
|
-
groups = []
|
|
431
|
-
for tag, v in core.describe(hst, fn):
|
|
432
|
-
if tag & 0x7F == catalog.CHANNEL_GROUP:
|
|
433
|
-
roles = dict(catalog.unpack_channel_group(v)[1])
|
|
434
|
-
groups.append((roles.get(1, 0xFFFF), roles.get(2, 0xFFFF)))
|
|
435
|
-
if len(groups) != 1:
|
|
436
|
-
raise SystemExit(f"{wire}: {len(groups)} pin sets on this probe - name one with --pins")
|
|
437
|
-
return groups[0]
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
def _plan_fn(hst, spec: str) -> tuple[int, dict[str, int]]:
|
|
441
|
-
"""fn and its role names (from the registry) for `spec`: an fn number, or name[#instance] (the list's instance,
|
|
442
|
-
0-based, core §7.2)."""
|
|
443
|
-
from . import registry as reg
|
|
444
|
-
if spec.isdigit():
|
|
445
|
-
fn = int(spec)
|
|
446
|
-
name = next((e.name for e in core.list_entries(hst) if e.fn == fn), "")
|
|
447
|
-
else:
|
|
448
|
-
name, _, k = spec.partition("#")
|
|
449
|
-
entries = [e for e in core.list_entries(hst, name, exact=True)]
|
|
450
|
-
if not entries:
|
|
451
|
-
raise SystemExit(f"the probe offers no {name}")
|
|
452
|
-
instance = int(k) if k else 0
|
|
453
|
-
fn = next((e.fn for e in entries if e.instance == instance), None)
|
|
454
|
-
if fn is None:
|
|
455
|
-
raise SystemExit(f"{name}: instances {sorted(e.instance for e in entries)}, not {instance}")
|
|
456
|
-
iface = reg.INTERFACES.get(name)
|
|
457
|
-
roles = dict(iface.enum.get("role", {})) if iface else {}
|
|
458
|
-
return fn, roles
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
def _wire_fn(hst, wire: str | None) -> int:
|
|
462
|
-
if wire is None:
|
|
463
|
-
wires = [e for e in core.list_entries(hst, "oep.wire") if e.name in ("oep.wire.rvswd", "oep.wire.swio")]
|
|
464
|
-
if len(wires) != 1:
|
|
465
|
-
raise SystemExit("this probe has " + (", ".join(f"{e.name} (fn {e.fn})" for e in wires) or "no RISC-V wire")
|
|
466
|
-
+ ": name one with --wire")
|
|
467
|
-
return wires[0].fn
|
|
468
|
-
name = wire if wire.startswith("oep.") else f"oep.wire.{wire}"
|
|
469
|
-
if wire.isdigit():
|
|
470
|
-
return int(wire)
|
|
471
|
-
try:
|
|
472
|
-
return core.find(hst, name)
|
|
473
|
-
except LookupError:
|
|
474
|
-
raise SystemExit(f"this probe does not offer {name}") from None
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
def _stream(spec: str, slots: dict[str, int]) -> tuple[str, int]:
|
|
478
|
-
kind, _, key = spec.partition(":")
|
|
479
|
-
if kind not in config.STREAM or not key:
|
|
480
|
-
raise SystemExit(f"--stream {spec}: want slot:NAME, slot:N or uart:FN")
|
|
481
|
-
if kind == "slot" and not key.isdigit():
|
|
482
|
-
if key not in slots:
|
|
483
|
-
raise SystemExit(f"--stream {spec}: no slot named {key} (see oep config show)")
|
|
484
|
-
return kind, slots[key]
|
|
485
|
-
return kind, int(key)
|
|
486
|
-
|
|
487
|
-
|
|
488
412
|
def _change(hst, cfg, items, save: bool) -> None:
|
|
489
413
|
core.take(hst, 3000, owner="oep config")
|
|
490
414
|
try:
|
|
491
|
-
|
|
492
|
-
print(f"set:
|
|
415
|
+
gen = cfg.set(items)
|
|
416
|
+
print(f"set: generation {gen}")
|
|
493
417
|
if save:
|
|
494
418
|
if cfg.needs_save():
|
|
495
|
-
print(f"saved:
|
|
419
|
+
print(f"saved: generation {cfg.save()}")
|
|
496
420
|
else:
|
|
497
|
-
print("saved already (
|
|
421
|
+
print("saved already (saved_generation is the current generation): not written")
|
|
498
422
|
finally:
|
|
499
423
|
hst.end()
|
|
500
424
|
|
|
@@ -507,63 +431,50 @@ def _config(args) -> int:
|
|
|
507
431
|
return _show(hst, cfg, args.json)
|
|
508
432
|
if args.action == "state":
|
|
509
433
|
return _state(cfg, args.json)
|
|
510
|
-
if args.action == "
|
|
511
|
-
fn = _wire_fn(hst, args.wire)
|
|
512
|
-
args.wire = args.wire or str(fn)
|
|
513
|
-
it = config.Slot(slot=args.slot, wire_fn=fn, pins=_pins(hst, fn, args.pins, args.wire), name=args.name,
|
|
514
|
-
attach=args.attach, retry_s=args.retry, mechanism=args.mechanism,
|
|
515
|
-
max_speed=args.max_speed, idle_clock=args.idle_clock)
|
|
516
|
-
_change(hst, cfg, [it], args.save)
|
|
517
|
-
elif args.action == "bind":
|
|
518
|
-
slots = {it.name: it.slot for it in cfg.items() if isinstance(it, config.Slot)}
|
|
519
|
-
_change(hst, cfg, [config.Bind(port=args.port, stream=_stream(args.stream, slots))], args.save)
|
|
520
|
-
elif args.action == "plan":
|
|
521
|
-
fn, roles = _plan_fn(hst, args.fn)
|
|
522
|
-
items = []
|
|
523
|
-
for spec in args.roles:
|
|
524
|
-
role, _, ch = spec.partition("=")
|
|
525
|
-
if not ch:
|
|
526
|
-
raise SystemExit(f"{spec}: want ROLE=CHANNEL")
|
|
527
|
-
number = int(role) if role.isdigit() else roles.get(role.lower())
|
|
528
|
-
if number is None:
|
|
529
|
-
raise SystemExit(f"{role}: not a role of fn {fn} (roles: {', '.join(sorted(roles)) or 'numbers only'})")
|
|
530
|
-
items.append(config.Plan(fn=fn, role=number, channel=int(ch, 0)))
|
|
531
|
-
_change(hst, cfg, items, args.save)
|
|
532
|
-
elif args.action == "uart":
|
|
533
|
-
fn, _ = _plan_fn(hst, args.fn)
|
|
534
|
-
from .fixture import FixtureUart
|
|
535
|
-
fmt = args.format.upper()
|
|
536
|
-
try:
|
|
537
|
-
byte = FixtureUart.format_byte(int(fmt[0]), fmt[1], int(fmt[2]))
|
|
538
|
-
except (KeyError, ValueError, IndexError):
|
|
539
|
-
raise SystemExit(f"--format {args.format}: want <data bits><parity><stop bits>, e.g. 8N1, 8E2, 7O1") from None
|
|
540
|
-
_change(hst, cfg, [config.Uart(fn=fn, baud=args.baud, format=byte)], args.save)
|
|
541
|
-
elif args.action == "label":
|
|
434
|
+
if args.action == "label":
|
|
542
435
|
_change(hst, cfg, [config.Label(channel=args.channel, text=args.text)], args.save)
|
|
543
436
|
elif args.action == "idle":
|
|
544
|
-
|
|
545
|
-
drive = Drive.level(args.drive_level) if args.drive_level is not None else None
|
|
546
|
-
if args.drive_ma is not None:
|
|
547
|
-
levels = Gpio(hst).drive_levels()
|
|
548
|
-
if levels is None:
|
|
549
|
-
raise SystemExit("--drive-ma: this probe declares no drive_levels (its strength cannot be chosen)")
|
|
550
|
-
drive = levels.at_most(args.drive_ma)
|
|
551
|
-
if drive is not None and args.mode not in ("output-low", "output-high"):
|
|
552
|
-
raise SystemExit(f"--drive-ma / --drive-level go with output-low / output-high, not {args.mode}")
|
|
553
|
-
_change(hst, cfg, [config.Idle(channel=args.channel, mode=args.mode, drive=drive)], args.save)
|
|
437
|
+
_change(hst, cfg, [config.Idle(channel=args.channel, mode=args.mode)], args.save)
|
|
554
438
|
elif args.action == "disable":
|
|
555
439
|
_change(hst, cfg, [config.Disable(channel=ch) for ch in args.channels], args.save)
|
|
556
440
|
elif args.action == "remove":
|
|
557
|
-
_change(hst, cfg, [config.remove(args.kind, args.
|
|
441
|
+
_change(hst, cfg, [config.remove(args.kind, args.channel)], args.save)
|
|
558
442
|
elif args.action == "wifi":
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
443
|
+
if args.keep:
|
|
444
|
+
passphrase = None
|
|
445
|
+
elif args.open:
|
|
446
|
+
passphrase = ""
|
|
447
|
+
elif args.passphrase_env:
|
|
448
|
+
passphrase = os.environ[args.passphrase_env]
|
|
449
|
+
else:
|
|
450
|
+
passphrase = getpass.getpass(f"passphrase for {args.ssid}: ")
|
|
451
|
+
_change(hst, cfg, [config.Wifi(entry=args.entry, ssid=args.ssid, passphrase=passphrase)], args.save)
|
|
452
|
+
elif args.action == "ipv4":
|
|
453
|
+
address = None if args.address == "dhcp" else args.address
|
|
454
|
+
_change(hst, cfg, [config.Ipv4(netif=args.netif, address=address, gateway=args.gateway, dns=args.dns)],
|
|
455
|
+
args.save)
|
|
456
|
+
elif args.action == "network":
|
|
457
|
+
return _network(cfg, args.json)
|
|
458
|
+
elif args.action == "passthrough":
|
|
459
|
+
_change(hst, cfg, [config.Passthrough(port=args.port, fn=_fn(hst, args.uart), rx=args.rx, baud=args.baud,
|
|
460
|
+
format=args.format)], args.save)
|
|
461
|
+
elif args.action == "console-passthrough":
|
|
462
|
+
from . import console as _console
|
|
463
|
+
cfn = _fn(hst, args.console)
|
|
464
|
+
names = [v.decode() for t, v in core.describe(hst, cfn) if t == _console.Console.TAG_MECHANISM]
|
|
465
|
+
if args.mechanism not in names:
|
|
466
|
+
raise SystemExit(f"the console declares no mechanism {args.mechanism} ({', '.join(names)})")
|
|
467
|
+
mech = names.index(args.mechanism) + 1 # the place in describe's list, from 1 (core §7.7)
|
|
468
|
+
_change(hst, cfg, [config.ConsolePassthrough(port=args.port, wire_fn=_fn(hst, args.wire), swdio=args.swdio,
|
|
469
|
+
swclk=args.swclk, max_speed=args.max_speed, console_fn=cfn,
|
|
470
|
+
mechanism=mech)], args.save)
|
|
471
|
+
elif args.action == "set":
|
|
472
|
+
_change(hst, cfg, [config.Own(args.name, _own_value(cfg, args.name, args.value), args.key)], args.save)
|
|
562
473
|
else:
|
|
563
474
|
core.take(hst, 3000, owner="oep config")
|
|
564
475
|
try:
|
|
565
476
|
if args.action == "save":
|
|
566
|
-
print(f"saved:
|
|
477
|
+
print(f"saved: generation {cfg.save()}")
|
|
567
478
|
else:
|
|
568
479
|
cfg.erase()
|
|
569
480
|
print("erased (the settings now in effect stay until the probe restarts)")
|
|
@@ -577,154 +488,80 @@ def _config(args) -> int:
|
|
|
577
488
|
hst.link.close()
|
|
578
489
|
|
|
579
490
|
|
|
580
|
-
def
|
|
581
|
-
"""
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
if
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
passphrase = None
|
|
618
|
-
else:
|
|
619
|
-
if not any(isinstance(it, config.Wifi) and it.index == args.index for it in cfg.items()):
|
|
620
|
-
raise SystemExit(f"wifi entry {args.index} does not exist yet: give --pass-prompt, --pass-env VAR or --open")
|
|
621
|
-
passphrase = config.KEEP
|
|
622
|
-
it = config.Wifi(index=args.index, ssid=args.ssid, passphrase=passphrase)
|
|
623
|
-
try:
|
|
624
|
-
it.value()
|
|
625
|
-
except ValueError as e:
|
|
626
|
-
raise SystemExit(str(e)) from None
|
|
627
|
-
_change(hst, cfg, [it], args.save)
|
|
628
|
-
print(f"wifi {args.index}: {it.shown()['ssid']!r}, passphrase {it.shown()['passphrase']}")
|
|
491
|
+
def _fn(hst, ref: str) -> int:
|
|
492
|
+
"""A fn by number, or by `name#instance` (host guide §5.3; #0 may be left out) resolved through list."""
|
|
493
|
+
if ref.isdigit():
|
|
494
|
+
return int(ref)
|
|
495
|
+
name, _, instance = ref.partition("#")
|
|
496
|
+
for e in core.list_entries(hst, name, exact=True):
|
|
497
|
+
if e.instance == int(instance or 0):
|
|
498
|
+
return e.fn
|
|
499
|
+
raise SystemExit(f"no {ref} on this probe")
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def _own_value(cfg, name: str, text: str):
|
|
503
|
+
"""A probe's own setting's value from the command line, by the form its describe declares (probe.config §1.6)."""
|
|
504
|
+
form = cfg.describe().by_name(name).form
|
|
505
|
+
if form == config.FORM["u32"]:
|
|
506
|
+
return int(text, 0)
|
|
507
|
+
if form == config.FORM["bool"]:
|
|
508
|
+
return text.lower() in ("1", "true", "on", "yes")
|
|
509
|
+
if form == config.FORM["bytes"]:
|
|
510
|
+
return bytes.fromhex(text)
|
|
511
|
+
return text
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def _network(cfg, as_json: bool) -> int:
|
|
515
|
+
"""op network (lock-free): the TCP port and each netif's state."""
|
|
516
|
+
net = cfg.network()
|
|
517
|
+
if as_json:
|
|
518
|
+
print(json.dumps({"tcp_port": net.tcp_port, "netifs": [vars(n) for n in net.netifs]}, indent=2))
|
|
519
|
+
return 0
|
|
520
|
+
print(f"tcp port: {net.tcp_port or 'not listening'}")
|
|
521
|
+
for n in net.netifs:
|
|
522
|
+
where = f" {n.address} gateway {n.gateway} dns {n.dns}" if n.address else ""
|
|
523
|
+
entry = f" entry {n.entry}" if n.entry is not None else ""
|
|
524
|
+
rssi = f" {n.rssi} dBm" if n.state == "up" and n.netif == "wifi" else ""
|
|
525
|
+
why = f" ({n.reason})" if n.reason != "none" else ""
|
|
526
|
+
print(f" {n.netif}: {n.state}{why}{entry}{rssi}{where}")
|
|
527
|
+
return 0
|
|
629
528
|
|
|
630
529
|
|
|
631
530
|
def _plain(o):
|
|
632
|
-
if hasattr(o, "shown"):
|
|
633
|
-
return o.shown() # a wifi item: never its passphrase
|
|
634
531
|
return {k: (v.hex() if isinstance(v, bytes) else v) for k, v in vars(o).items()} if hasattr(o, "__dict__") \
|
|
635
532
|
else list(o)
|
|
636
533
|
|
|
637
534
|
|
|
638
|
-
def _state_dict(st) -> dict:
|
|
639
|
-
return {**{k: v for k, v in vars(st).items() if k not in ("slots", "binds", "wifi")},
|
|
640
|
-
"slots": [_plain(s) for s in st.slots], "binds": [_plain(b) for b in st.binds],
|
|
641
|
-
**({"wifi": vars(st.wifi)} if st.wifi is not None else {})}
|
|
642
|
-
|
|
643
|
-
|
|
644
535
|
def _state(cfg, as_json: bool) -> int:
|
|
645
|
-
"""The
|
|
536
|
+
"""The storage state alone (op state, lock-free)."""
|
|
646
537
|
st = cfg.state()
|
|
647
538
|
if as_json:
|
|
648
|
-
print(json.dumps(
|
|
539
|
+
print(json.dumps(vars(st), indent=2))
|
|
649
540
|
return 0
|
|
650
|
-
why = f" ({st.
|
|
651
|
-
print(f"storage: {st.storage}{why}, saved
|
|
652
|
-
for s in st.slots:
|
|
653
|
-
print(f" slot {s.slot}: {s.state}" + (f", connection {s.connection}" if s.connection else "")
|
|
654
|
-
+ (f", tried at {s.last_try_at_ns / 1e9:.3f} s" if s.last_try_at_ns is not None else ""))
|
|
655
|
-
for b in st.binds:
|
|
656
|
-
print(f" port {b.port}: {b.flow}")
|
|
657
|
-
if st.wifi is not None:
|
|
658
|
-
print(f"wifi: {st.wifi.text()}")
|
|
541
|
+
why = f" ({st.reason})" if st.reason else ""
|
|
542
|
+
print(f"storage: {st.storage}{why}, saved generation {st.saved_generation}")
|
|
659
543
|
return 0
|
|
660
544
|
|
|
661
545
|
|
|
662
|
-
def _tids(hst) -> dict[int, str]:
|
|
663
|
-
"""connection -> its target_id as hex, from every wire's connections (the slot's target is the host's to check,
|
|
664
|
-
probe.config §1.1, debug §2.1); best effort."""
|
|
665
|
-
from . import riscv
|
|
666
|
-
out = {}
|
|
667
|
-
for e in core.list_entries(hst):
|
|
668
|
-
if e.name in ("oep.wire.rvswd", "oep.wire.swio"):
|
|
669
|
-
try:
|
|
670
|
-
for c in riscv.Wire(hst, e.name).connections():
|
|
671
|
-
if c.target_id:
|
|
672
|
-
out[c.connection] = c.target_id[1][::-1].hex()
|
|
673
|
-
except host.OepError:
|
|
674
|
-
pass
|
|
675
|
-
return out
|
|
676
|
-
|
|
677
|
-
|
|
678
546
|
def _show(hst, cfg, as_json: bool) -> int:
|
|
679
|
-
|
|
547
|
+
gen, _ = cfg.get()
|
|
680
548
|
items = cfg.items()
|
|
681
549
|
decl = cfg.describe()
|
|
682
|
-
st = cfg.state()
|
|
683
|
-
kinds = {i: _name(k) for i, k, _ in core.transports(hst)}
|
|
550
|
+
st = cfg.state() if cfg.offers(cfg.STATE) else None
|
|
684
551
|
if as_json:
|
|
685
|
-
out = {"
|
|
686
|
-
|
|
687
|
-
"declared": _plain(decl), "state":
|
|
552
|
+
out = {"generation": gen, "items": [dict(type=type(i).__name__, **_plain(i)) if hasattr(i, "__dict__")
|
|
553
|
+
else _plain(i) for i in items],
|
|
554
|
+
"declared": _plain(decl), "state": vars(st) if st else None}
|
|
688
555
|
print(json.dumps(out, indent=2, default=lambda o: o.hex() if isinstance(o, bytes) else str(o)))
|
|
689
556
|
return 0
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
for it in items:
|
|
697
|
-
if isinstance(it, config.Slot):
|
|
698
|
-
s = by_slot.get(it.slot)
|
|
699
|
-
pins = f"{it.pins[0]}" if it.pins[1] == 0xFFFF else f"{it.pins[0]},{it.pins[1]}"
|
|
700
|
-
retry = f" retry {it.retry_s:g} s" if it.attach == "at-boot" else ""
|
|
701
|
-
retry += (f" max {it.max_speed} Hz" if it.max_speed else "") + (" idle-low" if it.idle_clock == "low" else "")
|
|
702
|
-
live = ""
|
|
703
|
-
if s:
|
|
704
|
-
tried = "never tried" if s.last_try_at_ns is None else f"tried at {s.last_try_at_ns / 1e9:.3f} s"
|
|
705
|
-
tid = f" target_id {tids[s.connection]}" if s.connection in tids else ""
|
|
706
|
-
live = f" -> {s.state}" + (f" (connection {s.connection})" if s.connection else f" ({tried})") + tid
|
|
707
|
-
print(f" {it.slot} {it.name}: fn {it.wire_fn} pins {pins} {it.attach}{retry} {it.mechanism}{live}")
|
|
708
|
-
by_port = {b.port: b for b in st.binds}
|
|
709
|
-
print("binds:")
|
|
710
|
-
names = {it.slot: it.name for it in items if isinstance(it, config.Slot)}
|
|
711
|
-
for it in items:
|
|
712
|
-
if isinstance(it, config.Bind):
|
|
713
|
-
b = by_port.get(it.port)
|
|
714
|
-
k, i = it.stream
|
|
715
|
-
stream = f"slot:{names.get(i, i)}" if k == "slot" else f"{k}:{i}"
|
|
716
|
-
live = f" -> {b.flow}" if b else ""
|
|
717
|
-
print(f" port {it.port} ({kinds.get(it.port, '?')}): {stream}{live}")
|
|
718
|
-
if config.ITEM["wifi"] in decl.items:
|
|
719
|
-
print(f"wifi (up to {decl.wifi_max}): " + (st.wifi.text() if st.wifi is not None else "no state"))
|
|
720
|
-
for it in items:
|
|
721
|
-
if isinstance(it, config.Wifi):
|
|
722
|
-
s = it.shown()
|
|
723
|
-
use = " <- in use" if st.wifi is not None and st.wifi.entry == it.index else ""
|
|
724
|
-
print(f" {s['index']} {s['ssid']!r}: passphrase {s['passphrase']}{use}")
|
|
557
|
+
if st is not None:
|
|
558
|
+
why = f" ({st.reason})" if st.reason else ""
|
|
559
|
+
print(f"storage: {st.storage}{why} ({decl.storage_bytes} bytes), saved generation {st.saved_generation}; "
|
|
560
|
+
f"now {gen}")
|
|
561
|
+
else:
|
|
562
|
+
print(f"no storage; generation {gen}")
|
|
725
563
|
for it in items:
|
|
726
|
-
|
|
727
|
-
print(f" {it}")
|
|
564
|
+
print(f" {it}")
|
|
728
565
|
return 0
|
|
729
566
|
|
|
730
567
|
|