diff options
author | Lars Amsel <lars.amsel@ni.com> | 2022-01-13 16:50:11 +0100 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2022-03-23 16:27:04 -0500 |
commit | 99ad89609b6c71faff625adbb0a284bc2d405601 (patch) | |
tree | bfd93b3747cf8bc46b731be08f0192a8fee68e9f | |
parent | 5d20a5a40155e888484f7d57a277bdcebed44207 (diff) | |
download | uhd-99ad89609b6c71faff625adbb0a284bc2d405601.tar.gz uhd-99ad89609b6c71faff625adbb0a284bc2d405601.tar.bz2 uhd-99ad89609b6c71faff625adbb0a284bc2d405601.zip |
tools: Add general purpose tool for USRP configuration
Over the years the UHD code base got a whole bunch of tools to
control and configure devices. This is an attempt to unify these
tools into one.
Co-authored-by: Alexander Weber <alexander.weber@ni.com>
-rw-r--r-- | host/docs/CMakeLists.txt | 6 | ||||
-rw-r--r-- | host/docs/devices.dox | 4 | ||||
-rw-r--r-- | host/docs/uhd_cal_rx_iq_balance.1 | 2 | ||||
-rw-r--r-- | host/docs/uhd_cal_tx_dc_offset.1 | 2 | ||||
-rw-r--r-- | host/docs/uhd_cal_tx_iq_balance.1 | 2 | ||||
-rw-r--r-- | host/docs/uhd_config_info.1 | 2 | ||||
-rw-r--r-- | host/docs/uhd_find_devices.1 | 2 | ||||
-rw-r--r-- | host/docs/uhd_image_loader.1 | 2 | ||||
-rw-r--r-- | host/docs/uhd_images_downloader.1 | 2 | ||||
-rw-r--r-- | host/docs/uhd_usrp_probe.1 | 2 | ||||
-rw-r--r-- | host/docs/usrp2_card_burner.1 | 2 | ||||
-rw-r--r-- | host/docs/usrp_n2xx_simple_net_burner.1 | 2 | ||||
-rw-r--r-- | host/docs/usrpctl.1 | 93 | ||||
-rw-r--r-- | host/docs/usrpctl.dox | 72 | ||||
-rw-r--r-- | host/python/uhd/__init__.py | 1 | ||||
-rw-r--r-- | host/python/uhd/usrpctl/__init__.py | 7 | ||||
-rw-r--r-- | host/python/uhd/usrpctl/commands/__init__.py | 9 | ||||
-rw-r--r-- | host/python/uhd/usrpctl/commands/command.py | 133 | ||||
-rw-r--r-- | host/python/uhd/usrpctl/commands/find.py | 43 | ||||
-rw-r--r-- | host/python/uhd/usrpctl/commands/probe.py | 31 | ||||
-rw-r--r-- | host/utils/CMakeLists.txt | 10 | ||||
-rw-r--r-- | host/utils/usrpctl.py | 91 |
22 files changed, 510 insertions, 10 deletions
diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index 9f6b1eb2b..fc1d2f928 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -123,6 +123,12 @@ set(man_page_sources usrp2_card_burner.1 ) +if (ENABLE_PYTHON_API) + set(man_page_sources + usrpctl.1 + ) +endif(ENABLE_PYTHON_API) + ######################################################################## # Setup man pages ######################################################################## diff --git a/host/docs/devices.dox b/host/docs/devices.dox index b081a03d5..f65d48960 100644 --- a/host/docs/devices.dox +++ b/host/docs/devices.dox @@ -56,5 +56,9 @@ unless stated otherwise, they will still work with this version of UHD. \li \subpage page_octoclock +## Usrpctl + +\li \subpage page_usrpctl + */ // vim:ft=doxygen: diff --git a/host/docs/uhd_cal_rx_iq_balance.1 b/host/docs/uhd_cal_rx_iq_balance.1 index df77afb2c..3ca187bd2 100644 --- a/host/docs/uhd_cal_rx_iq_balance.1 +++ b/host/docs/uhd_cal_rx_iq_balance.1 @@ -55,7 +55,7 @@ uhd_cal_tx_dc_offset(1) uhd_cal_tx_iq_balance(1) This manual page was written by Maitland Bottoms and Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2012 Ettus Research LLC +Copyright (c) 2012-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/uhd_cal_tx_dc_offset.1 b/host/docs/uhd_cal_tx_dc_offset.1 index 50d3899e8..4830b7161 100644 --- a/host/docs/uhd_cal_tx_dc_offset.1 +++ b/host/docs/uhd_cal_tx_dc_offset.1 @@ -55,7 +55,7 @@ uhd_cal_rx_iq_balance(1) uhd_cal_tx_iq_balance(1) This manual page was written by Maitland Bottoms and Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2012 Ettus Research LLC +Copyright (c) 2012-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/uhd_cal_tx_iq_balance.1 b/host/docs/uhd_cal_tx_iq_balance.1 index 859cf9a84..accba9f6a 100644 --- a/host/docs/uhd_cal_tx_iq_balance.1 +++ b/host/docs/uhd_cal_tx_iq_balance.1 @@ -55,7 +55,7 @@ uhd_cal_tx_dc_offset(1) uhd_cal_rx_iq_balance(1) This manual page was written by Maitland Bottoms and Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2012 Ettus Research LLC +Copyright (c) 2012-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/uhd_config_info.1 b/host/docs/uhd_config_info.1 index edc1b7532..adc6cb859 100644 --- a/host/docs/uhd_config_info.1 +++ b/host/docs/uhd_config_info.1 @@ -51,7 +51,7 @@ This manual page was written by Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2015 National Instruments Corp. +Copyright (c) 2015-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/uhd_find_devices.1 b/host/docs/uhd_find_devices.1 index c628a2d86..15e94a1f1 100644 --- a/host/docs/uhd_find_devices.1 +++ b/host/docs/uhd_find_devices.1 @@ -98,7 +98,7 @@ uhd_usrp_probe(1) This manual page was written by Maitland Bottoms and Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2010 Ettus Research LLC +Copyright (c) 2010-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/uhd_image_loader.1 b/host/docs/uhd_image_loader.1 index 982784f9e..f3b033a70 100644 --- a/host/docs/uhd_image_loader.1 +++ b/host/docs/uhd_image_loader.1 @@ -115,7 +115,7 @@ uhd_images_downloader(1) usrp2_card_burner(1) This manual page was written by Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2015 Ettus Research LLC +Copyright (c) 2015-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/uhd_images_downloader.1 b/host/docs/uhd_images_downloader.1 index 19f109ec5..1f9fbc875 100644 --- a/host/docs/uhd_images_downloader.1 +++ b/host/docs/uhd_images_downloader.1 @@ -38,7 +38,7 @@ usrp2_card_burner(1) usrp_n2xx_simple_net_burner(1) usrp_x3xx_fpga_burner(1) oct This manual page was written by Maitland Bottoms and Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2012,2014 Ettus Research LLC +Copyright (c) 2012-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/uhd_usrp_probe.1 b/host/docs/uhd_usrp_probe.1 index 7d72b32fb..48f2d8667 100644 --- a/host/docs/uhd_usrp_probe.1 +++ b/host/docs/uhd_usrp_probe.1 @@ -112,7 +112,7 @@ uhd_find_devices(1) This manual page was written by Maitland Bottoms and Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2010 Ettus Research LLC +Copyright (c) 2010-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/usrp2_card_burner.1 b/host/docs/usrp2_card_burner.1 index b43484b99..ebf5f560d 100644 --- a/host/docs/usrp2_card_burner.1 +++ b/host/docs/usrp2_card_burner.1 @@ -39,7 +39,7 @@ uhd_images_downloader(1) usrp_n2xx_simple_net_burner(1) usrp_x3xx_fpga_burner(1) This manual page was written by Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2012,2014 Ettus Research LLC +Copyright (c) 2012-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/usrp_n2xx_simple_net_burner.1 b/host/docs/usrp_n2xx_simple_net_burner.1 index 85538ee22..719edc76c 100644 --- a/host/docs/usrp_n2xx_simple_net_burner.1 +++ b/host/docs/usrp_n2xx_simple_net_burner.1 @@ -46,7 +46,7 @@ uhd_images_downloader(1) usrp2_card_burner(1) usrp_x3xx_fpga_burner(1) octoclock This manual page was written by Nicholas Corgan for the Debian project (but may be used by others). .SH COPYRIGHT -Copyright (c) 2012,2014 Ettus Research LLC +Copyright (c) 2012-2022 Ettus Research, A National Instruments Brand .LP This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/host/docs/usrpctl.1 b/host/docs/usrpctl.1 new file mode 100644 index 000000000..1cf0f01eb --- /dev/null +++ b/host/docs/usrpctl.1 @@ -0,0 +1,93 @@ +.TH "usrpctl" 1 "4.0.0" UHD "User Commands" +.SH NAME +usrpctl \- USRP Hardware Driver Peripheral Configuration Tool +.SH DESCRIPTION +Report detailed information on UHD-supported Software Radio Peripherals +attached by USB, network, or embedded configuration. +Allows update and configuration of attached devices. +.LP +The UHD package is the universal hardware driver for Ettus Research products. The goal +is to provide a host driver and API for current and future Ettus Research products. +Users will be able to use the UHD driver standalone or with 3rd party applications. +.LP +Details include unit names, revision numbers, and available sensors on all attached +USRP motherboards and daughterboards. +.SH SYNOPSIS +.B usrpctl [ID] COMMAND [OPTIONS] +.SH ID +ID is the optional device argument. It is used to define a set +of USRP devices that COMMAND should be applied to. If ID is omitted +COMMAND is applied to all reachable devices. + +usrpctl understands the device args argument used by other UHD +tools like uhd_find_devices. + +.SH COMMAND +Is the action the tool is to take. Every command can be either applied to a +single device or a group of devices. Commands that run on a group of +devices repeat the command for every device. + +- Single device commands: + - config: Read/write configuration variables (e.g., IP address) + - probe: reads extended information about the USRP +- Multi device commands: + - update: Update binaries (e.g., FPGA image) + - reset: Reset the device or parts thereof (e.g., only reset MPM) + - find: finds all available USRPs in this network + +.SH OPTIONS +The options are not always mandatory. It depends on the given COMMAND. + +.SH find command + +The find command takes no further options. If ID is not given it scans the +system for available, supported devices and prints a list of discovered devices. +The print out is compatible to uhd_find_devices. +ID can be used to narrow down the list of discovered devices. + +.SH probe command +.IP "Print a complete property tree:" +-tree +.TP +The probe command can only be applied to a single device so make sure that +ID identifies exactly one device. Without arguments it displays detailed +information about the device such as name, serial, revision numbers, +firmware version sensor information on attached motherboard and daughterboards. + +.SH EXAMPLES +.TP \w'usrpctl\ 'u +.BI usrpctl\ find +find all supported devices +.TP +.BI usrpctl\ type=x300,product=X310 find +find all x310 devices +.TP +.BI usrpctl\ name=my_usrp\ find +find a device named my_usrp +.TP +.BI usrpctl\ addr=192.168.10.2\ find +find a device with the given IP. +.TP +.BI usrpctl\ addr=192.168.10.2\ probe +display device information for USRP with the given ID +.TP +.BI usprctl\ name=my_usrp\ probe\ \-tree +display property tree of device with the name my_usrp +.TP + +.SH SEE ALSO +UHD documentation: +.B http://files.ettus.com/manual/ +.LP +.SH COPYRIGHT +Copyright (c) 2022 Ettus Research, A National Instruments Brand +.LP +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +.LP +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. diff --git a/host/docs/usrpctl.dox b/host/docs/usrpctl.dox new file mode 100644 index 000000000..431f2ee66 --- /dev/null +++ b/host/docs/usrpctl.dox @@ -0,0 +1,72 @@ +/*! \page page_usrpctl Usrpctl + +\tableofcontents + +\section usrpctl_description Description + +usrpctl is the central and universal tool to +query, update or configure USRP devices. The command structure is: + + usrpctl $ID $COMMAND $OPTIONS + +`usrpctl` will run $COMMAND on the devices identified by $ID. $OPTIONS +is dependend on the chosen command. + +\section usrpctl_id $ID + +$ID is the optional device argument. It is used to define a set +of USRP devices that `$COMMAND` should be applied to. If `$ID` is omitted +$COMMAND is applied to all reachable devices. + +`usrpctl` understands the device args argument used by other UHD +tools like `uhd_find_devices`. + +\section usrpctl_command $COMMAND +Is the action the tool is to take. Every command can be either applied to a +single device or a group of devices. Commands that run on a group of +devices repeat the command for every device. + +- Single device commands: + - `config`: Read/write configuration variables (e.g., IP address) + - `probe`: reads extended information about the USRP +- Multi device commands: + - `update`: Update binaries (e.g., FPGA image) + - `reset`: Reset the device or parts thereof (e.g., only reset MPM) + - `find`: finds all available USRPs in this network + +\section usrpctl_options $OPTIONS + +The options depend on the chosen command. Optional arguments are prepended +with a dash, mandatory are not. + +\section usrpctl_commands Available commands + +\section usrpctl_find find + +The find command takes no further options. If `$ID` is not given it scans the +system for available, supported devices and prints a list of discovered devices. +The print out is compatible to \ref id_identifying_cmdline "`uhd_find_devices`". +`$ID` can be used to narrow down the list of discovered devices. + +Examples: + +- `usrpctl find` find all supported devices +- `usrpctl type=x300,product=X310 find` find all x310 devices +- `usrpctl name=my_usrp find` find a device named my_usrp +- `usrpctl addr=192.168.10.2 find` find a device with the given IP. + +\subsection usrpctl_probe probe +Arguments: +-`-tree`: print a list of the device property tree + +The probe command can only be applied to a single device so make sure that +$ID identifies exactly one device. Without arguments it displays detailed +information about the device such as name, serial, revision numbers, +firmware version sensor information on attached motherboard and daughterboards. + +Examples: +- `usrpctl addr=192.168.10.2 probe` display device information for USRP with the given ID +- `usprctl name=my_usrp probe -tree` display property tree of device with the name my_usrp + +*/ +// vim:ft=doxygen: diff --git a/host/python/uhd/__init__.py b/host/python/uhd/__init__.py index bfbe9a57f..b825cfa2e 100644 --- a/host/python/uhd/__init__.py +++ b/host/python/uhd/__init__.py @@ -9,6 +9,7 @@ UHD Python API module from . import types from . import usrp +from . import usrpctl from . import filters from . import rfnoc from . import dsp diff --git a/host/python/uhd/usrpctl/__init__.py b/host/python/uhd/usrpctl/__init__.py new file mode 100644 index 000000000..8c16e1823 --- /dev/null +++ b/host/python/uhd/usrpctl/__init__.py @@ -0,0 +1,7 @@ +""" +Copyright (c) 2022 Ettus Research, A National Instruments Brand + +SPDX-License-Identifier: GPL-3.0-or-later +""" + +from . import commands diff --git a/host/python/uhd/usrpctl/commands/__init__.py b/host/python/uhd/usrpctl/commands/__init__.py new file mode 100644 index 000000000..3a8fd045e --- /dev/null +++ b/host/python/uhd/usrpctl/commands/__init__.py @@ -0,0 +1,9 @@ +""" +Copyright (c) 2022 Ettus Research, A National Instruments Brand + +SPDX-License-Identifier: GPL-3.0-or-later +""" + +from .command import BaseCommand +from .find import FindCommand +from .probe import ProbeCommand diff --git a/host/python/uhd/usrpctl/commands/command.py b/host/python/uhd/usrpctl/commands/command.py new file mode 100644 index 000000000..9f19d33a5 --- /dev/null +++ b/host/python/uhd/usrpctl/commands/command.py @@ -0,0 +1,133 @@ +""" +Copyright (c) 2022 Ettus Research, A National Instruments Brand + +SPDX-License-Identifier: GPL-3.0-or-later +""" + +import functools +import re +import subprocess + +SSH_COMMAND = 'ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 {user}@{host}' +SCP_COMMAND = 'scp -o StrictHostKeyChecking=no -o ConnectTimeout=10 {src} {user}@{host}:{dest}' + +REBOOT_SCRIPT = r''' +max_timeout=600 + +function ssh_cmd() {{ + ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 {user}@{host} $1 +}} + +if ! {{ boot_id=$(ssh_cmd "cat /proc/sys/kernel/random/boot_id") \ + && [[ $boot_id ]]; }}; then + echo "Unable to retrieve boot ID" >&2 + exit 1 +fi + +ssh_cmd "reboot" + +timeout_at=$(( SECONDS + max_timeout )) +until new_boot_id=$(ssh_cmd "cat /proc/sys/kernel/random/boot_id") \ + && [[ $new_boot_id != "$boot_id" ]]; do + if (( SECONDS > timeout_at )); then + echo "System did not reboot within timeout" >&2 + exit 1 + fi + sleep 5 +done + +echo "System successfully rebooted" >&2 +''' + +class BaseCommand: + """ + Base class for all usrpctl commands + + Implements some helper useful for all command classes. + """ + + @classmethod + def command_name(cls): + """ + By default the command name is the class name (lowercase) without + the trailing "Command" + """ + return re.sub("(.*)Command$", r"\1", cls.__name__).lower() + + @classmethod + def add_parser(cls, parser): + """ + add_parser is used to tell usrpctl argparse which command line + argument the command accepts. + """ + + def _to_arg_list(self, args): + """ + Takes parsed arguments from argparse and converts it to + a flat list of key value pairs where the key is prepended with + two dashes. If value is falsy the pair is ommitted. + This is suitable to pass parsed arguments into another process. + Example: Suppose args is: + Namespace(foo='fval', bar=2, baz=None) + then this would result in this list: + ['--foo', 'fval', '--bar', 2] + """ + arg_list = {f"--{key}": value for key, value in vars(args).items() if value} + return list(functools.reduce( + lambda left, right: left + right, arg_list.items())) if arg_list else [] + + def _external_process(self, command): + """ + Run command in an external process. + + stderr is redirected into stdout and the oupput is + yielded while the process is running. + throws CalledProcessError on non zero returncode + """ + with subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, text=True) as process: + for line in iter(process.stdout.readline, ""): + yield line.rstrip() + returncode = process.wait() + if returncode != 0: + raise subprocess.CalledProcessError(returncode, command) + + def _reboot(self, user, host): + cmd = REBOOT_SCRIPT.format(user=user, host=host) + yield from self._external_process(["bash", "-c", cmd]) + + def _remote_cmd(self, user, host, cmd): + """ + Executes a command via SSH. + """ + ssh_cmd = SSH_COMMAND.format(user=user, host=host) + yield from self._external_process(ssh_cmd.split(' ') + [cmd]) + + def _remote_copy(self, user, host, src, dest): + """ + Uses scp to copy a file to a remote host + """ + cp_cmd = SCP_COMMAND.format(user=user, host=host, src=src, dest=dest) + yield from self._external_process(cp_cmd.split(' ')) + + def _process_output(self, line): + print(line) + + def _run_commands(self, usrp, args): + print(f"{self.__class__.__name__} is not yet implemented." + f"arguments usrp: {usrp} args: {args}") + + def is_multi_device_capable(self): + """ + Tell whether this command can serve multiple USRPs at once + """ + return False + + def run(self, usrps, args): + """ + Run the command + """ + for usrp in usrps: + print(f'{self.command_name()} {usrp.to_string()}') + for line in self._run_commands(usrp, args): + self._process_output(line) diff --git a/host/python/uhd/usrpctl/commands/find.py b/host/python/uhd/usrpctl/commands/find.py new file mode 100644 index 000000000..7a07a73c3 --- /dev/null +++ b/host/python/uhd/usrpctl/commands/find.py @@ -0,0 +1,43 @@ +""" +Copyright (c) 2022 Ettus Research, A National Instruments Brand + +SPDX-License-Identifier: GPL-3.0-or-later +""" + +from .command import BaseCommand + +class FindCommand(BaseCommand): + """ + Class that finds USRP devices + """ + + @classmethod + def add_parser(cls, parser): + """ + Adding subparser for find command + """ + parser.add_parser(cls.command_name(), + help="print devices found using id parameter") + + def is_multi_device_capable(self): + """ + Can handle multiple USRPs + """ + return True + + def run(self, usrps, args): + """ + Because usrpctl issued find to build the usrps list + from the id argument the only thing left to do is + print the found devices. Print mimics the behaviour + of uhd_find_devices. + """ + for index, usrp in enumerate(usrps): + print('--------------------------------------------------') + print(f"-- UHD Device {index}") + print('--------------------------------------------------') + print('Device Address:') + for key, value in usrp.to_dict().items(): + print(f" {key}: {value}") + print() + print() diff --git a/host/python/uhd/usrpctl/commands/probe.py b/host/python/uhd/usrpctl/commands/probe.py new file mode 100644 index 000000000..486844a58 --- /dev/null +++ b/host/python/uhd/usrpctl/commands/probe.py @@ -0,0 +1,31 @@ +""" +Copyright (c) 2022 Ettus Research, A National Instruments Brand + +SPDX-License-Identifier: GPL-3.0-or-later +""" + +from .command import BaseCommand + +class ProbeCommand(BaseCommand): + """ + Command that uses uhd_usrp_probe to query device properties. + Acts on single devices only. + """ + @classmethod + def add_parser(cls, parser): + """ + Allow -tree as argument. other uhd_usrp_probe arguments + are not supported right now + """ + subparser = parser.add_parser(cls.command_name(), + help="report detailed information on USRP device") + subparser.add_argument("-tree", const="tree", action="store_const", + help="reads the device tree") + + def _run_commands(self, usrp, args): + """ + probe the device + """ + yield from self._external_process( + ["uhd_usrp_probe", f"--args={usrp.to_string()}"] + + self._to_arg_list(args)) diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 1ac0b1c99..fcb4fd9b0 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -38,6 +38,16 @@ UHD_INSTALL(PROGRAMS DESTINATION ${RUNTIME_DIR} COMPONENT utilities ) +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/usrpctl.py" + "${CMAKE_CURRENT_BINARY_DIR}/usrpctl" +) +UHD_INSTALL(PROGRAMS + ${CMAKE_CURRENT_BINARY_DIR}/usrpctl + RENAME usrpctl + DESTINATION ${RUNTIME_DIR} + COMPONENT utilities +) ######################################################################## # Utilities that get installed into the share path diff --git a/host/utils/usrpctl.py b/host/utils/usrpctl.py new file mode 100644 index 000000000..c184befee --- /dev/null +++ b/host/utils/usrpctl.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +""" +Copyright (c) 2022 Ettus Research, A National Instruments Brand + +SPDX-License-Identifier: GPL-3.0-or-later +""" + +import argparse +import inspect +import os +import re +import sys + +import uhd +import uhd.usrpctl.commands + +def get_commands(): + """ + Returns a dictionary of all subclasses of BaseCommand + + Classes are searched in uhd.usrpctl.commands module. + Key is the command name of the command class. + Value is the command class itself. + + BaseCommand is not part of the resulting dictionary + """ + return {command[1].command_name(): command[1] for command in + inspect.getmembers(uhd.usrpctl.commands, inspect.isclass) + if issubclass(command[1], uhd.usrpctl.commands.BaseCommand) + and command[1] != uhd.usrpctl.commands.BaseCommand} + +def parse_args(commands): + """ + parse command line arguments and return USRPs to search for as well + as command to execute and command arguments + """ + parser = argparse.ArgumentParser() + parser.add_argument("id", nargs="?", + help="identifies USRPs devices utilizing dev_addr_type") + parser.add_argument("-v", action="count", default=0, + help="increase verbosity level ranging from -v to -vvvvv") + + subparsers = parser.add_subparsers(dest="command", + help="supported commands, detailed help with usrpctl <cmd> --help") + + for command, cls in commands.items(): + cls.add_parser(subparsers) + + args = parser.parse_args() + script_args = argparse.Namespace() + script_args.id = args.id + script_args.v = args.v + command = args.command + del args.id + del args.v + del args.command + return (script_args, command, args) + +def find_usrps(id_args): + """ + Find USRPs based on the given id_args. + """ + return uhd.find(id_args or "") + +def main(): + """ + Control all the USRPs! + """ + commands = get_commands() + script_args, cmd_name, cmd_args = parse_args(commands) + env = os.environ + env['UHD_LOG_CONSOLE_LEVEL'] = str(max(0, 5 - script_args.v)) + usrps = find_usrps(script_args.id) + + if not usrps: + print(f"No USRP found to act on (id={script_args.id})") + return 1 + + command = commands[cmd_name]() + + if not command.is_multi_device_capable(): + if len(usrps) > 1: + print(f"Found {len(usrps)} USRPs but {cmd_name} " + "can only act on single device") + return 2 + + return command.run(usrps, cmd_args) + +if __name__ == "__main__": + sys.exit(main()) |