Add urh
12
Software/Universal Radio Hacker/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6WDFF59DL56Z2'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
27
Software/Universal Radio Hacker/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
##### Expected Behavior
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
##### Actual Behavior
|
||||
|
||||
##### Steps To Reproduce
|
||||
<!-- Explain the steps to reproduce the behavior. -->
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
##### Screenshots
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
##### Platform Specifications
|
||||
<!-- please complete the following information -->
|
||||
- OS: [e.g. Arch Linux]
|
||||
- URH version: [e.g. 2.4.2]
|
||||
- Python version: [e.g. 3.7]
|
||||
- Installed via [e.g. pip]
|
18
Software/Universal Radio Hacker/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea to enhance URH
|
||||
|
||||
---
|
||||
|
||||
##### Is your feature request related to a problem?
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
-->
|
||||
|
||||
##### Describe the solution you'd like
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
##### Describe alternatives you've considered
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
##### Additional context
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
195
Software/Universal Radio Hacker/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
name: CI
|
||||
|
||||
env:
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags: [ "v*" ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-2019, macos-10.15]
|
||||
python-version: ['3.7', '3.8', '3.9', '3.10']
|
||||
architecture: [x64]
|
||||
include:
|
||||
- os: windows-2019
|
||||
python-version: '3.7'
|
||||
architecture: x86
|
||||
exclude:
|
||||
- os: windows-2019
|
||||
python-version: '3.8'
|
||||
- os: windows-2019
|
||||
python-version: '3.9'
|
||||
- os: windows-2019
|
||||
python-version: '3.10'
|
||||
- os: macOS-10.15
|
||||
python-version: '3.7'
|
||||
- os: macOS-10.15
|
||||
python-version: '3.8'
|
||||
- os: macOS-10.15
|
||||
python-version: '3.10'
|
||||
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
architecture: ${{ matrix.architecture }}
|
||||
|
||||
- name: Setup SDR Drivers (Windows)
|
||||
if: startsWith(matrix.os, 'windows')
|
||||
run: |
|
||||
choco install wget --no-progress
|
||||
wget -nv -O windrivers.zip https://github.com/jopohl/sdrbuild/releases/download/v1.1/win-$ARCH.zip
|
||||
7z x windrivers.zip -osrc/urh/dev/native/lib/shared
|
||||
ls src/urh/dev/native/lib/shared
|
||||
shell: bash
|
||||
env:
|
||||
ARCH: ${{ matrix.architecture }}
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -r data/requirements.txt
|
||||
if [[ $OS == ubuntu* ]]
|
||||
then
|
||||
sudo apt-get update
|
||||
sudo apt-get install libhackrf-dev librtlsdr-dev xvfb libxkbcommon-x11-0 x11-utils libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0
|
||||
pip install PyVirtualDisplay==0.2.5
|
||||
elif [[ $OS == windows* ]]
|
||||
then
|
||||
pip install pywin32 pipwin
|
||||
pipwin install pyaudio
|
||||
elif [[ $OS == mac* ]]
|
||||
then
|
||||
brew tap pothosware/homebrew-pothos
|
||||
brew install airspy hackrf librtlsdr libbladerf limesuite portaudio uhd
|
||||
|
||||
wget -nv https://github.com/analogdevicesinc/libiio/releases/download/v0.23/macOS-10.15.pkg
|
||||
sudo installer -pkg macOS-10.15.pkg -target /
|
||||
sudo cp /Library/Frameworks/iio.framework/iio /usr/local/lib/libiio.dylib
|
||||
sudo install_name_tool -id "/usr/local/lib/libiio.dylib" /usr/local/lib/libiio.dylib
|
||||
file /usr/local/lib/libiio.dylib
|
||||
otool -L /usr/local/lib/libiio.dylib
|
||||
sudo cp /Library/Frameworks/iio.framework/Versions/0.23/Headers/iio.h /usr/local/include
|
||||
|
||||
wget -nv https://www.sdrplay.com/software/SDRplay_RSP_API-MacOSX-2.13.2.pkg
|
||||
sudo installer -pkg SDRplay_RSP_API-MacOSX-2.13.2.pkg -target /
|
||||
|
||||
pip install pyaudio
|
||||
pip install pillow
|
||||
fi
|
||||
pip install twine setuptools pytest pytest-xvfb pytest-cov pytest-faulthandler six appdirs packaging pyinstaller
|
||||
python -c "import tempfile, os; open(os.path.join(tempfile.gettempdir(), 'urh_releasing'), 'w').close()"
|
||||
shell: bash
|
||||
env:
|
||||
OS: ${{ matrix.os }}
|
||||
|
||||
- name: Build Cython Extensions
|
||||
run: python src/urh/cythonext/build.py
|
||||
|
||||
- name: Create sdist
|
||||
if: ${{ matrix.python-version == '3.9' && startsWith(matrix.os, 'ubuntu') }}
|
||||
run: python setup.py sdist
|
||||
|
||||
- run: python setup.py bdist_wheel
|
||||
if: ${{ !startsWith(matrix.os, 'ubuntu') }}
|
||||
|
||||
- name: Build manylinux2014
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
docker run --rm \
|
||||
-e PYVER=$(python -c "import sys; print('%s%s' % (sys.version_info.major, sys.version_info.minor))") \
|
||||
-v `pwd`:/io jopohl/urh_manylinux2014 /io/data/make_manylinux2014_wheels.sh
|
||||
|
||||
- name: Check wheel
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
pip install dist/*.whl
|
||||
urh --version
|
||||
xvfb-run urh autoclose
|
||||
python data/check_native_backends.py
|
||||
|
||||
- name: Build .exe Installer
|
||||
if: startsWith(matrix.os, 'windows')
|
||||
run: |
|
||||
python data/pyinstaller_helper.py
|
||||
for /f %%i in ('python src/urh/version.py') do set URHVERSION=%%i
|
||||
iscc /dMyAppVersion=%URHVERSION% /dArch=%PYARCH% data/inno.iss
|
||||
shell: cmd
|
||||
env:
|
||||
PYARCH: ${{ matrix.architecture }}
|
||||
|
||||
- name: Check urh_debug.exe
|
||||
if: startsWith(matrix.os, 'windows')
|
||||
run: |
|
||||
cd pyinstaller\urh
|
||||
urh_debug.exe autoclose
|
||||
shell: cmd
|
||||
|
||||
- name: Build DMG
|
||||
if: startsWith(matrix.os, 'macos')
|
||||
run: |
|
||||
cp data/pyinstaller_macos.spec urh.spec
|
||||
pyinstaller --clean --distpath ./pyinstaller --workpath ./urh_build urh.spec
|
||||
mkdir -p dist
|
||||
cat pyinstaller/main.app/Contents/Info.plist
|
||||
hdiutil create -volname Universal.Radio.Hacker \
|
||||
-srcfolder pyinstaller/main.app \
|
||||
-ov -format UDZO \
|
||||
dist/Universal.Radio.Hacker-"$(python src/urh/version.py)".dmg
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist-${{ matrix.os }}
|
||||
path: dist
|
||||
|
||||
- name: Run pytest with coverage
|
||||
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.python-version == '3.9' }}
|
||||
run: |
|
||||
touch tests/show_gui
|
||||
cp tests/.coveragerc .
|
||||
pytest -s -v --junitxml=junit/test-results.xml --cov=src --cov-config=.coveragerc tests
|
||||
coverage xml
|
||||
coverage html
|
||||
|
||||
- name: Run pytest without coverage
|
||||
if: ${{ !startsWith(matrix.os, 'ubuntu') || matrix.python-version != '3.9' }}
|
||||
run: pytest -s -v --junitxml=junit/test-results.xml tests
|
||||
|
||||
- uses: ncipollo/release-action@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
artifacts: "dist/*.exe,dist/*.dmg"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
allowUpdates: true
|
||||
generateReleaseNotes: true
|
||||
omitBodyDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
|
||||
- name: Upload to PyPi
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
if [[ $OS == ubuntu* ]]
|
||||
then
|
||||
twine upload --skip-existing dist/*
|
||||
else
|
||||
twine upload --skip-existing dist/*.whl
|
||||
fi
|
||||
shell: bash
|
||||
env:
|
||||
TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
|
||||
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
|
||||
TWINE_REPOSITORY_URL: "https://upload.pypi.org/legacy/"
|
56
Software/Universal Radio Hacker/.gitignore
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
.coverage
|
||||
|
||||
.pytest_cache
|
||||
|
||||
# Pycharm
|
||||
.idea/
|
||||
|
||||
venv/
|
||||
|
||||
src/__pycache__/
|
||||
src/urh/__pycache__/
|
||||
__pycache__/
|
||||
build/
|
||||
src/urh/awre/__pycache__/
|
||||
src/urh/awre/components/__pycache__/
|
||||
src/urh/controller/__pycache__/
|
||||
src/urh/cythonext/__pycache__/
|
||||
src/urh/dev/__pycache__/
|
||||
src/urh/dev/gr/__pycache__/
|
||||
*.pyc
|
||||
src/urh/dev/native/__pycache__/
|
||||
src/urh/dev/native/lib/__pycache__/
|
||||
src/urh/models/__pycache__/
|
||||
src/urh/plugins/MessageBreak/__pycache__/
|
||||
src/urh/plugins/ZeroHide/__pycache__/
|
||||
src/urh/plugins/__pycache__/
|
||||
src/urh/signalprocessing/__pycache__/
|
||||
src/urh/ui/__pycache__/
|
||||
src/urh/ui/actions/__pycache__/
|
||||
src/urh/ui/delegates/__pycache__/
|
||||
src/urh/ui/views/__pycache__/
|
||||
src/urh/util/__pycache__/
|
||||
tmp/
|
||||
dist/
|
||||
src/urh.egg-info/
|
||||
.cache/
|
||||
tests/data/URHProject.xml
|
||||
src/urh/cythonext/*.html
|
||||
src/urh/cythonext/*.c
|
||||
src/urh/cythonext/*.cpp
|
||||
|
||||
src/urh/dev/native/lib/*.html
|
||||
src/urh/dev/native/lib/*.c
|
||||
src/urh/dev/native/lib/*.cpp
|
||||
|
||||
/tests/show_gui
|
||||
|
||||
src/urh/*.txt
|
||||
src/urh/URHProject.xml
|
||||
.coverage*
|
||||
src/urh/dev/gr/scripts/top_block.py
|
||||
|
||||
misc/*
|
674
Software/Universal Radio Hacker/LICENSE
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
Universal Radio Hacker: investigate wireless protocols like a boss
|
||||
Copyright (C) 2022 Johannes Pohl and Andreas Noack
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
Universal Radio Hacker Copyright (C) 2022 Johannes Pohl and Andreas Noack
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
195
Software/Universal Radio Hacker/README.md
Normal file
@ -0,0 +1,195 @@
|
||||
![URH image](https://raw.githubusercontent.com/jopohl/urh/master/data/icons/banner.png)
|
||||
|
||||
[![CI](https://github.com/jopohl/urh/actions/workflows/ci.yml/badge.svg)](https://github.com/jopohl/urh/actions/workflows/ci.yml)
|
||||
[![PyPI version](https://badge.fury.io/py/urh.svg)](https://badge.fury.io/py/urh)
|
||||
[![Packaging status](https://repology.org/badge/tiny-repos/urh.svg)](https://repology.org/project/urh/versions)
|
||||
[![Blackhat Arsenal 2017](https://rawgit.com/toolswatch/badges/master/arsenal/usa/2017.svg)](http://www.toolswatch.org/2017/06/the-black-hat-arsenal-usa-2017-phenomenal-line-up-announced/)
|
||||
[![Blackhat Arsenal 2018](https://rawgit.com/toolswatch/badges/master/arsenal/europe/2018.svg)](http://www.toolswatch.org/2018/09/black-hat-arsenal-europe-2018-lineup-announced/)
|
||||
|
||||
|
||||
The Universal Radio Hacker (URH) is a complete suite for wireless protocol investigation with native support for [many](https://github.com/jopohl/urh/wiki/Supported-devices) common __Software Defined Radios__.
|
||||
URH allows __easy demodulation__ of signals combined with an [automatic](https://dl.acm.org/doi/10.1145/3375894.3375896) detection of modulation parameters making it a breeze to identify the bits and bytes that fly over the air.
|
||||
As data often gets _encoded_ before transmission, URH offers __customizable decodings__ to crack even sophisticated encodings like CC1101 data whitening.
|
||||
When it comes to __protocol reverse-engineering__, URH is helpful in two ways. You can either manually assign protocol fields and message types or let URH __automatically infer protocol fields__ with a [rule-based intelligence](https://www.usenix.org/conference/woot19/presentation/pohl).
|
||||
Finally, URH entails a __fuzzing component__ aimed at stateless protocols and a __simulation environment__ for stateful attacks.
|
||||
|
||||
### Getting started
|
||||
In order to get started
|
||||
- view the [installation instructions](#Installation) on this page,
|
||||
- download the [official userguide (PDF)](https://github.com/jopohl/urh/releases/download/v2.0.0/userguide.pdf),
|
||||
- watch the [demonstration videos (YouTube)](https://www.youtube.com/watch?v=kuubkTDAxwA&index=1&list=PLlKjreY6G-1EKKBs9sucMdk8PwzcFuIPB),
|
||||
- check out the [wiki](https://github.com/jopohl/urh/wiki) for more information such as supported devices or
|
||||
- read some [articles about URH](#Articles) for inspiration.
|
||||
|
||||
If you like URH, please :star: this repository and [join our Slack channel](https://join.slack.com/t/stralsundsecurity/shared_invite/enQtMjEwOTIxNzMzODc3LTk3NmE4MGVjYjEyYTMzYTdmN2RlNzUzYzg0NTNjNTQ2ODBkMzI3MDZlOWY3MjE4YjBkNTM4ZjJlNTJlZmJhNDg). We appreciate your support!
|
||||
|
||||
### Citing URH
|
||||
We encourage researchers working with URH to cite [this](https://www.usenix.org/conference/woot18/presentation/pohl) WOOT'18 paper or directly use the following BibTeX entry.
|
||||
|
||||
<details>
|
||||
<summary> <b>URH BibTeX entry for your research paper</b> </summary>
|
||||
|
||||
```bibtex
|
||||
@inproceedings {220562,
|
||||
author = {Johannes Pohl and Andreas Noack},
|
||||
title = {Universal Radio Hacker: A Suite for Analyzing and Attacking Stateful Wireless Protocols},
|
||||
booktitle = {12th {USENIX} Workshop on Offensive Technologies ({WOOT} 18)},
|
||||
year = {2018},
|
||||
address = {Baltimore, MD},
|
||||
url = {https://www.usenix.org/conference/woot18/presentation/pohl},
|
||||
publisher = {{USENIX} Association},
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Installation
|
||||
URH runs on Windows, Linux and macOS. Click on your operating system below to view installation instructions.
|
||||
|
||||
<details>
|
||||
<summary><b>Windows</b></summary><br/>
|
||||
|
||||
On Windows, URH can be installed with its [Installer](https://github.com/jopohl/urh/releases). No further dependencies are required.
|
||||
|
||||
If you get an error about missing ```api-ms-win-crt-runtime-l1-1-0.dll```, run Windows Update or directly install [KB2999226](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Linux</b></summary>
|
||||
|
||||
|
||||
<details open>
|
||||
<summary><i>Generic Installation with pip (recommended)</i></summary><br/>
|
||||
|
||||
URH is available on [PyPi](https://pypi.org/project/urh/) so you can install it with
|
||||
```bash
|
||||
# IMPORTANT: Make sure your pip is up to date
|
||||
sudo python3 -m pip install --upgrade pip # Update your pip installation
|
||||
sudo python3 -m pip install urh # Install URH
|
||||
```
|
||||
This is the recommended way to install URH on Linux because it comes with __all native extensions__ precompiled.
|
||||
|
||||
In order to access your SDR as non-root user, install the according __udev rules__. You can find them [in the wiki](https://github.com/jopohl/urh/wiki/SDR-udev-rules).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><i>Install via Package Manager</i></summary><br/>
|
||||
|
||||
URH is included in the repositories of many linux distributions such as __Arch Linux__, __Gentoo__, __Fedora__, __openSUSE__ or __NixOS__. There is also a package for __FreeBSD__. If available, simply use your package manager to install URH.
|
||||
|
||||
__Note__: For native support, you must install the according ```-dev``` package(s) of your SDR(s) such as ```hackrf-dev``` __before__ installing URH.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><i>Snap</i></summary><br/>
|
||||
|
||||
URH is available as a snap: https://snapcraft.io/urh
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><i>Docker Image</i></summary><br/>
|
||||
|
||||
The official URH docker image is available [here](https://hub.docker.com/r/jopohl/urh/). It has all native backends included and ready to operate.
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>macOS</b></summary>
|
||||
|
||||
<details open>
|
||||
<summary><i>Using DMG</i></summary><br/>
|
||||
|
||||
It is recommended to use __at least macOS 10.14__ when using the DMG available [here](https://github.com/jopohl/urh/releases).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><i>With pip</i></summary><br/>
|
||||
|
||||
1. Install [Python 3 for Mac OS X](https://www.python.org/downloads/mac-osx/).
|
||||
_If you experience issues with preinstalled Python, make sure you update to a recent version using the given link._
|
||||
2. (Optional) Install desired native libs e.g. ```brew install librtlsdr``` for
|
||||
corresponding native device support.
|
||||
3. In a terminal, type: ```pip3 install urh```.
|
||||
4. Type ```urh``` in a terminal to get it started.
|
||||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Update your installation</b></summary><br/>
|
||||
|
||||
If you installed URH via pip you can keep it up to date with ``` python3 -m pip install --upgrade urh ```.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Running from source</b></summary>
|
||||
|
||||
<details>
|
||||
<summary><i>Without installation</i></summary><br/>
|
||||
|
||||
To execute the Universal Radio Hacker without installation, just run:
|
||||
```bash
|
||||
git clone https://github.com/jopohl/urh/
|
||||
cd urh/src/urh
|
||||
./main.py
|
||||
```
|
||||
|
||||
Note, before first usage the C++ extensions will be built.
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><i>Installing from source</i></summary><br/>
|
||||
|
||||
To install URH from source you need to have ```python-setuptools``` installed. You can get them with ```python3 -m pip install setuptools```.
|
||||
Once the setuptools are installed execute:
|
||||
```bash
|
||||
git clone https://github.com/jopohl/urh/
|
||||
cd urh
|
||||
python setup.py install
|
||||
```
|
||||
|
||||
And start the application by typing ```urh``` in a terminal.
|
||||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
## Articles
|
||||
### Hacking stuff with URH
|
||||
* [Hacking Burger Pagers](https://www.rtl-sdr.com/using-a-hackrf-to-reverse-engineer-and-control-restaurant-pagers/)
|
||||
* [Reverse-engineer and Clone a Remote Control](https://www.rtl-sdr.com/video-tutorial-using-universal-radio-hacker-an-rtl-sdr-and-a-microcontroller-to-clone-433-mhz-remotes/)
|
||||
* [Reverse-engineering Weather Station RF Signals](https://www.rtl-sdr.com/tag/universal-radio-hacker/)
|
||||
* [Reverse-engineering Wireless Blinds](https://www.rtl-sdr.com/reverse-engineering-wireless-blinds-with-an-rtl-sdr-and-controlling-them-with-amazon-alexa/)
|
||||
* [Attacking Logitech Wireless Presenters (German Article)](https://www.heise.de/security/meldung/Wireless-Presenter-von-Logitech-und-Inateck-anfaellig-fuer-Angriffe-ueber-Funk-4439795.html)
|
||||
* [Attacking Wireless Keyboards](https://threatpost.com/fujitsu-wireless-keyboard-unpatched-flaws/149477/)
|
||||
* [Reverse-engineering a 433MHz Remote-controlled Power Socket for use with Arduino](http://www.ignorantofthings.com/2018/11/reverse-engineering-433mhz-remote.html)
|
||||
|
||||
### General presentations and tutorials on URH
|
||||
* [Hackaday Article](https://hackaday.com/2017/02/23/universal-radio-hacker/)
|
||||
* [RTL-SDR.com Article](https://www.rtl-sdr.com/reverse-engineering-signals-universal-radio-hacker-software/)
|
||||
* [Short Tutorial on URH with LimeSDR Mini](https://www.crowdsupply.com/lime-micro/limesdr-mini/updates/investigating-wireless-protocols-with-universal-radio-hacker)
|
||||
* [Brute-forcing a RF Device: a Step-by-step Guide](https://pandwarf.com/news/brute-forcing-a-new-device-a-step-by-step-guide/)
|
||||
* [Hacking wireless sockets like a NOOB](https://olof-astrand.medium.com/hacking-wireless-sockets-like-a-noob-b57d4b4812d5)
|
||||
|
||||
## External decodings
|
||||
See [wiki](https://github.com/jopohl/urh/wiki/External-decodings) for a list of external decodings provided by our community! Thanks for that!
|
||||
|
||||
## Screenshots
|
||||
### Get the data out of raw signals
|
||||
![Interpretation phase](http://i.imgur.com/Wy17Zv3.png)
|
||||
|
||||
### Keep an overview even on complex protocols
|
||||
![Analysis phase](http://i.imgur.com/ubAL3pE.png)
|
||||
|
||||
### Record and send signals
|
||||
![Record](http://i.imgur.com/BfQpg23.png)
|
389
Software/Universal Radio Hacker/data/CHANGELOG.md
Normal file
@ -0,0 +1,389 @@
|
||||
# Changelog
|
||||
__This changelog file will not be updated anymore__.
|
||||
|
||||
Instead, the recent changes can be found at the releases page: https://github.com/jopohl/urh/releases
|
||||
|
||||
|
||||
## v2.5.3 (19/12/2018)
|
||||
### Bugfixes
|
||||
- fix crash when using spectrum analyzer with GNU Radio backend [#588](https://github.com/jopohl/urh/pull/588)
|
||||
|
||||
## v2.5.2 (10/12/2018)
|
||||
### Bugfixes
|
||||
- certain windows (e.g. decoding) can't be closed on OSX
|
||||
- prevent crash in substitution encoding
|
||||
- consider alignment offset when showing selected labels
|
||||
|
||||
### Adjustments
|
||||
- remove ```Save and Close``` of fuzzing dialog, as closing means saving here anyway
|
||||
|
||||
### New features
|
||||
- make application __font size__ configurable in ``` Options ``` -> ``` View ```
|
||||
|
||||
## v2.5.1 (25/11/2018)
|
||||
### Bugfixes
|
||||
- improve stability when capturing with SoundCard
|
||||
- fix bug making the docker container crash at startup
|
||||
- stop simulation instantly after finishing
|
||||
|
||||
## v2.5.0 (19/11/2018)
|
||||
### New features
|
||||
- Add native support for PlutoSDR [#574](https://github.com/jopohl/urh/pull/574)
|
||||
|
||||
### Bugfixes
|
||||
- do not add URH to autostart on windows [#569](https://github.com/jopohl/urh/pull/569)
|
||||
- save button was not shown when change on saved signal was undone [#571](https://github.com/jopohl/urh/pull/571)
|
||||
- y scale got falsely reset on save [#573](https://github.com/jopohl/urh/pull/573)
|
||||
|
||||
## v2.4.2 (11/11/2018)
|
||||
### New features
|
||||
- enhance settings for RTL-SDR [#561](https://github.com/jopohl/urh/pull/561) + [#566](https://github.com/jopohl/urh/pull/566)
|
||||
- ergonomic improvements [#564](https://github.com/jopohl/urh/pull/564)
|
||||
|
||||
### Bugfixes
|
||||
- fix problem with set reference message shortcut [#559](https://github.com/jopohl/urh/pull/559)
|
||||
- fix loading decodings and centralized place for decodings [#563](https://github.com/jopohl/urh/pull/563)
|
||||
|
||||
## v2.4.1 (23/10/2018)
|
||||
### New features
|
||||
- Add an option to disable automatic detection of interpretation parameters for newly loaded signals to the ``` Edit ``` menu [#555](https://github.com/jopohl/urh/pull/555)
|
||||
|
||||
### Bugfixes
|
||||
- fix off by one error when creating a new label in analysis
|
||||
- fix crash when opening a project with saved dc correction setting
|
||||
|
||||
## v2.4.0 (19/10/2018)
|
||||
### New features
|
||||
- added __font size zoom__ to table views (analysis/generator/simulator); more details in [#546](https://github.com/jopohl/urh/pull/546)
|
||||
- greatly enhance __accuracy of automatic interpretation__ [#550](https://github.com/jopohl/urh/pull/550)
|
||||
- added __DC correction__ option to recording dialogs and as a new filter type in Interpretation [#552](https://github.com/jopohl/urh/pull/552)
|
||||
|
||||
### Improvements
|
||||
- ignore case when searching for hex values in analysis [#544](https://github.com/jopohl/urh/pull/544)
|
||||
- RSSI is now given in dBm [#549](https://github.com/jopohl/urh/pull/549)
|
||||
|
||||
### Bugfixes
|
||||
- Fix display of RSSI indicator in Interpretation [#547](https://github.com/jopohl/urh/pull/547)
|
||||
|
||||
## v2.3.0 (28/09/2018)
|
||||
### New features
|
||||
- added native support for BladeRF [#524](https://github.com/jopohl/urh/pull/524)
|
||||
- added backward compatibility for SDRPlay < 2.13 [#528](https://github.com/jopohl/urh/pull/528)
|
||||
- improved UI for message type and label configuration in analysis [#532](https://github.com/jopohl/urh/pull/532)
|
||||
- rename __close all__ action to __close all files__ for more clarity [#532](https://github.com/jopohl/urh/pull/532)
|
||||
- added a __close project__ action [#532](https://github.com/jopohl/urh/pull/532)
|
||||
|
||||
|
||||
## v2.2.4 (30/08/2018)
|
||||
### Bugfixes
|
||||
- fix scaling of modulated preview in modulation dialog [#523](https://github.com/jopohl/urh/pull/523)
|
||||
- improve default parameters for PSK modulation in modulation dialog [#523](https://github.com/jopohl/urh/pull/523)
|
||||
|
||||
## v2.2.3 (28/07/2018)
|
||||
### New features
|
||||
- allow save and load of binary protocols (``` .bin ``` files) [#488](https://github.com/jopohl/urh/pull/488)
|
||||
- improve bootstrap of simulator messages [#500](https://github.com/jopohl/urh/pull/500)
|
||||
- auto assign destination when dropping messages to simulator
|
||||
- show participant address in participant legend if present
|
||||
- auto assign participant address when clicking analyze button in analysis based on SRC address label
|
||||
- consider API changes of SDRPlay 2.13 [#508](https://github.com/jopohl/urh/pull/508) thanks [@mehdideveloper](https://github.com/mehdideveloper)
|
||||
- also consider participant address (next to RSSI) when auto assigning participants in analysis [#512](https://github.com/jopohl/urh/pull/512)
|
||||
- Clear button stays enabled during operation so e.g. recordings can be cleared live [#514](https://github.com/jopohl/urh/pull/514)
|
||||
|
||||
### Bugfixes
|
||||
- antenna selection is not saved when reopening dialog [#494](https://github.com/jopohl/urh/pull/494)
|
||||
- hiding multiple rows at once in analysis not working properly [#499](https://github.com/jopohl/urh/pull/499)
|
||||
|
||||
|
||||
## v2.2.2 (01/07/2018)
|
||||
This release removes the ``` config.pxi ``` requirement which caused problems on Arch Linux and Gentoo during installation. More details in PR [#484](https://github.com/jopohl/urh/pull/484).
|
||||
|
||||
## v2.2.1 (30/06/2018)
|
||||
This is a hotfix release which targets issue [#481](https://github.com/jopohl/urh/issues/481), so if you had problems with a missing ``` config.pxi ``` make sure to use this version.
|
||||
|
||||
## v2.2.0 (29/06/2018)
|
||||
__Import announcement if you build URH manually__: Cython is now a __required__ dependency to build URH. If you install URH from PyPi (with ``` pip ```) or use the ``` .msi ``` installer you will not notice any difference. However, if you run URH from source you need to install cython which is as easy as ``` python3 -m pip install cython ```.
|
||||
|
||||
- [#478](https://github.com/jopohl/urh/pull/478) - make message pause configurable in simulator
|
||||
- [#476](https://github.com/jopohl/urh/pull/476) - add padding when sending very short messages with soundcard
|
||||
- [#473](https://github.com/jopohl/urh/pull/473) - move ``` .desktop ``` file to ``` data ``` folder. __Important if you build a package of URH__
|
||||
- [#471](https://github.com/jopohl/urh/pull/471) - make relative external programs paths relative to project path
|
||||
- [#470](https://github.com/jopohl/urh/pull/470) - improve conditional compiling of native device extensions
|
||||
- [#469](https://github.com/jopohl/urh/pull/469) - improve device selection in options, use a table instead of a list view
|
||||
- [#468](https://github.com/jopohl/urh/pull/468) - improve python2 interpreter settings for GNU Radio backend with empty ``` urh.ini ```
|
||||
- [#458](https://github.com/jopohl/urh/pull/458) - add alignment action to analysis
|
||||
![alignment image](https://i.imgur.com/xQt7H7Y.png)
|
||||
|
||||
|
||||
|
||||
## v2.1.1 (17/06/2018)
|
||||
This release updates the bundled SDR drivers on Windows.
|
||||
__Furthermore, this release adds native device support for 32 bit windows__.
|
||||
|
||||
Bugfix:
|
||||
- a bug was fixed where sample rate of a signal was not written correctly to wav file when exporting as wav
|
||||
|
||||
|
||||
## v2.1.0 (01/06/2018)
|
||||
The highlight of this release is a __Command Line Interface__ (CLI) for the Universal Radio Hacker.
|
||||
Learn more about this new feature [in the wiki](https://github.com/jopohl/urh/wiki/Command-Line-Interface).
|
||||
|
||||
Moreover, these two features were added:
|
||||
- Add export features #437
|
||||
- make refin and refout configurable for CRC #439
|
||||
|
||||
These bugs were fixed:
|
||||
- fix #441 (Reference signal is not kept when disabling and re-enabling "Mark diffs in protocol")
|
||||
- fix #442 (consider hidden zeros for show selection in interpretation)
|
||||
- fix #444 (Message Break error box popping up too early)
|
||||
- fix #448 (Include pyaudio in windows package for soundcard support)
|
||||
|
||||
|
||||
|
||||
## v2.0.4 (06/05/2018)
|
||||
|
||||
This version fixes a bug when importing 24 bit wav files on windows.
|
||||
|
||||
|
||||
|
||||
## v2.0.3 (06/05/2018)
|
||||
- Improve external program behaviour in Simulator #417
|
||||
- fix #421
|
||||
- Improve simulator useability #422
|
||||
- Improve transcript for external programs #425
|
||||
- make endianness selectable in order column #428
|
||||
- UI improvements #430
|
||||
- add support for soundcards as new SDR device #433
|
||||
- Multi device support #432
|
||||
- add support for 24bit wav #434
|
||||
|
||||
|
||||
## v2.0.2 (22/04/2018)
|
||||
- Improve external program behaviour in Simulator #417
|
||||
- fix #421
|
||||
- Improve simulator useability #422
|
||||
- Improve transcript for external programs #425
|
||||
- make endianness selectable in order column #428
|
||||
- UI improvements #430
|
||||
|
||||
|
||||
## v2.0.1 (23/03/2018)
|
||||
Changes:
|
||||
- improve appearance of splitters
|
||||
- add adaptive noise feature for protocol sniffer and simulator (#401)
|
||||
- improve native device rebuild button in options + added a new button to view the build log there (only visible after hitting the rebuild button) (#402)
|
||||
- improve performance of CRC calculation (#412)
|
||||
- save number of sending repeats when changed in send dialog (#415)
|
||||
|
||||
|
||||
## v2.0.0 (28/02/2018)
|
||||
URH 2.0 is here! This release adds a new tab to the main interface. This __Simulator__ tab enables you to simulate certain devices and crack even sophisticated security mechanisms like challenge response procedures. Learn more about this new feature [on this wiki page](https://github.com/jopohl/urh/wiki/Simulator).
|
||||
|
||||
Moreover, the overall performance and stability of URH increases with 2.0. The most notable changes are:
|
||||
- improve accuracy when sending messages with short pauses
|
||||
- improve accuracy of protocol sniffer
|
||||
- allow setting lower frequencies for HackRF (#396)
|
||||
- consider latest changes of LimeSuite API (#397)
|
||||
- add timestamp to protocol sniffer output (#392)
|
||||
- improve performance of modulations
|
||||
- improve performance of filtering in analysis
|
||||
- improve performance when starting sending
|
||||
- improve send accuracy of HackRF
|
||||
- improve performance when filtering messages in Analysis
|
||||
|
||||
|
||||
## v1.9.2 (19/01/2018)
|
||||
- Add BCD (Binary Coded Decimal) as new display format #386
|
||||
- Make bit order configurable in analysis view table #390
|
||||
- Improved loading of protocol files
|
||||
|
||||
|
||||
## v1.9.1 (17/12/2017)
|
||||
|
||||
This is a hotfix release that fixes an error with HackRF receiving (#379).
|
||||
|
||||
|
||||
|
||||
## v1.9.0 (15/12/2017)
|
||||
- added native support for SDRplay (#378)
|
||||
- improved performance for continuous send mode
|
||||
- added collapsable comboboxes to device dialog
|
||||
|
||||
|
||||
|
||||
## v1.8.17 (04/12/2017)
|
||||
Changes:
|
||||
- show warning at bottom if no project loaded (#374)
|
||||
- if no project is opened an new project is created, add currently opnened files to new project (#374)
|
||||
- add --version flag to command line script #375 (thanks to @Funcan for the initial work)
|
||||
- Enable specifying a custom python 2 interpreter on Windows (#372)
|
||||
|
||||
|
||||
## v1.8.16 (30/11/2017)
|
||||
|
||||
This release fixes an issue on Windows where processes ended with an error (#370).
|
||||
|
||||
Furthermore, the NetworkSDR can now be used in continuous send mode (#369).
|
||||
|
||||
|
||||
|
||||
## v1.8.15 (27/11/2017)
|
||||
|
||||
This release fixes a problem with GNU Radio backend on Windows mentioned in #366 and #368.
|
||||
|
||||
|
||||
|
||||
## v1.8.14 (26/11/2017)
|
||||
This release fixes an overflow error (#364) when modulating very long messages in Generator.
|
||||
|
||||
The highlight of this release is an enhanced spectrum analyzer (#365) with __increased performance__ and a __waterfall plot__ to have a different, time based perspective on the spectrum.
|
||||
![spectrum](https://user-images.githubusercontent.com/18219846/33239754-03bb62f6-d2a9-11e7-80aa-059df7b0b133.png)
|
||||
|
||||
|
||||
|
||||
|
||||
## v1.8.13 (18/11/2017)
|
||||
|
||||
This release enhances the stability for sending and receiving with all SDRs. Especially, it fixes nasty bug #360 which affected HackRF users under Windows.
|
||||
|
||||
Furthermore, the WAV file support was greatly enhanced. Now, you can use WAV files from SDR# (fix #359).
|
||||
|
||||
|
||||
|
||||
## v1.8.12 (16/11/2017)
|
||||
|
||||
This release fixes the following issues:
|
||||
|
||||
- fix #355 - added a CSV import wizard for generic support of USB oscilloscopes
|
||||
- fix #358 - MSI version of URH did not start on Windows
|
||||
|
||||
__So if you had trouble to install the previous version on Windows make sure you use this one.__
|
||||
|
||||
|
||||
|
||||
## v1.8.11 (13/11/2017)
|
||||
|
||||
The following issues were fixed in this release:
|
||||
|
||||
- fix #343 - crash when entering bits on empty position in Analysis / Generation
|
||||
- fix #344 - bandpass filter can now also work with negative frequencies
|
||||
- fix #346 - bandpass filter operations now run in a separate process and can be canceled with the ESC button
|
||||
- fix #349 - added a csv import to work with USB oscilloscopes
|
||||
- fix #352 - added a advanced modulation menu in Interpretation where a minimum message length for ASK can be configured
|
||||
|
||||
|
||||
|
||||
## v1.8.10 (21/10/2017)
|
||||
|
||||
This release fixes a crash when pressing the replay button in interpretation tab.
|
||||
|
||||
|
||||
|
||||
## (21/10/2017)
|
||||
|
||||
|
||||
|
||||
## v1.8.8 (16/10/2017)
|
||||
|
||||
These issues were fixed in this release:
|
||||
|
||||
- fix #339 - keep tree in analysis collapsed if check box toggled
|
||||
- fix #338 - make pause threshold configurable in interpretation
|
||||
- fix #333 - keep search string if search fails in analysis
|
||||
|
||||
|
||||
|
||||
## v1.8.7 (18/09/2017)
|
||||
This release fixes the following issues:
|
||||
|
||||
- [#330](https://github.com/jopohl/urh/pull/330) - Improve modulation for large protocols
|
||||
- [#329](https://github.com/jopohl/urh/pull/329) - Improve handling of protocol files
|
||||
- [#324](https://github.com/jopohl/urh/issues/324) - LimeSDR: Failed to receive stream
|
||||
- [#297](https://github.com/jopohl/urh/issues/297) - LimeSDR RX antenna always LNA_L
|
||||
|
||||
|
||||
## v1.8.6 (06/09/2017)
|
||||
|
||||
This release fixes two crashes as described in #327.
|
||||
|
||||
|
||||
|
||||
## v1.8.5 (30/08/2017)
|
||||
|
||||
This release fixes #323 .
|
||||
|
||||
|
||||
|
||||
## v1.8.4 (28/08/2017)
|
||||
|
||||
This is a hotfix release that fixes native device extensions on Windows when conflicting SDR software is installed.
|
||||
Furthermore, a health check button for native device extensions was added to options.
|
||||
|
||||
Details can be found in this PR: #321
|
||||
|
||||
|
||||
|
||||
## Version 1.8.0 (24/08/2017)
|
||||
|
||||
This release adds two highly demanded features to URH: __Spectrogram View__ and __Channel Separation__. Learn more about them in the [wiki](https://github.com/jopohl/urh/wiki/Spectrogram) and keep hacking like a boss!
|
||||
|
||||
|
||||
|
||||
## Version 1.7.1 (19/07/2017)
|
||||
|
||||
This release adds installers for Windows. If you use the new installer and should get an error about missing ``` api-ms-win-crt-runtime-l1-1-0.dll ```, run Windows Update or directly install [KB2999226](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows).
|
||||
__It is recommended to use the 64 bit version (amd64) of URH on Windows__, because 32 bit version has no native device support.
|
||||
|
||||
This release also fixes some bugs:
|
||||
|
||||
- Fix exhaustive fuzzing mode
|
||||
- Fix a rare crash in Generator tab when performing undo
|
||||
- fix checksum assignment to fuzzed messages when sending/generating data
|
||||
- refresh estimated time in generator if pause was edited
|
||||
|
||||
|
||||
## Version 1.7.0 (14/07/2017)
|
||||
The highlight of this release is support for __generic checksums__. You can define custom CRC polynomials or use predefined ones.
|
||||
Learn more about this feature [in the wiki](https://github.com/jopohl/urh/wiki/Checksums).
|
||||
|
||||
Other fixes/features include:
|
||||
- "Edit all" action in pause menu of generator tab
|
||||
- Open Project now additionally possible by opening the project file
|
||||
- bootstrapping of modulation when dropping first protocol to generator table
|
||||
- new icons and improved UI
|
||||
- improved auto detection of carrier frequency for modulation
|
||||
- improved ASK demodulation algorithm
|
||||
- fix a bug with relative paths on OS X
|
||||
- fix selection behavior when extending selection with shift
|
||||
- fix #306
|
||||
- fix #308
|
||||
- fix #310
|
||||
- fix #311
|
||||
|
||||
|
||||
|
||||
## Hotfix for Windows wheels (11/06/2017)
|
||||
|
||||
This is a hotfix release that fixes dependencies in the precompiled wheels for Windows which were introduced in the previous release.
|
||||
|
||||
|
||||
|
||||
## Version 1.6.5 (11/06/2017)
|
||||
This release brings the following changes:
|
||||
|
||||
- fix #278: added a __repeat button__ to fuzzing dialog, next to the table with fuzzing values
|
||||
- fix #284: fixed behaviour: "Your selection is empty!" sometimes pops up when creating a new signal from signal
|
||||
- fix #285: fixed a rare crash when undoing a crop action
|
||||
- fix #281: Optimized performance of protocol synchronization in Interpretation
|
||||
- fix #286: improved context menu in Analysis
|
||||
- fix #288: UI improvements: remove unneeded borders and increase visibility of splitter handle
|
||||
- fix #290: fixed a crash occurring when pressing Analysis button in certain circumstances
|
||||
- fix #291: created precompiled wheels for windows on PyPI, so no C++ compiler needed anymore.
|
||||
- improved visual appearance of comboboxes in protocol label list view
|
||||
|
||||
|
||||
## Add filter to Interpretation (28/05/2017)
|
||||
This release brings a filter button to the Interpretation phase:
|
||||
![bildschirmfoto_2017-05-28_12-29-58](https://cloud.githubusercontent.com/assets/18219846/26528462/a20c36ce-43ac-11e7-815e-0d929aa20cb8.png)
|
||||
|
||||
This way, you can smooth your signals right inside URH or unlock the full power of DSP fir filters by defining custom filters through the menu!
|
40
Software/Universal Radio Hacker/data/Dockerfile
Normal file
@ -0,0 +1,40 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
LABEL maintainer="Johannes.Pohl90@gmail.com"
|
||||
|
||||
ENV TZ=Europe/Berlin
|
||||
|
||||
# Debug QT plugins by exporting QT_DEBUG_PLUGINS=1 before running URH
|
||||
# To allow docker to connect to X run xhost +local:docker
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
|
||||
&& apt-get -qq update \
|
||||
&& apt-get -qq install software-properties-common \
|
||||
&& add-apt-repository -y ppa:myriadrf/drivers && apt-get -qq update \
|
||||
&& apt-get -qq install wget gcc g++ git \
|
||||
python3 python3-pip python3-pyaudio python3-pyqt5 python3-numpy python3-psutil \
|
||||
fonts-dejavu-core libgles2-mesa libusb-1.0-0 \
|
||||
gr-osmosdr \
|
||||
libhackrf-dev liblimesuite-dev libbladerf-dev librtlsdr-dev libairspy-dev libuhd-dev libiio-dev \
|
||||
&& python3 -m pip install setuptools cython \
|
||||
&& mkdir /tmp/sdrplay \
|
||||
&& wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-2.13.1.run -O /tmp/sdrplay/sdrplay.run \
|
||||
&& cd /tmp/sdrplay && bash sdrplay.run --tar xf \
|
||||
&& cp mirsdrapi-rsp.h /usr/local/include \
|
||||
&& cp x86_64/libmirsdrapi-rsp.so.2.13 /usr/lib/x86_64-linux-gnu/ \
|
||||
&& ln -s /usr/lib/x86_64-linux-gnu/libmirsdrapi-rsp.so.2.13 /usr/lib/x86_64-linux-gnu/libmirsdrapi-rsp.so \
|
||||
&& rm -rf /tmp/sdrplay \
|
||||
\
|
||||
&& cd /tmp && git clone --depth=1 https://github.com/jopohl/urh \
|
||||
&& cd /tmp/urh \
|
||||
&& python3 setup.py install \
|
||||
&& rm -rf /tmp/urh \
|
||||
\
|
||||
&& apt-get -qq remove wget gcc g++ git ttf-bitstream-vera \
|
||||
&& apt-get -qq autoremove \
|
||||
&& dbus-uuidgen > /var/lib/dbus/machine-id \
|
||||
&& apt-get -qq clean all \
|
||||
&& mkdir /tmp/runtime-root \
|
||||
&& chmod 0700 /tmp/runtime-root
|
||||
|
||||
CMD XDG_RUNTIME_DIR=/tmp/runtime-root urh
|
89
Software/Universal Radio Hacker/data/build_icons.py
Normal file
@ -0,0 +1,89 @@
|
||||
# Build Qt Resource File from custom Icon Theme for Windows
|
||||
import os
|
||||
|
||||
import shutil
|
||||
import xml.etree.ElementTree as ET
|
||||
from subprocess import call
|
||||
|
||||
OXYGEN_PATH = "/usr/share/icons/oxygen/base"
|
||||
|
||||
|
||||
def get_python_files():
|
||||
python_files = []
|
||||
code_dir = os.path.join(os.curdir, "..", "src")
|
||||
assert os.path.isdir(code_dir)
|
||||
for path, subdirs, files in os.walk(code_dir):
|
||||
for name in files:
|
||||
if name.endswith(".py"):
|
||||
python_files.append(os.path.join(path, name))
|
||||
return python_files
|
||||
|
||||
|
||||
def get_used_icon_names():
|
||||
icons = set()
|
||||
for sourcefile in get_python_files():
|
||||
with open(sourcefile, "r") as f:
|
||||
for line in f:
|
||||
if "QIcon.fromTheme" in line:
|
||||
icon = line[line.find("QIcon.fromTheme"):]
|
||||
icon = icon.replace('"', "'")
|
||||
start = icon.find("'") + 1
|
||||
end = icon.find("'", start)
|
||||
icons.add(icon[start:end])
|
||||
return icons
|
||||
|
||||
|
||||
def copy_icons(icon_names: set):
|
||||
target_dir = "/tmp/oxy"
|
||||
sizes = [s for s in os.listdir(OXYGEN_PATH) if os.path.isdir(os.path.join(OXYGEN_PATH, s))] # 8x8, 22x22 ...
|
||||
for size in sizes:
|
||||
target_size_dir = os.path.join(target_dir, size)
|
||||
os.makedirs(target_size_dir, exist_ok=True)
|
||||
oxy_dir = os.path.join(OXYGEN_PATH, size)
|
||||
for icon_name in icon_names:
|
||||
for path, subdirs, files in os.walk(oxy_dir):
|
||||
for f in files:
|
||||
if os.path.splitext(f)[0] == icon_name:
|
||||
src = os.path.join(path, f)
|
||||
shutil.copyfile(src, os.path.join(target_size_dir, f))
|
||||
break
|
||||
|
||||
# Create theme file
|
||||
with open(os.path.join(target_dir, "index.theme"), "w") as f:
|
||||
f.write("[Icon Theme]\n")
|
||||
f.write("Name=oxy\n")
|
||||
f.write("Comment=Subset of oxygen icons\n")
|
||||
f.write("Inherits=default\n")
|
||||
f.write("Directories=" + ",".join(sizes) + "\n")
|
||||
|
||||
for size in sizes:
|
||||
f.write("\n")
|
||||
f.write("[" + size + "]\n")
|
||||
f.write("Size=" + size[:size.index("x")] + "\n")
|
||||
f.write("\n")
|
||||
|
||||
root = ET.Element("RCC")
|
||||
root.set("version", "1.0")
|
||||
res = ET.SubElement(root, "qresource")
|
||||
res.set("prefix", "icons/oxy")
|
||||
relpath = os.path.relpath(os.path.join(target_dir, "index.theme"), "/tmp")
|
||||
ET.SubElement(res, "file", alias="index.theme").text = relpath
|
||||
|
||||
for size in sizes:
|
||||
size_dir = os.path.join(target_dir, size)
|
||||
for icon in os.listdir(size_dir):
|
||||
relpath = os.path.relpath(os.path.join(size_dir, icon), "/tmp")
|
||||
ET.SubElement(res, "file", alias=size + "/" + icon).text = relpath
|
||||
|
||||
tree = ET.ElementTree(root)
|
||||
tree.write("/tmp/xtra_icons.qrc")
|
||||
call(["pyrcc5", "/tmp/xtra_icons.qrc", "-o", "/tmp/xtra_icons_rc.py"])
|
||||
tar_path = os.path.dirname(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
tar_path = os.path.join(tar_path, "src/urh/ui")
|
||||
shutil.copy("/tmp/xtra_icons_rc.py", tar_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
icons = get_used_icon_names()
|
||||
print(icons)
|
||||
copy_icons(icons)
|
26
Software/Universal Radio Hacker/data/build_snap.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR=$(dirname "$(readlink -f "$0")")
|
||||
|
||||
echo "Copy snapcraft.yaml to base directory"
|
||||
cd $DIR
|
||||
cp snapcraft.yaml ..
|
||||
cd ..
|
||||
sed -i "s/version\: git/version\: $(python3 src/urh/version.py)/" snapcraft.yaml
|
||||
|
||||
mkdir -p snap/gui
|
||||
cp data/icons/appicon.png snap/gui/urh.png
|
||||
|
||||
echo "Create desktop entry for snap"
|
||||
echo "[Desktop Entry]" > snap/gui/urh.desktop
|
||||
echo "Type=Application" >> snap/gui/urh.desktop
|
||||
echo "Name=Universal Radio Hacker" >> snap/gui/urh.desktop
|
||||
echo "Comment=Investigate Wireless Protocols Like A Boss" >> snap/gui/urh.desktop
|
||||
echo "Exec=urh" >> snap/gui/urh.desktop
|
||||
echo "Icon=\${SNAP}/meta/gui/urh.png" >> snap/gui/urh.desktop
|
||||
echo "Terminal=false" >> snap/gui/urh.desktop
|
||||
|
||||
SNAPCRAFT_BUILD_ENVIRONMENT_CPU=8 SNAPCRAFT_BUILD_ENVIRONMENT_MEMORY=24G snapcraft
|
||||
|
||||
#sudo snap install --dangerous urh*.snap
|
||||
#urh
|
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
rc = 0
|
||||
|
||||
if sys.platform == "win32":
|
||||
shared_lib_dir = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "src/urh/dev/native/lib/shared"))
|
||||
print("Attempting to read", shared_lib_dir)
|
||||
if os.path.isdir(shared_lib_dir):
|
||||
os.environ["PATH"] = os.environ.get("PATH", "") + os.pathsep + shared_lib_dir
|
||||
print("PATH updated")
|
||||
|
||||
for sdr in ("AirSpy", "BladeRF", "HackRF", "RTLSDR", "LimeSDR", "PlutoSDR", "SDRPlay", "USRP"):
|
||||
try:
|
||||
importlib.import_module('.{}'.format(sdr.lower()), 'urh.dev.native.lib')
|
||||
print("{:<10} \033[92mSUCCESS\033[0m".format(sdr+":"))
|
||||
except ImportError as e:
|
||||
print("{:<10} \033[91mFAILURE\033[0m ({})".format(sdr+":", e))
|
||||
rc = 1
|
||||
|
||||
sys.exit(rc)
|
@ -0,0 +1,54 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, len = strlen(argv[2]);
|
||||
|
||||
if (argc>2)
|
||||
{
|
||||
if (argv[1][0]=='d')
|
||||
for(i = 0; i < len; i++)
|
||||
switch(i % 12)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 8:
|
||||
case 9:
|
||||
putchar(argv[2][i]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else
|
||||
for(i = 0; i < len; i++)
|
||||
switch(i % 8)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
putchar(argv[2][i]);
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
putchar(argv[2][i]);
|
||||
if(argv[2][i] == '0') putchar('1');
|
||||
else putchar('0');
|
||||
break;
|
||||
case 7:
|
||||
putchar(argv[2][i]);
|
||||
if(i < len - 1)
|
||||
printf("01");
|
||||
}
|
||||
|
||||
}
|
||||
else printf("Usage: %s <d/e> <bit sequence>\n\td - decode\n\te - encode\n\tbit sequence as string of 0 and 1.\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
BIN
Software/Universal Radio Hacker/data/decodings/homematic
Normal file
102
Software/Universal Radio Hacker/data/decodings/homematic.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
byte str2byte(char str[8])
|
||||
{
|
||||
int ret = 0, i;
|
||||
for(i = 0; i < 8; i++)
|
||||
if (str[i]=='1') ret |= (1<<(7-i));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_binary(byte inpt)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 8; i++)
|
||||
if (inpt & (1<<(7-i))) putchar('1');
|
||||
else putchar('0');
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, max, offset;
|
||||
byte dec[256]={0}, enc[256]={0};
|
||||
char string[2048]={0};
|
||||
|
||||
offset = 8; // Preamble + Sync
|
||||
|
||||
if (argc>2)
|
||||
{
|
||||
if (argv[1][0]=='d')
|
||||
{
|
||||
if (strlen(argv[2]) > 256*8 || strlen(argv[2]) < 4) return -1;
|
||||
memcpy(string, argv[2], strlen(argv[2]));
|
||||
|
||||
for (i = 0; i < strlen(string)-3; i+=8)
|
||||
enc[i/8] = str2byte(&string[i]);
|
||||
max = i/8;
|
||||
memcpy(&dec, &enc, 256);
|
||||
|
||||
/*
|
||||
* byte[] Dec = new byte[Enc.Length];
|
||||
* Dec[0] = Enc[0]; //Packet length
|
||||
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
|
||||
* int j;
|
||||
* for (j = 2; j < Dec[0]; j++)
|
||||
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
|
||||
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
|
||||
*/
|
||||
|
||||
dec[offset+0] = enc[offset+0];
|
||||
|
||||
dec[offset+1] = (~enc[offset+1])^0x89;
|
||||
for(i = offset + 2; i < max - 3; i++)
|
||||
dec[i] = (enc[i-1]+0xdc) ^ enc[i];
|
||||
dec[i] = enc[i] ^ dec[offset+2];
|
||||
|
||||
dec[max-1]=0; // Set CRC to 0x0000
|
||||
dec[max-2]=0;
|
||||
|
||||
for(i = 0; i < max; i++)
|
||||
print_binary(dec[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(argv[2]) > 256*8 || strlen(argv[2]) < 4) return -1;
|
||||
memcpy(string, argv[2], strlen(argv[2]));
|
||||
|
||||
for (i = 0; i < strlen(string)-3; i+=8)
|
||||
dec[i/8] = str2byte(&string[i]);
|
||||
max = i/8;
|
||||
memcpy(&enc, &dec, 256);
|
||||
|
||||
/*
|
||||
* byte[] Dec = new byte[Enc.Length];
|
||||
* Dec[0] = Enc[0]; //Packet length
|
||||
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
|
||||
* int j;
|
||||
* for (j = 2; j < Dec[0]; j++)
|
||||
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
|
||||
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
|
||||
*/
|
||||
|
||||
enc[offset+0] = dec[offset+0];
|
||||
|
||||
enc[offset+1] = ~(dec[offset+1]^0x89);
|
||||
for(i = offset + 2; i < max - 3; i++)
|
||||
enc[i] = (enc[i-1]+0xdc) ^ dec[i];
|
||||
enc[i] = dec[i] ^ dec[offset+2];
|
||||
|
||||
enc[max-1]=0; // Set CRC to 0x0000
|
||||
enc[max-2]=0;
|
||||
|
||||
for(i = 0; i < max; i++)
|
||||
print_binary(enc[i]);
|
||||
}
|
||||
}
|
||||
else printf("Usage: %s <d/e> <bit sequence>\n\td - decode\n\te - encode\n\tbit sequence as string of 0 and 1.\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,239 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SHORTEN_PREAMBLE_TO_32 0
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
uint16 crc(byte *data, int len)
|
||||
{
|
||||
byte i, x, crcdata;
|
||||
uint16 crcReg = 0xFFFF;
|
||||
for (x = 0; x < len; x++)
|
||||
{
|
||||
crcdata = data[x];
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (((crcReg & 0x8000) >> 8) ^ (crcdata & 0x80))
|
||||
crcReg = (crcReg << 1) ^ 0x8005;
|
||||
else
|
||||
crcReg = (crcReg << 1);
|
||||
crcdata <<= 1;
|
||||
}
|
||||
}
|
||||
return crcReg;
|
||||
}
|
||||
|
||||
byte str2byte(char str[8])
|
||||
{
|
||||
int ret = 0, i;
|
||||
for(i = 0; i < 8; i++)
|
||||
if (str[i]=='1') ret |= (1<<(7-i));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_binary(byte inpt)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 8; i++)
|
||||
if (inpt & (1<<(7-i))) putchar('1');
|
||||
else putchar('0');
|
||||
}
|
||||
|
||||
void print_preamble_nibbles(int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
printf("1010");
|
||||
}
|
||||
|
||||
int find_preamble_start_in_bit(char *string, int len)
|
||||
{
|
||||
char homematic_sync[] = "11101001110010101110100111001010";
|
||||
for(int i = 0, j = 0; i < len; i++)
|
||||
{
|
||||
if(string[i] == homematic_sync[j])
|
||||
{
|
||||
j++;
|
||||
if(j == 32 && i>= 63) return i-63;
|
||||
}
|
||||
else j = 0;
|
||||
}
|
||||
return -1; //not found
|
||||
}
|
||||
|
||||
void xor_lfsr(char *string)
|
||||
{
|
||||
int i, j, x, len = strlen(string);
|
||||
byte polynomial[9] = {0, 0, 0, 1, 0, 0, 0, 0, 1};
|
||||
byte lfsr_state[9];
|
||||
byte first_bit;
|
||||
|
||||
// Init with 8x 1 Bit
|
||||
memset(lfsr_state, 1, 9);
|
||||
for(j = 0; j < 8; j++)
|
||||
if(string[j]=='1')
|
||||
string[j]='0';
|
||||
else
|
||||
string[j]='1';
|
||||
|
||||
for(x = 8; x < len-7; x += 8)
|
||||
{
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
first_bit = 255;
|
||||
for(j = 8; j >= 0; j--)
|
||||
if(polynomial[j] && lfsr_state[j])
|
||||
{
|
||||
if(first_bit == 255)
|
||||
first_bit = 1;
|
||||
else
|
||||
first_bit = (first_bit==1) ? 0 : 1;
|
||||
}
|
||||
if(first_bit == 255)
|
||||
first_bit = 0;
|
||||
|
||||
// Clock
|
||||
for(j = 8; j >= 0; j--)
|
||||
lfsr_state[j] = lfsr_state[j-1];
|
||||
lfsr_state[0] = first_bit;
|
||||
}
|
||||
|
||||
// Xor
|
||||
for(j = 0; j < 8; j++)
|
||||
if(lfsr_state[j+1] == 1)
|
||||
if(string[x+j]=='1')
|
||||
string[x+j]='0';
|
||||
else
|
||||
string[x+j]='1';
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, j, max, offset, len, preamble_additional_length;
|
||||
byte dec[1024]={0}, enc[1024]={0}, crc_ok;
|
||||
char string[65536]={0};
|
||||
uint16 crcvalue;
|
||||
offset = 8; // Preamble + Sync
|
||||
|
||||
// Copy data (argv[2]) to string if length is ok, shorten to multiple of 8 bit
|
||||
if (strlen(argv[2]) > 8192*8 || strlen(argv[2]) < 4) return -1;
|
||||
len = strlen(argv[2]);
|
||||
|
||||
i = find_preamble_start_in_bit(argv[2], len);
|
||||
if(i < 0) return 0; // preamble+sync not found or wrong length
|
||||
preamble_additional_length = i;
|
||||
|
||||
len = (len-i)-(len-i)%8;
|
||||
memcpy(string, argv[2]+i, len);
|
||||
|
||||
if (argc>2)
|
||||
{
|
||||
if (argv[1][0]=='d')
|
||||
{
|
||||
// Apply datawhitening
|
||||
xor_lfsr(string+64);
|
||||
|
||||
// Pack to bytes
|
||||
for (i = 0; i < strlen(string)-3; i+=8)
|
||||
enc[i/8] = str2byte(&string[i]);
|
||||
max = i/8;
|
||||
memcpy(&dec, &enc, 1024);
|
||||
|
||||
// Check CRC
|
||||
crcvalue = crc(&dec[8], max-2-8);
|
||||
crc_ok = 0;
|
||||
if( ((crcvalue >> 8) & 0xFF) == dec[max-2] && (crcvalue & 0xFF) == dec[max-1]) crc_ok = 1;
|
||||
|
||||
/*
|
||||
* byte[] Dec = new byte[Enc.Length];
|
||||
* Dec[0] = Enc[0]; //Packet length
|
||||
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
|
||||
* int j;
|
||||
* for (j = 2; j < Dec[0]; j++)
|
||||
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
|
||||
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
|
||||
*/
|
||||
|
||||
// Decrypt
|
||||
dec[offset+0] = enc[offset+0];
|
||||
dec[offset+1] = (~enc[offset+1])^0x89;
|
||||
for(i = offset + 2; i < max - 3; i++)
|
||||
dec[i] = (enc[i-1]+0xdc) ^ enc[i];
|
||||
dec[i] = enc[i] ^ dec[offset+2];
|
||||
|
||||
// Recompute CRC and overwrite with FAKE-CRC, if CRC was OK before
|
||||
if(crc_ok)
|
||||
{
|
||||
crcvalue = crc(&dec[8], max-2-8);
|
||||
dec[max-1] = crcvalue & 0xFF;
|
||||
dec[max-2] = (crcvalue >> 8) & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
dec[max-1] = 0x0F; // Set magic code for wrong CRC
|
||||
dec[max-2] = 0xD0;
|
||||
}
|
||||
|
||||
// Prepend preamble longer than 32 bits
|
||||
if(0 == SHORTEN_PREAMBLE_TO_32 && preamble_additional_length > 0)
|
||||
print_preamble_nibbles(preamble_additional_length/4);
|
||||
|
||||
for(i = 0; i < max; i++)
|
||||
print_binary(dec[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pack to bytes
|
||||
for (i = 0; i < strlen(string)-3; i+=8)
|
||||
dec[i/8] = str2byte(&string[i]);
|
||||
max = i/8;
|
||||
memcpy(&enc, &dec, 1024);
|
||||
|
||||
/*
|
||||
* byte[] Dec = new byte[Enc.Length];
|
||||
* Dec[0] = Enc[0]; //Packet length
|
||||
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
|
||||
* int j;
|
||||
* for (j = 2; j < Dec[0]; j++)
|
||||
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
|
||||
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
|
||||
*/
|
||||
|
||||
// Encrypt
|
||||
enc[offset+0] = dec[offset+0];
|
||||
enc[offset+1] = ~(dec[offset+1])^0x89;
|
||||
for(i = offset + 2; i < max - 3; i++)
|
||||
enc[i] = (enc[i-1]+0xdc) ^ dec[i];
|
||||
enc[i] = dec[i] ^ dec[offset+2];
|
||||
|
||||
// Overwrite with correct CRC
|
||||
crcvalue = crc(&enc[8], max-2-8);
|
||||
enc[max-1] = crcvalue & 0xFF;
|
||||
enc[max-2] = (crcvalue >> 8) & 0xFF;
|
||||
|
||||
// Convert to string
|
||||
memset(string, 0, 65536);
|
||||
for(i = 0; i < max; i++)
|
||||
{
|
||||
for(j = 0; j < 8; j++)
|
||||
if(enc[i] & (1<<(7-j))) string[i*8+j]='1';
|
||||
else string[i*8+j]='0';
|
||||
}
|
||||
// Apply datawhitening
|
||||
xor_lfsr(string+64);
|
||||
|
||||
// Prepend preamble longer than 32 bits
|
||||
if(0 == SHORTEN_PREAMBLE_TO_32 && preamble_additional_length > 0) // Add preamble longer than 32 bits
|
||||
print_preamble_nibbles(preamble_additional_length/4);
|
||||
|
||||
// Print bits and duplicate last bit
|
||||
printf("%s%c\n", string, string[strlen(string)-1]);
|
||||
}
|
||||
}
|
||||
else printf("Usage: %s <d/e> <bit sequence>\n\td - decode\n\te - encode\n\tbit sequence as string of 0 and 1.\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
BIN
Software/Universal Radio Hacker/data/decodings/test
Normal file
47
Software/Universal Radio Hacker/data/decodings/test.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, count, what;
|
||||
if(argc>2)
|
||||
{
|
||||
if(argv[1][0]=='d')
|
||||
{
|
||||
for(i = 0; i < strlen(argv[2]); i++)
|
||||
if(argv[2][i] == '0') printf("000");
|
||||
else printf("11");
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
what = -1;
|
||||
for(i = 0; i < strlen(argv[2]); i++)
|
||||
{
|
||||
if(argv[2][i] == '0')
|
||||
{
|
||||
if(what == 1) count = 0;
|
||||
what = 0;
|
||||
count++;
|
||||
if(count == 3)
|
||||
{
|
||||
putchar('0');
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(what == 0) count = 0;
|
||||
what = 1;
|
||||
count++;
|
||||
if(count == 2)
|
||||
{
|
||||
putchar('1');
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
2
Software/Universal Radio Hacker/data/decodings/test.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
echo "$1$1"
|
72
Software/Universal Radio Hacker/data/generate_ui.py
Normal file
@ -0,0 +1,72 @@
|
||||
import sys
|
||||
import os
|
||||
from subprocess import call
|
||||
import fileinput
|
||||
|
||||
|
||||
def gen(force=False):
|
||||
if sys.platform == "win32":
|
||||
bindir = r"c:\Python34\Lib\site-packages\PyQt5"
|
||||
else:
|
||||
bindir = "/usr/bin"
|
||||
|
||||
if sys.platform == "win32":
|
||||
uic_path = os.path.join(bindir, "pyuic5.bat")
|
||||
rcc_path = os.path.join(bindir, "pyrcc5.exe")
|
||||
else:
|
||||
uic_path = os.path.join(bindir, "pyuic5")
|
||||
rcc_path = os.path.join(bindir, "pyrcc5")
|
||||
|
||||
file_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "ui")
|
||||
ui_path = file_dir
|
||||
rc_path = file_dir
|
||||
out_path = os.path.join(file_dir, "..", "..", "src", "urh", "ui")
|
||||
|
||||
ui_files = [f for f in os.listdir(ui_path) if f.endswith(".ui")]
|
||||
rc_files = [f for f in os.listdir(rc_path) if f.endswith(".qrc")]
|
||||
|
||||
for f in ui_files:
|
||||
file_path = os.path.join(ui_path, f)
|
||||
outfile = "ui_" + f.replace(".ui", ".py")
|
||||
out_file_path = os.path.join(out_path, outfile)
|
||||
time_ui_file = os.path.getmtime(file_path)
|
||||
try:
|
||||
time_generated_file = os.path.getmtime(out_file_path)
|
||||
except os.error:
|
||||
time_generated_file = 0
|
||||
|
||||
if time_generated_file >= time_ui_file and not force:
|
||||
# Generated file is already there and newer than ui file, no need to recompile it
|
||||
continue
|
||||
|
||||
call([uic_path, "--from-imports", file_path, "-o", out_file_path])
|
||||
|
||||
# Remove Line: # Form implementation generated from reading ui file '/home/joe/GIT/urh/ui/fuzzing.ui'
|
||||
# to avoid useless git updates when working on another computer
|
||||
for line in fileinput.input(out_file_path, inplace=True):
|
||||
if line.startswith("# Form implementation generated from reading ui file") or line.startswith(
|
||||
"# Created by: "):
|
||||
continue
|
||||
if line.strip().startswith("QtCore.QMetaObject.connectSlotsByName("):
|
||||
# disable auto slot connection, as we do not use it, and it causes crash on python 3.7
|
||||
continue
|
||||
print(line, end='')
|
||||
|
||||
for f in rc_files:
|
||||
file_path = os.path.join(rc_path, f)
|
||||
out_file = f.replace(".qrc", "_rc.py")
|
||||
out_file_path = os.path.join(out_path, out_file)
|
||||
|
||||
time_rc_file = os.path.getmtime(file_path)
|
||||
try:
|
||||
time_generated_file = os.path.getmtime(out_file_path)
|
||||
except os.error:
|
||||
time_generated_file = 0
|
||||
|
||||
if time_generated_file < time_rc_file or force:
|
||||
# Only create, when generated file is old than rc file to prevent unneeded git pushes
|
||||
call([rcc_path, file_path, "-o", out_file_path])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
gen()
|
BIN
Software/Universal Radio Hacker/data/icons/appicon.icns
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
Software/Universal Radio Hacker/data/icons/appicon.ico
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
Software/Universal Radio Hacker/data/icons/appicon.png
Normal file
After Width: | Height: | Size: 85 KiB |
255
Software/Universal Radio Hacker/data/icons/appicon.svg
Normal file
After Width: | Height: | Size: 516 KiB |
BIN
Software/Universal Radio Hacker/data/icons/appicon_big.png
Normal file
After Width: | Height: | Size: 138 KiB |
430
Software/Universal Radio Hacker/data/icons/appicon_big.svg
Normal file
After Width: | Height: | Size: 523 KiB |
BIN
Software/Universal Radio Hacker/data/icons/banner.png
Normal file
After Width: | Height: | Size: 98 KiB |
382
Software/Universal Radio Hacker/data/icons/banner.svg
Normal file
After Width: | Height: | Size: 521 KiB |
63
Software/Universal Radio Hacker/data/icons/collapse.svg
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="collapse.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="-25.75"
|
||||
inkscape:cy="8"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<path
|
||||
id="path1447"
|
||||
inkscape:label="Triangle"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.0745703;stroke-opacity:1"
|
||||
d="m 4,4 v 8 l 8,-4.0000001 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
107
Software/Universal Radio Hacker/data/icons/decoding.svg
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="decoding.svg"
|
||||
inkscape:export-filename="/home/joe/GIT/urh/data/icons/decoding.svg.png"
|
||||
inkscape:export-xdpi="94.889999"
|
||||
inkscape:export-ydpi="94.889999">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="2.84375"
|
||||
inkscape:cy="20.0625"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
showguides="false" />
|
||||
<defs
|
||||
id="defs33" />
|
||||
<metadata
|
||||
id="metadata36">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<rect
|
||||
id="rect72"
|
||||
width="16.1875"
|
||||
height="2.125"
|
||||
x="0"
|
||||
y="7"
|
||||
style="stroke-width:0.57454073" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Ebene 2">
|
||||
<g
|
||||
aria-label="101"
|
||||
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Semi-Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="text51">
|
||||
<path
|
||||
d="M 0.33433331,6.4375 H 4.6649998 V 5.1495 H 3.3956665 V 0.52016687 H 2.2196666 C 1.7529999,0.80016686 1.2863333,0.96816685 0.57699997,1.0988335 V 2.0881668 H 1.7903333 V 5.1495 H 0.33433331 Z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
|
||||
id="path4542" />
|
||||
<path
|
||||
d="m 8.0213539,6.5495 c 1.3906666,0 2.3333331,-1.0733333 2.3333331,-3.0986666 0,-2.0253332 -0.9426665,-3.04266653 -2.3333331,-3.04266653 -1.3906666,0 -2.3333332,1.01733333 -2.3333332,3.04266653 0,2.0253333 0.9426666,3.0986666 2.3333332,3.0986666 z m 0,-1.232 c -0.4946666,0 -0.9146666,-0.3919999 -0.9146666,-1.8666666 0,-1.4746666 0.42,-1.8106666 0.9146666,-1.8106666 0.4946667,0 0.9146666,0.336 0.9146666,1.8106666 0,1.4746667 -0.4199999,1.8666666 -0.9146666,1.8666666 z m 0,-1.1199999 c 0.4293333,0 0.7466667,-0.2986667 0.7466667,-0.7466667 0,-0.4479999 -0.3173334,-0.7466666 -0.7466667,-0.7466666 -0.4293333,0 -0.7466666,0.2986667 -0.7466666,0.7466666 0,0.448 0.3173333,0.7466667 0.7466666,0.7466667 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
|
||||
id="path4544" />
|
||||
<path
|
||||
d="m 11.527041,6.4375 h 4.330667 V 5.1495 H 14.588375 V 0.52016687 h -1.176 C 12.945708,0.80016686 12.479041,0.96816685 11.769708,1.0988335 v 0.9893333 h 1.213333 V 5.1495 h -1.456 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
|
||||
id="path4546" />
|
||||
</g>
|
||||
<g
|
||||
aria-label="010"
|
||||
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:9.33333302px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Semi-Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="text51-0">
|
||||
<path
|
||||
d="m 2.4780495,15.7097 c 1.3906666,0 2.3333332,-1.073333 2.3333332,-3.098666 0,-2.025334 -0.9426666,-3.042667 -2.3333332,-3.042667 -1.3906667,0 -2.33333328,1.017333 -2.33333328,3.042667 0,2.025333 0.94266658,3.098666 2.33333328,3.098666 z m 0,-1.232 c -0.4946667,0 -0.9146667,-0.392 -0.9146667,-1.866666 0,-1.474667 0.42,-1.810667 0.9146667,-1.810667 0.4946666,0 0.9146666,0.336 0.9146666,1.810667 0,1.474666 -0.42,1.866666 -0.9146666,1.866666 z m 0,-1.12 c 0.4293333,0 0.7466666,-0.298666 0.7466666,-0.746666 0,-0.448 -0.3173333,-0.746667 -0.7466666,-0.746667 -0.4293333,0 -0.7466667,0.298667 -0.7466667,0.746667 0,0.448 0.3173334,0.746666 0.7466667,0.746666 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
|
||||
id="path4549" />
|
||||
<path
|
||||
d="m 5.9837369,15.5977 h 4.3306661 v -1.288 H 9.0450701 V 9.680367 H 7.8690702 c -0.4666667,0.28 -0.9333334,0.448 -1.6426667,0.578667 v 0.989333 H 7.4397368 V 14.3097 H 5.9837369 Z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
|
||||
id="path4551" />
|
||||
<path
|
||||
d="m 13.670757,15.7097 c 1.390667,0 2.333334,-1.073333 2.333334,-3.098666 0,-2.025334 -0.942667,-3.042667 -2.333334,-3.042667 -1.390666,0 -2.333333,1.017333 -2.333333,3.042667 0,2.025333 0.942667,3.098666 2.333333,3.098666 z m 0,-1.232 c -0.494666,0 -0.914666,-0.392 -0.914666,-1.866666 0,-1.474667 0.42,-1.810667 0.914666,-1.810667 0.494667,0 0.914667,0.336 0.914667,1.810667 0,1.474666 -0.42,1.866666 -0.914667,1.866666 z m 0,-1.12 c 0.429334,0 0.746667,-0.298666 0.746667,-0.746666 0,-0.448 -0.317333,-0.746667 -0.746667,-0.746667 -0.429333,0 -0.746666,0.298667 -0.746666,0.746667 0,0.448 0.317333,0.746666 0.746666,0.746666 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
|
||||
id="path4553" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.6 KiB |
77
Software/Universal Radio Hacker/data/icons/equals.svg
Normal file
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32px"
|
||||
height="32px"
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="equals.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="-7.8340023"
|
||||
inkscape:cy="9.8125"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs4485" />
|
||||
<metadata
|
||||
id="metadata4488">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="8.375"
|
||||
y="7.875"
|
||||
id="text5091"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5089"
|
||||
x="8.375"
|
||||
y="14.875" /></text>
|
||||
<g
|
||||
transform="translate(-2.8046876,-0.0527343)"
|
||||
aria-label=" ≟"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#0055d4;fill-opacity:1;stroke:none"
|
||||
id="text5046" />
|
||||
<path
|
||||
id="path5687"
|
||||
style="fill:#0055d4;fill-opacity:1;stroke:none;stroke-width:0.94488192;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 3.1054687,18.119141 H 28.144531 v 4.628906 H 3.1054687 Z m 0,-8.886719 H 28.144531 v 4.589844 H 3.1054687 Z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
66
Software/Universal Radio Hacker/data/icons/equals_qm.svg
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32px"
|
||||
height="32px"
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="equals_qm.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="20.384743"
|
||||
inkscape:cy="14.953125"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs4485" />
|
||||
<metadata
|
||||
id="metadata4488">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<g
|
||||
aria-label=" ≟"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#0055d4;fill-opacity:1;stroke:none"
|
||||
id="text5046">
|
||||
<path
|
||||
d="M 3.9726563,17.472656 H 29.011719 V 22.0625 H 3.9726563 Z m 0,8.886719 H 29.011719 v 4.628906 H 3.9726563 Z M 17.585937,10.539063 h -3.535156 v -0.46875 q 0,-0.820313 0.3125,-1.4257817 0.332032,-0.625 1.367188,-1.5820313 l 0.625,-0.5664063 q 0.566406,-0.5078125 0.820312,-0.9570312 0.253906,-0.4492188 0.253906,-0.8984375 0,-0.6835937 -0.46875,-1.0546875 -0.46875,-0.390625 -1.308593,-0.390625 -0.800781,0 -1.71875,0.3320313 -0.917969,0.3125 -1.894531,0.9570312 V 1.4179687 Q 13.210938,1.0078125 14.1875,0.8125 q 0.976563,-0.1953125 1.875,-0.1953125 2.382812,0 3.632812,0.9765625 1.25,0.9765625 1.25,2.8320312 0,0.9570313 -0.371093,1.71875 Q 20.203125,6.90625 19.265625,7.765625 l -0.625,0.546875 q -0.664063,0.625 -0.859375,0.9960938 -0.195313,0.3515625 -0.195313,0.8007812 z m -3.535156,1.445312 h 3.535156 v 3.476563 h -3.535156 z"
|
||||
style="fill:#0055d4;fill-opacity:1"
|
||||
id="path5048" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Software/Universal Radio Hacker/data/icons/icon.xcf
Normal file
105
Software/Universal Radio Hacker/data/icons/lock.svg
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="lock.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="2.438584"
|
||||
inkscape:cy="8.4622059"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="844"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs10" />
|
||||
<metadata
|
||||
id="metadata13">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Ebene 3" />
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<rect
|
||||
style="fill:#0055d4;fill-opacity:1;stroke-width:1.29552507"
|
||||
id="rect26"
|
||||
width="13.1875"
|
||||
height="9.4109621"
|
||||
x="1.53125"
|
||||
y="6.1827879"
|
||||
ry="1.668939" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#0055d4;stroke-width:2.37899995;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path955"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="8.0946102"
|
||||
sodipodi:cy="4.9240141"
|
||||
sodipodi:rx="4.0718422"
|
||||
sodipodi:ry="3.1146088"
|
||||
sodipodi:start="3.1334605"
|
||||
sodipodi:end="3.1328231"
|
||||
d="M 4.0229027,4.9493423 A 4.0718422,3.1146088 0 0 1 8.0608489,1.8095124 4.0718422,3.1146088 0 0 1 12.166307,4.8976933 4.0718422,3.1146088 0 0 1 8.1296692,8.0385074 4.0718422,3.1146088 0 0 1 4.0229246,4.9513275"
|
||||
sodipodi:open="true" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Ebene 2">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.50427711;stroke-opacity:1"
|
||||
id="path853"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="8.0742912"
|
||||
sodipodi:cy="8.8435822"
|
||||
sodipodi:rx="1.8158679"
|
||||
sodipodi:ry="1.7158939"
|
||||
sodipodi:start="3.1415927"
|
||||
sodipodi:end="2.8204603"
|
||||
d="M 6.2584233,8.8435821 A 1.8158679,1.7158939 0 0 1 7.9286644,7.1332151 1.8158679,1.7158939 0 0 1 9.8668015,8.56925 1.8158679,1.7158939 0 0 1 8.5074256,10.509948 1.8158679,1.7158939 0 0 1 6.351253,9.385189"
|
||||
sodipodi:open="true" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79365373;stroke-opacity:1"
|
||||
id="rect1685"
|
||||
width="1.2488354"
|
||||
height="4.0842142"
|
||||
x="7.4914622"
|
||||
y="10.344006" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
68
Software/Universal Radio Hacker/data/icons/message_type.svg
Normal file
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="message_type.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="4.9678955"
|
||||
inkscape:cy="8.278417"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:14.66666698px;line-height:1.25;font-family:'Source Sans Pro';-inkscape-font-specification:'Source Sans Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#008000;fill-opacity:1;stroke:none"
|
||||
x="-0.75"
|
||||
y="12.0625"
|
||||
id="text1376"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1374"
|
||||
x="-0.75"
|
||||
y="12.0625"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:12.66666698px;line-height:1;font-family:'Source Sans Pro';-inkscape-font-specification:'Source Sans Pro Heavy';fill:#008000">MT</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
84
Software/Universal Radio Hacker/data/icons/modulation.svg
Normal file
After Width: | Height: | Size: 70 KiB |
76
Software/Universal Radio Hacker/data/icons/plus.svg
Normal file
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32px"
|
||||
height="32px"
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="plus.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="20.384743"
|
||||
inkscape:cy="17.390625"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs4485" />
|
||||
<metadata
|
||||
id="metadata4488">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="8.375"
|
||||
y="7.875"
|
||||
id="text5091"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5089"
|
||||
x="8.375"
|
||||
y="14.875" /></text>
|
||||
<g
|
||||
aria-label="+"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:53.33333206px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#0055d4;fill-opacity:1;stroke:none"
|
||||
id="text5707">
|
||||
<path
|
||||
d="m 12.755833,28.8875 h 6.613333 v -9.6 h 9.28 v -6.4 h -9.28 V 3.2875007 H 12.755833 V 12.8875 H 3.4758333 v 6.4 h 9.2799997 z"
|
||||
style=""
|
||||
id="path5709" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
162
Software/Universal Radio Hacker/data/icons/sniffer.svg
Normal file
@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
sodipodi:docname="sniffer.svg"
|
||||
inkscape:version="0.92.1 r">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="2.7848469"
|
||||
inkscape:cy="9.5734649"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs5036">
|
||||
<linearGradient
|
||||
id="linearGradient7079"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#aaccff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7077" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter914">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood904" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite906" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="0.5"
|
||||
result="blur"
|
||||
id="feGaussianBlur908" />
|
||||
<feOffset
|
||||
dx="0.1"
|
||||
dy="0.1"
|
||||
result="offset"
|
||||
id="feOffset910" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite912" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter938">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood928" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite930" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="0.5"
|
||||
result="blur"
|
||||
id="feGaussianBlur932" />
|
||||
<feOffset
|
||||
dx="0.1"
|
||||
dy="0.1"
|
||||
result="offset"
|
||||
id="feOffset934" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite936" />
|
||||
</filter>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata5039">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Ebene 2">
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:1.88976378;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter938)"
|
||||
d="m 11.303085,11.154756 3.83883,3.910488"
|
||||
id="path5611"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<circle
|
||||
style="fill:#afc6e9;fill-opacity:0.78417263;stroke:#ff0000;stroke-width:1.19093943;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter914)"
|
||||
id="path5605"
|
||||
cx="6.8475037"
|
||||
cy="6.8600025"
|
||||
r="6.0412431" />
|
||||
<g
|
||||
aria-label="10"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:10.66666698px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="text5597"
|
||||
transform="matrix(0.7643067,0,0,0.85162896,0.65422787,0.02035532)">
|
||||
<path
|
||||
d="M 2.4981667,11.1875 H 7.4475002 V 9.7155 H 5.9968335 V 4.4248331 H 4.6528334 c -0.5333333,0.32 -1.0666667,0.512 -1.8773334,0.6613334 V 6.2168332 H 4.1621667 V 9.7155 h -1.664 z"
|
||||
id="path7117"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:1" />
|
||||
<path
|
||||
d="m 11.283334,11.3155 c 1.589333,0 2.666666,-1.226667 2.666666,-3.5413334 0,-2.3146668 -1.077333,-3.4773335 -2.666666,-3.4773335 -1.5893338,0 -2.6666672,1.1626667 -2.6666672,3.4773335 0,2.3146664 1.0773334,3.5413334 2.6666672,3.5413334 z m 0,-1.408 C 10.718,9.9075 10.238,9.4594999 10.238,7.7741666 c 0,-1.6853334 0.48,-2.0693334 1.045334,-2.0693334 0.565333,0 1.045333,0.384 1.045333,2.0693334 0,1.6853333 -0.48,2.1333334 -1.045333,2.1333334 z m 0,-1.2800001 c 0.490666,0 0.853333,-0.3413333 0.853333,-0.8533333 0,-0.5120001 -0.362667,-0.8533334 -0.853333,-0.8533334 -0.490667,0 -0.853334,0.3413333 -0.853334,0.8533334 0,0.512 0.362667,0.8533333 0.853334,0.8533333 z"
|
||||
id="path7119"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.6 KiB |
67
Software/Universal Radio Hacker/data/icons/spectrum.svg
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="spectrum.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="45.254834"
|
||||
inkscape:cx="4.0007222"
|
||||
inkscape:cy="7.9550105"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs5788" />
|
||||
<metadata
|
||||
id="metadata5791">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 2"
|
||||
id="layer2"
|
||||
inkscape:groupmode="layer" />
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<path
|
||||
style="fill:#80b3ff;fill-rule:evenodd;stroke:#7d7d7d;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M -0.1767767,13.19367 C -0.15467961,13.061088 0.79549512,7.2716507 0.79549512,7.2716507 L 1.6130873,12.818019 2.9610096,8.4648934 4.0216698,13.326252 5.5021746,7.7135924 6.2755727,12.199301 8.2201163,0.50994206 10.341437,13.171573 l 1.635184,-5.1707185 0.861787,4.1542525 0.773397,-3.9995729 0.662913,4.8171649 1.038563,-5.5905629 0.795495,5.8115339"
|
||||
id="path4631"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16mm"
|
||||
height="8mm"
|
||||
viewBox="0 0 16 8"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="splitter_handle_horizontal.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.2"
|
||||
inkscape:cx="28.682636"
|
||||
inkscape:cy="13.700107"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-289)">
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4487"
|
||||
cx="2.0135045"
|
||||
cy="293.08649"
|
||||
r="1.9135045" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4487-6"
|
||||
cx="7.9135046"
|
||||
cy="293.08649"
|
||||
r="1.9135045" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4487-7"
|
||||
cx="14.013505"
|
||||
cy="293.08649"
|
||||
r="1.9135045" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="8mm"
|
||||
height="16mm"
|
||||
viewBox="0 0 8 16"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="splitter_handle_vertical.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.2"
|
||||
inkscape:cx="28.682636"
|
||||
inkscape:cy="35.128679"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-281)">
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4487"
|
||||
cx="-294.98648"
|
||||
cy="3.9135046"
|
||||
r="1.9135045"
|
||||
transform="rotate(-90)" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4487-6"
|
||||
cx="-289.08649"
|
||||
cy="3.9135046"
|
||||
r="1.9135045"
|
||||
transform="rotate(-90)" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4487-7"
|
||||
cx="-282.98648"
|
||||
cy="3.9135046"
|
||||
r="1.9135045"
|
||||
transform="rotate(-90)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
63
Software/Universal Radio Hacker/data/icons/uncollapse.svg
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="uncollapse.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="-8.875"
|
||||
inkscape:cy="8"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1141"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<path
|
||||
id="path1447"
|
||||
inkscape:label="Triangle"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.0745703;stroke-opacity:1"
|
||||
d="M 12,4 H 4 l 4.000001,8 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
105
Software/Universal Radio Hacker/data/icons/unlock.svg
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:version="0.92.1 r"
|
||||
sodipodi:docname="unlock.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="2.438584"
|
||||
inkscape:cy="8.4622059"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="844"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true" />
|
||||
<defs
|
||||
id="defs10" />
|
||||
<metadata
|
||||
id="metadata13">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Ebene 3" />
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Ebene 1">
|
||||
<rect
|
||||
style="fill:#0055d4;fill-opacity:1;stroke-width:1.29552507"
|
||||
id="rect26"
|
||||
width="13.1875"
|
||||
height="9.4109621"
|
||||
x="1.53125"
|
||||
y="6.1827879"
|
||||
ry="1.668939" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#0055d4;stroke-width:2.37899995;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path955"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="8.0946102"
|
||||
sodipodi:cy="4.9240141"
|
||||
sodipodi:rx="4.0718422"
|
||||
sodipodi:ry="3.1146088"
|
||||
sodipodi:start="4.709543"
|
||||
sodipodi:end="1.5424001"
|
||||
d="M 8.0830218,1.8094179 A 4.0718422,3.1146088 0 0 1 12.165956,4.8753624 4.0718422,3.1146088 0 0 1 8.2102196,8.0373672"
|
||||
sodipodi:open="true" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Ebene 2">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.50427711;stroke-opacity:1"
|
||||
id="path853"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="8.0742912"
|
||||
sodipodi:cy="8.8435822"
|
||||
sodipodi:rx="1.8158679"
|
||||
sodipodi:ry="1.7158939"
|
||||
sodipodi:start="3.1415927"
|
||||
sodipodi:end="2.8204603"
|
||||
d="M 6.2584233,8.8435821 A 1.8158679,1.7158939 0 0 1 7.9286644,7.1332151 1.8158679,1.7158939 0 0 1 9.8668015,8.56925 1.8158679,1.7158939 0 0 1 8.5074256,10.509948 1.8158679,1.7158939 0 0 1 6.351253,9.385189"
|
||||
sodipodi:open="true" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79365373;stroke-opacity:1"
|
||||
id="rect1685"
|
||||
width="1.2488354"
|
||||
height="4.0842142"
|
||||
x="7.4914622"
|
||||
y="10.344006" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
38
Software/Universal Radio Hacker/data/inno.iss
Normal file
@ -0,0 +1,38 @@
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application.
|
||||
; Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{8A0E36A6-DE56-46B8-BCC3-C16D1BC759CC}
|
||||
AppName=Universal Radio Hacker
|
||||
AppVersion={#MyAppVersion}
|
||||
VersionInfoVersion={#MyAppVersion}
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
UninstallDisplayName=Universal Radio Hacker
|
||||
AppPublisher=Johannes Pohl
|
||||
AppPublisherURL=https://github.com/jopohl/urh
|
||||
AppSupportURL=https://github.com/jopohl/urh
|
||||
AppUpdatesURL=https://github.com/jopohl/urh
|
||||
DefaultDirName={commonpf}\Universal Radio Hacker
|
||||
DisableProgramGroupPage=yes
|
||||
LicenseFile=..\LICENSE
|
||||
OutputDir=..\dist
|
||||
OutputBaseFilename=Universal.Radio.Hacker-{#MyAppVersion}-{#Arch}
|
||||
Compression=lzma2/ultra
|
||||
SolidCompression=yes
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "..\pyinstaller\urh\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Icons]
|
||||
Name: "{commonprograms}\Universal Radio Hacker"; Filename: "{app}\urh.exe"
|
||||
Name: "{commondesktop}\Universal Radio Hacker"; Filename: "{app}\urh.exe"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\urh.exe"; Description: "{cm:LaunchProgram,Universal Radio Hacker}"; Flags: nowait postinstall skipifsilent
|
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# for adapted jopohl/urh_manylinux
|
||||
|
||||
touch /tmp/urh_releasing
|
||||
for PYBIN in /opt/python/*$PYVER*/bin; do # for all if PYVER not set
|
||||
echo -e "\033[1mInstalling requirements for $PYBIN\033[0m"
|
||||
"${PYBIN}/pip" install -r /io/data/requirements.txt
|
||||
|
||||
cd /io || return
|
||||
echo -e "\033[1mBuilding extentions for $PYBIN\033[0m"
|
||||
"${PYBIN}/python3" setup.py build_ext "-j$(nproc)"
|
||||
|
||||
echo -e "\033[1mBuilding wheel for $PYBIN\033[0m"
|
||||
"${PYBIN}/pip" wheel --no-deps /io/ -w /wheelhouse/
|
||||
done
|
||||
|
||||
# Bundle external libs into wheels
|
||||
echo -e '\033[92mRepairing wheels...\033[0m'
|
||||
for whl in /wheelhouse/*.whl; do
|
||||
auditwheel repair "$whl" -w /io/dist/
|
||||
done
|
@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
|
||||
# for plain quay.io/pypa/manylinux2014_x86_64
|
||||
|
||||
AIRSPY_VERSION="1.0.9"
|
||||
BLADERF_VERSION="2018.08"
|
||||
LIMESUITE_VERSION="20.01.0"
|
||||
SDRPLAY_VERSION="2.13"
|
||||
RTLSDR_VERSION="0.6.0"
|
||||
|
||||
echo -e '\033[92mInstalling dependencies...\033[0m'
|
||||
yum -y -q install wget cmake3 hackrf-devel uhd-devel\
|
||||
https://github.com/analogdevicesinc/libiio/releases/download/v0.19/libiio-0.19.g5f5af2e-centos-7-x86_64.rpm
|
||||
|
||||
build_airspy() {
|
||||
&> /dev/null
|
||||
tar xf /tmp/airspy.tar.gz -C /tmp
|
||||
cmake3 -Wno-dev -S /tmp/airspyone_host-$AIRSPY_VERSION -B /tmp/build_airspy > /dev/null
|
||||
make --silent -C /tmp/build_airspy > /dev/null
|
||||
make --silent -C /tmp/build_airspy install > /dev/null
|
||||
}
|
||||
|
||||
build_bladerf() {
|
||||
wget https://github.com/Nuand/bladeRF/archive/$BLADERF_VERSION.tar.gz -O /tmp/bladeRF.tar.gz &> /dev/null
|
||||
tar xf /tmp/bladeRF.tar.gz -C /tmp
|
||||
cmake3 -Wno-dev -S /tmp/bladeRF-$BLADERF_VERSION/host -B /tmp/build_blade > /dev/null
|
||||
make --silent -C /tmp/build_blade > /dev/null
|
||||
make --silent -C /tmp/build_blade install > /dev/null
|
||||
}
|
||||
|
||||
build_limesdr() {
|
||||
wget https://github.com/myriadrf/LimeSuite/archive/v$LIMESUITE_VERSION.tar.gz -O /tmp/lime.tar.gz &> /dev/null
|
||||
tar xf /tmp/lime.tar.gz -C /tmp
|
||||
cmake3 -Wno-dev -S /tmp/LimeSuite-$LIMESUITE_VERSION -B /tmp/build_lime > /dev/null
|
||||
make --silent -C /tmp/build_lime > /dev/null
|
||||
make --silent -C /tmp/build_lime install > /dev/null
|
||||
}
|
||||
|
||||
build_rtlsdr() {
|
||||
wget https://github.com/osmocom/rtl-sdr/archive/$RTLSDR_VERSION.tar.gz -O /tmp/rtlsdr.tar.gz &> /dev/null
|
||||
tar xf /tmp/rtlsdr.tar.gz -C /tmp
|
||||
cmake3 -Wno-dev -DDETACH_KERNEL_DRIVER=ON -S /tmp/rtl-sdr-$RTLSDR_VERSION -B /tmp/build_rtlsdr > /dev/null
|
||||
make --silent -C /tmp/build_rtlsdr > /dev/null
|
||||
make --silent -C /tmp/build_rtlsdr install > /dev/null
|
||||
}
|
||||
|
||||
build_sdrplay() {
|
||||
wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-$SDRPLAY_VERSION.1.run -O /tmp/sdrplay.run &> /dev/null
|
||||
bash /tmp/sdrplay.run --tar xf -C /tmp
|
||||
mv /tmp/mirsdrapi-rsp.h /usr/include
|
||||
mv /tmp/x86_64/* /usr/lib64
|
||||
ln -s /usr/lib64/libmirsdrapi-rsp.so.$SDRPLAY_VERSION /usr/lib64/libmirsdrapi-rsp.so
|
||||
}
|
||||
|
||||
echo -e '\033[92mCompiling SDR libs...\033[0m'
|
||||
build_airspy &
|
||||
build_bladerf &
|
||||
build_limesdr &
|
||||
build_rtlsdr &
|
||||
build_sdrplay &
|
||||
wait
|
||||
|
||||
touch /tmp/urh_releasing
|
||||
for PYBIN in /opt/python/*/bin; do
|
||||
echo -e "\033[1mInstalling requirements for $PYBIN\033[0m"
|
||||
"${PYBIN}/pip" install -r /io/data/requirements.txt > /dev/null
|
||||
|
||||
cd /io || return
|
||||
echo -e "\033[1mBuilding extentions for $PYBIN\033[0m"
|
||||
"${PYBIN}/python3" setup.py build_ext "-j$(nproc)" | grep --color=always "Skipping"
|
||||
|
||||
echo -e "\033[1mBuilding wheel for $PYBIN\033[0m"
|
||||
"${PYBIN}/pip" wheel --no-deps /io/ -w /wheelhouse/ > /dev/null
|
||||
done
|
||||
|
||||
# Bundle external libs into wheels
|
||||
echo -e '\033[92mRepairing wheels...\033[0m'
|
||||
for whl in /wheelhouse/*.whl; do
|
||||
auditwheel repair "$whl" -w /io/dist/
|
||||
done
|
@ -0,0 +1,48 @@
|
||||
FROM quay.io/pypa/manylinux2014_x86_64
|
||||
|
||||
RUN export AIRSPY_VERSION="1.0.9" \
|
||||
&& export BLADERF_VERSION="2018.08" \
|
||||
&& export LIMESUITE_VERSION="20.01.0" \
|
||||
&& export SDRPLAY_VERSION="2.13" \
|
||||
&& export RTLSDR_VERSION="0.6.0" \
|
||||
&& export UHD_VERSION="3.15.0.0" \
|
||||
&& yum -y install wget cmake3 hackrf-devel boost169-devel https://github.com/analogdevicesinc/libiio/releases/download/v0.19/libiio-0.19.g5f5af2e-centos-7-x86_64.rpm \
|
||||
# UHD
|
||||
&& wget https://github.com/EttusResearch/uhd/archive/v$UHD_VERSION.tar.gz -O /tmp/uhd.tar.gz \
|
||||
&& tar xf /tmp/uhd.tar.gz -C /tmp \
|
||||
&& python3.9 -m pip install mako \
|
||||
&& cmake3 -DBOOST_INCLUDEDIR=/usr/include/boost169/ -DBOOST_LIBRARYDIR=/usr/lib64/boost169/ -DENABLE_EXAMPLES=OFF -DENABLE_UTILS=OFF -DENABLE_C_API=ON -DENABLE_TESTS=OFF -DENABLE_MAN_PAGES=OFF -S /tmp/uhd-$UHD_VERSION/host -B /tmp/build_uhd \
|
||||
&& make -j$(nproc) -C /tmp/build_uhd \
|
||||
&& make -C /tmp/build_uhd install \
|
||||
# AirSpy
|
||||
&& wget https://github.com/airspy/airspyone_host/archive/v$AIRSPY_VERSION.tar.gz -O /tmp/airspy.tar.gz \
|
||||
&& tar xf /tmp/airspy.tar.gz -C /tmp \
|
||||
&& cmake3 -Wno-dev -S /tmp/airspyone_host-$AIRSPY_VERSION -B /tmp/build_airspy \
|
||||
&& make -j$(nproc) -C /tmp/build_airspy \
|
||||
&& make -C /tmp/build_airspy install \
|
||||
# BladeRF
|
||||
&& wget https://github.com/Nuand/bladeRF/archive/$BLADERF_VERSION.tar.gz -O /tmp/bladeRF.tar.gz \
|
||||
&& tar xf /tmp/bladeRF.tar.gz -C /tmp \
|
||||
&& cmake3 -Wno-dev -S /tmp/bladeRF-$BLADERF_VERSION/host -B /tmp/build_blade \
|
||||
&& make -j$(nproc) -C /tmp/build_blade \
|
||||
&& make -C /tmp/build_blade install \
|
||||
&& wget https://github.com/myriadrf/LimeSuite/archive/v$LIMESUITE_VERSION.tar.gz -O /tmp/lime.tar.gz \
|
||||
# Lime
|
||||
&& tar xf /tmp/lime.tar.gz -C /tmp \
|
||||
&& cmake3 -S /tmp/LimeSuite-$LIMESUITE_VERSION -B /tmp/build_lime \
|
||||
&& make -j$(nproc) -C /tmp/build_lime \
|
||||
&& make -C /tmp/build_lime install \
|
||||
# RTLSDR
|
||||
&& wget https://github.com/osmocom/rtl-sdr/archive/$RTLSDR_VERSION.tar.gz -O /tmp/rtlsdr.tar.gz \
|
||||
&& tar xf /tmp/rtlsdr.tar.gz -C /tmp \
|
||||
&& cmake3 -DDETACH_KERNEL_DRIVER=ON -S /tmp/rtl-sdr-$RTLSDR_VERSION -B /tmp/build_rtlsdr \
|
||||
&& make -j$(nproc) -C /tmp/build_rtlsdr \
|
||||
&& make -C /tmp/build_rtlsdr install \
|
||||
# SDRPLAY
|
||||
&& wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-$SDRPLAY_VERSION.1.run -O /tmp/sdrplay.run \
|
||||
&& bash /tmp/sdrplay.run --tar xf -C /tmp \
|
||||
&& mv /tmp/mirsdrapi-rsp.h /usr/include \
|
||||
&& mv /tmp/x86_64/* /usr/lib64 \
|
||||
&& ln -s /usr/lib64/libmirsdrapi-rsp.so.$SDRPLAY_VERSION /usr/lib64/libmirsdrapi-rsp.so \
|
||||
&& rm -rf /tmp/* \
|
||||
&& yum clean all
|
74
Software/Universal Radio Hacker/data/pyinstaller_helper.py
Normal file
@ -0,0 +1,74 @@
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
HIDDEN_IMPORTS = ["packaging.specifiers", "packaging.requirements", "pkg_resources.py2_warn",
|
||||
"numpy.core._methods", "numpy.core._dtype_ctypes",
|
||||
"numpy.random.common", "numpy.random.entropy", "numpy.random.bounded_integers"]
|
||||
DATA = [("src/urh/dev/native/lib/shared", "."), ("src/urh/plugins", "urh/plugins"), ]
|
||||
EXCLUDE = ["matplotlib"]
|
||||
|
||||
|
||||
def run_pyinstaller(cmd_list: list, env: list=None):
|
||||
cmd = " ".join(cmd_list)
|
||||
print(cmd, flush=True)
|
||||
|
||||
env = [] if env is None else env
|
||||
if env:
|
||||
os.system(" ".join(env) + " " + cmd)
|
||||
else:
|
||||
os.system(cmd)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cmd = ["pyinstaller", "--clean"]
|
||||
if sys.platform == "darwin":
|
||||
cmd.append("--onefile")
|
||||
|
||||
for hidden_import in HIDDEN_IMPORTS:
|
||||
cmd.append("--hidden-import={}".format(hidden_import))
|
||||
|
||||
for src, dst in DATA:
|
||||
cmd.append("--add-data")
|
||||
cmd.append('"{}{}{}"'.format(src, os.pathsep, dst))
|
||||
|
||||
for exclude in EXCLUDE:
|
||||
cmd.append("--exclude-module={}".format(exclude))
|
||||
|
||||
urh_path = os.path.realpath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
if sys.platform == "darwin":
|
||||
cmd.append('--icon="{}"'.format(os.path.join(urh_path, "data/icons/appicon.icns")))
|
||||
else:
|
||||
cmd.append('--icon="{}"'.format(os.path.join(urh_path, "data/icons/appicon.ico")))
|
||||
|
||||
cmd.extend(["--distpath", "./pyinstaller"])
|
||||
|
||||
urh_cmd = cmd + ["--name=urh", "--windowed", "--workpath", "./urh_build",
|
||||
os.path.join(urh_path, "src/urh/main.py")]
|
||||
|
||||
urh_debug_cmd = cmd + ["--name=urh_debug", "--workpath", "./urh_debug_build",
|
||||
os.path.join(urh_path, "src/urh/main.py")]
|
||||
|
||||
cli_cmd = cmd + ["--workpath", "./urh_cli_build",
|
||||
os.path.join(urh_path, "src/urh/cli/urh_cli.py")]
|
||||
|
||||
os.makedirs("./pyinstaller")
|
||||
if sys.platform == "darwin":
|
||||
run_pyinstaller(urh_cmd, env=["DYLD_LIBRARY_PATH=src/urh/dev/native/lib/shared"])
|
||||
|
||||
import plistlib
|
||||
with open("pyinstaller/urh.app/Contents/Info.plist", "rb") as f:
|
||||
p = plistlib.load(f)
|
||||
p["NSHighResolutionCapable"] = True
|
||||
p["NSRequiresAquaSystemAppearance"] = True
|
||||
p["NSMicrophoneUsageDescription"] = "URH needs access to your microphone to capture signals via Soundcard."
|
||||
with open("pyinstaller/urh.app/Contents/Info.plist", "wb") as f:
|
||||
plistlib.dump(p, f)
|
||||
|
||||
else:
|
||||
for cmd in [urh_cmd, cli_cmd, urh_debug_cmd]:
|
||||
run_pyinstaller(cmd)
|
||||
|
||||
shutil.copy("./pyinstaller/urh_cli/urh_cli.exe", "./pyinstaller/urh/urh_cli.exe")
|
||||
shutil.copy("./pyinstaller/urh_debug/urh_debug.exe", "./pyinstaller/urh/urh_debug.exe")
|
54
Software/Universal Radio Hacker/data/pyinstaller_macos.spec
Normal file
@ -0,0 +1,54 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['src/urh/main.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[('src/urh/plugins', 'urh/plugins')],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=['matplotlib'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='main',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None , icon='data/icons/appicon.icns')
|
||||
coll = COLLECT(exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='main')
|
||||
app = BUNDLE(coll,
|
||||
name='main.app',
|
||||
icon='./data/icons/appicon.icns',
|
||||
bundle_identifier=None,
|
||||
info_plist={
|
||||
'NSRequiresAquaSystemAppearance': True,
|
||||
'NSMicrophoneUsageDescription': 'URH needs access to your microphone to capture signals via Soundcard.',
|
||||
'CFBundleDisplayName': 'URH',
|
||||
'CFBundleName': 'URH'
|
||||
},)
|
83
Software/Universal Radio Hacker/data/release.py
Normal file
@ -0,0 +1,83 @@
|
||||
import fileinput
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from subprocess import call, check_output
|
||||
|
||||
|
||||
def cleanup():
|
||||
"""
|
||||
Remove all cache directories
|
||||
:return:
|
||||
"""
|
||||
script_dir = os.path.dirname(__file__) if not os.path.islink(__file__) else os.path.dirname(os.readlink(__file__))
|
||||
script_dir = os.path.realpath(os.path.join(script_dir, ".."))
|
||||
shutil.rmtree(os.path.join(script_dir, "dist"), ignore_errors=True)
|
||||
shutil.rmtree(os.path.join(script_dir, "tmp"), ignore_errors=True)
|
||||
shutil.rmtree(os.path.join(script_dir, "urh.egg-info"), ignore_errors=True)
|
||||
shutil.rmtree(os.path.join(script_dir, "src", "urh.egg-info"), ignore_errors=True)
|
||||
shutil.rmtree(os.path.join(script_dir, "src", "urh", "tmp"), ignore_errors=True)
|
||||
|
||||
|
||||
def release():
|
||||
script_dir = os.path.dirname(__file__) if not os.path.islink(__file__) else os.path.dirname(os.readlink(__file__))
|
||||
script_dir = os.path.realpath(os.path.join(script_dir, ".."))
|
||||
os.chdir(script_dir)
|
||||
|
||||
current_branch = check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).decode("UTF-8").strip()
|
||||
|
||||
if current_branch != "master":
|
||||
print("You can only release from master!")
|
||||
sys.exit(1)
|
||||
|
||||
open(os.path.join(tempfile.gettempdir(), "urh_releasing"), "w").close()
|
||||
|
||||
from src.urh import version
|
||||
version_file = os.path.realpath(os.path.join(script_dir, "src", "urh", "version.py"))
|
||||
|
||||
cur_version = version.VERSION
|
||||
numbers = cur_version.split(".")
|
||||
numbers[-1] = str(int(numbers[-1]) + 1)
|
||||
cur_version = ".".join(numbers)
|
||||
|
||||
for line in fileinput.input(version_file, inplace=True):
|
||||
if line.startswith("VERSION"):
|
||||
line = 'VERSION = "{0}" \n'.format(cur_version)
|
||||
print(line, end='')
|
||||
|
||||
# Publish new version number
|
||||
call(["git", "add", version_file])
|
||||
call(["git", "commit", "-m", "version" + cur_version])
|
||||
|
||||
input("Pushing to GitHub now. Press a key to continue.")
|
||||
call(["git", "push"])
|
||||
|
||||
os.chdir(script_dir)
|
||||
|
||||
# Remove local tags
|
||||
call("git tag -l | xargs git tag -d", shell=True)
|
||||
call(["git", "fetch", "--tags"])
|
||||
|
||||
# Push new tag
|
||||
call(["git", "tag", "v" + cur_version, "-m", "version " + cur_version])
|
||||
call(["git", "push", "origin", "--tags"]) # Creates tar package on https://github.com/jopohl/urh/tarball/va.b.c.d
|
||||
|
||||
os.remove(os.path.join(tempfile.gettempdir(), "urh_releasing"))
|
||||
|
||||
# region Build docker image and push to DockerHub
|
||||
os.chdir(os.path.dirname(__file__))
|
||||
call(["docker", "login"])
|
||||
call(["docker", "build", "--no-cache",
|
||||
"--tag", "jopohl/urh:latest",
|
||||
"--tag", "jopohl/urh:{}".format(cur_version), "."])
|
||||
call(["docker", "push", "jopohl/urh:latest"])
|
||||
call(["docker", "push", "jopohl/urh:{}".format(cur_version)])
|
||||
# endregion
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cleanup()
|
||||
input("Starting release. Hit a key to continue.")
|
||||
release()
|
||||
cleanup()
|
4
Software/Universal Radio Hacker/data/requirements.txt
Normal file
@ -0,0 +1,4 @@
|
||||
numpy
|
||||
pyqt5
|
||||
psutil
|
||||
cython!=0.29.18
|
280
Software/Universal Radio Hacker/data/semwraplib.c
Normal file
@ -0,0 +1,280 @@
|
||||
// Source: https://github.com/snapcore/snapcraft-preloads/blob/master/semaphores/preload-semaphores.c
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $ gcc -Wall -fPIC -shared -o mylib.so ./lib.c -ldl
|
||||
* $ LD_PRELOAD=./mylib.so ...
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <semaphore.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
||||
static sem_t *(*original_sem_open) (const char *, int, ...);
|
||||
static int (*original_sem_unlink) (const char *);
|
||||
|
||||
// Format is: 'sem.snap.SNAP_NAME.<something>'. So: 'sem.snap.' + '.' = 10
|
||||
#define MAX_NAME_SIZE NAME_MAX - 10
|
||||
#define SHM_DIR "/dev/shm"
|
||||
|
||||
void debug(char *s, ...)
|
||||
{
|
||||
if (secure_getenv("SEMWRAP_DEBUG")) {
|
||||
va_list va;
|
||||
va_start(va, s);
|
||||
fprintf(stderr, "SEMWRAP: ");
|
||||
vfprintf(stderr, s, va);
|
||||
va_end(va);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
const char *get_snap_name(void)
|
||||
{
|
||||
const char *snapname = getenv("SNAP_INSTANCE_NAME");
|
||||
if (!snapname) {
|
||||
snapname = getenv("SNAP_NAME");
|
||||
}
|
||||
if (!snapname) {
|
||||
debug("SNAP_NAME and SNAP_INSTANCE_NAME not set");
|
||||
}
|
||||
return snapname;
|
||||
}
|
||||
|
||||
int rewrite(const char *snapname, const char *name, char *rewritten,
|
||||
size_t rmax)
|
||||
{
|
||||
if (strlen(snapname) + strlen(name) > MAX_NAME_SIZE) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *tmp = name;
|
||||
if (tmp[0] == '/') {
|
||||
// If specified with leading '/', just strip it to avoid
|
||||
// having to mkdir(), etc
|
||||
tmp = &name[1];
|
||||
}
|
||||
|
||||
int n = snprintf(rewritten, rmax, "snap.%s.%s", snapname, tmp);
|
||||
if (n < 0 || n >= rmax) {
|
||||
fprintf(stderr, "snprintf truncated\n");
|
||||
return -1;
|
||||
}
|
||||
rewritten[rmax-1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sem_t *sem_open(const char *name, int oflag, ...)
|
||||
{
|
||||
mode_t mode;
|
||||
unsigned int value;
|
||||
|
||||
debug("sem_open()");
|
||||
debug("requested name: %s", name);
|
||||
|
||||
// lookup the libc's sem_open() if we haven't already
|
||||
if (!original_sem_open) {
|
||||
dlerror();
|
||||
original_sem_open = dlsym(RTLD_NEXT, "sem_open");
|
||||
if (!original_sem_open) {
|
||||
debug("could not find sem_open in libc");
|
||||
return SEM_FAILED;
|
||||
}
|
||||
dlerror();
|
||||
}
|
||||
|
||||
// mode and value must be set with O_CREAT
|
||||
va_list argp;
|
||||
va_start(argp, oflag);
|
||||
if (oflag & O_CREAT) {
|
||||
mode = va_arg(argp, mode_t);
|
||||
value = va_arg(argp, unsigned int);
|
||||
if (value > SEM_VALUE_MAX) {
|
||||
errno = EINVAL;
|
||||
return SEM_FAILED;
|
||||
}
|
||||
}
|
||||
va_end(argp);
|
||||
|
||||
const char *snapname = get_snap_name();
|
||||
|
||||
// just call libc's sem_open() if snapname not set
|
||||
if (!snapname) {
|
||||
if (oflag & O_CREAT) {
|
||||
return original_sem_open(name, oflag, mode, value);
|
||||
}
|
||||
return original_sem_open(name, oflag);
|
||||
}
|
||||
|
||||
// Format the rewritten name
|
||||
char rewritten[MAX_NAME_SIZE+1];
|
||||
if (rewrite(snapname, name, rewritten, MAX_NAME_SIZE + 1) != 0) {
|
||||
return SEM_FAILED;
|
||||
}
|
||||
debug("rewritten name: %s", rewritten);
|
||||
|
||||
if (oflag & O_CREAT) {
|
||||
// glibc's sem_open with O_CREAT will create a file in /dev/shm
|
||||
// by creating a tempfile, initializing it, hardlinking it and
|
||||
// unlinking the tempfile. We:
|
||||
// 1. create a temporary file in /dev/shm with rewritten path
|
||||
// as the template and the specified mode
|
||||
// 2. initializing a sem_t with sem_init
|
||||
// 3. writing the initialized sem_t to the temporary file using
|
||||
// sem_open()s declared value. We used '1' for pshared since
|
||||
// that is how glibc sets up a named semaphore
|
||||
// 4. close the temporary file
|
||||
// 5. hard link the temporary file to the rewritten path. If
|
||||
// O_EXCL is not specified, ignore EEXIST and just cleanup
|
||||
// as per documented behavior in 'man sem_open'. If O_EXCL
|
||||
// is specified and file exists, exit with error. If link is
|
||||
// successful, cleanup.
|
||||
// 6. call glibc's sem_open() without O_CREAT|O_EXCL
|
||||
//
|
||||
// See glibc's fbtl/sem_open.c for more details
|
||||
|
||||
// First, calculate the requested path
|
||||
char path[PATH_MAX] = { 0 };
|
||||
// /sem. + '/0' = 14
|
||||
int max_path_size = strlen(SHM_DIR) + strlen(rewritten) + 6;
|
||||
if (max_path_size >= PATH_MAX) {
|
||||
// Should never happen since PATH_MAX should be much
|
||||
// larger than NAME_MAX, but be defensive.
|
||||
errno = ENAMETOOLONG;
|
||||
return SEM_FAILED;
|
||||
}
|
||||
int n = snprintf(path, max_path_size, "%s/sem.%s", SHM_DIR,
|
||||
rewritten);
|
||||
if (n < 0 || n >= max_path_size) {
|
||||
errno = ENAMETOOLONG;
|
||||
return SEM_FAILED;
|
||||
}
|
||||
path[max_path_size-1] = '\0';
|
||||
|
||||
// Then calculate the template path
|
||||
char tmp[PATH_MAX] = { 0 };
|
||||
n = snprintf(tmp, PATH_MAX, "%s/%s.XXXXXX", SHM_DIR,
|
||||
rewritten);
|
||||
if (n < 0 || n >= PATH_MAX) {
|
||||
errno = ENAMETOOLONG;
|
||||
return SEM_FAILED;
|
||||
}
|
||||
tmp[PATH_MAX-1] = '\0';
|
||||
|
||||
// Next, create a temporary file
|
||||
int fd = mkstemp(tmp);
|
||||
if (fd < 0) {
|
||||
return SEM_FAILED;
|
||||
}
|
||||
debug("tmp name: %s", tmp);
|
||||
|
||||
// Update the temporary file to have the requested mode
|
||||
if (fchmod(fd, mode) < 0) {
|
||||
close(fd);
|
||||
unlink(tmp);
|
||||
return SEM_FAILED;
|
||||
}
|
||||
|
||||
// Then write out an empty semaphore and set the initial value.
|
||||
// We use '1' for pshared since that is how glibc sets up the
|
||||
// semaphore (see glibc's fbtl/sem_open.c)
|
||||
sem_t initsem;
|
||||
sem_init(&initsem, 1, value);
|
||||
if (write(fd, &initsem, sizeof(sem_t)) < 0) {
|
||||
close(fd);
|
||||
unlink(tmp);
|
||||
return SEM_FAILED;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
// Then link the file into place. If the target exists and
|
||||
// O_EXCL was not specified, just cleanup and proceed to open
|
||||
// the existing file as per documented behavior in 'man
|
||||
// sem_open'.
|
||||
int existed = 0;
|
||||
if (link(tmp, path) < 0) {
|
||||
// Note: snapd initially didn't allow 'l' in its
|
||||
// policy so we first try with link() since it is
|
||||
// race-free but fallback to rename() if necessary.
|
||||
if (errno == EACCES || errno == EPERM) {
|
||||
fprintf(stderr, "sem_open() wrapper: hard linking tempfile denied. Falling back to rename()\n");
|
||||
if (rename(tmp, path) < 0) {
|
||||
unlink(tmp);
|
||||
return SEM_FAILED;
|
||||
}
|
||||
} else if (oflag & O_EXCL || errno != EEXIST) {
|
||||
unlink(tmp);
|
||||
return SEM_FAILED;
|
||||
}
|
||||
existed = 1;
|
||||
}
|
||||
unlink(tmp);
|
||||
|
||||
// Then call sem_open() on the created file, stripping out the
|
||||
// O_CREAT|O_EXCL since we just created it
|
||||
sem_t *sem = original_sem_open(rewritten,
|
||||
oflag & ~(O_CREAT | O_EXCL));
|
||||
if (sem == SEM_FAILED) {
|
||||
if (!existed) {
|
||||
unlink(path);
|
||||
}
|
||||
return SEM_FAILED;
|
||||
}
|
||||
|
||||
return sem;
|
||||
} else {
|
||||
// without O_CREAT, just call sem_open with rewritten
|
||||
return original_sem_open(rewritten, oflag);
|
||||
}
|
||||
|
||||
return SEM_FAILED;
|
||||
}
|
||||
|
||||
// sem_unlink
|
||||
int sem_unlink(const char *name)
|
||||
{
|
||||
debug("sem_unlink()");
|
||||
debug("requested name: %s", name);
|
||||
|
||||
// lookup the libc's sem_unlink() if we haven't already
|
||||
if (!original_sem_unlink) {
|
||||
dlerror();
|
||||
original_sem_unlink = dlsym(RTLD_NEXT, "sem_unlink");
|
||||
if (!original_sem_unlink) {
|
||||
debug("could not find sem_unlink in libc");
|
||||
return -1;
|
||||
}
|
||||
dlerror();
|
||||
}
|
||||
|
||||
const char *snapname = get_snap_name();
|
||||
|
||||
// just call libc's sem_unlink() if snapname not set
|
||||
if (!snapname) {
|
||||
return original_sem_unlink(name);
|
||||
}
|
||||
|
||||
// Format the rewritten name
|
||||
char rewritten[MAX_NAME_SIZE+1];
|
||||
if (rewrite(snapname, name, rewritten, MAX_NAME_SIZE + 1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
debug("rewritten name: %s", rewritten);
|
||||
|
||||
return original_sem_unlink(rewritten);
|
||||
}
|
207
Software/Universal Radio Hacker/data/snapcraft.yaml
Normal file
@ -0,0 +1,207 @@
|
||||
name: urh
|
||||
title: Universal Radio Hacker
|
||||
version: git
|
||||
summary: Investigate Wireless Protocols Like A Boss
|
||||
description: |
|
||||
The Universal Radio Hacker (URH) is a complete suite for wireless protocol investigation with native support for many common **Software Defined Radios**.
|
||||
URH allows **easy demodulation** of signals combined with an automatic detection of modulation parameters making it a breeze to identify the bits and bytes that fly over the air.
|
||||
As data often gets _encoded_ before transmission, URH offers **customizable decodings** to crack even sophisticated encodings like CC1101 data whitening.
|
||||
When it comes to **protocol reverse-engineering**, URH is helpful in two ways. You can either manually assign protocol fields and message types or let URH **automatically infer protocol fields** with a rule-based intelligence.
|
||||
Finally, URH entails a **fuzzing component** aimed at stateless protocols and a **simulation environment** to perform stateful attacks.
|
||||
|
||||
After installation, give URH access to your USB in order to access your USB based SDRs:
|
||||
|
||||
sudo snap connect urh:raw-usb
|
||||
|
||||
In order to access your SDR as non-root user, install the according **udev rules** available at https://github.com/jopohl/urh/wiki/SDR-udev-rules.
|
||||
|
||||
If you want to use your Soundcard as an SDR for receiving please execute:
|
||||
|
||||
sudo snap connect urh:audio-record
|
||||
|
||||
icon: data/icons/appicon.png
|
||||
|
||||
|
||||
grade: stable # must be 'stable' to release into candidate/stable channels
|
||||
confinement: strict # use 'strict' once you have the right plugs and slots
|
||||
base: core18
|
||||
|
||||
plugs: # plugs for theming, font settings, cursor and to use gtk3 file chooser
|
||||
gtk-3-themes:
|
||||
interface: content
|
||||
target: $SNAP/data-dir/themes
|
||||
default-provider: gtk-common-themes:gtk-3-themes
|
||||
icon-themes:
|
||||
interface: content
|
||||
target: $SNAP/data-dir/icons
|
||||
default-provider: gtk-common-themes:icon-themes
|
||||
sound-themes:
|
||||
interface: content
|
||||
target: $SNAP/data-dir/sounds
|
||||
default-provider: gtk-common-themes:sounds-themes
|
||||
|
||||
|
||||
apps:
|
||||
urh:
|
||||
adapter: full
|
||||
command: snap/command-chain/alsa-launch desktop-launch $SNAP/bin/urh
|
||||
plugs:
|
||||
- desktop
|
||||
- desktop-legacy
|
||||
- wayland
|
||||
- x11
|
||||
- unity7
|
||||
- gsettings
|
||||
- home
|
||||
- opengl
|
||||
- raw-usb
|
||||
- audio-playback
|
||||
- audio-record
|
||||
- network
|
||||
environment:
|
||||
QT_QPA_PLATFORMTHEME: gtk3
|
||||
LD_PRELOAD: $SNAP/lib/semwraplib.so
|
||||
BLADERF_SEARCH_DIR: $SNAP/bladefpgas
|
||||
|
||||
layout:
|
||||
/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib:
|
||||
bind: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib
|
||||
|
||||
parts:
|
||||
alsa-mixin:
|
||||
plugin: dump
|
||||
source: https://github.com/diddlesnaps/snapcraft-alsa.git
|
||||
source-subdir: snapcraft-assets
|
||||
build-packages:
|
||||
- libasound2-dev
|
||||
|
||||
semwraplib:
|
||||
plugin: nil
|
||||
source: data
|
||||
override-build: |
|
||||
snapcraftctl build
|
||||
mkdir -p $SNAPCRAFT_PART_INSTALL/lib
|
||||
gcc -g -O0 -Wall -Wstrict-prototypes -fPIC -shared semwraplib.c -o $SNAPCRAFT_PART_INSTALL/lib/semwraplib.so -ldl
|
||||
build-packages:
|
||||
- build-essential
|
||||
|
||||
desktop-qt5:
|
||||
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
|
||||
source-subdir: qt
|
||||
plugin: make
|
||||
make-parameters: ["FLAVOR=qt5"]
|
||||
build-packages:
|
||||
- build-essential
|
||||
- qtbase5-dev
|
||||
- dpkg-dev
|
||||
stage-packages:
|
||||
- libxkbcommon0
|
||||
- ttf-ubuntu-font-family
|
||||
- dmz-cursor-theme
|
||||
- light-themes
|
||||
- libgstreamer-plugins-base1.0-0
|
||||
- adwaita-icon-theme
|
||||
- gnome-themes-standard
|
||||
- shared-mime-info
|
||||
- libgomp1
|
||||
- libqt5gui5
|
||||
- libgdk-pixbuf2.0-0
|
||||
- libqt5svg5 # for loading icon themes which are svg
|
||||
- try: [appmenu-qt5] # not available on core18
|
||||
- locales-all
|
||||
- xdg-user-dirs
|
||||
- fcitx-frontend-qt5
|
||||
- libatk1.0-0
|
||||
- libgtk2.0-0
|
||||
- libxcomposite1
|
||||
- libxcursor1
|
||||
- libxinerama1
|
||||
- libxrandr2
|
||||
- libasyncns0
|
||||
- libatk-bridge2.0-0
|
||||
- libatspi2.0-0
|
||||
- libcairo-gobject2
|
||||
- libepoxy0
|
||||
- libflac8
|
||||
- libgtk-3-0
|
||||
- libogg0
|
||||
- libpulse0
|
||||
- libsndfile1
|
||||
- libvorbis0a
|
||||
- libvorbisenc2
|
||||
- libwayland-cursor0
|
||||
- libwayland-egl1
|
||||
- libodbc1
|
||||
- libpq5
|
||||
- libpulse-mainloop-glib0
|
||||
- libspeechd2
|
||||
- python3
|
||||
- python3-pyqt5
|
||||
- python3-pyaudio
|
||||
- dbus
|
||||
- qtwayland5
|
||||
- qt5-gtk-platformtheme
|
||||
- libqt5x11extras5
|
||||
- locales
|
||||
- libcanberra-gtk3-module
|
||||
- libairspy-dev
|
||||
- libhackrf-dev
|
||||
- libiio-dev
|
||||
- liblimesuite-dev
|
||||
- librtlsdr-dev
|
||||
- libuhd-dev
|
||||
- libc-bin
|
||||
- libasound2
|
||||
- libasound2-plugins
|
||||
- python3-distutils
|
||||
|
||||
urh:
|
||||
after: [desktop-qt5, sdrplay, alsa-mixin]
|
||||
plugin: python
|
||||
requirements: [data/requirements.txt]
|
||||
source: .
|
||||
override-build: |
|
||||
git clone https://github.com/Nuand/bladeRF.git
|
||||
cd bladeRF/host
|
||||
mkdir build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=$SNAPCRAFT_PART_INSTALL ..
|
||||
make -j$(nproc)
|
||||
make install
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
make install
|
||||
snapcraftctl build
|
||||
build-packages:
|
||||
- libairspy-dev
|
||||
- libhackrf-dev
|
||||
- libiio-dev
|
||||
- liblimesuite-dev
|
||||
- librtlsdr-dev
|
||||
- libuhd-dev
|
||||
- wget
|
||||
- execstack
|
||||
- build-essential
|
||||
- cmake
|
||||
- pkg-config
|
||||
|
||||
sdrplay:
|
||||
plugin: dump
|
||||
source: /lib
|
||||
stage: [libmirsdrapi-rsp.so.2.13]
|
||||
override-build: |
|
||||
wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-2.13.1.run -O sdrplay.run
|
||||
bash sdrplay.run --tar xf
|
||||
cp mirsdrapi-rsp.h /usr/include
|
||||
cp x86_64/* /lib
|
||||
cp x86_64/* .
|
||||
ln -sf /lib/libmirsdrapi-rsp.so.2.13 /lib/libmirsdrapi-rsp.so
|
||||
snapcraftctl build
|
||||
|
||||
bladerf-fpga:
|
||||
plugin: dump
|
||||
source: .
|
||||
override-build: |
|
||||
snapcraftctl build
|
||||
wget https://www.nuand.com/fpga/v0.11.0/hostedxA4.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas
|
||||
wget https://www.nuand.com/fpga/v0.11.0/hostedxA9.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas
|
||||
wget https://www.nuand.com/fpga/v0.11.0/hostedx40.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas
|
||||
wget https://www.nuand.com/fpga/v0.11.0/hostedx115.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas
|
@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogAdvancedModSettings</class>
|
||||
<widget class="QDialog" name="DialogAdvancedModSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>527</width>
|
||||
<height>501</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Advanced Modulation Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Pause Threshold</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>The pause threshold gives you control <span style=" font-weight:600;">when to insert a message break.</span></p><p>The pause threshold is the maximum length of consecutive zero bits represented by a pause before a new message begins.</p><p>Special value is 0 to disable message breaking completely.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxPauseThreshold">
|
||||
<property name="specialValueText">
|
||||
<string>Disable</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Message Length Divisor</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>With the message <span style=" font-weight:600;">divisor length</span> you can control the minimum message length in a flexible way. URH will try to demodulate signals in such a way, that the resulting message has a number of bits that is divisble by the configured divisor. <br/><br/><span style=" font-style:italic;">How does the zero padding work? Remaining zero bits are taken from the pause behind the message if possible.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxMessageLengthDivisor">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogAdvancedModSettings</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DialogAdvancedModSettings</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
1192
Software/Universal Radio Hacker/data/ui/analysis.ui
Normal file
@ -0,0 +1,305 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ChecksumOptions</class>
|
||||
<widget class="QWidget" name="ChecksumOptions">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>775</width>
|
||||
<height>836</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Checksum</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>738</width>
|
||||
<height>827</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Checksum category:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxCategory">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>CRC</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Wireless Short Packet Checksum</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_crc">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineEditFinalXOR"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>CRC polynomial (hex):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Configure data ranges for CRC</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="tableViewDataRanges">
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnAddRange">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff>../../../</normaloff>../../../</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnRemoveRange">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove">
|
||||
<normaloff>../../../</normaloff>../../../</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEditStartValue"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>CRC function:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Final XOR (hex):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Start value (hex):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditCRCPolynomial"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxCRCFunction"/>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_crc_info">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Order=17</p><p>Length of checksum=16</p><p>start value length =16</p><p>final XOR length = 16</p><p>Polynomial = x<span style=" vertical-align:super;">1</span> + 4</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxRefIn">
|
||||
<property name="text">
|
||||
<string>RefIn (Reflect input)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxRefOut">
|
||||
<property name="text">
|
||||
<string>RefOut (Reflect output)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_wsp">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>The Wireless Short Packet (WSP) standard uses three different checksums. URH can automatically detect the used checksum algorithm from the message. However, you can enforce the usage of a certain checksum if you need to.</p><p>With <span style=" font-weight:600;">Automatic</span> setting, checksums are chosen by these rules:</p><p>1) 4 Bit Checksum - For Switch Telegram (RORG=5 or 6 and STATUS = 0x20 or 0x30)</p><p>2) 8 Bit Checksum: STATUS bit 2<span style=" vertical-align:super;">7</span> = 0</p><p>3) 8 Bit CRC: STATUS bit 2<span style=" vertical-align:super;">7</span> = 1</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonWSPAuto">
|
||||
<property name="text">
|
||||
<string>Automatic (recommended)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonWSPChecksum4">
|
||||
<property name="text">
|
||||
<string>Force Checksum4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonWSPChecksum8">
|
||||
<property name="text">
|
||||
<string>Force Checksum8</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonWSPCRC8">
|
||||
<property name="text">
|
||||
<string>Force CRC8</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>107</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>comboBoxCRCFunction</tabstop>
|
||||
<tabstop>lineEditCRCPolynomial</tabstop>
|
||||
<tabstop>lineEditStartValue</tabstop>
|
||||
<tabstop>lineEditFinalXOR</tabstop>
|
||||
<tabstop>tableViewDataRanges</tabstop>
|
||||
<tabstop>btnAddRange</tabstop>
|
||||
<tabstop>radioButtonWSPAuto</tabstop>
|
||||
<tabstop>btnRemoveRange</tabstop>
|
||||
<tabstop>radioButtonWSPChecksum4</tabstop>
|
||||
<tabstop>radioButtonWSPChecksum8</tabstop>
|
||||
<tabstop>radioButtonWSPCRC8</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
108
Software/Universal Radio Hacker/data/ui/costa.ui
Normal file
@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogCosta</class>
|
||||
<widget class="QDialog" name="DialogCosta">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Costas Loop</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>URH uses a Costas loop for PSK demodulation. Configure the loop bandwidth below.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelLoopBandwidth">
|
||||
<property name="text">
|
||||
<string>Loop Bandwidth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxLoopBandwidth">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogCosta</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DialogCosta</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
280
Software/Universal Radio Hacker/data/ui/csv_wizard.ui
Normal file
@ -0,0 +1,280 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogCSVImport</class>
|
||||
<widget class="QDialog" name="DialogCSVImport">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>635</width>
|
||||
<height>674</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>CSV Import</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="labelFileNotFound">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" color:#ff0000;">Could not open the selected file.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxCSVSeparator">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>,</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>;</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnAddSeparator">
|
||||
<property name="toolTip">
|
||||
<string>Add a custom separator.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QSpinBox" name="spinBoxTimestampColumn">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p> If your dataset contains timestamps URH will calculate the sample rate from them. You can manually edit the sample rate after import in the signal details.</p></body></html></string>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>Not present</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>I Data Column:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QSpinBox" name="spinBoxQDataColumn">
|
||||
<property name="specialValueText">
|
||||
<string>Not present</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p> If your dataset contains timestamps URH will calculate the sample rate from them. You can manually edit the sample rate after import in the signal details.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Timestamp Column:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Q Data Column:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="3">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidgetPreview">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Timestamp</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>I</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Q</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEditFilename"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnChooseFile">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QSpinBox" name="spinBoxIDataColumn">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>CSV Separator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QGroupBox" name="groupBoxFilePreview">
|
||||
<property name="title">
|
||||
<string>File Content (at most 100 rows)</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="plainTextEditFilePreview">
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>File to import:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<widget class="QPushButton" name="btnAutoDefault">
|
||||
<property name="text">
|
||||
<string>Prevent Dialog From Close with Enter</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>lineEditFilename</tabstop>
|
||||
<tabstop>btnChooseFile</tabstop>
|
||||
<tabstop>plainTextEditFilePreview</tabstop>
|
||||
<tabstop>comboBoxCSVSeparator</tabstop>
|
||||
<tabstop>btnAddSeparator</tabstop>
|
||||
<tabstop>spinBoxIDataColumn</tabstop>
|
||||
<tabstop>spinBoxQDataColumn</tabstop>
|
||||
<tabstop>spinBoxTimestampColumn</tabstop>
|
||||
<tabstop>tableWidgetPreview</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogCSVImport</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>375</x>
|
||||
<y>641</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DialogCSVImport</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>443</x>
|
||||
<y>647</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
732
Software/Universal Radio Hacker/data/ui/decoding.ui
Normal file
@ -0,0 +1,732 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Decoder</class>
|
||||
<widget class="QDialog" name="Decoder">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>2200</width>
|
||||
<height>1398</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Decoding</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="combobox_decodings">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Non Return to Zero (NRZ)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Empty</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="delete_decoding">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="saveas">
|
||||
<property name="text">
|
||||
<string>Save as...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Base Functions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="basefunctions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Additional Functions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="additionalfunctions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Your Decoding</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ListWidget" name="decoderchain">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideMiddle</enum>
|
||||
</property>
|
||||
<property name="resizeMode">
|
||||
<enum>QListView::Fixed</enum>
|
||||
</property>
|
||||
<property name="viewMode">
|
||||
<enum>QListView::ListMode</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_infoandoptions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Information and Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="info">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Please drag functions from the categories base and additional to the decoding process (Decoder). You can reorder functions by drag and drop and remove functions by dropping them outside the Decoder box. Click on every function for detailed information.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="optionWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_empty"/>
|
||||
<widget class="QWidget" name="page_redundancy">
|
||||
<widget class="QSpinBox" name="multiple">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>56</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>60</x>
|
||||
<y>0</y>
|
||||
<width>171</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number of redundant bits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_carrier">
|
||||
<widget class="QLineEdit" name="carrier">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>113</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>120</x>
|
||||
<y>0</y>
|
||||
<width>171</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Carrier ('1_' -> 1_1_1_...)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_substitution">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSpinBox" name="substitution_rows">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Rows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="substitution">
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_external">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Decoder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="external_decoder"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnChooseDecoder">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Encoder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="external_encoder"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnChooseEncoder">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>158</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_data_whitening">
|
||||
<widget class="QLineEdit" name="datawhitening_sync">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>171</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>180</x>
|
||||
<y>0</y>
|
||||
<width>1461</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Synchronization bytes (hex coded)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="datawhitening_polynomial">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>30</y>
|
||||
<width>171</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>180</x>
|
||||
<y>30</y>
|
||||
<width>1461</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Data whitening polynomial (LFSR, hex, w/o first bit)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="datawhitening_overwrite_crc">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>60</y>
|
||||
<width>1641</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Overwrite CRC16 field with correct value when encoding</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_cut">
|
||||
<widget class="QLineEdit" name="cutmark">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>30</y>
|
||||
<width>181</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1010</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>190</x>
|
||||
<y>30</y>
|
||||
<width>121</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sequence</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="rB_delbefore">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>131</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Cut before</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="rB_delafter">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>150</x>
|
||||
<y>0</y>
|
||||
<width>111</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cut afte&r</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="rB_delbeforepos">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>70</y>
|
||||
<width>111</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cut before</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="rB_delafterpos">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>150</x>
|
||||
<y>70</y>
|
||||
<width>111</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cut after</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="cutmark2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>100</y>
|
||||
<width>181</width>
|
||||
<height>33</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>190</x>
|
||||
<y>100</y>
|
||||
<width>121</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Position (in bit)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_morse">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>10</y>
|
||||
<width>341</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Maximum (<=) length of 1-sequence for: Low (0)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="morse_low">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>56</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>40</y>
|
||||
<width>351</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Minimum (>=) length of 1-sequence for: High (1)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="morse_high">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>40</y>
|
||||
<width>56</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>70</y>
|
||||
<width>371</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number of 0s between 1-sequences (just for encoding)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSpinBox" name="morse_wait">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>70</y>
|
||||
<width>56</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAddtoYourDecoding">
|
||||
<property name="text">
|
||||
<string>Add to Your Decoding</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>optionWidget</zorder>
|
||||
<zorder>info</zorder>
|
||||
<zorder>btnAddtoYourDecoding</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="inpt">
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhDigitsOnly</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QComboBox" name="combobox_signals">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="ZoomableGraphicView" name="graphicsView_signal"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Signal {0,1}:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="ZoomableGraphicView" name="graphicsView_decoded"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="output">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Decoded Bits:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="decoding_errors_label">
|
||||
<property name="text">
|
||||
<string>[Decoding Errors = 0]</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ZoomableGraphicView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>urh.ui.views.ZoomableGraphicView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ListWidget</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>urh.ui.ListWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -0,0 +1,268 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogFilterBandwidth</class>
|
||||
<widget class="QDialog" name="DialogFilterBandwidth">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>502</width>
|
||||
<height>426</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Filter Bandwidth</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,3,1">
|
||||
<property name="spacing">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelExplanation">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body>To separate the frequency bands from each other a <b>bandpass</b> filter is used. You can configure the <b>bandwidth</b> of this filter here. The bandwidth determines the <b>length N</b> of the<b> filter kernel</b>. Decreasing the bandwidth will increase the accuracy of the filter, at cost of higher computation time.</body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxCustomBandwidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000100000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QSpinBox" name="spinBoxCustomKernelLength">
|
||||
<property name="minimum">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonCustom">
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="labelMediumKernelLength">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonWide">
|
||||
<property name="text">
|
||||
<string>Wide</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="labelVeryWideKernelLength">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonNarrow">
|
||||
<property name="text">
|
||||
<string>Narrow</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="labelWideBandwidth">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="labelVeryNarrowKernelLength">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="labelBandwidthCaption">
|
||||
<property name="text">
|
||||
<string><b>Bandwidth (Hz)</b></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="labelNarrowBandwidth">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="labelNarrowKernelLength">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelVeryNarrowBandwidth">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelKernelLengthCaption">
|
||||
<property name="text">
|
||||
<string><b >Kernel Length N</b></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="labelWideKernelLength">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonVery_Wide">
|
||||
<property name="text">
|
||||
<string>Very Wide</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonVery_Narrow">
|
||||
<property name="text">
|
||||
<string>Very Narrow</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><b>Choose </b></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="labelVeryWideBandwidth">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonMedium">
|
||||
<property name="text">
|
||||
<string>Medium</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="labelMediumBandwidth">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DialogFilterBandwidth</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DialogFilterBandwidth</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
175
Software/Universal Radio Hacker/data/ui/filter_dialog.ui
Normal file
@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FilterDialog</class>
|
||||
<widget class="QDialog" name="FilterDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>528</width>
|
||||
<height>485</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure filter</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset theme="view-filter">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="9" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonCustomTaps">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom taps:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="radioButtonMovingAverage">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Moving average</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxNumTaps">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>A DC correction filter will remove the DC component (mean value) of the signal and center it around zero.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLineEdit" name="lineEditCustomTaps">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>You can configure custom filter taps here either explicit using [0.1, 0.2, 0.3] or with <span style=" font-weight:600;">python programming shortcuts</span> like [0.1] * 3 + [0.2] * 4 will result in [0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2]</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>[0.1]*10</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Number of taps:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>You can imagine taps as weighting factors applied to n samples of the signal whereby n is the number of taps. By default we use 10 taps with each tap set to 0.1 producing a moving average filter.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>These n weighted samples get summed up to produce the output of the filter. In DSP terms you configure the impulse response of the filter here.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="radioButtonDCcorrection">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>DC correction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
678
Software/Universal Radio Hacker/data/ui/fuzzing.ui
Normal file
@ -0,0 +1,678 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FuzzingDialog</class>
|
||||
<widget class="QDialog" name="FuzzingDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>523</width>
|
||||
<height>632</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Fuzzing</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxFuzzMessage">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="comboBoxStrategy">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Add Range of Values</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Add Boundaries</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Add Random Values from Range</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Add De Bruijn Sequence</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QPushButton" name="btnAddFuzzingValues">
|
||||
<property name="text">
|
||||
<string>Add to Fuzzed Values</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" rowspan="2">
|
||||
<widget class="QStackedWidget" name="stackedWidgetLabels">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="pageAddRangeLabel">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lStart">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start (Decimal):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lEnd">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>End (Decimal):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lStep">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Step (Decimal):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageAddBoundariesLabel">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxLowerBound">
|
||||
<property name="text">
|
||||
<string>Lower Bound</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxUpperBound">
|
||||
<property name="text">
|
||||
<string>Upper Bound</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lNumberBoundaries">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Values per Boundary:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageAddRandomLabel">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lRandomMin">
|
||||
<property name="text">
|
||||
<string>Range Minimum:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lRandomMax">
|
||||
<property name="text">
|
||||
<string>Range Maximum:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lNumRandom">
|
||||
<property name="text">
|
||||
<string>Number Values:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="lPreBits">
|
||||
<property name="text">
|
||||
<string>1111</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lFuzzedBits">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1010</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lPostBits">
|
||||
<property name="text">
|
||||
<string>010101</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="lFuzzedValues">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fuzzed Values</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chkBRemoveDuplicates">
|
||||
<property name="text">
|
||||
<string>Remove Duplicates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="1" column="1">
|
||||
<widget class="QToolButton" name="btnDelRow">
|
||||
<property name="toolTip">
|
||||
<string>Remove selected values or last value if nothing is selected.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="4">
|
||||
<widget class="FuzzingTableView" name="tblFuzzingValues">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QToolButton" name="btnAddRow">
|
||||
<property name="toolTip">
|
||||
<string>Add a new value.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QToolButton" name="btnRepeatValues">
|
||||
<property name="toolTip">
|
||||
<string>Repeat selected values or all values if nothing is selected.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="media-playlist-repeat">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="7" column="1" rowspan="2">
|
||||
<widget class="QStackedWidget" name="stackedWidgetSpinboxes">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="pageAddRange">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sBAddRangeStart"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sBAddRangeEnd"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sBAddRangeStep">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageAddBoundaries">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxLowerBound"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxUpperBound">
|
||||
<property name="value">
|
||||
<number>13</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxBoundaryNumber">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageAddRandom">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxRandomMinimum"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxRandomMaximum">
|
||||
<property name="value">
|
||||
<number>42</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxNumberRandom">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lSourceBlock">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Source Message:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lFuzzingReferenceBlock">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Message to fuzz:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lFuzzingEnd">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fuzzing Label End Index:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="lStrategy">
|
||||
<property name="text">
|
||||
<string>Strategy:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxFuzzingLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxFuzzingEnd">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxFuzzingStart">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lFuzzingStart">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fuzzing Label Start Index:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lFuzzingLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fuzzing Label:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>FuzzingTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>urh.ui.views.FuzzingTableView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>comboBoxStrategy</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>stackedWidgetLabels</receiver>
|
||||
<slot>setCurrentIndex(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>201</x>
|
||||
<y>593</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>100</x>
|
||||
<y>614</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>comboBoxStrategy</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>stackedWidgetSpinboxes</receiver>
|
||||
<slot>setCurrentIndex(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>444</x>
|
||||
<y>591</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>809</x>
|
||||
<y>616</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
769
Software/Universal Radio Hacker/data/ui/generator.ui
Normal file
@ -0,0 +1,769 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GeneratorTab</class>
|
||||
<widget class="QWidget" name="GeneratorTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1287</width>
|
||||
<height>774</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1287</width>
|
||||
<height>774</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QSplitter::handle:horizontal {
|
||||
margin: 4px 0px;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
||||
stop:0 rgba(255, 255, 255, 0),
|
||||
stop:0.5 rgba(100, 100, 100, 100),
|
||||
stop:1 rgba(255, 255, 255, 0));
|
||||
image: url(:/icons/icons/splitter_handle_vertical.svg);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTabWidget::pane { border: 0; }</string>
|
||||
</property>
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::North</enum>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_proto">
|
||||
<attribute name="title">
|
||||
<string>Protocols</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="GeneratorTreeView" name="treeProtocols">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Drag&amp;Drop Protocols to the table on the right to fill the generation table.</p></body></html></string>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>57</number>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_pauses">
|
||||
<attribute name="title">
|
||||
<string>Pauses</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="GeneratorListWidget" name="lWPauses">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The pauses will be added automatically when you drag a protocol from the tree above to the table on the right.<br/></p><p>You can see the <span style=" font-weight:600;">position</span> of each pause by <span style=" font-weight:600;">selecting it</span>. There will be drawn a line in the table indicating the position of the pause.<br/></p><p>Use context menu or double click to <span style=" font-weight:600;">edit a pauses' length</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::NoDragDrop</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_fuzzing">
|
||||
<attribute name="title">
|
||||
<string>Fuzzing</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="GeneratorListView" name="listViewProtoLabels">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Add fuzzing values to generated data</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidgetFuzzing">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="pageFuzzingUI">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnFuzz">
|
||||
<property name="text">
|
||||
<string>Fuzz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rBSuccessive">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>For multiple labels per message the fuzzed values are inserted <span style=" font-weight:600;">one-by-one</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>S&uccessive</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbConcurrent">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>For multiple labels per message the labels are fuzzed <span style=" font-weight:600;">at the same time</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Concurrent</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rBExhaustive">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>For multiple labels per message the fuzzed values are inserted in <span style=" font-weight:600;">all possible combinations</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E&xhaustive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageFuzzingProgressBar">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBarFuzzing">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%v/%m</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="modulationLayout_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lCarrierFreqValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="lModType">
|
||||
<property name="text">
|
||||
<string>Modulation Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="lModTypeValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_carrier_phase">
|
||||
<property name="text">
|
||||
<string>Carrier Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="lCarrierPhaseValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lBitLength">
|
||||
<property name="text">
|
||||
<string>Symbol Length:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="lBitLenValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lEncoding">
|
||||
<property name="text">
|
||||
<string>Encoding:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="lEncodingValue">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="lSampleRate">
|
||||
<property name="text">
|
||||
<string>Sample Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="lSampleRateValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lCarrierFrequency">
|
||||
<property name="text">
|
||||
<string>Carrier Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="ElidedLabel" name="labelParameterValues">
|
||||
<property name="text">
|
||||
<string>0/100</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="lParamCaption">
|
||||
<property name="text">
|
||||
<string>Amplitudes:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Bits per Symbol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="labelBitsPerSymbol">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cBoxModulations">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MyModulation</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QProgressBar" name="prBarGeneration">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>Modulating %p%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QPushButton" name="btnSend">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send data...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="media-playback-start">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="btnEditModulation">
|
||||
<property name="text">
|
||||
<string>Edit ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lModulation">
|
||||
<property name="text">
|
||||
<string>Modulation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="btnGenerate">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Generate the complex file of the modulated signal, after tuning all parameters above.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate file...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-new">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item row="2" column="6">
|
||||
<widget class="QComboBox" name="cbViewType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bit</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ASCII</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="5">
|
||||
<widget class="QLabel" name="lViewType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Viewtype:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="7">
|
||||
<widget class="GeneratorTableView" name="tableMessages">
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropOverwriteMode">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DropOnly</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::CopyAction</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="7">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelGeneratedData">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generated Data</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSave">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Save current fuzz profile.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnOpen">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Load a fuzz profile.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-open">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="btnNetworkSDRSend">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">Send encoded data to your external application via TCP.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send via Network</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="network-wired">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="btnRfCatSend">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">Send encoded data via RfCat. </span></p><p><span style=" font-style:italic;">Hit again for stopping the sending process. Note that you can set the number of repetitions (from 1 to infinite) in:</span></p><p><span style=" font-style:italic;">Edit-&gt;Options-&gt;Device-&gt;'Device sending repetitions'</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send via RfCat</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="network-wireless">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="lEstimatedTime">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The estimated average time is based on the average number of bits per message and average sample rate, you set for the modulations.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Estimated Time: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" colspan="2">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>38</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ElidedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>urh.ui.ElidedLabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GeneratorTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>urh.ui.views.GeneratorTreeView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GeneratorTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>urh.ui.views.GeneratorTableView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GeneratorListWidget</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>urh.ui.GeneratorListWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GeneratorListView</class>
|
||||
<extends>QListView</extends>
|
||||
<header>urh.ui.views.GeneratorListView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
837
Software/Universal Radio Hacker/data/ui/main.ui
Normal file
@ -0,0 +1,837 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>798</width>
|
||||
<height>469</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Universal Radio Hacker</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="urh.qrc">
|
||||
<normaloff>:/icons/icons/appicon.png</normaloff>:/icons/icons/appicon.png</iconset>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="dockNestingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="100,1">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QSplitter::handle:horizontal {
|
||||
margin: 4px 0px;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
||||
stop:0 rgba(255, 255, 255, 0),
|
||||
stop:0.5 rgba(100, 100, 100, 100),
|
||||
stop:1 rgba(255, 255, 255, 0));
|
||||
image: url(:/icons/icons/splitter_handle_vertical.svg);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lnEdtTreeFilter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhDialableCharactersOnly</set>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Filter</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnFileTreeGoUp">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="go-up">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="DirectoryTreeView" name="fileTree">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||
<horstretch>10</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="autoScroll">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget_Project">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTabWidget::pane { border: 0; }</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabParticipants">
|
||||
<attribute name="title">
|
||||
<string>Participants</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListView" name="listViewParticipants">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabDescription">
|
||||
<attribute name="title">
|
||||
<string>Description</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEditProjectDescription"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_interpretation">
|
||||
<attribute name="title">
|
||||
<string>Interpretation</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_protocol">
|
||||
<attribute name="title">
|
||||
<string>Analysis</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_generator">
|
||||
<attribute name="title">
|
||||
<string>Generator</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_simulator">
|
||||
<attribute name="title">
|
||||
<string>Simulator</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelNonProjectMode">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background: rgba(255,255,0,64)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Warning: You are running URH in non project mode. All your settings will be lost after closing the program. If you want to keep your settings create a project via File -&gt; <a href="open_new_project_dialog"><span style=" text-decoration: underline; color:#0000ff;">New Project</span></a>. <a href="dont_show_non_project_again"><span style=" text-decoration: underline; color:#0000ff;">Don't show this hint</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>798</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>Fi&le</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuImport">
|
||||
<property name="title">
|
||||
<string>Import</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-import">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<addaction name="actionSamples_from_csv"/>
|
||||
</widget>
|
||||
<addaction name="actionNew_Project"/>
|
||||
<addaction name="actionProject_settings"/>
|
||||
<addaction name="actionSave_project"/>
|
||||
<addaction name="actionClose_project"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionOpen_directory"/>
|
||||
<addaction name="menuImport"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSpectrum_Analyzer"/>
|
||||
<addaction name="actionRecord"/>
|
||||
<addaction name="actionSniff_protocol"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSaveAllSignals"/>
|
||||
<addaction name="actionCloseAllFiles"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionConvert_Folder_to_Project"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
<string>Edi&t</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuDefault_noise_threshold">
|
||||
<property name="title">
|
||||
<string>Default noise threshold</string>
|
||||
</property>
|
||||
<addaction name="actionAutomaticNoiseThreshold"/>
|
||||
<addaction name="action1NoiseThreshold"/>
|
||||
<addaction name="action5NoiseThreshold"/>
|
||||
<addaction name="action10NoiseThreshold"/>
|
||||
<addaction name="action100NoiseThreshold"/>
|
||||
</widget>
|
||||
<addaction name="actionDecoding"/>
|
||||
<addaction name="actionOptions"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShowFileTree"/>
|
||||
<addaction name="actionFullscreen_mode"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionAuto_detect_new_signals"/>
|
||||
<addaction name="menuDefault_noise_threshold"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>Hel&p</string>
|
||||
</property>
|
||||
<addaction name="actionAbout_AutomaticHacker"/>
|
||||
<addaction name="actionAbout_Qt"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<action name="actionFSK">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Undo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOOK">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Redo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPSK">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PSK</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNone">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>None (bei .bin)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAuto_Fit_Y">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Auto Fit Y</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUndo">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-undo">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Undo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRedo">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-redo">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Redo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_Confirm_Close_Dialog">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Show Confirm Close Dialog</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTest">
|
||||
<property name="text">
|
||||
<string>test</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHold_Shift_to_Drag">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Hold Shift to Drag</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDocumentation">
|
||||
<property name="icon">
|
||||
<iconset theme="help-contents">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Documentation</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout_AutomaticHacker">
|
||||
<property name="icon">
|
||||
<iconset theme="help-about">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&About Universal Radio Hacker...</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenSignal">
|
||||
<property name="text">
|
||||
<string>&Signal</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenProtocol">
|
||||
<property name="text">
|
||||
<string>&Protocol</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_Compare_Frame">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show &Compare Frame</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCloseAllFiles">
|
||||
<property name="icon">
|
||||
<iconset theme="window-close">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close all files</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSaveAllSignals">
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Save all signals</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSeperate_Protocols_in_Compare_Frame">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Separate &Protocols in Compare Frame</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenArchive">
|
||||
<property name="text">
|
||||
<string>&Archive</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen">
|
||||
<property name="icon">
|
||||
<iconset theme="document-open">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Open...</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Folder">
|
||||
<property name="icon">
|
||||
<iconset theme="folder-open">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open &Folder..</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_only_Compare_Frame">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Compare Frame only</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionConfigurePlugins">
|
||||
<property name="text">
|
||||
<string>Configure...</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSort_Frames_by_Name">
|
||||
<property name="text">
|
||||
<string>Sort &Frames by Name</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionConvert_Folder_to_Project">
|
||||
<property name="text">
|
||||
<string>Conv&ert Folder to Project</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDecoding">
|
||||
<property name="icon">
|
||||
<iconset resource="urh.qrc">
|
||||
<normaloff>:/icons/icons/decoding.svg</normaloff>:/icons/icons/decoding.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Decoding...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRecord">
|
||||
<property name="icon">
|
||||
<iconset theme="media-record">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Record signal...</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSpectrum_Analyzer">
|
||||
<property name="icon">
|
||||
<iconset resource="urh.qrc">
|
||||
<normaloff>:/icons/icons/spectrum.svg</normaloff>:/icons/icons/spectrum.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Spectrum &Analyzer...</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOptions">
|
||||
<property name="icon">
|
||||
<iconset theme="configure">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Options...</string>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNew_Project">
|
||||
<property name="icon">
|
||||
<iconset theme="folder-new">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&New Project..</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSniff_protocol">
|
||||
<property name="icon">
|
||||
<iconset resource="urh.qrc">
|
||||
<normaloff>:/icons/icons/sniffer.svg</normaloff>:/icons/icons/sniffer.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sn&iff protocol...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionProject_settings">
|
||||
<property name="icon">
|
||||
<iconset theme="configure">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Project settings...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_project">
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sa&ve project</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFullscreen_mode">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Fullscreen mode</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_directory">
|
||||
<property name="icon">
|
||||
<iconset theme="folder-open">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open &folder...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout_Qt">
|
||||
<property name="text">
|
||||
<string>About &Qt</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowFileTree">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Show file tree</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSamples_from_csv">
|
||||
<property name="icon">
|
||||
<iconset theme="text-csv">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IQ samples from csv</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose_project">
|
||||
<property name="icon">
|
||||
<iconset theme="document-close">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close project</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAuto_detect_new_signals">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto detect signals on loading</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAutomaticNoiseThreshold">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Automatic</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action1NoiseThreshold">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1%</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action5NoiseThreshold">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>5%</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action10NoiseThreshold">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>10%</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action100NoiseThreshold">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>100% (disables demodulation)</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>DirectoryTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>urh.ui.views.DirectoryTreeView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
109
Software/Universal Radio Hacker/data/ui/messagetype_options.ui
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogMessageType</class>
|
||||
<widget class="QDialog" name="DialogMessageType">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>471</width>
|
||||
<height>359</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="cbRulesetMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All rules must apply (AND)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>At least one rule must apply (OR)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>No rule must apply (NOR)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" rowspan="3" colspan="2">
|
||||
<widget class="QTableView" name="tblViewRuleset">
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QToolButton" name="btnRemoveRule">
|
||||
<property name="toolTip">
|
||||
<string>Remove ruleset</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="rbAssignManually">
|
||||
<property name="text">
|
||||
<string>Assi&gn manually</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QRadioButton" name="rbAssignAutomatically">
|
||||
<property name="text">
|
||||
<string>Assign a&utomatically</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>145</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QToolButton" name="btnAddRule">
|
||||
<property name="toolTip">
|
||||
<string>Add ruleset</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
1142
Software/Universal Radio Hacker/data/ui/modulation.ui
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogModulationParameters</class>
|
||||
<widget class="QDialog" name="DialogModulationParameters">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>303</width>
|
||||
<height>286</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Modulation Parameters</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tblSymbolParameters">
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="rowCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<row/>
|
||||
<row/>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Symbol</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Amplitude</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -0,0 +1,261 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ModulationSettings</class>
|
||||
<widget class="QWidget" name="ModulationSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>821</width>
|
||||
<height>635</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSniffSettings">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox
|
||||
{
|
||||
border: none;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
QGroupBox::indicator:unchecked {
|
||||
image: url(:/icons/icons/collapse.svg)
|
||||
}
|
||||
QGroupBox::indicator:checked {
|
||||
image: url(:/icons/icons/uncollapse.svg)
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Modulation settings</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelModulationProfile">
|
||||
<property name="text">
|
||||
<string>Choose profile:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxModulationProfiles"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="labelCarrierFrequencyValue">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="labelSampleRate">
|
||||
<property name="text">
|
||||
<string>Sample Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5" rowspan="2">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelCarrierFrequency">
|
||||
<property name="text">
|
||||
<string>Carrier Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="labelSamplesPerSymbol">
|
||||
<property name="text">
|
||||
<string>Samples per Symbol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="labelSampleRateValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelModulationType">
|
||||
<property name="text">
|
||||
<string>Modulation type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="labelSamplesPerSymbolValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelModulationTypeValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6">
|
||||
<widget class="QLabel" name="labelParameters">
|
||||
<property name="text">
|
||||
<string>Amplitudes in %:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="7">
|
||||
<widget class="ElidedLabel" name="labelParameterValues">
|
||||
<property name="text">
|
||||
<string>0/100</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Bits per Symbol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
<widget class="QLabel" name="labelBitsPerSymbol">
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnConfigurationDialog">
|
||||
<property name="text">
|
||||
<string>Open modulation configuration dialog...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="configure">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ElidedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>urh.ui.ElidedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>groupBoxSniffSettings</tabstop>
|
||||
<tabstop>comboBoxModulationProfiles</tabstop>
|
||||
<tabstop>btnConfigurationDialog</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>groupBoxSniffSettings</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>frame</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>33</x>
|
||||
<y>10</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>18</x>
|
||||
<y>53</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
630
Software/Universal Radio Hacker/data/ui/options.ui
Normal file
@ -0,0 +1,630 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogOptions</class>
|
||||
<widget class="QDialog" name="DialogOptions">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>814</width>
|
||||
<height>822</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset theme="configure">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabGeneration">
|
||||
<attribute name="title">
|
||||
<string>Generation</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelFuzzingSamples">
|
||||
<property name="text">
|
||||
<string>Samples</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxDefaultFuzzingPause">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If you disable the default pause, the pause of the fuzzed message will be used.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use a default pause for fuzzed messages</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="KillerDoubleSpinBox" name="doubleSpinBoxFuzzingPause">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxMultipleModulations">
|
||||
<property name="text">
|
||||
<string>Enable modulation profiles</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxModulationAccuracy">
|
||||
<property name="title">
|
||||
<string>Modulation Accuracy</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonLowModulationAccuracy">
|
||||
<property name="text">
|
||||
<string>Low (2x8 bit) - Recommended for HackRF and RTL-SDR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonMediumModulationAccuracy">
|
||||
<property name="text">
|
||||
<string>Medium (2x16 bit) - Recommended for BladeRF, PlutoSDR and SDRPlay</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonHighModulationAccuracy">
|
||||
<property name="text">
|
||||
<string>High (2x32 bit) - Recommended if you are not sure what to choose</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabView">
|
||||
<attribute name="title">
|
||||
<string>View</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Default View:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxDefaultView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bit</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ASCII</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxShowConfirmCloseDialog">
|
||||
<property name="text">
|
||||
<string>Show "confirm close" dialog</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxHoldShiftToDrag">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, you need to <span style=" font-weight:600;">hold the Shift key to drag</span> with the mouse inside graphic views like the drawn signal in Interpretation tab, while making a selection with the mouse does not require holding any buttons.</p><p>If unchecked, this is inverted: Hold shift to make a selection, and drag by default.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hold shift to drag</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxPauseTime">
|
||||
<property name="text">
|
||||
<string>Show pauses as time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxAlignLabels">
|
||||
<property name="text">
|
||||
<string>Align on labels</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelFontSize">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Application font size (<span style=" font-weight:600;">restart</span> for full effect):</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxFontSize">
|
||||
<property name="suffix">
|
||||
<string>pt</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Choose application theme (requires restart):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxTheme">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>native look (default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>fallback theme</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>fallback theme (dark)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelIconTheme">
|
||||
<property name="text">
|
||||
<string>Choose icon theme (requires restart):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxIconTheme">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>bundled icons (default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>native icon theme</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSpectrogramColormap">
|
||||
<property name="title">
|
||||
<string>Spectrogram Colormap</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollAreaSpectrogramColormap">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetSpectrogramColormapContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>762</width>
|
||||
<height>397</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabFieldtypes">
|
||||
<attribute name="title">
|
||||
<string>Fieldtypes</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QTableView" name="tblLabeltypes">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnAddLabelType">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnRemoveLabeltype">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>203</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_plugins">
|
||||
<attribute name="title">
|
||||
<string>Plugins</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabDevices">
|
||||
<attribute name="title">
|
||||
<string>Device</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelInfoDeviceTable">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Use the checkboxes in the table below to choose device backends and enable or disable devices. Disabled devices will not show up in device related dialogs such as send or receive.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tblDevices">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>200</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDeviceMissingInfo">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Missing a native backend? Perform a <a href="health_check"><span style=" text-decoration: underline; color:#0000ff;">health check</span></a>! If GNU Radio backend is not available double check the GNU Radio settings below.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxNativeOptions">
|
||||
<property name="title">
|
||||
<string>Native options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelLibDirs">
|
||||
<property name="text">
|
||||
<string>Library directories:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLineEdit" name="lineEditIncludeDirs">
|
||||
<property name="placeholderText">
|
||||
<string>Comma separated list of additional include directories</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="QLabel" name="labelNativeRebuildInfo">
|
||||
<property name="text">
|
||||
<string>You can rebuild the native device extensions here. This is useful, when you installed a device driver afterwards or your drivers are stored in an unusual location.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLineEdit" name="lineEditLibDirs">
|
||||
<property name="placeholderText">
|
||||
<string>Comma separated list of additional library directories</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelIncludeDirs">
|
||||
<property name="text">
|
||||
<string>Include directories:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="btnViewBuildLog">
|
||||
<property name="text">
|
||||
<string>View log</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="utilities-log-viewer">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QPushButton" name="btnRebuildNative">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Rebuild the native device extensions. You need to restart URH after this, to use new extensions.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rebuild</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="view-refresh">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="labelRebuildNativeStatus">
|
||||
<property name="text">
|
||||
<string>Rebuild <x> new device extensions. Please restart URH to use them.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>GNU Radio options (optional)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Choose a python interpreter which has access to your GNU Radio installation, that is, you can do <span style=" font-weight:600;">python -c &quot;import gnuradio&quot;</span> with it on the command line.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Python Interpreter:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditGRPythonInterpreter">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Choose a python interpreter which has access to your GNU Radio installation, that is, you can do <span style=" font-weight:600;">python -c &quot;import gnuradio&quot;</span> with it on the command line.</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Enter python interpreter path e.g. /usr/bin/python</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="btnChooseGRPythonInterpreter">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Default sending repititions:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxNumSendingRepeats">
|
||||
<property name="specialValueText">
|
||||
<string>Infinite</string>
|
||||
</property>
|
||||
<property name="showGroupSeparator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Use this percentage of available RAM for buffer allocation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxRAMThreshold">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KillerDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
<header>urh.ui.KillerDoubleSpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
98
Software/Universal Radio Hacker/data/ui/plugins.ui
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FramePlugins</class>
|
||||
<widget class="QFrame" name="FramePlugins">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>806</width>
|
||||
<height>683</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Plugins</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Available Plugins</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="listViewPlugins">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="txtEditPluginDescription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSettings">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
412
Software/Universal Radio Hacker/data/ui/project.ui
Normal file
@ -0,0 +1,412 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProjectDialog</class>
|
||||
<widget class="QDialog" name="ProjectDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>803</width>
|
||||
<height>936</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create a new project</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="lNewProject">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblName">
|
||||
<property name="text">
|
||||
<string><Name></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>17</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="4" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Sps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="lineEdit_Path">
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="lblNewPath">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-style:italic;">Note: A new directory will be created.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="4" colspan="2">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>57</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="10" column="3">
|
||||
<widget class="QPlainTextEdit" name="txtEdDescription"/>
|
||||
</item>
|
||||
<item row="11" column="3" rowspan="5">
|
||||
<widget class="ParticipantTableView" name="tblParticipants">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>100</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="KillerDoubleSpinBox" name="spinBoxBandwidth">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Default frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="KillerDoubleSpinBox" name="spinBoxFreq">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>433920000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="KillerDoubleSpinBox" name="spinBoxSampleRate">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="3">
|
||||
<widget class="QLineEdit" name="lineEditBroadcastAddress">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enter the broadcast address of your protocol in <span style=" font-weight:600;">hex</span>. If you do not know what to enter here, just leave the default.</p></body></html></string>
|
||||
</property>
|
||||
<property name="inputMask">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ffff</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="6">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Default bandwidth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="4" colspan="2">
|
||||
<widget class="QToolButton" name="btnAddParticipant">
|
||||
<property name="toolTip">
|
||||
<string>Add participant</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" colspan="2">
|
||||
<widget class="QToolButton" name="btnSelectPath">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="6">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4" colspan="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Hz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Default sample rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Choose a path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="4" colspan="2">
|
||||
<widget class="QToolButton" name="btnRemoveParticipant">
|
||||
<property name="toolTip">
|
||||
<string>Remove participant</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<widget class="QSpinBox" name="spinBoxGain">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Broadcast address (hex):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4" colspan="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Hz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Default gain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="4">
|
||||
<widget class="QToolButton" name="btnUp">
|
||||
<property name="toolTip">
|
||||
<string>Move selected participants up</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="go-up">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="4">
|
||||
<widget class="QLabel" name="lOpenSpectrumAnalyzer">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Tip: Open <a href="open_spectrum_analyzer">spectrum analyzer</a> to find these values.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" rowspan="5" colspan="2">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Participants:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="4">
|
||||
<widget class="QToolButton" name="btnDown">
|
||||
<property name="toolTip">
|
||||
<string>Move selected participants down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="go-down">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="3">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ParticipantTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>urh.ui.views.ParticipantTableView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>KillerDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
<header>urh.ui.KillerDoubleSpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>lineEdit_Path</tabstop>
|
||||
<tabstop>btnSelectPath</tabstop>
|
||||
<tabstop>spinBoxSampleRate</tabstop>
|
||||
<tabstop>spinBoxFreq</tabstop>
|
||||
<tabstop>spinBoxBandwidth</tabstop>
|
||||
<tabstop>spinBoxGain</tabstop>
|
||||
<tabstop>txtEdDescription</tabstop>
|
||||
<tabstop>tblParticipants</tabstop>
|
||||
<tabstop>btnAddParticipant</tabstop>
|
||||
<tabstop>btnRemoveParticipant</tabstop>
|
||||
<tabstop>lineEditBroadcastAddress</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
144
Software/Universal Radio Hacker/data/ui/properties_dialog.ui
Normal file
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogLabels</class>
|
||||
<widget class="QDialog" name="DialogLabels">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>714</width>
|
||||
<height>463</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Manage Protocol Labels</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QSplitter::handle:vertical {
|
||||
margin: 4px 0px;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
||||
stop:0 rgba(255, 255, 255, 0),
|
||||
stop:0.5 rgba(100, 100, 100, 100),
|
||||
stop:1 rgba(255, 255, 255, 0));
|
||||
image: url(:/icons/icons/splitter_handle_horizontal.svg);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="groupBoxSettings">
|
||||
<property name="title">
|
||||
<string>Protocol Label Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="ProtocolLabelTableView" name="tblViewProtoLabels">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>false</underline>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start/End values refer to view type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbProtoView">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bits</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ASCII</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBoxAdvancedSettings">
|
||||
<property name="title">
|
||||
<string>Advanced Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidgetAdvancedSettings"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnConfirm">
|
||||
<property name="text">
|
||||
<string>Confirm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ProtocolLabelTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>urh.ui.views.ProtocolLabelTableView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
610
Software/Universal Radio Hacker/data/ui/send_recv.ui
Normal file
@ -0,0 +1,610 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SendRecvDialog</class>
|
||||
<widget class="QDialog" name="SendRecvDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1246</width>
|
||||
<height>1123</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Record Signal</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QSplitter::handle:horizontal {
|
||||
margin: 4px 0px;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
||||
stop:0 rgba(255, 255, 255, 0),
|
||||
stop:0.5 rgba(100, 100, 100, 100),
|
||||
stop:1 rgba(255, 255, 255, 0));
|
||||
image: url(:/icons/icons/splitter_handle_vertical.svg);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>621</width>
|
||||
<height>1101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox
|
||||
{
|
||||
border: none;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="19" column="0">
|
||||
<widget class="QProgressBar" name="progressBarMessage">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%v/%m</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<widget class="QLabel" name="labelCurrentMessage">
|
||||
<property name="text">
|
||||
<string>Current message:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="lReceiveBufferFullText">
|
||||
<property name="text">
|
||||
<string>Receive buffer full:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="21" column="0">
|
||||
<widget class="QProgressBar" name="progressBarSample">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%v/%m</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="0">
|
||||
<widget class="QLabel" name="lSamplesSentText">
|
||||
<property name="text">
|
||||
<string>Current sample:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="lTimeText">
|
||||
<property name="text">
|
||||
<string>Time (in seconds):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="lSamplesCapturedText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Samples captured:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="lSignalSizeText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Signal size (in MiB):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lSamplesCaptured">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lTime">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lSignalSize">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="lblRepeatText">
|
||||
<property name="text">
|
||||
<string>Current iteration:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<widget class="QLabel" name="lblCurrentRepeatValue">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="labelReceiveBufferFull">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0%</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnStart">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Record signal</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="media-record">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnStop">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Stop recording</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="media-playback-stop">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSave">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnClear">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="view-refresh">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="txtEditErrors">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_receive">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="LiveGraphicView" name="graphicsViewReceive">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_send">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="EditableGraphicView" name="graphicsViewSend">
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="renderHints">
|
||||
<set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
|
||||
</property>
|
||||
<property name="transformationAnchor">
|
||||
<enum>QGraphicsView::NoAnchor</enum>
|
||||
</property>
|
||||
<property name="resizeAnchor">
|
||||
<enum>QGraphicsView::NoAnchor</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hint: You can edit the raw signal before sending.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_continuous_send">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="LiveGraphicView" name="graphicsViewContinuousSend">
|
||||
<property name="renderHints">
|
||||
<set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_spectrum">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7" stretch="1,1">
|
||||
<item>
|
||||
<widget class="LiveGraphicView" name="graphicsViewFFT"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="graphicsViewSpectrogram">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="renderHints">
|
||||
<set>QPainter::SmoothPixmapTransform|QPainter::TextAntialiasing</set>
|
||||
</property>
|
||||
<property name="cacheMode">
|
||||
<set>QGraphicsView::CacheNone</set>
|
||||
</property>
|
||||
<property name="viewportUpdateMode">
|
||||
<enum>QGraphicsView::MinimalViewportUpdate</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_sniff">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="LiveGraphicView" name="graphicsView_sniff_Preview"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="txtEd_sniff_Preview">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QPlainTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximumBlockCount">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAccept">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Accept the sniffed data and load it into <span style=" font-weight:600;">Analysis</span> tab.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Accept data (Open in Analysis)</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_y_scale">
|
||||
<property name="text">
|
||||
<string>Y-Scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderYscale">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LiveGraphicView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>urh.ui.views.LiveGraphicView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>EditableGraphicView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>urh.ui.views.EditableGraphicView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>btnStart</tabstop>
|
||||
<tabstop>btnStop</tabstop>
|
||||
<tabstop>btnSave</tabstop>
|
||||
<tabstop>btnClear</tabstop>
|
||||
<tabstop>txtEd_sniff_Preview</tabstop>
|
||||
<tabstop>sliderYscale</tabstop>
|
||||
<tabstop>txtEditErrors</tabstop>
|
||||
<tabstop>graphicsViewSend</tabstop>
|
||||
<tabstop>graphicsViewReceive</tabstop>
|
||||
<tabstop>btnAccept</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -0,0 +1,619 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FormDeviceSettings</class>
|
||||
<widget class="QWidget" name="FormDeviceSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>859</width>
|
||||
<height>741</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxDeviceSettings">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox
|
||||
{
|
||||
border: none;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
QGroupBox::indicator:unchecked {
|
||||
image: url(:/icons/icons/collapse.svg)
|
||||
}
|
||||
QGroupBox::indicator:checked {
|
||||
image: url(:/icons/icons/uncollapse.svg)
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Device settings</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<property name="topMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelAntenna">
|
||||
<property name="text">
|
||||
<string>Antenna:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="labelBasebandGain">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The baseband gain is applied to the baseband signal in your software defined radio. The baseband signal is at low frequency and gathered from the RF signal by <span style=" font-weight:600;">complex downsampling</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Baseband gain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEditSubdevice">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Configure the subdevice of your USRP. For example, <span style=" font-weight:600;">B:0 </span>to select a WBX on slot B. You can learn more at <a href="http://files.ettus.com/manual/page_configuration.html#config_subdev"><span style=" text-decoration: underline; color:#2980b9;">http://files.ettus.com/manual/page_configuration.html#config_subdev.</span></a></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="KillerDoubleSpinBox" name="spinBoxBandwidth">
|
||||
<property name="decimals">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelSubdevice">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Configure the subdevice of your USRP. For example, <span style=" font-weight:600;">B:0 </span>to select a WBX on slot B. You can learn more at <a href="http://files.ettus.com/manual/page_configuration.html#config_subdev"><span style=" text-decoration: underline; color:#2980b9;">http://files.ettus.com/manual/page_configuration.html#config_subdev.</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Subdevice:</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="KillerDoubleSpinBox" name="spinBoxFreq">
|
||||
<property name="decimals">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>433920000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEditIP">
|
||||
<property name="text">
|
||||
<string>127.0.0.1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QToolButton" name="btnRefreshDeviceIdentifier">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Automatically detect connected SDRs of the above configured type. There is <span style=" font-weight:600;">no need</span> to press this button if you have only one SDR of a certain type attached. </p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="view-refresh">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="labelDirectSampling">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Set the direct sampling mode. If you do not know what to choose here, just set it to disabled. The<span style=" font-weight:600;"> native backend</span> is recommended, when using this setting.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Direct sampling:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="labelBandwidth">
|
||||
<property name="text">
|
||||
<string>Bandwidth (Hz):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSlider" name="sliderGain">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The gain (more exactly RF gain) is the gain applied to the RF signal. This amplifies the high frequent signal arriving at the antenna of your Software Defined Radio.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxGain">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The gain (more exactly RF gain) is the gain applied to the RF signal. This amplifies the high frequent signal arriving at the antenna of your Software Defined Radio.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>40</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="labelSampleRate">
|
||||
<property name="text">
|
||||
<string>Sample rate (Sps):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSlider" name="sliderIFGain">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The IF Gain is applied to the Intermediate Frequency signal in your Software Defined Radio. An IF signal has a lower frequency than the high frequent RF signal, so signal processing can be applied more efficiently.</p></body></html></string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxIFGain">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The IF Gain is applied to the Intermediate Frequency signal in your Software Defined Radio. An IF signal has a lower frequency than the high frequent RF signal, so signal processing can be applied more efficiently.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="labelFreqCorrection">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Set the frequency correction in <span style=" font-weight:600;">ppm</span>. If you do not know what to enter here, just leave it to one.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Frequency correction:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxDeviceIdentifier">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>You can enter a device identifier here if you have multiple SDRs of the same type attached to separate them. There is no need to configure this value otherwise. URH will <span style=" font-weight:600;">automatically</span> select an attached SDR of the configured type if you leave this value empty.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cbDevice">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>USRP</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>HackRF</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxNRepeat">
|
||||
<property name="specialValueText">
|
||||
<string>Infinite</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSlider" name="sliderBasebandGain">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The baseband gain is applied to the baseband signal in your software defined radio. The baseband signal is at low frequency and gathered from the RF signal by <span style=" font-weight:600;">complex downsampling</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="invertedControls">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::NoTicks</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxBasebandGain">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The baseband gain is applied to the baseband signal in your software defined radio. The baseband signal is at low frequency and gathered from the RF signal by <span style=" font-weight:600;">complex downsampling</span>.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="labelPort">
|
||||
<property name="text">
|
||||
<string>Port number:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="KillerDoubleSpinBox" name="spinBoxSampleRate">
|
||||
<property name="decimals">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="labelGain">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The gain (more exactly RF gain) is the gain applied to the RF signal. This amplifies the high frequent signal arriving at the antenna of your Software Defined Radio.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxDCCorrection">
|
||||
<property name="toolTip">
|
||||
<string>Apply DC correction during recording, that is, ensure the captured signal has a mean value of zero.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply DC correction</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelDeviceIdentifier">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>You can enter a device identifier here if you have multiple SDRs of the same type attached to separate them. There is no need to configure this value otherwise. URH will <span style=" font-weight:600;">automatically</span> select an attached SDR of the configured type if you leave this value empty.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Device Identifier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="comboBoxAntenna"/>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="labelFreq">
|
||||
<property name="text">
|
||||
<string>Frequency (Hz):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxPort">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1234</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelIP">
|
||||
<property name="text">
|
||||
<string>IP address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxFreqCorrection">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Set the frequency correction in <span style=" font-weight:600;">ppm</span>. If you do not know what to enter here, just leave it to one.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-1000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="labelNRepeat">
|
||||
<property name="text">
|
||||
<string>Repeat:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QComboBox" name="comboBoxDirectSampling">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Set the direct sampling mode. If you do not know what to choose here, just set it to disabled. The<span style=" font-weight:600;"> native backend</span> is recommended, when using this setting.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<widget class="QLabel" name="labelDCCorrection">
|
||||
<property name="toolTip">
|
||||
<string>Apply DC correction during recording, that is, ensure the captured signal has a mean value of zero.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>DC correction:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxChannel"/>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="labelIFGain">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The IF Gain is applied to the Intermediate Frequency signal in your Software Defined Radio. An IF signal has a lower frequency than the high frequent RF signal, so signal processing can be applied more efficiently.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IF Gain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelChannel">
|
||||
<property name="text">
|
||||
<string>Channel:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2" rowspan="2">
|
||||
<widget class="QToolButton" name="btnLockBWSR">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="urh.qrc">
|
||||
<normaloff>:/icons/icons/lock.svg</normaloff>:/icons/icons/lock.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Device:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="labelBiasTee">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable the bias tee of your SDR, if you have an external LNA connected. Leave this disabled if you have no external LNA attached.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bias Tee:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxBiasTee">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable the bias tee of your SDR, if you have an external LNA connected. Leave this disabled if you have no external LNA attached.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Bias Tee</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KillerDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
<header>urh.ui.KillerDoubleSpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>groupBoxDeviceSettings</tabstop>
|
||||
<tabstop>cbDevice</tabstop>
|
||||
<tabstop>comboBoxDeviceIdentifier</tabstop>
|
||||
<tabstop>btnRefreshDeviceIdentifier</tabstop>
|
||||
<tabstop>lineEditSubdevice</tabstop>
|
||||
<tabstop>comboBoxChannel</tabstop>
|
||||
<tabstop>comboBoxAntenna</tabstop>
|
||||
<tabstop>lineEditIP</tabstop>
|
||||
<tabstop>spinBoxPort</tabstop>
|
||||
<tabstop>spinBoxFreq</tabstop>
|
||||
<tabstop>spinBoxSampleRate</tabstop>
|
||||
<tabstop>btnLockBWSR</tabstop>
|
||||
<tabstop>spinBoxBandwidth</tabstop>
|
||||
<tabstop>sliderGain</tabstop>
|
||||
<tabstop>spinBoxGain</tabstop>
|
||||
<tabstop>sliderIFGain</tabstop>
|
||||
<tabstop>spinBoxIFGain</tabstop>
|
||||
<tabstop>sliderBasebandGain</tabstop>
|
||||
<tabstop>spinBoxBasebandGain</tabstop>
|
||||
<tabstop>spinBoxFreqCorrection</tabstop>
|
||||
<tabstop>comboBoxDirectSampling</tabstop>
|
||||
<tabstop>spinBoxNRepeat</tabstop>
|
||||
<tabstop>checkBoxDCCorrection</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>groupBoxDeviceSettings</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>frame_2</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>115</x>
|
||||
<y>17</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>31</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -0,0 +1,397 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SniffSettings</class>
|
||||
<widget class="QWidget" name="SniffSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>482</width>
|
||||
<height>510</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSniffSettings">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox
|
||||
{
|
||||
border: none;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
QGroupBox::indicator:unchecked {
|
||||
image: url(:/icons/icons/collapse.svg)
|
||||
}
|
||||
QGroupBox::indicator:checked {
|
||||
image: url(:/icons/icons/uncollapse.svg)
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Sniff settings</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_sniff_Center">
|
||||
<property name="text">
|
||||
<string>Center:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="spinbox_sniff_Noise">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxAdaptiveNoise">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>With adaptive noise URH will update the noise level automatically during RX. This is helpful in a dynamic environment where noise differs in time.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Adaptive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_sniff_Modulation">
|
||||
<property name="text">
|
||||
<string>Modulation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_sniff_Signal">
|
||||
<property name="text">
|
||||
<string>Use values from:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="spinbox_sniff_ErrorTolerance">
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="combox_sniff_Modulation">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ASK</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FSK</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PSK</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_sniff_Tolerance">
|
||||
<property name="text">
|
||||
<string>Error Tolerance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinbox_sniff_SamplesPerSymbol">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_sniff_viewtype">
|
||||
<property name="text">
|
||||
<string>View:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_sniff_OutputFile">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>None</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_sniff_BitLength">
|
||||
<property name="text">
|
||||
<string>Samples per Symbol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinBoxCenterSpacing">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_sniff_signal">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_sniff_use_signal">
|
||||
<property name="text">
|
||||
<string>Use</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_sniff_OutputFile">
|
||||
<property name="text">
|
||||
<string>Write bitstream to file:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="spinbox_sniff_Center">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-3.140000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>3.140000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxAutoCenter">
|
||||
<property name="text">
|
||||
<string>Automatic</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_sniff_encoding">
|
||||
<property name="text">
|
||||
<string>Encoding:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_sniff_viewtype">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bit</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ASCII</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_sniff_Timestamp">
|
||||
<property name="text">
|
||||
<string>Show Timestamp</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_sniff_Noise">
|
||||
<property name="text">
|
||||
<string>Noise:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="comboBox_sniff_encoding">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelCenterSpacing">
|
||||
<property name="text">
|
||||
<string>Center Spacing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="labelBitsPerSymbol">
|
||||
<property name="text">
|
||||
<string>Bits per Symbol:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxBitsPerSymbol">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>groupBoxSniffSettings</tabstop>
|
||||
<tabstop>spinbox_sniff_Noise</tabstop>
|
||||
<tabstop>spinbox_sniff_SamplesPerSymbol</tabstop>
|
||||
<tabstop>spinbox_sniff_ErrorTolerance</tabstop>
|
||||
<tabstop>combox_sniff_Modulation</tabstop>
|
||||
<tabstop>comboBox_sniff_encoding</tabstop>
|
||||
<tabstop>comboBox_sniff_viewtype</tabstop>
|
||||
<tabstop>checkBox_sniff_Timestamp</tabstop>
|
||||
<tabstop>lineEdit_sniff_OutputFile</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>groupBoxSniffSettings</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>frame</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>93</x>
|
||||
<y>17</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>113</x>
|
||||
<y>35</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
186
Software/Universal Radio Hacker/data/ui/signal_details.ui
Normal file
@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SignalDetails</class>
|
||||
<widget class="QDialog" name="SignalDetails">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>469</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Signal details</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="KillerDoubleSpinBox" name="dsb_sample_rate">
|
||||
<property name="wrapping">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="showGroupSeparator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999999999945575230987042816.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lblFile">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Samples:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Sample Rate (Sps):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="lblSamplesTotal">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>File size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="lblName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="lblFileSize">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>File created:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="lFileCreated">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Duration:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="lDuration">
|
||||
<property name="text">
|
||||
<string>42s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>135</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KillerDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
<header>urh.ui.KillerDoubleSpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
1379
Software/Universal Radio Hacker/data/ui/signal_frame.ui
Normal file
912
Software/Universal Radio Hacker/data/ui/simulator.ui
Normal file
@ -0,0 +1,912 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SimulatorTab</class>
|
||||
<widget class="QWidget" name="SimulatorTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>842</width>
|
||||
<height>689</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>842</width>
|
||||
<height>689</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitterLeftRight">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QSplitter::handle:horizontal {
|
||||
margin: 4px 0px;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
||||
stop:0 rgba(255, 255, 255, 0),
|
||||
stop:0.5 rgba(100, 100, 100, 100),
|
||||
stop:1 rgba(255, 255, 255, 0));
|
||||
image: url(:/icons/icons/splitter_handle_vertical.svg);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Protocols (Drag&Drop to Flow Graph):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="GeneratorTreeView" name="treeProtocols"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Simulate these participants:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListView" name="listViewSimulate">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Repeat simulation this often:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxNRepeat">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>Infinite</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Timeout:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxTimeout">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>ms</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>In case of an overdue response:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxError">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Resend last message</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Stop simulation</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Restart simulation</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Maximum retries:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxRetries">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnStartSim">
|
||||
<property name="text">
|
||||
<string>Simulate...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="media-playback-start">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QSplitter::handle:vertical {
|
||||
margin: 4px 0px;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
||||
stop:0 rgba(255, 255, 255, 0),
|
||||
stop:0.5 rgba(100, 100, 100, 100),
|
||||
stop:1 rgba(255, 255, 255, 0));
|
||||
image: url(:/icons/icons/splitter_handle_horizontal.svg);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTabWidget::pane { border: 0; }</string>
|
||||
</property>
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::North</enum>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Flow Graph</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="SimulatorGraphicsView" name="gvSimulator">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Messages</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="SimulatorMessageTableView" name="tblViewMessage">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="lNumSelectedColumns">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lColumnsSelectedText">
|
||||
<property name="text">
|
||||
<string>column(s) selected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>138</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Viewtype:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbViewType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bit</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ASCII</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabParticipants">
|
||||
<attribute name="title">
|
||||
<string>Participants</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ParticipantTableView" name="tableViewParticipants"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnAddParticipant">
|
||||
<property name="toolTip">
|
||||
<string>Add participant</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnRemoveParticipant">
|
||||
<property name="toolTip">
|
||||
<string>Remove participant</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnUp">
|
||||
<property name="toolTip">
|
||||
<string>Move selected participants up</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="go-up">
|
||||
<normaloff>../../../../</normaloff>../../../../</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnDown">
|
||||
<property name="toolTip">
|
||||
<string>Move selected participants down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="go-down">
|
||||
<normaloff>../../../../</normaloff>../../../../</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblMsgFieldsValues">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Detail view for item</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="detail_view_widget">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_empty"/>
|
||||
<widget class="QWidget" name="page_goto_action">
|
||||
<layout class="QGridLayout" name="verticalLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Goto:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="goto_combobox"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_message">
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copies:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="SimulatorLabelTableView" name="tblViewFieldValues">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Labels:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="spinBoxRepeat">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Coding:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="lblEncodingDecoding">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_rule">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Condition:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="ExpressionLineEdit" name="ruleCondLineEdit">
|
||||
<property name="placeholderText">
|
||||
<string>not (item1.crc == 0b1010 and item2.length >=3)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_ext_prog_action">
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="2" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="checkBoxPassTranscriptSTDIN">
|
||||
<property name="text">
|
||||
<string>Pass transcript to STDIN</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Command:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditTriggerCommand">
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Path [+arguments] to external command e.g. mail or sendsms</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QToolButton" name="btnChooseCommand">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>You can access the return code of this item in formulas and rules using the item identifier followed by <span style=" font-style:italic;">.rc</span> e.g.<span style=" font-style:italic;"> item5.rc</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_sleep">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Sleep for:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxSleep">
|
||||
<property name="suffix">
|
||||
<string>s</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>231</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxCounterStep">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Start:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Step:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxCounterStart">
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>This counter will increase by <span style=" font-weight:600;">step</span> each time it gets hit during simulation. It will preserve it's value during simulation repeats and retries. To reset all counters stop the simulation and start it again.</p><p>Access the value of this counter using item&lt;Number&gt;.counter_value in <span style=" font-weight:600;">Formulas</span> or as parameter in <span style=" font-weight:600;">external programs</span> e.g. <span style=" font-style:italic;">external_py -c item5.counter_value</span>. The value of this counter will be inserted during simulation time.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ParticipantTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>urh.ui.views.ParticipantTableView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GeneratorTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>urh.ui.views.GeneratorTreeView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SimulatorGraphicsView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>urh.ui.views.SimulatorGraphicsView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SimulatorMessageTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>urh.ui.views.SimulatorMessageTableView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ExpressionLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>urh.ui.ExpressionLineEdit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SimulatorLabelTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>urh.ui.views.SimulatorLabelTableView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
603
Software/Universal Radio Hacker/data/ui/simulator_dialog.ui
Normal file
@ -0,0 +1,603 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DialogSimulator</class>
|
||||
<widget class="QDialog" name="DialogSimulator">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1088</width>
|
||||
<height>823</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Simulation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidgetSimulatorSettings">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTabWidget::pane { border: 0; }</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabLog">
|
||||
<attribute name="title">
|
||||
<string>Log settings</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="LoggingGraphicsView" name="gvSimulator">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnLogAll">
|
||||
<property name="text">
|
||||
<string>Log all</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnLogNone">
|
||||
<property name="text">
|
||||
<string>Log none</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnToggleLog">
|
||||
<property name="text">
|
||||
<string>Toggle selected</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabRX">
|
||||
<attribute name="title">
|
||||
<string>RX settings</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollAreaRX">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContentsRX">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1066</width>
|
||||
<height>766</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnTestSniffSettings">
|
||||
<property name="text">
|
||||
<string>Test sniffer settings</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="urh.qrc">
|
||||
<normaloff>:/icons/icons/sniffer.svg</normaloff>:/icons/icons/sniffer.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabTX">
|
||||
<attribute name="title">
|
||||
<string>TX settings</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollAreaTX">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContentsTX">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1066</width>
|
||||
<height>766</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabSimulation">
|
||||
<attribute name="title">
|
||||
<string>Simulation</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTabWidget::pane { border: 0; }</string>
|
||||
</property>
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::West</enum>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Triangular</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_simulation">
|
||||
<attribute name="title">
|
||||
<string>Status</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSimulationStatus">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox
|
||||
{
|
||||
border: none;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
QGroupBox::indicator:unchecked {
|
||||
image: url(:/icons/icons/collapse.svg)
|
||||
}
|
||||
QGroupBox::indicator:checked {
|
||||
image: url(:/icons/icons/uncollapse.svg)
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Simulation Status</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<property name="topMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEditSimulation">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Current iteration:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblCurrentRepeatValue">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Current item:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblCurrentItemValue">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSaveLog">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxRXStatus">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QGroupBox
|
||||
{
|
||||
border: none;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
QGroupBox::indicator:unchecked {
|
||||
image: url(:/icons/icons/collapse.svg)
|
||||
}
|
||||
QGroupBox::indicator:checked {
|
||||
image: url(:/icons/icons/uncollapse.svg)
|
||||
}</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>RX Status</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<property name="topMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxCaptureFullRX">
|
||||
<property name="text">
|
||||
<string>Capture complete RX</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSaveRX">
|
||||
<property name="toolTip">
|
||||
<string>Save current capture</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LiveGraphicView" name="graphicsViewPreview"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Messages</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEditTranscript">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Here you will find all messages that were sent and received during simulation.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonTranscriptBit">
|
||||
<property name="text">
|
||||
<string>Bit &view</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonTranscriptHex">
|
||||
<property name="text">
|
||||
<string>Hex view</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnOpenInAnalysis">
|
||||
<property name="text">
|
||||
<string>Open in Analysis</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnSaveTranscript">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_device">
|
||||
<attribute name="title">
|
||||
<string>Devices</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEditDevices">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>After simulation start you will see the log messages of your configured SDRs here.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnStartStop">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="media-playback-start">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LiveGraphicView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>urh.ui.views.LiveGraphicView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LoggingGraphicsView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>urh.ui.views.LoggingGraphicsView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>groupBoxSimulationStatus</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>frame</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>167</x>
|
||||
<y>99</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>164</x>
|
||||
<y>108</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>groupBoxRXStatus</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>frame_2</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>616</x>
|
||||
<y>478</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>629</x>
|
||||
<y>544</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
145
Software/Universal Radio Hacker/data/ui/tab_interpretation.ui
Normal file
@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Interpretation</class>
|
||||
<widget class="QWidget" name="Interpretation">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>631</width>
|
||||
<height>561</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrlAreaSignals">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>631</width>
|
||||
<height>561</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QSplitter::handle:vertical {
|
||||
margin: 4px 0px;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
|
||||
stop:0 rgba(255, 255, 255, 0),
|
||||
stop:0.5 rgba(100, 100, 100, 100),
|
||||
stop:1 rgba(255, 255, 255, 0));
|
||||
image: url(:/icons/icons/splitter_handle_horizontal.svg);
|
||||
}</string>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QLabel" name="labelGettingStarted">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>32</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Open a file or record a new signal using the <b>File menu</b> to get started.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="placeholderLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ScrollArea</class>
|
||||
<extends>QScrollArea</extends>
|
||||
<header>urh.ui.ScrollArea.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="urh.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
20
Software/Universal Radio Hacker/data/ui/urh.qrc
Normal file
@ -0,0 +1,20 @@
|
||||
<RCC>
|
||||
<qresource prefix="icons">
|
||||
<file>../icons/appicon.ico</file>
|
||||
<file>../icons/decoding.svg</file>
|
||||
<file>../icons/equals_qm.svg</file>
|
||||
<file>../icons/appicon.png</file>
|
||||
<file>../icons/collapse.svg</file>
|
||||
<file>../icons/uncollapse.svg</file>
|
||||
<file>../icons/equals.svg</file>
|
||||
<file>../icons/lock.svg</file>
|
||||
<file>../icons/modulation.svg</file>
|
||||
<file>../icons/plus.svg</file>
|
||||
<file>../icons/sniffer.svg</file>
|
||||
<file>../icons/spectrum.svg</file>
|
||||
<file>../icons/splitter_handle_horizontal.svg</file>
|
||||
<file>../icons/splitter_handle_vertical.svg</file>
|
||||
<file>../icons/unlock.svg</file>
|
||||
<file>../icons/message_type.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
8
Software/Universal Radio Hacker/data/urh.desktop
Normal file
@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Universal Radio Hacker
|
||||
Comment=investigate wireless protocols like a boss
|
||||
Exec=/usr/bin/urh
|
||||
Icon=urh
|
||||
Terminal=false
|
||||
Categories=HamRadio
|
146
Software/Universal Radio Hacker/setup.py
Normal file
@ -0,0 +1,146 @@
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
if sys.version_info < (3, 4):
|
||||
print("You need at least Python 3.4 for this application!")
|
||||
if sys.version_info[0] < 3:
|
||||
print("try running with python3 {}".format(" ".join(sys.argv)))
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from setuptools import setup, Extension
|
||||
from setuptools.command.build_ext import build_ext as _build_ext
|
||||
except ImportError:
|
||||
print("Could not find setuptools")
|
||||
print("Try installing them with pip install setuptools")
|
||||
sys.exit(1)
|
||||
|
||||
from src.urh.dev.native import ExtensionHelper
|
||||
from src.urh.dev.native.ExtensionHelper import COMPILER_DIRECTIVES
|
||||
import src.urh.version as version
|
||||
|
||||
if sys.platform == "win32":
|
||||
OPEN_MP_FLAG = "/openmp"
|
||||
NO_NUMPY_WARNINGS_FLAG = ""
|
||||
elif sys.platform == "darwin":
|
||||
OPEN_MP_FLAG = "" # no OpenMP support in default Mac OSX compiler
|
||||
NO_NUMPY_WARNINGS_FLAG = "-Wno-#warnings"
|
||||
else:
|
||||
OPEN_MP_FLAG = "-fopenmp"
|
||||
NO_NUMPY_WARNINGS_FLAG = "-Wno-cpp"
|
||||
|
||||
UI_SUBDIRS = ("actions", "delegates", "views")
|
||||
PLUGINS = [path for path in os.listdir("src/urh/plugins") if os.path.isdir(os.path.join("src/urh/plugins", path))]
|
||||
URH_DIR = "urh"
|
||||
|
||||
IS_RELEASE = os.path.isfile(os.path.join(tempfile.gettempdir(), "urh_releasing"))
|
||||
|
||||
try:
|
||||
from Cython.Build import cythonize
|
||||
except ImportError:
|
||||
print("You need Cython to build URH's extensions!\n"
|
||||
"You can get it e.g. with python3 -m pip install cython.",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class build_ext(_build_ext):
|
||||
def finalize_options(self):
|
||||
print("Finalizing options")
|
||||
_build_ext.finalize_options(self)
|
||||
# Prevent numpy from thinking it is still in its setup process:
|
||||
__builtins__.__NUMPY_SETUP__ = False
|
||||
import numpy
|
||||
self.include_dirs.append(numpy.get_include())
|
||||
|
||||
|
||||
def get_packages():
|
||||
packages = [URH_DIR]
|
||||
separator = os.path.normpath("/")
|
||||
for dirpath, dirnames, filenames in os.walk(os.path.join("./src/", URH_DIR)):
|
||||
package_path = os.path.relpath(dirpath, os.path.join("./src/", URH_DIR)).replace(separator, ".")
|
||||
if len(package_path) > 1:
|
||||
packages.append(URH_DIR + "." + package_path)
|
||||
|
||||
return packages
|
||||
|
||||
|
||||
def get_package_data():
|
||||
package_data = {"urh.cythonext": ["*.pyx", "*.pxd"]}
|
||||
for plugin in PLUGINS:
|
||||
package_data["urh.plugins." + plugin] = ['*.ui', "*.txt"]
|
||||
|
||||
package_data["urh.dev.native.lib"] = ["*.pyx", "*.pxd"]
|
||||
|
||||
if IS_RELEASE and sys.platform == "win32":
|
||||
package_data["urh.dev.native.lib.shared"] = ["*.dll", "*.txt"]
|
||||
|
||||
return package_data
|
||||
|
||||
|
||||
def get_extensions():
|
||||
filenames = [os.path.splitext(f)[0] for f in os.listdir("src/urh/cythonext") if f.endswith(".pyx")]
|
||||
extensions = [Extension("urh.cythonext." + f, ["src/urh/cythonext/" + f + ".pyx"],
|
||||
extra_compile_args=[OPEN_MP_FLAG],
|
||||
extra_link_args=[OPEN_MP_FLAG],
|
||||
language="c++") for f in filenames]
|
||||
|
||||
ExtensionHelper.USE_RELATIVE_PATHS = True
|
||||
device_extensions, device_extras = ExtensionHelper.get_device_extensions_and_extras()
|
||||
extensions += device_extensions
|
||||
|
||||
if NO_NUMPY_WARNINGS_FLAG:
|
||||
for extension in extensions:
|
||||
extension.extra_compile_args.append(NO_NUMPY_WARNINGS_FLAG)
|
||||
|
||||
extensions = cythonize(extensions, compiler_directives=COMPILER_DIRECTIVES, compile_time_env=device_extras)
|
||||
return extensions
|
||||
|
||||
|
||||
def read_long_description():
|
||||
try:
|
||||
with open("README.md") as f:
|
||||
text = f.read()
|
||||
return text
|
||||
except:
|
||||
return ""
|
||||
|
||||
|
||||
install_requires = ["numpy", "psutil", "cython"]
|
||||
if IS_RELEASE:
|
||||
install_requires.append("pyqt5")
|
||||
else:
|
||||
try:
|
||||
import PyQt5
|
||||
except ImportError:
|
||||
install_requires.append("pyqt5")
|
||||
|
||||
if sys.version_info < (3, 4):
|
||||
install_requires.append('enum34')
|
||||
|
||||
setup(
|
||||
name="urh",
|
||||
version=version.VERSION,
|
||||
description="Universal Radio Hacker: investigate wireless protocols like a boss",
|
||||
long_description=read_long_description(),
|
||||
long_description_content_type="text/markdown",
|
||||
author="Johannes Pohl",
|
||||
author_email="Johannes.Pohl90@gmail.com",
|
||||
package_dir={"": "src"},
|
||||
package_data=get_package_data(),
|
||||
url="https://github.com/jopohl/urh",
|
||||
license="GNU General Public License (GPL)",
|
||||
download_url="https://github.com/jopohl/urh/tarball/v" + str(version.VERSION),
|
||||
install_requires=install_requires,
|
||||
setup_requires=['numpy'],
|
||||
packages=get_packages(),
|
||||
ext_modules=get_extensions(),
|
||||
cmdclass={'build_ext': build_ext},
|
||||
zip_safe=False,
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'urh = urh.main:main',
|
||||
'urh_cli = urh.cli.urh_cli:main',
|
||||
]}
|
||||
)
|
0
Software/Universal Radio Hacker/src/urh/__init__.py
Normal file
@ -0,0 +1,434 @@
|
||||
import fractions
|
||||
import itertools
|
||||
import math
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
import numpy as np
|
||||
|
||||
from urh.ainterpretation import Wavelet
|
||||
from urh.cythonext import auto_interpretation as c_auto_interpretation
|
||||
from urh.cythonext import signal_functions
|
||||
from urh.cythonext import util
|
||||
from urh.signalprocessing.IQArray import IQArray
|
||||
|
||||
|
||||
def max_without_outliers(data: np.ndarray, z=3):
|
||||
if len(data) == 0:
|
||||
return None
|
||||
|
||||
return np.max(data[abs(data - np.mean(data)) <= z * np.std(data)])
|
||||
|
||||
|
||||
def min_without_outliers(data: np.ndarray, z=2):
|
||||
if len(data) == 0:
|
||||
return None
|
||||
|
||||
return np.min(data[abs(data - np.mean(data)) <= z * np.std(data)])
|
||||
|
||||
def get_most_frequent_value(values: list):
|
||||
"""
|
||||
Return the most frequent value in list.
|
||||
If there is no unique one, return the maximum of the most frequent values
|
||||
|
||||
:param values:
|
||||
:return:
|
||||
"""
|
||||
if len(values) == 0:
|
||||
return None
|
||||
|
||||
most_common = Counter(values).most_common()
|
||||
result, max_count = most_common[0]
|
||||
for value, count in most_common:
|
||||
if count < max_count:
|
||||
return result
|
||||
else:
|
||||
result = value
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def most_common(values: list):
|
||||
"""
|
||||
Return the most common value in a list. In case of ties, return the value that appears first in list
|
||||
:param values:
|
||||
:return:
|
||||
"""
|
||||
counter = Counter(values)
|
||||
return max(values, key=counter.get)
|
||||
|
||||
|
||||
def detect_noise_level(magnitudes):
|
||||
if len(magnitudes) <= 3:
|
||||
return 0
|
||||
|
||||
# 1% for best accuracy and performance for large signals
|
||||
chunksize_percent = 1
|
||||
chunksize = max(1, int(len(magnitudes) * chunksize_percent / 100))
|
||||
|
||||
chunks = [magnitudes[i - chunksize:i] for i in range(len(magnitudes), 0, -chunksize) if i - chunksize >= 0]
|
||||
|
||||
mean_values = np.fromiter((np.mean(chunk) for chunk in chunks), dtype=np.float32, count=len(chunks))
|
||||
minimum, maximum = util.minmax(mean_values)
|
||||
if maximum == 0 or minimum / maximum > 0.9:
|
||||
# Mean values are very close to each other, so there is probably no noise in the signal
|
||||
return 0
|
||||
|
||||
# Get all indices for values which are in range of 10% of minimum mean value
|
||||
indices = np.nonzero(mean_values <= 1.1 * np.min(mean_values))[0]
|
||||
|
||||
try:
|
||||
result = np.max([np.max(chunks[i]) for i in indices if len(chunks[i]) > 0])
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
# Round up to fourth digit
|
||||
return math.ceil(result * 10000) / 10000
|
||||
|
||||
|
||||
def segment_messages_from_magnitudes(magnitudes: np.ndarray, noise_threshold: float):
|
||||
"""
|
||||
Get the list of start, end indices of messages
|
||||
|
||||
:param magnitudes: Magnitudes of samples
|
||||
:param noise_threshold: Threshold for noise
|
||||
:return:
|
||||
"""
|
||||
return c_auto_interpretation.segment_messages_from_magnitudes(magnitudes, noise_threshold)
|
||||
|
||||
|
||||
def merge_message_segments_for_ook(segments: list):
|
||||
if len(segments) <= 1:
|
||||
return segments
|
||||
|
||||
result = []
|
||||
# Get a array of pauses for comparison
|
||||
pauses = np.fromiter(
|
||||
(segments[i + 1][0] - segments[i][1] for i in range(len(segments) - 1)),
|
||||
count=len(segments) - 1,
|
||||
dtype=np.uint64
|
||||
)
|
||||
|
||||
pulses = np.fromiter(
|
||||
(segments[i][1] - segments[i][0] for i in range(len(segments))),
|
||||
count=len(segments),
|
||||
dtype=np.uint64
|
||||
)
|
||||
|
||||
# Find relatively large pauses, these mark new messages
|
||||
min_pulse_length = min_without_outliers(pulses, z=1)
|
||||
large_pause_indices = np.nonzero(pauses >= 8 * min_pulse_length)[0]
|
||||
|
||||
# Merge Pulse Lengths between long pauses
|
||||
for i in range(0, len(large_pause_indices) + 1):
|
||||
if i == 0:
|
||||
start, end = 0, large_pause_indices[i] + 1 if len(large_pause_indices) >= 1 else len(segments)
|
||||
elif i == len(large_pause_indices):
|
||||
start, end = large_pause_indices[i - 1] + 1, len(segments)
|
||||
else:
|
||||
start, end = large_pause_indices[i - 1] + 1, large_pause_indices[i] + 1
|
||||
|
||||
msg_begin = segments[start][0]
|
||||
msg_length = sum(segments[j][1] - segments[j][0] for j in range(start, end))
|
||||
msg_length += sum(segments[j][0] - segments[j - 1][1] for j in range(start + 1, end))
|
||||
|
||||
result.append((msg_begin, msg_begin + msg_length))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def detect_modulation(data: np.ndarray, wavelet_scale=4, median_filter_order=11) -> str:
|
||||
n_data = len(data)
|
||||
data = data[np.abs(data) > 0]
|
||||
if len(data) == 0:
|
||||
return None
|
||||
|
||||
if n_data - len(data) > 3:
|
||||
return "OOK"
|
||||
|
||||
data = data / np.abs(np.max(data))
|
||||
mag_wavlt = np.abs(Wavelet.cwt_haar(data, scale=wavelet_scale))
|
||||
if len(mag_wavlt) == 0:
|
||||
return None
|
||||
|
||||
norm_mag_wavlt = np.abs(Wavelet.cwt_haar(data / np.abs(data), scale=wavelet_scale))
|
||||
|
||||
var_mag = np.var(mag_wavlt)
|
||||
var_norm_mag = np.var(norm_mag_wavlt)
|
||||
|
||||
var_filtered_mag = np.var(c_auto_interpretation.median_filter(mag_wavlt, k=median_filter_order))
|
||||
var_filtered_norm_mag = np.var(c_auto_interpretation.median_filter(norm_mag_wavlt, k=median_filter_order))
|
||||
|
||||
if all(v < 0.15 for v in (var_mag, var_norm_mag, var_filtered_mag, var_filtered_norm_mag)):
|
||||
return "OOK"
|
||||
|
||||
if var_mag > 1.5 * var_norm_mag:
|
||||
# ASK or QAM
|
||||
# todo: consider qam, compare filtered mag and filtered norm mag
|
||||
return "ASK"
|
||||
else:
|
||||
# FSK or PSK
|
||||
if var_mag > 10 * var_filtered_mag:
|
||||
return "PSK"
|
||||
else:
|
||||
# Now we either have a FSK signal or we a have OOK single pulse
|
||||
# If we have an FSK, there should be at least two peaks in FFT
|
||||
fft = np.fft.fft(data[0:2 ** int(np.log2(len(data)))])
|
||||
fft = np.abs(np.fft.fftshift(fft))
|
||||
ten_greatest_indices = np.argsort(fft)[::-1][0:10]
|
||||
greatest_index = ten_greatest_indices[0]
|
||||
min_distance = 10
|
||||
min_freq = 100 # 100 seems to be magnitude of noise frequency
|
||||
|
||||
if any(abs(i - greatest_index) >= min_distance and fft[i] >= min_freq for i in ten_greatest_indices):
|
||||
return "FSK"
|
||||
else:
|
||||
return "OOK"
|
||||
|
||||
|
||||
def detect_modulation_for_messages(signal: IQArray, message_indices: list) -> str:
|
||||
max_messages = 100
|
||||
|
||||
modulations_for_messages = []
|
||||
complex = signal.as_complex64()
|
||||
for start, end in message_indices[0:max_messages]:
|
||||
mod = detect_modulation(complex[start:end])
|
||||
if mod is not None:
|
||||
modulations_for_messages.append(mod)
|
||||
|
||||
if len(modulations_for_messages) == 0:
|
||||
return None
|
||||
|
||||
return most_common(modulations_for_messages)
|
||||
|
||||
|
||||
def detect_center(rectangular_signal: np.ndarray, max_size=None):
|
||||
rect = rectangular_signal[rectangular_signal > -4] # do not consider noise
|
||||
|
||||
# Ignore the first and last 5% of samples,
|
||||
# because there tends to be an overshoot at start/end of rectangular signal
|
||||
rect = rect[int(0.05*len(rect)):int(0.95*len(rect))]
|
||||
|
||||
if max_size is not None and len(rect) > max_size:
|
||||
rect = rect[0:max_size]
|
||||
|
||||
hist_min, hist_max = util.minmax(rect)
|
||||
|
||||
# The step size of histogram is set to variance of the rectangular signal
|
||||
# If a signal has low variance we need to be more accurate at center detection
|
||||
hist_step = float(np.var(rect))
|
||||
|
||||
try:
|
||||
y, x = np.histogram(rect, bins=np.arange(hist_min, hist_max + hist_step, hist_step))
|
||||
except (ZeroDivisionError, ValueError):
|
||||
# For a segment with zero variance (constant line) it is not possible to find a center
|
||||
return None
|
||||
|
||||
num_values = 2
|
||||
most_common_levels = []
|
||||
|
||||
window_size = max(2, int(0.05*len(y)) + 1)
|
||||
|
||||
def get_elem(arr, index: int, default):
|
||||
if 0 <= index < len(arr):
|
||||
return arr[index]
|
||||
else:
|
||||
return default
|
||||
|
||||
for index in np.argsort(y)[::-1]:
|
||||
# check if we have a local maximum in histogram, if yes, append the value
|
||||
if all(y[index] > get_elem(y, index+i, 0) and
|
||||
y[index] > get_elem(y, index-i, 0)
|
||||
for i in range(1, window_size)):
|
||||
most_common_levels.append(x[index])
|
||||
|
||||
if len(most_common_levels) == num_values:
|
||||
break
|
||||
|
||||
if len(most_common_levels) == 0:
|
||||
return None
|
||||
|
||||
# todo if num values greater two return more centers
|
||||
return np.mean(most_common_levels)
|
||||
|
||||
|
||||
def estimate_tolerance_from_plateau_lengths(plateau_lengths, relative_max=0.05) -> int:
|
||||
if len(plateau_lengths) <= 1:
|
||||
return None
|
||||
|
||||
unique = np.unique(plateau_lengths)
|
||||
maximum = max_without_outliers(unique, z=2)
|
||||
|
||||
limit = relative_max * maximum
|
||||
# limit = np.mean(plateau_lengths) - 1 * np.std(plateau_lengths)
|
||||
if unique[0] > 1 and unique[0] >= limit:
|
||||
return 0
|
||||
|
||||
result = 0
|
||||
for value in unique:
|
||||
if value > 1 and value >= limit:
|
||||
break
|
||||
result = value
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def merge_plateau_lengths(plateau_lengths, tolerance=None) -> list:
|
||||
if tolerance is None:
|
||||
tolerance = estimate_tolerance_from_plateau_lengths(plateau_lengths)
|
||||
|
||||
if tolerance == 0 or tolerance is None:
|
||||
return plateau_lengths
|
||||
|
||||
return c_auto_interpretation.merge_plateaus(plateau_lengths, tolerance, max_count=10000)
|
||||
|
||||
|
||||
def round_plateau_lengths(plateau_lengths: list):
|
||||
"""
|
||||
Round plateau lengths to next divisible number of digit count e.g. 99 -> 100, 293 -> 300
|
||||
|
||||
:param plateau_lengths:
|
||||
:return:
|
||||
"""
|
||||
# round to n_digits of most common value
|
||||
digit_counts = [len(str(p)) for p in plateau_lengths]
|
||||
n_digits = min(3, int(np.percentile(digit_counts, 50)))
|
||||
f = 10 ** (n_digits - 1)
|
||||
|
||||
for i, plateau_len in enumerate(plateau_lengths):
|
||||
plateau_lengths[i] = int(round(plateau_len / f)) * f
|
||||
|
||||
|
||||
def get_tolerant_greatest_common_divisor(numbers):
|
||||
"""
|
||||
Get the greatest common divisor of the numbers in a tolerant manner:
|
||||
Calculate each gcd of each pair of numbers and return the most common one
|
||||
|
||||
"""
|
||||
gcd = math.gcd if sys.version_info >= (3, 5) else fractions.gcd
|
||||
|
||||
gcds = [gcd(x, y) for x, y in itertools.combinations(numbers, 2) if gcd(x, y) != 1]
|
||||
if len(gcds) == 0:
|
||||
return 1
|
||||
|
||||
return get_most_frequent_value(gcds)
|
||||
|
||||
|
||||
def get_bit_length_from_plateau_lengths(merged_plateau_lengths) -> int:
|
||||
if len(merged_plateau_lengths) == 0:
|
||||
return 0
|
||||
|
||||
if len(merged_plateau_lengths) == 1:
|
||||
return int(merged_plateau_lengths[0])
|
||||
|
||||
round_plateau_lengths(merged_plateau_lengths)
|
||||
histogram = c_auto_interpretation.get_threshold_divisor_histogram(merged_plateau_lengths)
|
||||
|
||||
if len(histogram) == 0:
|
||||
return 0
|
||||
else:
|
||||
# Can't return simply argmax, since this could be a multiple of result (e.g. 2 1s are transmitted often)
|
||||
sorted_indices = np.argsort(histogram)[::-1]
|
||||
max_count = histogram[sorted_indices[0]]
|
||||
result = sorted_indices[0]
|
||||
|
||||
for i in range(1, len(sorted_indices)):
|
||||
if histogram[sorted_indices[i]] < 0.25 * max_count:
|
||||
break
|
||||
if sorted_indices[i] <= 0.5 * result:
|
||||
result = sorted_indices[i]
|
||||
|
||||
return int(result)
|
||||
|
||||
|
||||
def estimate(iq_array: IQArray, noise: float = None, modulation: str = None) -> dict:
|
||||
if isinstance(iq_array, np.ndarray):
|
||||
iq_array = IQArray(iq_array)
|
||||
|
||||
magnitudes = iq_array.magnitudes
|
||||
# find noise threshold
|
||||
noise = detect_noise_level(magnitudes) if noise is None else noise
|
||||
|
||||
# segment messages
|
||||
message_indices = segment_messages_from_magnitudes(magnitudes, noise_threshold=noise)
|
||||
|
||||
# detect modulation
|
||||
modulation = detect_modulation_for_messages(iq_array, message_indices) if modulation is None else modulation
|
||||
if modulation is None:
|
||||
return None
|
||||
|
||||
if modulation == "OOK":
|
||||
message_indices = merge_message_segments_for_ook(message_indices)
|
||||
|
||||
if modulation == "OOK" or modulation == "ASK":
|
||||
data = signal_functions.afp_demod(iq_array.data, noise, "ASK", 2)
|
||||
elif modulation == "FSK":
|
||||
data = signal_functions.afp_demod(iq_array.data, noise, "FSK", 2)
|
||||
elif modulation == "PSK":
|
||||
data = signal_functions.afp_demod(iq_array.data, noise, "PSK", 2)
|
||||
else:
|
||||
raise ValueError("Unsupported Modulation")
|
||||
|
||||
centers = []
|
||||
bit_lengths = []
|
||||
tolerances = []
|
||||
for start, end in message_indices:
|
||||
msg_rect_data = data[start:end]
|
||||
|
||||
center = detect_center(msg_rect_data)
|
||||
if center is None:
|
||||
continue
|
||||
|
||||
plateau_lengths = c_auto_interpretation.get_plateau_lengths(msg_rect_data, center, percentage=25)
|
||||
tolerance = estimate_tolerance_from_plateau_lengths(plateau_lengths)
|
||||
if tolerance is None:
|
||||
tolerance = 0
|
||||
else:
|
||||
tolerances.append(tolerance)
|
||||
|
||||
merged_lengths = merge_plateau_lengths(plateau_lengths, tolerance=tolerance)
|
||||
if len(merged_lengths) < 2:
|
||||
continue
|
||||
|
||||
bit_length = get_bit_length_from_plateau_lengths(merged_lengths)
|
||||
|
||||
min_bit_length = tolerance + 1
|
||||
|
||||
if bit_length > min_bit_length:
|
||||
# only add to score if found bit length surpasses minimum bit length
|
||||
centers.append(center)
|
||||
bit_lengths.append(bit_length)
|
||||
|
||||
# Since we cannot have different centers per message (yet) we need to combine them to return a common center
|
||||
if modulation == "OOK" or modulation == "ASK":
|
||||
# for ask modulations the center tends to be the minimum of all found centers
|
||||
center = min_without_outliers(np.array(centers), z=2)
|
||||
if center is None:
|
||||
# did not find any centers at all so we cannot return a valid estimation
|
||||
return None
|
||||
elif len(centers) > 0:
|
||||
# for other modulations it is a better strategy to take the mean of found centers
|
||||
center = np.mean(centers)
|
||||
else:
|
||||
# did not find any centers at all so we cannot return a valid estimation
|
||||
return None
|
||||
|
||||
bit_length = get_most_frequent_value(bit_lengths)
|
||||
if bit_length is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
tolerance = np.percentile(tolerances, 50)
|
||||
except IndexError:
|
||||
# no tolerances found, default to 5% of bit length
|
||||
tolerance = max(1, int(0.05 * bit_length))
|
||||
|
||||
result = {
|
||||
"modulation_type": "ASK" if modulation == "OOK" else modulation,
|
||||
"bit_length": bit_length,
|
||||
"center": center,
|
||||
"tolerance": int(tolerance),
|
||||
"noise": noise
|
||||
}
|
||||
|
||||
return result
|
@ -0,0 +1,134 @@
|
||||
import numpy as np
|
||||
|
||||
from urh.cythonext import auto_interpretation as cy_auto_interpretation
|
||||
from urh.signalprocessing.Modulator import Modulator
|
||||
|
||||
|
||||
def normalized_haar_wavelet(omega, scale):
|
||||
omega_cpy = omega[:] / scale
|
||||
omega_cpy[0] = 1.0 # first element always zero, so prevent division by zero later
|
||||
|
||||
result = (1j * np.square(-1 + np.exp(0.5j * omega))) / omega_cpy
|
||||
return result
|
||||
|
||||
|
||||
def cwt_haar(x: np.ndarray, scale=10):
|
||||
"""
|
||||
continuous haar wavelet transform based on the paper
|
||||
"A practical guide to wavelet analysis" by Christopher Torrence and Gilbert P Compo
|
||||
|
||||
"""
|
||||
next_power_two = 2 ** int(np.log2(len(x)))
|
||||
|
||||
x = x[0:next_power_two]
|
||||
num_data = len(x)
|
||||
|
||||
# get FFT of x (eq. (3) in paper)
|
||||
x_hat = np.fft.fft(x)
|
||||
|
||||
# Get omega (eq. (5) in paper)
|
||||
f = (2.0 * np.pi / num_data)
|
||||
omega = f * np.concatenate((np.arange(0, num_data // 2), np.arange(num_data // 2, num_data) * -1))
|
||||
|
||||
# get psi hat (eq. (6) in paper)
|
||||
psi_hat = np.sqrt(2.0 * np.pi * scale) * normalized_haar_wavelet(scale * omega, scale)
|
||||
|
||||
# get W (eq. (4) in paper)
|
||||
W = np.fft.ifft(x_hat * psi_hat)
|
||||
|
||||
return W[2 * scale:-2 * scale]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
# data = np.fromfile("/home/joe/GIT/urh/tests/data/fsk.complex", dtype=np.complex64)[5:15000]
|
||||
# data = np.fromfile("/home/joe/GIT/urh/tests/data/ask.complex", dtype=np.complex64)[462:754]
|
||||
# data = np.fromfile("/home/joe/GIT/urh/tests/data/enocean.complex", dtype=np.complex64)[9724:10228]
|
||||
data = np.fromfile("/home/joe/GIT/publications/ainterpretation/experiments/signals/esaver_test4on.complex",
|
||||
dtype=np.complex64)[86452:115541]
|
||||
|
||||
# data = np.fromfile("/home/joe/GIT/urh/tests/data/action_ook.complex", dtype=np.complex64)[3780:4300]
|
||||
|
||||
# data = np.fromfile("/home/joe/GIT/urh/tests/data/ask50.complex", dtype=np.complex64)
|
||||
# Wavelet transform the data
|
||||
# data = np.fromfile("/home/joe/GIT/urh/tests/data/ask.complex", dtype=np.complex64)[0:2 ** 13]
|
||||
|
||||
# data = np.fromfile("/tmp/generated.complex", dtype=np.complex64)
|
||||
|
||||
# data = np.fromfile("/tmp/psk.complex", dtype=np.complex64)
|
||||
# data = np.fromfile("/home/joe/GIT/urh/tests/data/psk_generated.complex", dtype=np.complex64)[0:8000]
|
||||
modulator = Modulator("")
|
||||
modulator.modulation_type = "PSK"
|
||||
modulator.parameters[0] = 0
|
||||
modulator.parameters[1] = 180
|
||||
modulator.carrier_freq_hz = 5e3
|
||||
modulator.sample_rate = 200e3
|
||||
# data = modulator.modulate("1010", pause=0)
|
||||
|
||||
# data = np.fromfile("/tmp/ask25.complex", dtype=np.complex64)
|
||||
# data = np.fromfile("/tmp/ask1080.complex", dtype=np.complex64)
|
||||
|
||||
scale = 4
|
||||
median_filter_order = 11
|
||||
data = data[np.abs(data) > 0]
|
||||
|
||||
# Normalize with max of data to prevent increasing variance for signals with lower amplitude
|
||||
data = data / np.abs(np.max(data))
|
||||
|
||||
mag_wvlt = np.abs(cwt_haar(data, scale=scale))
|
||||
|
||||
norm_mag_wvlt = np.abs(cwt_haar(data / np.abs(data), scale=scale))
|
||||
|
||||
median_filter = cy_auto_interpretation.median_filter
|
||||
|
||||
filtered_mag_wvlt = median_filter(mag_wvlt, k=median_filter_order)
|
||||
|
||||
filtered_mag_norm_wvlt = median_filter(norm_mag_wvlt, k=median_filter_order)
|
||||
|
||||
plt.subplot(421)
|
||||
plt.title("Original data")
|
||||
plt.plot(data)
|
||||
|
||||
plt.subplot(422)
|
||||
plt.title("Amplitude normalized data")
|
||||
plt.plot(data / np.abs(data))
|
||||
|
||||
plt.subplot(423)
|
||||
plt.title("CWT ({0:.4f})".format(np.var(mag_wvlt)))
|
||||
plt.plot(mag_wvlt)
|
||||
|
||||
plt.subplot(424)
|
||||
plt.title("Filtered CWT ({0:.4f})".format(np.var(filtered_mag_wvlt)))
|
||||
plt.plot(filtered_mag_wvlt)
|
||||
|
||||
plt.subplot(425)
|
||||
plt.title("Norm CWT ({0:.4f})".format(np.var(norm_mag_wvlt)))
|
||||
plt.plot(norm_mag_wvlt)
|
||||
|
||||
plt.subplot(426)
|
||||
plt.title("Filtered Norm CWT ({0:.4f})".format(np.var(filtered_mag_norm_wvlt)))
|
||||
plt.plot(filtered_mag_norm_wvlt)
|
||||
|
||||
plt.subplot(427)
|
||||
plt.title("FFT magnitude")
|
||||
fft = np.fft.fft(data)
|
||||
fft = np.abs(fft)
|
||||
ten_greatest_indices = np.argsort(fft)[::-1][0:10]
|
||||
print(ten_greatest_indices)
|
||||
print(fft[ten_greatest_indices])
|
||||
plt.plot(np.fft.fftshift(fft))
|
||||
|
||||
plt.subplot(428)
|
||||
fft = np.fft.fftshift(np.fft.fft(data))
|
||||
fft[np.abs(fft) < 0.2 * np.max(np.abs(fft))] = 0
|
||||
fft_phase = np.angle(fft)
|
||||
ten_greatest_indices = np.argsort(np.abs(fft_phase))[::-1][0:10]
|
||||
print("FFT phases:")
|
||||
print(ten_greatest_indices)
|
||||
print(fft_phase[ten_greatest_indices])
|
||||
|
||||
plt.title("FFT phase ({:.2f})".format(np.var(fft_phase)))
|
||||
plt.plot(fft_phase)
|
||||
|
||||
plt.show()
|
65
Software/Universal Radio Hacker/src/urh/awre/AutoAssigner.py
Normal file
@ -0,0 +1,65 @@
|
||||
import numpy as np
|
||||
|
||||
from urh.cythonext import util
|
||||
from urh.signalprocessing.Message import Message
|
||||
|
||||
|
||||
def auto_assign_participants(messages, participants):
|
||||
"""
|
||||
|
||||
:type messages: list of Message
|
||||
:type participants: list of Participant
|
||||
:return:
|
||||
"""
|
||||
if len(participants) == 0:
|
||||
return
|
||||
|
||||
if len(participants) == 1:
|
||||
for message in messages: # type: Message
|
||||
message.participant = participants[0]
|
||||
return
|
||||
|
||||
# Try to assign participants based on SRC_ADDRESS label and participant address
|
||||
for msg in filter(lambda m: m.participant is None, messages):
|
||||
src_address = msg.get_src_address_from_data()
|
||||
if src_address:
|
||||
try:
|
||||
msg.participant = next(p for p in participants if p.address_hex == src_address)
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
# Assign remaining participants based on RSSI of messages
|
||||
rssis = np.array([msg.rssi for msg in messages], dtype=np.float32)
|
||||
min_rssi, max_rssi = util.minmax(rssis)
|
||||
center_spacing = (max_rssi - min_rssi) / (len(participants) - 1)
|
||||
centers = [min_rssi + i * center_spacing for i in range(0, len(participants))]
|
||||
rssi_assigned_centers = []
|
||||
|
||||
for rssi in rssis:
|
||||
center_index = np.argmin(np.abs(rssi - centers))
|
||||
rssi_assigned_centers.append(int(center_index))
|
||||
|
||||
participants.sort(key=lambda participant: participant.relative_rssi)
|
||||
for message, center_index in zip(messages, rssi_assigned_centers):
|
||||
if message.participant is None:
|
||||
message.participant = participants[center_index]
|
||||
|
||||
|
||||
def auto_assign_participant_addresses(messages, participants):
|
||||
"""
|
||||
|
||||
:type messages: list of Message
|
||||
:type participants: list of Participant
|
||||
:return:
|
||||
"""
|
||||
participants_without_address = [p for p in participants if not p.address_hex]
|
||||
|
||||
if len(participants_without_address) == 0:
|
||||
return
|
||||
|
||||
for msg in messages:
|
||||
if msg.participant in participants_without_address:
|
||||
src_address = msg.get_src_address_from_data()
|
||||
if src_address:
|
||||
participants_without_address.remove(msg.participant)
|
||||
msg.participant.address_hex = src_address
|
296
Software/Universal Radio Hacker/src/urh/awre/CommonRange.py
Normal file
@ -0,0 +1,296 @@
|
||||
import copy
|
||||
import itertools
|
||||
|
||||
import numpy as np
|
||||
|
||||
from urh.util import util
|
||||
from urh.util.GenericCRC import GenericCRC
|
||||
|
||||
|
||||
class CommonRange(object):
|
||||
def __init__(self, start, length, value: np.ndarray = None, score=0, field_type="Generic", message_indices=None,
|
||||
range_type="bit", byte_order="big"):
|
||||
"""
|
||||
|
||||
:param start:
|
||||
:param length:
|
||||
:param value: Value for this common range as string
|
||||
"""
|
||||
self.start = start
|
||||
self.length = length
|
||||
|
||||
self.__byte_order = byte_order
|
||||
self.sync_end = 0
|
||||
|
||||
if isinstance(value, str):
|
||||
value = np.array(list(map(lambda x: int(x, 16), value)), dtype=np.uint8)
|
||||
|
||||
self.values = [value] if value is not None else []
|
||||
self.score = score
|
||||
self.field_type = field_type # can also be length, address etc.
|
||||
|
||||
self.range_type = range_type.lower() # one of bit/hex/byte
|
||||
|
||||
self.message_indices = set() if message_indices is None else set(message_indices)
|
||||
"""
|
||||
Set of message indices, this range applies to
|
||||
"""
|
||||
|
||||
@property
|
||||
def end(self):
|
||||
return self.start + self.length - 1
|
||||
|
||||
@property
|
||||
def bit_start(self):
|
||||
return self.__convert_number(self.start) + self.sync_end
|
||||
|
||||
@property
|
||||
def bit_end(self):
|
||||
return self.__convert_number(self.start) + self.__convert_number(self.length) - 1 + self.sync_end
|
||||
|
||||
@property
|
||||
def length_in_bits(self):
|
||||
return self.bit_end - self.bit_start - 1
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
if len(self.values) == 0:
|
||||
return None
|
||||
elif len(self.values) == 1:
|
||||
return self.values[0]
|
||||
else:
|
||||
raise ValueError("This range has multiple values!")
|
||||
|
||||
@value.setter
|
||||
def value(self, val):
|
||||
if len(self.values) == 0:
|
||||
self.values = [val]
|
||||
elif len(self.values) == 1:
|
||||
self.values[0] = val
|
||||
else:
|
||||
raise ValueError("This range has multiple values!")
|
||||
|
||||
@property
|
||||
def byte_order(self):
|
||||
if self.byte_order_is_unknown:
|
||||
return "big"
|
||||
return self.__byte_order
|
||||
|
||||
@byte_order.setter
|
||||
def byte_order(self, val: str):
|
||||
self.__byte_order = val
|
||||
|
||||
@property
|
||||
def byte_order_is_unknown(self) -> bool:
|
||||
return self.__byte_order is None
|
||||
|
||||
def matches(self, start: int, value: np.ndarray):
|
||||
return self.start == start and \
|
||||
self.length == len(value) and \
|
||||
self.value.tobytes() == value.tobytes()
|
||||
|
||||
def __convert_number(self, n):
|
||||
if self.range_type == "bit":
|
||||
return n
|
||||
elif self.range_type == "hex":
|
||||
return n * 4
|
||||
elif self.range_type == "byte":
|
||||
return n * 8
|
||||
else:
|
||||
raise ValueError("Unknown range type {}".format(self.range_type))
|
||||
|
||||
def __repr__(self):
|
||||
result = "{} {}-{} ({} {})".format(self.field_type, self.bit_start,
|
||||
self.bit_end, self.length, self.range_type)
|
||||
|
||||
result += " Values: " + " ".join(map(util.convert_numbers_to_hex_string, self.values))
|
||||
if self.score is not None:
|
||||
result += " Score: " + str(self.score)
|
||||
result += " Message indices: {" + ",".join(map(str, sorted(self.message_indices))) + "}"
|
||||
return result
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, CommonRange):
|
||||
return False
|
||||
|
||||
return self.bit_start == other.bit_start and \
|
||||
self.bit_end == other.bit_end and \
|
||||
self.field_type == other.field_type
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.start, self.length, self.field_type))
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.bit_start < other.bit_start
|
||||
|
||||
def overlaps_with(self, other) -> bool:
|
||||
if not isinstance(other, CommonRange):
|
||||
raise ValueError("Need another bit range to compare")
|
||||
return any(i in range(self.bit_start, self.bit_end)
|
||||
for i in range(other.bit_start, other.bit_end))
|
||||
|
||||
def ensure_not_overlaps(self, start: int, end: int):
|
||||
"""
|
||||
|
||||
:param start:
|
||||
:param end:
|
||||
:rtype: list of CommonRange
|
||||
"""
|
||||
if end < self.start or start > self.end:
|
||||
# Other range is right or left of our range -> no overlapping
|
||||
return [copy.deepcopy(self)]
|
||||
|
||||
if start <= self.start < end < self.end:
|
||||
# overlaps on the left
|
||||
result = copy.deepcopy(self)
|
||||
result.length -= end - result.start
|
||||
result.start = end
|
||||
result.value = result.value[result.start-self.start:(result.start-self.start)+result.length]
|
||||
return [result]
|
||||
|
||||
if self.start < start <= self.end <= end:
|
||||
# overlaps on the right
|
||||
result = copy.deepcopy(self)
|
||||
result.length -= self.end + 1 - start
|
||||
result.value = result.value[:result.length]
|
||||
return [result]
|
||||
|
||||
if self.start < start and self.end > end:
|
||||
# overlaps in the middle
|
||||
left = copy.deepcopy(self)
|
||||
right = copy.deepcopy(self)
|
||||
|
||||
left.length -= (left.end + 1 - start)
|
||||
left.value = self.value[:left.length]
|
||||
|
||||
right.start = end + 1
|
||||
right.length = self.end - end
|
||||
right.value = self.value[right.start-self.start:(right.start-self.start)+right.length]
|
||||
return [left, right]
|
||||
|
||||
return []
|
||||
|
||||
|
||||
class ChecksumRange(CommonRange):
|
||||
def __init__(self, start, length, crc: GenericCRC, data_range_start, data_range_end, value: np.ndarray = None,
|
||||
score=0, field_type="Generic", message_indices=None, range_type="bit"):
|
||||
super().__init__(start, length, value, score, field_type, message_indices, range_type)
|
||||
self.data_range_start = data_range_start
|
||||
self.data_range_end = data_range_end
|
||||
self.crc = crc
|
||||
|
||||
@property
|
||||
def data_range_bit_start(self):
|
||||
return self.data_range_start + self.sync_end
|
||||
|
||||
@property
|
||||
def data_range_bit_end(self):
|
||||
return self.data_range_end + self.sync_end
|
||||
|
||||
def __eq__(self, other):
|
||||
return super().__eq__(other) \
|
||||
and self.data_range_start == other.data_range_start \
|
||||
and self.data_range_end == other.data_range_end \
|
||||
and self.crc == other.crc
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.start, self.length, self.data_range_start, self.data_range_end, self.crc))
|
||||
|
||||
def __repr__(self):
|
||||
return super().__repr__() + " \t" + \
|
||||
"{}".format(self.crc.caption) + \
|
||||
" Datarange: {}-{} ".format(self.data_range_start, self.data_range_end)
|
||||
|
||||
|
||||
class EmptyCommonRange(CommonRange):
|
||||
"""
|
||||
Empty Common Bit Range, to indicate, that no common Bit Range was found
|
||||
"""
|
||||
|
||||
def __init__(self, field_type="Generic"):
|
||||
super().__init__(0, 0, "")
|
||||
self.field_type = field_type
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, EmptyCommonRange) \
|
||||
and other.field_type == self.field_type
|
||||
|
||||
def __repr__(self):
|
||||
return "No " + self.field_type
|
||||
|
||||
def __hash__(self):
|
||||
return hash(super)
|
||||
|
||||
|
||||
class CommonRangeContainer(object):
|
||||
"""
|
||||
This is the raw equivalent of a Message Type:
|
||||
A container of common ranges
|
||||
"""
|
||||
|
||||
def __init__(self, ranges: list, message_indices: set = None):
|
||||
|
||||
assert isinstance(ranges, list)
|
||||
|
||||
self.__ranges = ranges # type: list[CommonRange]
|
||||
self.__ranges.sort()
|
||||
|
||||
if message_indices is None:
|
||||
self.update_message_indices()
|
||||
else:
|
||||
self.message_indices = message_indices
|
||||
|
||||
@property
|
||||
def ranges_overlap(self) -> bool:
|
||||
return self.has_overlapping_ranges(self.__ranges)
|
||||
|
||||
def update_message_indices(self):
|
||||
if len(self) == 0:
|
||||
self.message_indices = set()
|
||||
else:
|
||||
self.message_indices = set(self[0].message_indices)
|
||||
for i in range(1, len(self)):
|
||||
self.message_indices.intersection_update(self[i].message_indices)
|
||||
|
||||
def add_range(self, rng: CommonRange):
|
||||
self.__ranges.append(rng)
|
||||
self.__ranges.sort()
|
||||
|
||||
def add_ranges(self, ranges: list):
|
||||
self.__ranges.extend(ranges)
|
||||
self.__ranges.sort()
|
||||
|
||||
def has_same_ranges(self, ranges: list) -> bool:
|
||||
return self.__ranges == ranges
|
||||
|
||||
def has_same_ranges_as_container(self, container):
|
||||
if not isinstance(container, CommonRangeContainer):
|
||||
return False
|
||||
|
||||
return self.__ranges == container.__ranges
|
||||
|
||||
@staticmethod
|
||||
def has_overlapping_ranges(ranges: list) -> bool:
|
||||
for rng1, rng2 in itertools.combinations(ranges, 2):
|
||||
if rng1.overlaps_with(rng2):
|
||||
return True
|
||||
return False
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__ranges)
|
||||
|
||||
def __iter__(self):
|
||||
return self.__ranges.__iter__()
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.__ranges[item]
|
||||
|
||||
def __repr__(self):
|
||||
from pprint import pformat
|
||||
return pformat(self.__ranges)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, CommonRangeContainer):
|
||||
return False
|
||||
|
||||
return self.__ranges == other.__ranges and self.message_indices == other.message_indices
|
435
Software/Universal Radio Hacker/src/urh/awre/FormatFinder.py
Normal file
@ -0,0 +1,435 @@
|
||||
import copy
|
||||
import math
|
||||
from collections import defaultdict
|
||||
|
||||
import numpy as np
|
||||
|
||||
from urh.awre import AutoAssigner
|
||||
from urh.awre.CommonRange import CommonRange, EmptyCommonRange, CommonRangeContainer, ChecksumRange
|
||||
from urh.awre.Preprocessor import Preprocessor
|
||||
from urh.awre.engines.AddressEngine import AddressEngine
|
||||
from urh.awre.engines.ChecksumEngine import ChecksumEngine
|
||||
from urh.awre.engines.LengthEngine import LengthEngine
|
||||
from urh.awre.engines.SequenceNumberEngine import SequenceNumberEngine
|
||||
from urh.cythonext import awre_util
|
||||
from urh.signalprocessing.ChecksumLabel import ChecksumLabel
|
||||
from urh.signalprocessing.FieldType import FieldType
|
||||
from urh.signalprocessing.Message import Message
|
||||
from urh.signalprocessing.MessageType import MessageType
|
||||
from urh.signalprocessing.ProtocoLabel import ProtocolLabel
|
||||
from urh.util.WSPChecksum import WSPChecksum
|
||||
|
||||
|
||||
class FormatFinder(object):
|
||||
MIN_MESSAGES_PER_CLUSTER = 2
|
||||
|
||||
def __init__(self, messages, participants=None, shortest_field_length=None):
|
||||
"""
|
||||
|
||||
:type messages: list of Message
|
||||
:param participants:
|
||||
"""
|
||||
if participants is not None:
|
||||
AutoAssigner.auto_assign_participants(messages, participants)
|
||||
|
||||
existing_message_types_by_msg = {i: msg.message_type for i, msg in enumerate(messages)}
|
||||
self.existing_message_types = defaultdict(list)
|
||||
for i, message_type in existing_message_types_by_msg.items():
|
||||
self.existing_message_types[message_type].append(i)
|
||||
|
||||
preprocessor = Preprocessor(self.get_bitvectors_from_messages(messages), existing_message_types_by_msg)
|
||||
self.preamble_starts, self.preamble_lengths, sync_len = preprocessor.preprocess()
|
||||
self.sync_ends = self.preamble_starts + self.preamble_lengths + sync_len
|
||||
|
||||
n = shortest_field_length
|
||||
if n is None:
|
||||
# 0 = no sync found
|
||||
n = 8 if sync_len >= 8 else 4 if sync_len >= 4 else 1 if sync_len >= 1 else 0
|
||||
|
||||
for i, value in enumerate(self.sync_ends):
|
||||
# In doubt it is better to under estimate the sync end
|
||||
if n > 0:
|
||||
self.sync_ends[i] = n * max(int(math.floor((value - self.preamble_starts[i]) / n)), 1) + \
|
||||
self.preamble_starts[i]
|
||||
else:
|
||||
self.sync_ends[i] = self.preamble_starts[i]
|
||||
|
||||
if self.sync_ends[i] - self.preamble_starts[i] < self.preamble_lengths[i]:
|
||||
self.preamble_lengths[i] = self.sync_ends[i] - self.preamble_starts[i]
|
||||
|
||||
self.bitvectors = self.get_bitvectors_from_messages(messages, self.sync_ends)
|
||||
self.hexvectors = self.get_hexvectors(self.bitvectors)
|
||||
self.current_iteration = 0
|
||||
|
||||
participants = list(sorted(set(msg.participant for msg in messages if msg.participant is not None)))
|
||||
self.participant_indices = [participants.index(msg.participant) if msg.participant is not None else -1
|
||||
for msg in messages]
|
||||
self.known_participant_addresses = {
|
||||
participants.index(p): np.array([int(h, 16) for h in p.address_hex], dtype=np.uint8)
|
||||
for p in participants if p and p.address_hex
|
||||
}
|
||||
|
||||
@property
|
||||
def message_types(self):
|
||||
"""
|
||||
|
||||
:rtype: list of MessageType
|
||||
"""
|
||||
return sorted(self.existing_message_types.keys(), key=lambda x: x.name)
|
||||
|
||||
def perform_iteration_for_message_type(self, message_type: MessageType):
|
||||
"""
|
||||
Perform a field inference iteration for messages of the given message type
|
||||
This routine will return newly found fields as a set of Common Ranges
|
||||
|
||||
:param message_type:
|
||||
:rtype: set of CommonRange
|
||||
"""
|
||||
indices = self.existing_message_types[message_type]
|
||||
engines = []
|
||||
|
||||
# We can take an arbitrary sync end to correct the already labeled fields for this message type,
|
||||
# because if the existing labels would have different sync positions,
|
||||
# they would not belong to the same message type in the first place
|
||||
sync_end = self.sync_ends[indices[0]] if indices else 0
|
||||
already_labeled = [(lbl.start - sync_end, lbl.end - sync_end) for lbl in message_type if lbl.start >= sync_end]
|
||||
|
||||
if not message_type.get_first_label_with_type(FieldType.Function.LENGTH):
|
||||
engines.append(LengthEngine([self.bitvectors[i] for i in indices], already_labeled=already_labeled))
|
||||
|
||||
if not message_type.get_first_label_with_type(FieldType.Function.SRC_ADDRESS):
|
||||
engines.append(AddressEngine([self.hexvectors[i] for i in indices],
|
||||
[self.participant_indices[i] for i in indices],
|
||||
self.known_participant_addresses,
|
||||
already_labeled=already_labeled))
|
||||
elif not message_type.get_first_label_with_type(FieldType.Function.DST_ADDRESS):
|
||||
engines.append(AddressEngine([self.hexvectors[i] for i in indices],
|
||||
[self.participant_indices[i] for i in indices],
|
||||
self.known_participant_addresses,
|
||||
already_labeled=already_labeled,
|
||||
src_field_present=True))
|
||||
|
||||
if not message_type.get_first_label_with_type(FieldType.Function.SEQUENCE_NUMBER):
|
||||
engines.append(SequenceNumberEngine([self.bitvectors[i] for i in indices], already_labeled=already_labeled))
|
||||
if not message_type.get_first_label_with_type(FieldType.Function.CHECKSUM):
|
||||
# If checksum was not found in first iteration, it will also not be found in next one
|
||||
if self.current_iteration == 0:
|
||||
engines.append(ChecksumEngine([self.bitvectors[i] for i in indices], already_labeled=already_labeled))
|
||||
|
||||
result = set()
|
||||
for engine in engines:
|
||||
high_scored_ranges = engine.find() # type: list[CommonRange]
|
||||
high_scored_ranges = self.retransform_message_indices(high_scored_ranges, indices, self.sync_ends)
|
||||
merged_ranges = self.merge_common_ranges(high_scored_ranges)
|
||||
result.update(merged_ranges)
|
||||
return result
|
||||
|
||||
def perform_iteration(self) -> bool:
|
||||
new_field_found = False
|
||||
|
||||
for message_type in self.existing_message_types.copy():
|
||||
new_fields_for_message_type = self.perform_iteration_for_message_type(message_type)
|
||||
new_fields_for_message_type.update(
|
||||
self.get_preamble_and_sync(self.preamble_starts, self.preamble_lengths, self.sync_ends,
|
||||
message_type_indices=self.existing_message_types[message_type])
|
||||
)
|
||||
|
||||
self.remove_overlapping_fields(new_fields_for_message_type, message_type)
|
||||
containers = self.create_common_range_containers(new_fields_for_message_type)
|
||||
|
||||
# Store addresses of participants if we found a SRC address field
|
||||
participants_with_unknown_address = set(self.participant_indices) - set(self.known_participant_addresses)
|
||||
participants_with_unknown_address.discard(-1)
|
||||
|
||||
if participants_with_unknown_address:
|
||||
for container in containers:
|
||||
src_range = next((rng for rng in container if rng.field_type == "source address"), None)
|
||||
if src_range is None:
|
||||
continue
|
||||
for msg_index in src_range.message_indices:
|
||||
if len(participants_with_unknown_address) == 0:
|
||||
break
|
||||
p = self.participant_indices[msg_index]
|
||||
if p not in self.known_participant_addresses:
|
||||
hex_vector = self.hexvectors[msg_index]
|
||||
self.known_participant_addresses[p] = hex_vector[src_range.start:src_range.end + 1]
|
||||
participants_with_unknown_address.discard(p)
|
||||
|
||||
new_field_found |= len(containers) > 0
|
||||
|
||||
if len(containers) == 1:
|
||||
for rng in containers[0]:
|
||||
self.add_range_to_message_type(rng, message_type)
|
||||
elif len(containers) > 1:
|
||||
del self.existing_message_types[message_type]
|
||||
|
||||
for i, container in enumerate(containers):
|
||||
new_message_type = copy.deepcopy(message_type) # type: MessageType
|
||||
|
||||
if i > 0:
|
||||
new_message_type.name = "Message Type {}.{}".format(self.current_iteration+1, i)
|
||||
new_message_type.give_new_id()
|
||||
|
||||
for rng in container:
|
||||
self.add_range_to_message_type(rng, new_message_type)
|
||||
|
||||
self.existing_message_types[new_message_type].extend(sorted(container.message_indices))
|
||||
|
||||
return new_field_found
|
||||
|
||||
def run(self, max_iterations=10):
|
||||
self.current_iteration = 0
|
||||
while self.perform_iteration() and self.current_iteration < max_iterations:
|
||||
self.current_iteration += 1
|
||||
|
||||
if len(self.message_types) > 0:
|
||||
messages_without_message_type = set(range(len(self.bitvectors))) - set(
|
||||
i for l in self.existing_message_types.values() for i in l)
|
||||
|
||||
# add to default message type
|
||||
self.existing_message_types[self.message_types[0]].extend(list(messages_without_message_type))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def remove_overlapping_fields(common_ranges, message_type: MessageType):
|
||||
"""
|
||||
Remove all fields from a set of CommonRanges which overlap with fields of the existing message type
|
||||
|
||||
:type common_ranges: set of CommonRange
|
||||
:param message_type:
|
||||
:return:
|
||||
"""
|
||||
if len(message_type) == 0:
|
||||
return
|
||||
|
||||
for rng in common_ranges.copy():
|
||||
for lbl in message_type: # type: ProtocolLabel
|
||||
if any(i in range(rng.bit_start, rng.bit_end) for i in range(lbl.start, lbl.end)):
|
||||
common_ranges.discard(rng)
|
||||
break
|
||||
|
||||
@staticmethod
|
||||
def merge_common_ranges(common_ranges):
|
||||
"""
|
||||
Merge common ranges if possible
|
||||
|
||||
:type common_ranges: list of CommonRange
|
||||
:rtype: list of CommonRange
|
||||
"""
|
||||
merged_ranges = []
|
||||
for common_range in common_ranges:
|
||||
assert isinstance(common_range, CommonRange)
|
||||
try:
|
||||
same_range = next(rng for rng in merged_ranges
|
||||
if rng.bit_start == common_range.bit_start
|
||||
and rng.bit_end == common_range.bit_end
|
||||
and rng.field_type == common_range.field_type)
|
||||
same_range.values.extend(common_range.values)
|
||||
same_range.message_indices.update(common_range.message_indices)
|
||||
except StopIteration:
|
||||
merged_ranges.append(common_range)
|
||||
|
||||
return merged_ranges
|
||||
|
||||
@staticmethod
|
||||
def add_range_to_message_type(common_range: CommonRange, message_type: MessageType):
|
||||
field_type = FieldType.from_caption(common_range.field_type)
|
||||
label = message_type.add_protocol_label(name=common_range.field_type,
|
||||
start=common_range.bit_start, end=common_range.bit_end,
|
||||
auto_created=True,
|
||||
type=field_type
|
||||
)
|
||||
label.display_endianness = common_range.byte_order
|
||||
|
||||
if field_type.function == FieldType.Function.CHECKSUM:
|
||||
assert isinstance(label, ChecksumLabel)
|
||||
assert isinstance(common_range, ChecksumRange)
|
||||
label.data_ranges = [[common_range.data_range_bit_start, common_range.data_range_bit_end]]
|
||||
|
||||
if isinstance(common_range.crc, WSPChecksum):
|
||||
label.category = ChecksumLabel.Category.wsp
|
||||
else:
|
||||
label.checksum = copy.copy(common_range.crc)
|
||||
|
||||
@staticmethod
|
||||
def get_hexvectors(bitvectors: list):
|
||||
result = awre_util.get_hexvectors(bitvectors)
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def get_bitvectors_from_messages(messages: list, sync_ends: np.ndarray = None):
|
||||
if sync_ends is None:
|
||||
sync_ends = defaultdict(lambda: None)
|
||||
|
||||
return [np.array(msg.decoded_bits[sync_ends[i]:], dtype=np.uint8, order="C") for i, msg in enumerate(messages)]
|
||||
|
||||
@staticmethod
|
||||
def create_common_range_containers(label_set: set, num_messages: int = None):
|
||||
"""
|
||||
Create message types from set of labels.
|
||||
Handle overlapping conflicts and create multiple message types if needed
|
||||
|
||||
:param label_set:
|
||||
:param num_messages:
|
||||
:return:
|
||||
:rtype: list of CommonRangeContainer
|
||||
"""
|
||||
if num_messages is None:
|
||||
message_indices = sorted(set(i for rng in label_set for i in rng.message_indices))
|
||||
else:
|
||||
message_indices = range(num_messages)
|
||||
|
||||
result = []
|
||||
for i in message_indices:
|
||||
labels = sorted(set(rng for rng in label_set if i in rng.message_indices
|
||||
and not isinstance(rng, EmptyCommonRange)))
|
||||
|
||||
container = next((container for container in result if container.has_same_ranges(labels)), None)
|
||||
if container is None:
|
||||
result.append(CommonRangeContainer(labels, message_indices={i}))
|
||||
else:
|
||||
container.message_indices.add(i)
|
||||
|
||||
result = FormatFinder.handle_overlapping_conflict(result)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def handle_overlapping_conflict(containers):
|
||||
"""
|
||||
Handle overlapping conflicts for a list of CommonRangeContainers
|
||||
|
||||
:type containers: list of CommonRangeContainer
|
||||
:return:
|
||||
"""
|
||||
result = []
|
||||
for container in containers:
|
||||
if container.ranges_overlap:
|
||||
conflicted_handled = FormatFinder.__handle_container_overlapping_conflict(container)
|
||||
else:
|
||||
conflicted_handled = container
|
||||
|
||||
try:
|
||||
same_rng_container = next(c for c in result if c.has_same_ranges_as_container(conflicted_handled))
|
||||
same_rng_container.message_indices.update(conflicted_handled.message_indices)
|
||||
except StopIteration:
|
||||
result.append(conflicted_handled)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def __handle_container_overlapping_conflict(container: CommonRangeContainer):
|
||||
"""
|
||||
Handle overlapping conflict for a CommRangeContainer.
|
||||
We can assert that all labels in the container share the same message indices
|
||||
because we partitioned them in a step before.
|
||||
If two or more labels overlap we have three ways to resolve the conflict:
|
||||
|
||||
1. Choose the range with the highest score
|
||||
2. If multiple ranges overlap choose the ranges that maximize the overall (cumulated) score
|
||||
3. If the overlapping is very small i.e. only 1 or 2 bits we can adjust the start/end of the conflicting ranges
|
||||
|
||||
The ranges inside the container _must_ be sorted i.e. the range with lowest start must be at front
|
||||
|
||||
:param container:
|
||||
:return:
|
||||
"""
|
||||
partitions = [] # type: list[list[CommonRange]]
|
||||
# partition the container into overlapping partitions
|
||||
# results in something like [[A], [B,C], [D], [E,F,G]]] where B and C and E, F, G are overlapping
|
||||
for cur_rng in container:
|
||||
if len(partitions) == 0:
|
||||
partitions.append([cur_rng])
|
||||
continue
|
||||
|
||||
last_rng = partitions[-1][-1] # type: CommonRange
|
||||
if cur_rng.overlaps_with(last_rng):
|
||||
partitions[-1].append(cur_rng)
|
||||
else:
|
||||
partitions.append([cur_rng])
|
||||
|
||||
# Todo: Adjust start/end of conflicting ranges if overlapping is very small (i.e. 1 or 2 bits)
|
||||
|
||||
result = []
|
||||
# Go through these partitions and handle overlapping conflicts
|
||||
for partition in partitions:
|
||||
possible_solutions = []
|
||||
for i, rng in enumerate(partition):
|
||||
# Append every range to this solution that does not overlap with current rng
|
||||
solution = [rng] + [r for r in partition[i + 1:] if not rng.overlaps_with(r)]
|
||||
possible_solutions.append(solution)
|
||||
|
||||
# Take solution that maximizes score. In case of tie, choose solution with shorter total length.
|
||||
# if there is still a tie prefer solution that contains a length field as is is very likely to be correct
|
||||
# if nothing else helps break tie by names of field types to prevent randomness
|
||||
best_solution = max(possible_solutions,
|
||||
key=lambda sol: (sum(r.score for r in sol),
|
||||
-sum(r.length_in_bits for r in sol),
|
||||
"length" in {r.field_type for r in sol},
|
||||
"".join(r.field_type[0] for r in sol)))
|
||||
result.extend(best_solution)
|
||||
|
||||
return CommonRangeContainer(result, message_indices=container.message_indices)
|
||||
|
||||
@staticmethod
|
||||
def retransform_message_indices(common_ranges, message_type_indices: list, sync_ends) -> list:
|
||||
"""
|
||||
Retransform the found message indices of an engine to the original index space
|
||||
based on the message indices of the message type.
|
||||
|
||||
Furthermore, set the sync_end of the common ranges so bit_start and bit_end
|
||||
match the position in the original space
|
||||
|
||||
:type common_ranges: list of CommonRange
|
||||
:param message_type_indices: Messages belonging to the message type the engine ran for
|
||||
:type sync_ends: np.ndarray
|
||||
:return:
|
||||
"""
|
||||
result = []
|
||||
for common_range in common_ranges:
|
||||
# Retransform message indices into original space
|
||||
message_indices = np.fromiter((message_type_indices[i] for i in common_range.message_indices),
|
||||
dtype=int, count=len(common_range.message_indices))
|
||||
|
||||
# If we have different sync_ends we need to create a new common range for each different sync_length
|
||||
matching_sync_ends = sync_ends[message_indices]
|
||||
for sync_end in np.unique(matching_sync_ends):
|
||||
rng = copy.deepcopy(common_range)
|
||||
rng.sync_end = sync_end
|
||||
rng.message_indices = set(message_indices[np.nonzero(matching_sync_ends == sync_end)])
|
||||
result.append(rng)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def get_preamble_and_sync(preamble_starts, preamble_lengths, sync_ends, message_type_indices):
|
||||
"""
|
||||
Get preamble and sync common ranges based on the data
|
||||
|
||||
:type preamble_starts: np.ndarray
|
||||
:type preamble_lengths: np.ndarray
|
||||
:type sync_ends: np.ndarray
|
||||
:type message_type_indices: list
|
||||
:rtype: set of CommonRange
|
||||
"""
|
||||
assert len(preamble_starts) == len(preamble_lengths) == len(sync_ends)
|
||||
|
||||
result = set() # type: set[CommonRange]
|
||||
for i in message_type_indices:
|
||||
preamble = CommonRange(preamble_starts[i], preamble_lengths[i], field_type="preamble", message_indices={i})
|
||||
existing_preamble = next((rng for rng in result if preamble == rng), None)
|
||||
if existing_preamble is not None:
|
||||
existing_preamble.message_indices.add(i)
|
||||
elif preamble_lengths[i] > 0:
|
||||
result.add(preamble)
|
||||
|
||||
preamble_end = preamble_starts[i] + preamble_lengths[i]
|
||||
sync_end = sync_ends[i]
|
||||
sync = CommonRange(preamble_end, sync_end - preamble_end, field_type="synchronization", message_indices={i})
|
||||
existing_sync = next((rng for rng in result if sync == rng), None)
|
||||
if existing_sync is not None:
|
||||
existing_sync.message_indices.add(i)
|
||||
elif sync_end - preamble_end > 0:
|
||||
result.add(sync)
|
||||
|
||||
return result
|
116
Software/Universal Radio Hacker/src/urh/awre/Histogram.py
Normal file
@ -0,0 +1,116 @@
|
||||
from collections import defaultdict
|
||||
|
||||
import numpy as np
|
||||
|
||||
from urh.awre.CommonRange import CommonRange
|
||||
from urh.cythonext import awre_util
|
||||
|
||||
|
||||
class Histogram(object):
|
||||
"""
|
||||
Create a histogram based on the equalness of vectors
|
||||
"""
|
||||
|
||||
def __init__(self, vectors, indices=None, normalize=True, debug=False):
|
||||
"""
|
||||
|
||||
:type vectors: list of np.ndarray
|
||||
:param indices: Indices of vectors for which the Histogram shall be created.
|
||||
This is useful for clustering.
|
||||
If None Histogram will be created over all bitvectors
|
||||
:type: list of int
|
||||
:param normalize:
|
||||
"""
|
||||
self.__vectors = vectors # type: list[np.ndarray]
|
||||
self.__active_indices = list(range(len(vectors))) if indices is None else indices
|
||||
|
||||
self.normalize = normalize
|
||||
self.data = self.__create_histogram()
|
||||
|
||||
def __create_histogram(self):
|
||||
return awre_util.create_difference_histogram(self.__vectors, self.__active_indices)
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.data.tolist())
|
||||
|
||||
def find_common_ranges(self, alpha=0.95, range_type="bit"):
|
||||
"""
|
||||
Find all common ranges where at least alpha percent of numbers are equal
|
||||
|
||||
:param range_type: on of bit/hex/byte
|
||||
:param alpha:
|
||||
:return:
|
||||
"""
|
||||
data_indices = np.argwhere(self.data >= alpha).flatten()
|
||||
|
||||
if len(data_indices) < 2:
|
||||
return []
|
||||
|
||||
result = []
|
||||
start, length = None, 0
|
||||
for i in range(1, len(data_indices)):
|
||||
if start is None:
|
||||
start = data_indices[i - 1]
|
||||
length = 1
|
||||
|
||||
if data_indices[i] - data_indices[i - 1] == 1:
|
||||
length += 1
|
||||
else:
|
||||
if length >= 2:
|
||||
value = self.__get_value_for_common_range(start, length)
|
||||
result.append(CommonRange(start, length, value, message_indices=set(self.__active_indices),
|
||||
range_type=range_type))
|
||||
|
||||
start, length = None, 0
|
||||
|
||||
if i == len(data_indices) - 1 and length >= 2:
|
||||
value = self.__get_value_for_common_range(start, length)
|
||||
result.append(CommonRange(start, length, value, message_indices=set(self.__active_indices),
|
||||
range_type=range_type))
|
||||
|
||||
return result
|
||||
|
||||
def __get_value_for_common_range(self, start: int, length: int):
|
||||
"""
|
||||
Get the value for a range of common numbers. This is the value that appears most.
|
||||
|
||||
:param start: Start of the common bit range
|
||||
:param length: Length of the common bit range
|
||||
:return:
|
||||
"""
|
||||
values = defaultdict(list)
|
||||
for i in self.__active_indices:
|
||||
vector = self.__vectors[i]
|
||||
values[vector[start:start + length].tostring()].append(i)
|
||||
value = max(values, key=lambda x: len(x))
|
||||
indices = values[value]
|
||||
return self.__vectors[indices[0]][start:start + length]
|
||||
|
||||
def __vector_to_string(self, data_vector) -> str:
|
||||
lut = {i: "{0:x}".format(i) for i in range(16)}
|
||||
return "".join(lut[x] if x in lut else " {} ".format(x) for x in data_vector)
|
||||
|
||||
def plot(self):
|
||||
import matplotlib.pyplot as plt
|
||||
self.subplot_on(plt)
|
||||
plt.show()
|
||||
|
||||
def subplot_on(self, plt):
|
||||
plt.grid()
|
||||
plt.plot(self.data)
|
||||
plt.xticks(np.arange(4, len(self.data), 4))
|
||||
plt.xlabel("Bit position")
|
||||
if self.normalize:
|
||||
plt.ylabel("Number common bits (normalized)")
|
||||
else:
|
||||
plt.ylabel("Number common bits")
|
||||
plt.ylim(ymin=0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
bv1 = np.array([1, 0, 1, 0, 1, 1, 1, 1], dtype=np.int8)
|
||||
bv2 = np.array([1, 0, 1, 0, 1, 0, 0, 0], dtype=np.int8)
|
||||
bv3 = np.array([1, 0, 1, 0, 1, 1, 1, 1], dtype=np.int8)
|
||||
bv4 = np.array([1, 0, 1, 0, 0, 0, 0, 0], dtype=np.int8)
|
||||
h = Histogram([bv1, bv2, bv3, bv4])
|
||||
h.plot()
|
@ -0,0 +1,55 @@
|
||||
from urh.signalprocessing.ChecksumLabel import ChecksumLabel
|
||||
|
||||
from urh.signalprocessing.FieldType import FieldType
|
||||
from urh.signalprocessing.MessageType import MessageType
|
||||
from urh.signalprocessing.ProtocoLabel import ProtocolLabel
|
||||
|
||||
|
||||
class MessageTypeBuilder(object):
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
self.message_type = MessageType(name)
|
||||
|
||||
def add_label(self, label_type: FieldType.Function, length: int, name: str=None):
|
||||
try:
|
||||
start = self.message_type[-1].end
|
||||
color_index = self.message_type[-1].color_index + 1
|
||||
except IndexError:
|
||||
start, color_index = 0, 0
|
||||
|
||||
if name is None:
|
||||
name = label_type.value
|
||||
|
||||
lbl = ProtocolLabel(name, start, start+length-1, color_index, field_type=FieldType(label_type.name, label_type))
|
||||
self.message_type.append(lbl)
|
||||
|
||||
def add_checksum_label(self, length, checksum, data_start=None, data_end=None, name: str=None):
|
||||
label_type = FieldType.Function.CHECKSUM
|
||||
try:
|
||||
start = self.message_type[-1].end
|
||||
color_index = self.message_type[-1].color_index + 1
|
||||
except IndexError:
|
||||
start, color_index = 0, 0
|
||||
|
||||
if name is None:
|
||||
name = label_type.value
|
||||
|
||||
if data_start is None:
|
||||
# End of sync or preamble
|
||||
sync_label = self.message_type.get_first_label_with_type(FieldType.Function.SYNC)
|
||||
if sync_label:
|
||||
data_start = sync_label.end
|
||||
else:
|
||||
preamble_label = self.message_type.get_first_label_with_type(FieldType.Function.PREAMBLE)
|
||||
if preamble_label:
|
||||
data_start = preamble_label.end
|
||||
else:
|
||||
data_start = 0
|
||||
|
||||
if data_end is None:
|
||||
data_end = start
|
||||
|
||||
lbl = ChecksumLabel(name, start, start+length-1, color_index, field_type=FieldType(label_type.name, label_type))
|
||||
lbl.data_ranges = [(data_start, data_end)]
|
||||
lbl.checksum = checksum
|
||||
self.message_type.append(lbl)
|
271
Software/Universal Radio Hacker/src/urh/awre/Preprocessor.py
Normal file
@ -0,0 +1,271 @@
|
||||
import itertools
|
||||
import math
|
||||
import os
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
import numpy as np
|
||||
|
||||
from urh.cythonext import awre_util
|
||||
from urh.signalprocessing.FieldType import FieldType
|
||||
|
||||
|
||||
class Preprocessor(object):
|
||||
"""
|
||||
This class preprocesses the messages in the following ways
|
||||
1) Identify preamble / length of preamble
|
||||
2) Identify sync word(s)
|
||||
3) Align all given messages on the identified preamble information
|
||||
"""
|
||||
|
||||
_DEBUG_ = False
|
||||
|
||||
def __init__(self, bitvectors: list, existing_message_types: dict = None):
|
||||
self.bitvectors = bitvectors # type: list[np.ndarray]
|
||||
self.existing_message_types = existing_message_types if existing_message_types is not None else dict()
|
||||
|
||||
def preprocess(self) -> (np.ndarray, int):
|
||||
raw_preamble_positions = self.get_raw_preamble_positions()
|
||||
existing_sync_words = self.__get_existing_sync_words()
|
||||
if len(existing_sync_words) == 0:
|
||||
sync_words = self.find_possible_syncs(raw_preamble_positions)
|
||||
else:
|
||||
# NOTE: This does not cover the case if protocol has multiple sync words and not all of them were labeled
|
||||
sync_words = existing_sync_words
|
||||
|
||||
preamble_starts = raw_preamble_positions[:, 0]
|
||||
preamble_lengths = self.get_preamble_lengths_from_sync_words(sync_words, preamble_starts=preamble_starts)
|
||||
sync_len = len(sync_words[0]) if len(sync_words) > 0 else 0
|
||||
return preamble_starts, preamble_lengths, sync_len
|
||||
|
||||
def get_preamble_lengths_from_sync_words(self, sync_words: list, preamble_starts: np.ndarray):
|
||||
"""
|
||||
Get the preamble lengths based on the found sync words for all messages.
|
||||
If there should be more than one sync word in a message, use the first one.
|
||||
|
||||
:param sync_words:
|
||||
:param preamble_starts:
|
||||
:return:
|
||||
"""
|
||||
# If there should be varying sync word lengths we need to return an array of sync lengths per message
|
||||
assert all(len(sync_word) == len(sync_words[0]) for sync_word in sync_words)
|
||||
|
||||
byte_sync_words = [bytes(map(int, sync_word)) for sync_word in sync_words]
|
||||
|
||||
result = np.zeros(len(self.bitvectors), dtype=np.uint32)
|
||||
|
||||
for i, bitvector in enumerate(self.bitvectors):
|
||||
preamble_lengths = []
|
||||
bits = bitvector.tobytes()
|
||||
|
||||
for sync_word in byte_sync_words:
|
||||
sync_start = bits.find(sync_word)
|
||||
if sync_start != -1:
|
||||
if sync_start - preamble_starts[i] >= 2:
|
||||
preamble_lengths.append(sync_start - preamble_starts[i])
|
||||
|
||||
# Consider case where sync word starts with preamble pattern
|
||||
sync_start = bits.find(sync_word, sync_start + 1, sync_start + 2 * len(sync_word))
|
||||
|
||||
if sync_start != -1:
|
||||
if sync_start - preamble_starts[i] >= 2:
|
||||
preamble_lengths.append(sync_start - preamble_starts[i])
|
||||
|
||||
preamble_lengths.sort()
|
||||
|
||||
if len(preamble_lengths) == 0:
|
||||
result[i] = 0
|
||||
elif len(preamble_lengths) == 1:
|
||||
result[i] = preamble_lengths[0]
|
||||
else:
|
||||
# consider all indices not more than one byte before first one
|
||||
preamble_lengths = list(filter(lambda x: x < preamble_lengths[0] + 7, preamble_lengths))
|
||||
|
||||
# take the smallest preamble_length, but prefer a greater one if it is divisible by 8 (or 4)
|
||||
preamble_length = next((pl for pl in preamble_lengths if pl % 8 == 0), None)
|
||||
if preamble_length is None:
|
||||
preamble_length = next((pl for pl in preamble_lengths if pl % 4 == 0), None)
|
||||
if preamble_length is None:
|
||||
preamble_length = preamble_lengths[0]
|
||||
result[i] = preamble_length
|
||||
|
||||
return result
|
||||
|
||||
def find_possible_syncs(self, raw_preamble_positions=None):
|
||||
difference_matrix = self.get_difference_matrix()
|
||||
if raw_preamble_positions is None:
|
||||
raw_preamble_positions = self.get_raw_preamble_positions()
|
||||
return self.determine_sync_candidates(raw_preamble_positions, difference_matrix, n_gram_length=4)
|
||||
|
||||
@staticmethod
|
||||
def merge_possible_sync_words(possible_sync_words: dict, n_gram_length: int):
|
||||
"""
|
||||
Merge possible sync words by looking for common prefixes
|
||||
|
||||
:param possible_sync_words: dict of possible sync words and their frequencies
|
||||
:return:
|
||||
"""
|
||||
result = defaultdict(int)
|
||||
if len(possible_sync_words) < 2:
|
||||
return possible_sync_words.copy()
|
||||
|
||||
for sync1, sync2 in itertools.combinations(possible_sync_words, 2):
|
||||
common_prefix = os.path.commonprefix([sync1, sync2])
|
||||
if len(common_prefix) > n_gram_length:
|
||||
result[common_prefix] += possible_sync_words[sync1] + possible_sync_words[sync2]
|
||||
else:
|
||||
result[sync1] += possible_sync_words[sync1]
|
||||
result[sync2] += possible_sync_words[sync2]
|
||||
return result
|
||||
|
||||
def determine_sync_candidates(self,
|
||||
raw_preamble_positions: np.ndarray,
|
||||
difference_matrix: np.ndarray,
|
||||
n_gram_length=4) -> list:
|
||||
|
||||
possible_sync_words = awre_util.find_possible_sync_words(difference_matrix, raw_preamble_positions,
|
||||
self.bitvectors, n_gram_length)
|
||||
|
||||
self.__debug("Possible sync words", possible_sync_words)
|
||||
if len(possible_sync_words) == 0:
|
||||
return []
|
||||
|
||||
possible_sync_words = self.merge_possible_sync_words(possible_sync_words, n_gram_length)
|
||||
self.__debug("Merged sync words", possible_sync_words)
|
||||
|
||||
scores = self.__score_sync_lengths(possible_sync_words)
|
||||
|
||||
sorted_scores = sorted(scores, reverse=True, key=scores.get)
|
||||
estimated_sync_length = sorted_scores[0]
|
||||
if estimated_sync_length % 8 != 0:
|
||||
for other in filter(lambda x: 0 < estimated_sync_length-x < 7, sorted_scores):
|
||||
if other % 8 == 0:
|
||||
estimated_sync_length = other
|
||||
break
|
||||
|
||||
# Now we look at all possible sync words with this length
|
||||
sync_words = {word: frequency for word, frequency in possible_sync_words.items()
|
||||
if len(word) == estimated_sync_length}
|
||||
self.__debug("Sync words", sync_words)
|
||||
|
||||
additional_syncs = self.__find_additional_sync_words(estimated_sync_length, sync_words, possible_sync_words)
|
||||
|
||||
if additional_syncs:
|
||||
self.__debug("Found additional sync words", additional_syncs)
|
||||
sync_words.update(additional_syncs)
|
||||
|
||||
result = []
|
||||
for sync_word in sorted(sync_words, key=sync_words.get, reverse=True):
|
||||
# Convert bytes back to string
|
||||
result.append("".join(str(c) for c in sync_word))
|
||||
|
||||
return result
|
||||
|
||||
def __find_additional_sync_words(self, sync_length: int, present_sync_words, possible_sync_words) -> dict:
|
||||
"""
|
||||
Look for additional sync words, in case we had varying preamble lengths and multiple sync words
|
||||
(see test_with_three_syncs_different_preamble_lengths for an example)
|
||||
|
||||
:param sync_length:
|
||||
:type present_sync_words: dict
|
||||
:type possible_sync_words: dict
|
||||
:return:
|
||||
"""
|
||||
np_syn = [np.fromiter(map(int, sync_word), dtype=np.uint8, count=len(sync_word))
|
||||
for sync_word in present_sync_words]
|
||||
|
||||
messages_without_sync = [i for i, bv in enumerate(self.bitvectors)
|
||||
if not any(awre_util.find_occurrences(bv, s, return_after_first=True) for s in np_syn)]
|
||||
|
||||
result = dict()
|
||||
if len(messages_without_sync) == 0:
|
||||
return result
|
||||
|
||||
# Is there another sync word that applies to all messages without sync?
|
||||
additional_candidates = {word: score for word, score in possible_sync_words.items()
|
||||
if len(word) > sync_length and not any(s in word for s in present_sync_words)}
|
||||
|
||||
for sync in sorted(additional_candidates, key=additional_candidates.get, reverse=True):
|
||||
if len(messages_without_sync) == 0:
|
||||
break
|
||||
|
||||
score = additional_candidates[sync]
|
||||
s = sync[:sync_length]
|
||||
np_s = np.fromiter(s, dtype=np.uint8, count=len(s))
|
||||
matching = [i for i in messages_without_sync
|
||||
if awre_util.find_occurrences(self.bitvectors[i], np_s, return_after_first=True)]
|
||||
if matching:
|
||||
result[s] = score
|
||||
for m in matching:
|
||||
messages_without_sync.remove(m)
|
||||
|
||||
return result
|
||||
|
||||
def get_raw_preamble_positions(self) -> np.ndarray:
|
||||
"""
|
||||
Return a 2D numpy array where first column is the start of preamble
|
||||
second and third columns are lower and upper bound for preamble length by message, respectively
|
||||
"""
|
||||
result = np.zeros((len(self.bitvectors), 3), dtype=np.uint32)
|
||||
|
||||
for i, bitvector in enumerate(self.bitvectors):
|
||||
if i in self.existing_message_types:
|
||||
preamble_label = self.existing_message_types[i].get_first_label_with_type(FieldType.Function.PREAMBLE)
|
||||
else:
|
||||
preamble_label = None
|
||||
|
||||
if preamble_label is None:
|
||||
start, lower, upper = awre_util.get_raw_preamble_position(bitvector)
|
||||
else:
|
||||
# If this message is already labeled with a preamble we just use it's values
|
||||
start, lower, upper = preamble_label.start, preamble_label.end, preamble_label.end
|
||||
|
||||
result[i, 0] = start
|
||||
result[i, 1] = lower - start
|
||||
result[i, 2] = upper - start
|
||||
|
||||
return result
|
||||
|
||||
def get_difference_matrix(self) -> np.ndarray:
|
||||
"""
|
||||
Return a matrix of the first difference index between all messages
|
||||
:return:
|
||||
"""
|
||||
return awre_util.get_difference_matrix(self.bitvectors)
|
||||
|
||||
def __score_sync_lengths(self, possible_sync_words: dict):
|
||||
sync_lengths = defaultdict(int)
|
||||
for sync_word, score in possible_sync_words.items():
|
||||
sync_lengths[len(sync_word)] += score
|
||||
|
||||
self.__debug("Sync lengths", sync_lengths)
|
||||
|
||||
return sync_lengths
|
||||
|
||||
def __get_existing_sync_words(self) -> list:
|
||||
result = []
|
||||
for i, bitvector in enumerate(self.bitvectors):
|
||||
if i in self.existing_message_types:
|
||||
sync_label = self.existing_message_types[i].get_first_label_with_type(FieldType.Function.SYNC)
|
||||
else:
|
||||
sync_label = None
|
||||
|
||||
if sync_label is not None:
|
||||
result.append("".join(map(str, bitvector[sync_label.start:sync_label.end])))
|
||||
return result
|
||||
|
||||
def __debug(self, *args):
|
||||
if self._DEBUG_:
|
||||
print("[PREPROCESSOR]", *args)
|
||||
|
||||
@staticmethod
|
||||
def get_next_multiple_of_n(number: int, n: int):
|
||||
return n * int(math.ceil(number / n))
|
||||
|
||||
@staticmethod
|
||||
def lower_multiple_of_n(number: int, n: int):
|
||||
return n * int(math.floor(number / n))
|
||||
|
||||
@staticmethod
|
||||
def get_next_lower_multiple_of_two(number: int):
|
||||
return number if number % 2 == 0 else number - 1
|
@ -0,0 +1,260 @@
|
||||
import math
|
||||
import struct
|
||||
from array import array
|
||||
from collections import defaultdict
|
||||
|
||||
from urh.util import util
|
||||
|
||||
from urh.awre.MessageTypeBuilder import MessageTypeBuilder
|
||||
from urh.signalprocessing.ChecksumLabel import ChecksumLabel
|
||||
from urh.signalprocessing.FieldType import FieldType
|
||||
from urh.signalprocessing.Message import Message
|
||||
from urh.signalprocessing.MessageType import MessageType
|
||||
from urh.signalprocessing.Participant import Participant
|
||||
from urh.signalprocessing.ProtocoLabel import ProtocolLabel
|
||||
from urh.signalprocessing.ProtocolAnalyzer import ProtocolAnalyzer
|
||||
|
||||
|
||||
class ProtocolGenerator(object):
|
||||
DEFAULT_PREAMBLE = "10101010"
|
||||
DEFAULT_SYNC = "1001"
|
||||
BROADCAST_ADDRESS = "0xffff"
|
||||
|
||||
def __init__(self, message_types: list, participants: list = None, preambles_by_mt=None,
|
||||
syncs_by_mt=None, little_endian=False, length_in_bytes=True, sequence_numbers=None,
|
||||
sequence_number_increment=1, message_type_codes=None):
|
||||
"""
|
||||
|
||||
:param message_types:
|
||||
:param participants:
|
||||
:param preambles_by_mt:
|
||||
:param syncs_by_mt:
|
||||
:param byte_order:
|
||||
:param length_in_bytes: If false length will be given in bit
|
||||
"""
|
||||
self.participants = participants if participants is not None else []
|
||||
|
||||
self.protocol = ProtocolAnalyzer(None)
|
||||
self.protocol.message_types = message_types
|
||||
|
||||
self.length_in_bytes = length_in_bytes
|
||||
self.little_endian = little_endian
|
||||
|
||||
preambles_by_mt = dict() if preambles_by_mt is None else preambles_by_mt
|
||||
|
||||
self.preambles_by_message_type = defaultdict(lambda: self.DEFAULT_PREAMBLE)
|
||||
for mt, preamble in preambles_by_mt.items():
|
||||
self.preambles_by_message_type[mt] = self.to_bits(preamble)
|
||||
|
||||
syncs_by_mt = dict() if syncs_by_mt is None else syncs_by_mt
|
||||
|
||||
self.syncs_by_message_type = defaultdict(lambda: self.DEFAULT_SYNC)
|
||||
for mt, sync in syncs_by_mt.items():
|
||||
self.syncs_by_message_type[mt] = self.to_bits(sync)
|
||||
|
||||
sequence_numbers = dict() if sequence_numbers is None else sequence_numbers
|
||||
self.sequence_numbers = defaultdict(lambda: 0)
|
||||
self.sequence_number_increment = sequence_number_increment
|
||||
|
||||
for mt, seq in sequence_numbers.items():
|
||||
self.sequence_numbers[mt] = seq
|
||||
|
||||
if message_type_codes is None:
|
||||
message_type_codes = dict()
|
||||
for i, mt in enumerate(self.message_types):
|
||||
message_type_codes[mt] = i
|
||||
self.message_type_codes = message_type_codes
|
||||
|
||||
|
||||
@property
|
||||
def messages(self):
|
||||
return self.protocol.messages
|
||||
|
||||
@property
|
||||
def message_types(self):
|
||||
return self.protocol.message_types
|
||||
|
||||
def __get_address_for_participant(self, participant: Participant):
|
||||
if participant is None:
|
||||
return self.to_bits(self.BROADCAST_ADDRESS)
|
||||
|
||||
address = "0x" + participant.address_hex if not participant.address_hex.startswith(
|
||||
"0x") else participant.address_hex
|
||||
return self.to_bits(address)
|
||||
|
||||
@staticmethod
|
||||
def to_bits(bit_or_hex_str: str):
|
||||
if bit_or_hex_str.startswith("0x"):
|
||||
lut = {"{0:x}".format(i): "{0:04b}".format(i) for i in range(16)}
|
||||
return "".join(lut[c] for c in bit_or_hex_str[2:])
|
||||
else:
|
||||
return bit_or_hex_str
|
||||
|
||||
def decimal_to_bits(self, number: int, num_bits: int) -> str:
|
||||
len_formats = {8: "B", 16: "H", 32: "I", 64: "Q"}
|
||||
if num_bits not in len_formats:
|
||||
raise ValueError("Invalid length for length field: {} bits".format(num_bits))
|
||||
|
||||
struct_format = "<" if self.little_endian else ">"
|
||||
struct_format += len_formats[num_bits]
|
||||
|
||||
byte_length = struct.pack(struct_format, number)
|
||||
return "".join("{0:08b}".format(byte) for byte in byte_length)
|
||||
|
||||
def generate_message(self, message_type=None, data="0x00", source: Participant = None,
|
||||
destination: Participant = None):
|
||||
for participant in (source, destination):
|
||||
if isinstance(participant, Participant) and participant not in self.participants:
|
||||
self.participants.append(participant)
|
||||
|
||||
if isinstance(message_type, MessageType):
|
||||
message_type_index = self.protocol.message_types.index(message_type)
|
||||
elif isinstance(message_type, int):
|
||||
message_type_index = message_type
|
||||
else:
|
||||
message_type_index = 0
|
||||
|
||||
data = self.to_bits(data)
|
||||
|
||||
mt = self.protocol.message_types[message_type_index] # type: MessageType
|
||||
mt.sort()
|
||||
|
||||
bits = []
|
||||
|
||||
start = 0
|
||||
|
||||
data_label_present = mt.get_first_label_with_type(FieldType.Function.DATA) is not None
|
||||
|
||||
if data_label_present:
|
||||
message_length = mt[-1].end - 1
|
||||
else:
|
||||
message_length = mt[-1].end - 1 + len(data)
|
||||
|
||||
checksum_labels = []
|
||||
|
||||
for lbl in mt: # type: ProtocolLabel
|
||||
bits.append("0" * (lbl.start - start))
|
||||
len_field = lbl.end - lbl.start # in bits
|
||||
|
||||
if isinstance(lbl, ChecksumLabel):
|
||||
checksum_labels.append(lbl)
|
||||
continue # processed last
|
||||
|
||||
if lbl.field_type.function == FieldType.Function.PREAMBLE:
|
||||
preamble = self.preambles_by_message_type[mt]
|
||||
assert len(preamble) == len_field
|
||||
bits.append(preamble)
|
||||
message_length -= len(preamble)
|
||||
elif lbl.field_type.function == FieldType.Function.SYNC:
|
||||
sync = self.syncs_by_message_type[mt]
|
||||
assert len(sync) == len_field
|
||||
bits.append(sync)
|
||||
message_length -= len(sync)
|
||||
elif lbl.field_type.function == FieldType.Function.LENGTH:
|
||||
value = int(math.ceil(message_length / 8))
|
||||
|
||||
if not self.length_in_bytes:
|
||||
value *= 8
|
||||
|
||||
bits.append(self.decimal_to_bits(value, len_field))
|
||||
elif lbl.field_type.function == FieldType.Function.TYPE:
|
||||
bits.append(self.decimal_to_bits(self.message_type_codes[mt] % (2 ** len_field), len_field))
|
||||
elif lbl.field_type.function == FieldType.Function.SEQUENCE_NUMBER:
|
||||
bits.append(self.decimal_to_bits(self.sequence_numbers[mt] % (2 ** len_field), len_field))
|
||||
elif lbl.field_type.function == FieldType.Function.DST_ADDRESS:
|
||||
dst_bits = self.__get_address_for_participant(destination)
|
||||
|
||||
if len(dst_bits) != len_field:
|
||||
raise ValueError(
|
||||
"Length of dst ({0} bits) != length dst field ({1} bits)".format(len(dst_bits), len_field))
|
||||
|
||||
bits.append(dst_bits)
|
||||
elif lbl.field_type.function == FieldType.Function.SRC_ADDRESS:
|
||||
src_bits = self.__get_address_for_participant(source)
|
||||
|
||||
if len(src_bits) != len_field:
|
||||
raise ValueError(
|
||||
"Length of src ({0} bits) != length src field ({1} bits)".format(len(src_bits), len_field))
|
||||
|
||||
bits.append(src_bits)
|
||||
elif lbl.field_type.function == FieldType.Function.DATA:
|
||||
if len(data) != len_field:
|
||||
raise ValueError(
|
||||
"Length of data ({} bits) != length data field ({} bits)".format(len(data), len_field))
|
||||
bits.append(data)
|
||||
|
||||
start = lbl.end
|
||||
|
||||
if not data_label_present:
|
||||
bits.append(data)
|
||||
|
||||
msg = Message.from_plain_bits_str("".join(bits))
|
||||
msg.message_type = mt
|
||||
msg.participant = source
|
||||
self.sequence_numbers[mt] += self.sequence_number_increment
|
||||
|
||||
for checksum_label in checksum_labels:
|
||||
msg[checksum_label.start:checksum_label.end] = checksum_label.calculate_checksum_for_message(msg, False)
|
||||
|
||||
self.protocol.messages.append(msg)
|
||||
|
||||
def to_file(self, filename: str):
|
||||
self.protocol.to_xml_file(filename, [], self.participants, write_bits=True)
|
||||
|
||||
def export_to_latex(self, filename: str, number: int):
|
||||
def export_message_type_to_latex(message_type, f):
|
||||
f.write(" \\begin{itemize}\n")
|
||||
for lbl in message_type: # type: ProtocolLabel
|
||||
if lbl.field_type.function == FieldType.Function.SYNC:
|
||||
sync = array("B", map(int, self.syncs_by_message_type[message_type]))
|
||||
f.write(" \\item {}: \\texttt{{0x{}}}\n".format(lbl.name, util.bit2hex(sync)))
|
||||
elif lbl.field_type.function == FieldType.Function.PREAMBLE:
|
||||
preamble = array("B", map(int, self.preambles_by_message_type[message_type]))
|
||||
f.write(" \\item {}: \\texttt{{0x{}}}\n".format(lbl.name, util.bit2hex(preamble)))
|
||||
elif lbl.field_type.function == FieldType.Function.CHECKSUM:
|
||||
f.write(" \\item {}: {}\n".format(lbl.name, lbl.checksum.caption))
|
||||
elif lbl.field_type.function in (FieldType.Function.LENGTH, FieldType.Function.SEQUENCE_NUMBER) and lbl.length > 8:
|
||||
f.write(" \\item {}: {} bit (\\textbf{{{} endian}})\n".format(lbl.name, lbl.length, "little" if self.little_endian else "big"))
|
||||
elif lbl.field_type.function == FieldType.Function.DATA:
|
||||
f.write(" \\item payload: {} byte\n".format(lbl.length // 8))
|
||||
else:
|
||||
f.write(" \\item {}: {} bit\n".format(lbl.name, lbl.length))
|
||||
f.write(" \\end{itemize}\n")
|
||||
|
||||
with open(filename, "a") as f:
|
||||
f.write("\\subsection{{Protocol {}}}\n".format(number))
|
||||
|
||||
if len(self.participants) > 1:
|
||||
f.write("There were {} participants involved in communication: ".format(len(self.participants)))
|
||||
f.write(", ".join("{} (\\texttt{{0x{}}})".format(p.name, p.address_hex) for p in self.participants[:-1]))
|
||||
f.write(" and {} (\\texttt{{0x{}}})".format(self.participants[-1].name, self.participants[-1].address_hex))
|
||||
f.write(".\n")
|
||||
|
||||
if len(self.message_types) == 1:
|
||||
f.write("The protocol has one message type with the following fields:\n")
|
||||
export_message_type_to_latex(self.message_types[0], f)
|
||||
else:
|
||||
f.write("The protocol has {} message types with the following fields:\n".format(len(self.message_types)))
|
||||
f.write("\\begin{itemize}\n")
|
||||
for mt in self.message_types:
|
||||
f.write(" \\item \\textbf{{{}}}\n".format(mt.name))
|
||||
export_message_type_to_latex(mt, f)
|
||||
f.write("\\end{itemize}\n")
|
||||
|
||||
f.write("\n")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mb = MessageTypeBuilder("test")
|
||||
mb.add_label(FieldType.Function.PREAMBLE, 8)
|
||||
mb.add_label(FieldType.Function.SYNC, 4)
|
||||
mb.add_label(FieldType.Function.LENGTH, 8)
|
||||
mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 16)
|
||||
mb.add_label(FieldType.Function.SRC_ADDRESS, 16)
|
||||
mb.add_label(FieldType.Function.DST_ADDRESS, 16)
|
||||
pg = ProtocolGenerator([mb.message_type], [], little_endian=False)
|
||||
pg.generate_message(data="1" * 8)
|
||||
pg.generate_message(data="1" * 16)
|
||||
pg.generate_message(data="0xab", source=Participant("Alice", "A", "1234"),
|
||||
destination=Participant("Bob", "B", "4567"))
|
||||
pg.to_file("/tmp/test.proto")
|
@ -0,0 +1,399 @@
|
||||
import itertools
|
||||
import math
|
||||
from array import array
|
||||
from collections import defaultdict, Counter
|
||||
|
||||
import numpy as np
|
||||
|
||||
from urh.awre.CommonRange import CommonRange
|
||||
from urh.awre.engines.Engine import Engine
|
||||
from urh.cythonext import awre_util
|
||||
from urh.util.Logger import logger
|
||||
|
||||
|
||||
class AddressEngine(Engine):
|
||||
def __init__(self, msg_vectors, participant_indices, known_participant_addresses: dict = None,
|
||||
already_labeled: list = None, src_field_present=False):
|
||||
"""
|
||||
|
||||
:param msg_vectors: Message data behind synchronization
|
||||
:type msg_vectors: list of np.ndarray
|
||||
:param participant_indices: list of participant indices
|
||||
where ith position holds participants index for ith messages
|
||||
:type participant_indices: list of int
|
||||
"""
|
||||
assert len(msg_vectors) == len(participant_indices)
|
||||
|
||||
self.minimum_score = 0.1
|
||||
|
||||
self.msg_vectors = msg_vectors
|
||||
self.participant_indices = participant_indices
|
||||
self.already_labeled = []
|
||||
|
||||
self.src_field_present = src_field_present
|
||||
|
||||
if already_labeled is not None:
|
||||
for start, end in already_labeled:
|
||||
# convert it to hex
|
||||
self.already_labeled.append((int(math.ceil(start / 4)), int(math.ceil(end / 4))))
|
||||
|
||||
self.message_indices_by_participant = defaultdict(list)
|
||||
for i, participant_index in enumerate(self.participant_indices):
|
||||
self.message_indices_by_participant[participant_index].append(i)
|
||||
|
||||
if known_participant_addresses is None:
|
||||
self.known_addresses_by_participant = dict() # type: dict[int, np.ndarray]
|
||||
else:
|
||||
self.known_addresses_by_participant = known_participant_addresses # type: dict[int, np.ndarray]
|
||||
|
||||
@staticmethod
|
||||
def cross_swap_check(rng1: CommonRange, rng2: CommonRange):
|
||||
return (rng1.start == rng2.start + rng1.length or rng1.start == rng2.start - rng1.length) \
|
||||
and rng1.value.tobytes() == rng2.value.tobytes()
|
||||
|
||||
@staticmethod
|
||||
def ack_check(rng1: CommonRange, rng2: CommonRange):
|
||||
return rng1.start == rng2.start and rng1.length == rng2.length and rng1.value.tobytes() != rng2.value.tobytes()
|
||||
|
||||
def find(self):
|
||||
addresses_by_participant = {p: [addr.tostring()] for p, addr in self.known_addresses_by_participant.items()}
|
||||
addresses_by_participant.update(self.find_addresses())
|
||||
self._debug("Addresses by participant", addresses_by_participant)
|
||||
|
||||
# Find the address candidates by participant in messages
|
||||
ranges_by_participant = defaultdict(list) # type: dict[int, list[CommonRange]]
|
||||
|
||||
addresses = [np.array(np.frombuffer(a, dtype=np.uint8))
|
||||
for address_list in addresses_by_participant.values()
|
||||
for a in address_list]
|
||||
|
||||
already_labeled_cols = array("L", [e for rng in self.already_labeled for e in range(*rng)])
|
||||
|
||||
# Find occurrences of address candidates in messages and create common ranges over matching positions
|
||||
for i, msg_vector in enumerate(self.msg_vectors):
|
||||
participant = self.participant_indices[i]
|
||||
for address in addresses:
|
||||
for index in awre_util.find_occurrences(msg_vector, address, already_labeled_cols):
|
||||
common_ranges = ranges_by_participant[participant]
|
||||
rng = next((cr for cr in common_ranges if cr.matches(index, address)), None) # type: CommonRange
|
||||
if rng is not None:
|
||||
rng.message_indices.add(i)
|
||||
else:
|
||||
common_ranges.append(CommonRange(index, len(address), address,
|
||||
message_indices={i},
|
||||
range_type="hex"))
|
||||
|
||||
num_messages_by_participant = defaultdict(int)
|
||||
for participant in self.participant_indices:
|
||||
num_messages_by_participant[participant] += 1
|
||||
|
||||
# Look for cross swapped values between participant clusters
|
||||
for p1, p2 in itertools.combinations(ranges_by_participant, 2):
|
||||
ranges1_set, ranges2_set = set(ranges_by_participant[p1]), set(ranges_by_participant[p2])
|
||||
|
||||
for rng1, rng2 in itertools.product(ranges_by_participant[p1], ranges_by_participant[p2]):
|
||||
if rng1 in ranges2_set and rng2 in ranges1_set:
|
||||
if self.cross_swap_check(rng1, rng2):
|
||||
rng1.score += len(rng2.message_indices) / num_messages_by_participant[p2]
|
||||
rng2.score += len(rng1.message_indices) / num_messages_by_participant[p1]
|
||||
elif self.ack_check(rng1, rng2):
|
||||
# Add previous score in divisor to add bonus to ranges that apply to all messages
|
||||
rng1.score += len(rng2.message_indices) / (num_messages_by_participant[p2] + rng1.score)
|
||||
rng2.score += len(rng1.message_indices) / (num_messages_by_participant[p1] + rng2.score)
|
||||
|
||||
if len(ranges_by_participant) == 1 and not self.src_field_present:
|
||||
for p, ranges in ranges_by_participant.items():
|
||||
for rng in sorted(ranges):
|
||||
try:
|
||||
if np.array_equal(rng.value, self.known_addresses_by_participant[p]):
|
||||
# Only one participant in this iteration and address already known -> Highscore
|
||||
rng.score = 1
|
||||
break # Take only the first (leftmost) range
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
high_scored_ranges_by_participant = defaultdict(list)
|
||||
|
||||
address_length = self.__estimate_address_length(ranges_by_participant)
|
||||
|
||||
# Get highscored ranges by participant
|
||||
for participant, common_ranges in ranges_by_participant.items():
|
||||
# Sort by negative score so ranges with highest score appear first
|
||||
# Secondary sort by tuple to ensure order when ranges have same score
|
||||
sorted_ranges = sorted(filter(lambda cr: cr.score > self.minimum_score, common_ranges),
|
||||
key=lambda cr: (-cr.score, cr))
|
||||
if len(sorted_ranges) == 0:
|
||||
addresses_by_participant[participant] = dict()
|
||||
continue
|
||||
|
||||
addresses_by_participant[participant] = {a for a in addresses_by_participant.get(participant, [])
|
||||
if len(a) == address_length}
|
||||
|
||||
for rng in filter(lambda r: r.length == address_length, sorted_ranges):
|
||||
rng.score = min(rng.score, 1.0)
|
||||
high_scored_ranges_by_participant[participant].append(rng)
|
||||
|
||||
# Now we find the most probable address for all participants
|
||||
self.__assign_participant_addresses(addresses_by_participant, high_scored_ranges_by_participant)
|
||||
|
||||
# Eliminate participants for which we could not assign an address
|
||||
for participant, address in addresses_by_participant.copy().items():
|
||||
if address is None:
|
||||
del addresses_by_participant[participant]
|
||||
|
||||
# Now we can separate SRC and DST
|
||||
for participant, ranges in high_scored_ranges_by_participant.items():
|
||||
try:
|
||||
address = addresses_by_participant[participant]
|
||||
except KeyError:
|
||||
high_scored_ranges_by_participant[participant] = []
|
||||
continue
|
||||
|
||||
result = []
|
||||
|
||||
for rng in sorted(ranges, key=lambda r: r.score, reverse=True):
|
||||
rng.field_type = "source address" if rng.value.tostring() == address else "destination address"
|
||||
if len(result) == 0:
|
||||
result.append(rng)
|
||||
else:
|
||||
subset = next((r for r in result if rng.message_indices.issubset(r.message_indices)), None)
|
||||
if subset is not None:
|
||||
if rng.field_type == subset.field_type:
|
||||
# Avoid adding same address type twice
|
||||
continue
|
||||
|
||||
if rng.length != subset.length or (rng.start != subset.end + 1 and rng.end + 1 != subset.start):
|
||||
# Ensure addresses are next to each other
|
||||
continue
|
||||
|
||||
result.append(rng)
|
||||
|
||||
high_scored_ranges_by_participant[participant] = result
|
||||
|
||||
self.__find_broadcast_fields(high_scored_ranges_by_participant, addresses_by_participant)
|
||||
|
||||
result = [rng for ranges in high_scored_ranges_by_participant.values() for rng in ranges]
|
||||
# If we did not find a SRC address, lower the score a bit,
|
||||
# so DST fields do not win later e.g. again length fields in case of tie
|
||||
if not any(rng.field_type == "source address" for rng in result):
|
||||
for rng in result:
|
||||
rng.score *= 0.95
|
||||
|
||||
return result
|
||||
|
||||
def __estimate_address_length(self, ranges_by_participant: dict):
|
||||
"""
|
||||
Estimate the address length which is assumed to be the same for all participants
|
||||
|
||||
:param ranges_by_participant:
|
||||
:return:
|
||||
"""
|
||||
address_lengths = []
|
||||
for participant, common_ranges in ranges_by_participant.items():
|
||||
sorted_ranges = sorted(filter(lambda cr: cr.score > self.minimum_score, common_ranges),
|
||||
key=lambda cr: (-cr.score, cr))
|
||||
|
||||
max_scored = [r for r in sorted_ranges if r.score == sorted_ranges[0].score]
|
||||
|
||||
# Prevent overestimation of address length by looking for substrings
|
||||
for rng in max_scored[:]:
|
||||
same_message_rng = [r for r in sorted_ranges
|
||||
if r not in max_scored and r.score > 0 and r.message_indices == rng.message_indices]
|
||||
|
||||
if len(same_message_rng) > 1 and all(
|
||||
r.value.tobytes() in rng.value.tobytes() for r in same_message_rng):
|
||||
# remove the longer range and add the smaller ones
|
||||
max_scored.remove(rng)
|
||||
max_scored.extend(same_message_rng)
|
||||
|
||||
possible_address_lengths = [r.length for r in max_scored]
|
||||
|
||||
# Count possible address lengths.
|
||||
frequencies = Counter(possible_address_lengths)
|
||||
# Take the most common one. On tie, take the shorter one
|
||||
try:
|
||||
addr_len = max(frequencies, key=lambda x: (frequencies[x], -x))
|
||||
address_lengths.append(addr_len)
|
||||
except ValueError: # max() arg is an empty sequence
|
||||
pass
|
||||
|
||||
# Take most common address length of participants, to ensure they all have same address length
|
||||
counted = Counter(address_lengths)
|
||||
try:
|
||||
address_length = max(counted, key=lambda x: (counted[x], -x))
|
||||
return address_length
|
||||
except ValueError: # max() arg is an empty sequence
|
||||
return 0
|
||||
|
||||
def __assign_participant_addresses(self, addresses_by_participant, high_scored_ranges_by_participant):
|
||||
scored_participants_addresses = dict()
|
||||
for participant in addresses_by_participant:
|
||||
scored_participants_addresses[participant] = defaultdict(int)
|
||||
|
||||
for participant, addresses in addresses_by_participant.items():
|
||||
if participant in self.known_addresses_by_participant:
|
||||
address = self.known_addresses_by_participant[participant].tostring()
|
||||
scored_participants_addresses[participant][address] = 9999999999
|
||||
continue
|
||||
|
||||
for i in self.message_indices_by_participant[participant]:
|
||||
matching = [rng for rng in high_scored_ranges_by_participant[participant]
|
||||
if i in rng.message_indices and rng.value.tostring() in addresses]
|
||||
|
||||
if len(matching) == 1:
|
||||
address = matching[0].value.tostring()
|
||||
# only one address, so probably a destination and not a source
|
||||
scored_participants_addresses[participant][address] *= 0.9
|
||||
|
||||
# Since this is probably an ACK, the address is probably SRC of participant of previous message
|
||||
if i > 0 and self.participant_indices[i - 1] != participant:
|
||||
prev_participant = self.participant_indices[i - 1]
|
||||
prev_matching = [rng for rng in high_scored_ranges_by_participant[prev_participant]
|
||||
if i - 1 in rng.message_indices and rng.value.tostring() in addresses]
|
||||
if len(prev_matching) > 1:
|
||||
for prev_rng in filter(lambda r: r.value.tostring() == address, prev_matching):
|
||||
scored_participants_addresses[prev_participant][address] += prev_rng.score
|
||||
|
||||
elif len(matching) > 1:
|
||||
# more than one address, so there must be a source address included
|
||||
for rng in matching:
|
||||
scored_participants_addresses[participant][rng.value.tostring()] += rng.score
|
||||
|
||||
minimum_score = 0.5
|
||||
taken_addresses = set()
|
||||
self._debug("Scored addresses", scored_participants_addresses)
|
||||
|
||||
# If all participants have exactly one possible address and they all differ, we can assign them right away
|
||||
if all(len(addresses) == 1 for addresses in scored_participants_addresses.values()):
|
||||
all_addresses = [list(addresses)[0] for addresses in scored_participants_addresses.values()]
|
||||
if len(all_addresses) == len(set(all_addresses)): # ensure all addresses are different
|
||||
for p, addresses in scored_participants_addresses.items():
|
||||
addresses_by_participant[p] = list(addresses)[0]
|
||||
return
|
||||
|
||||
for participant, addresses in sorted(scored_participants_addresses.items()):
|
||||
try:
|
||||
# sort filtered results to prevent randomness for equal scores
|
||||
found_address = max(sorted(
|
||||
filter(lambda a: a not in taken_addresses and addresses[a] >= minimum_score, addresses),
|
||||
reverse=True
|
||||
), key=addresses.get)
|
||||
except ValueError:
|
||||
# Could not assign address for this participant
|
||||
addresses_by_participant[participant] = None
|
||||
continue
|
||||
|
||||
addresses_by_participant[participant] = found_address
|
||||
taken_addresses.add(found_address)
|
||||
|
||||
def __find_broadcast_fields(self, high_scored_ranges_by_participant, addresses_by_participant: dict):
|
||||
"""
|
||||
Last we check for messages that were sent to broadcast
|
||||
1. we search for messages that have a SRC address but no DST address
|
||||
2. we look at other messages that have this SRC field and find the corresponding DST position
|
||||
3. we evaluate the value of message without DST from 1 and compare these values with each other.
|
||||
if they match, we found the broadcast address
|
||||
:param high_scored_ranges_by_participant:
|
||||
:return:
|
||||
"""
|
||||
if -1 in addresses_by_participant:
|
||||
# broadcast address is already known
|
||||
return
|
||||
|
||||
broadcast_bag = defaultdict(list) # type: dict[CommonRange, list[int]]
|
||||
for common_ranges in high_scored_ranges_by_participant.values():
|
||||
src_address_fields = sorted(filter(lambda r: r.field_type == "source address", common_ranges))
|
||||
dst_address_fields = sorted(filter(lambda r: r.field_type == "destination address", common_ranges))
|
||||
msg_with_dst = {i for dst_address_field in dst_address_fields for i in dst_address_field.message_indices}
|
||||
|
||||
for src_address_field in src_address_fields: # type: CommonRange
|
||||
msg_without_dst = {i for i in src_address_field.message_indices if i not in msg_with_dst}
|
||||
if len(msg_without_dst) == 0:
|
||||
continue
|
||||
try:
|
||||
matching_dst = next(dst for dst in dst_address_fields
|
||||
if all(i in dst.message_indices
|
||||
for i in src_address_field.message_indices - msg_without_dst))
|
||||
except StopIteration:
|
||||
continue
|
||||
for msg in msg_without_dst:
|
||||
broadcast_bag[matching_dst].append(msg)
|
||||
|
||||
if len(broadcast_bag) == 0:
|
||||
return
|
||||
|
||||
broadcast_address = None
|
||||
for dst, messages in broadcast_bag.items():
|
||||
for msg_index in messages:
|
||||
value = self.msg_vectors[msg_index][dst.start:dst.end + 1]
|
||||
if broadcast_address is None:
|
||||
broadcast_address = value
|
||||
elif value.tobytes() != broadcast_address.tobytes():
|
||||
# Address is not common across messages so it can't be a broadcast address
|
||||
return
|
||||
|
||||
addresses_by_participant[-1] = broadcast_address.tobytes()
|
||||
for dst, messages in broadcast_bag.items():
|
||||
dst.values.append(broadcast_address)
|
||||
dst.message_indices.update(messages)
|
||||
|
||||
def find_addresses(self) -> dict:
|
||||
already_assigned = list(self.known_addresses_by_participant.keys())
|
||||
if len(already_assigned) == len(self.message_indices_by_participant):
|
||||
self._debug("Skipping find addresses as already known.")
|
||||
return dict()
|
||||
|
||||
common_ranges_by_participant = dict()
|
||||
for participant, message_indices in self.message_indices_by_participant.items():
|
||||
# Cluster by length
|
||||
length_clusters = defaultdict(list)
|
||||
for i in message_indices:
|
||||
length_clusters[len(self.msg_vectors[i])].append(i)
|
||||
|
||||
common_ranges_by_length = self.find_common_ranges_by_cluster(self.msg_vectors, length_clusters, range_type="hex")
|
||||
common_ranges_by_participant[participant] = []
|
||||
for ranges in common_ranges_by_length.values():
|
||||
common_ranges_by_participant[participant].extend(self.ignore_already_labeled(ranges,
|
||||
self.already_labeled))
|
||||
|
||||
self._debug("Common ranges by participant:", common_ranges_by_participant)
|
||||
|
||||
result = defaultdict(set)
|
||||
participants = sorted(common_ranges_by_participant) # type: list[int]
|
||||
|
||||
if len(participants) < 2:
|
||||
return result
|
||||
|
||||
# If we already know the address length we do not need to bother with other candidates
|
||||
if len(already_assigned) > 0:
|
||||
addr_len = len(self.known_addresses_by_participant[already_assigned[0]])
|
||||
if any(len(self.known_addresses_by_participant[i]) != addr_len for i in already_assigned):
|
||||
logger.warning("Addresses do not have a common length. Assuming length of {}".format(addr_len))
|
||||
else:
|
||||
addr_len = None
|
||||
|
||||
for p1, p2 in itertools.combinations(participants, 2):
|
||||
p1_already_assigned = p1 in already_assigned
|
||||
p2_already_assigned = p2 in already_assigned
|
||||
|
||||
if p1_already_assigned and p2_already_assigned:
|
||||
continue
|
||||
|
||||
# common ranges are not merged yet, so there is only one element in values
|
||||
values1 = [cr.value for cr in common_ranges_by_participant[p1]]
|
||||
values2 = [cr.value for cr in common_ranges_by_participant[p2]]
|
||||
for seq1, seq2 in itertools.product(values1, values2):
|
||||
lcs = self.find_longest_common_sub_sequences(seq1, seq2)
|
||||
vals = lcs if len(lcs) > 0 else [seq1, seq2]
|
||||
# Address candidate must be at least 2 values long
|
||||
for val in filter(lambda v: len(v) >= 2, vals):
|
||||
if addr_len is not None and len(val) != addr_len:
|
||||
continue
|
||||
if not p1_already_assigned and not p2_already_assigned:
|
||||
result[p1].add(val.tostring())
|
||||
result[p2].add(val.tostring())
|
||||
elif p1_already_assigned and val.tostring() != self.known_addresses_by_participant[p1].tostring():
|
||||
result[p2].add(val.tostring())
|
||||
elif p2_already_assigned and val.tostring() != self.known_addresses_by_participant[p2].tostring():
|
||||
result[p1].add(val.tostring())
|
||||
return result
|
@ -0,0 +1,121 @@
|
||||
import copy
|
||||
import math
|
||||
from collections import defaultdict
|
||||
|
||||
import numpy as np
|
||||
from urh.util.WSPChecksum import WSPChecksum
|
||||
|
||||
from urh.awre.CommonRange import ChecksumRange
|
||||
from urh.awre.engines.Engine import Engine
|
||||
from urh.cythonext import awre_util
|
||||
from urh.util.GenericCRC import GenericCRC
|
||||
|
||||
|
||||
class ChecksumEngine(Engine):
|
||||
def __init__(self, bitvectors, n_gram_length=8, minimum_score=0.9, already_labeled: list = None):
|
||||
"""
|
||||
:type bitvectors: list of np.ndarray
|
||||
:param bitvectors: bitvectors behind the synchronization
|
||||
"""
|
||||
self.bitvectors = bitvectors
|
||||
self.n_gram_length = n_gram_length
|
||||
self.minimum_score = minimum_score
|
||||
if already_labeled is None:
|
||||
self.already_labeled_cols = set()
|
||||
else:
|
||||
self.already_labeled_cols = {e for rng in already_labeled for e in range(*rng)}
|
||||
|
||||
def find(self):
|
||||
result = list()
|
||||
bitvectors_by_n_gram_length = defaultdict(list)
|
||||
for i, bitvector in enumerate(self.bitvectors):
|
||||
bin_num = int(math.ceil(len(bitvector) / self.n_gram_length))
|
||||
bitvectors_by_n_gram_length[bin_num].append(i)
|
||||
|
||||
crc = GenericCRC()
|
||||
for length, message_indices in bitvectors_by_n_gram_length.items():
|
||||
checksums_for_length = []
|
||||
for index in message_indices:
|
||||
bits = self.bitvectors[index]
|
||||
data_start, data_stop, crc_start, crc_stop = WSPChecksum.search_for_wsp_checksum(bits)
|
||||
if (data_start, data_stop, crc_start, crc_stop) != (0, 0, 0, 0):
|
||||
checksum_range = ChecksumRange(start=crc_start, length=crc_stop-crc_start,
|
||||
data_range_start=data_start, data_range_end=data_stop,
|
||||
crc=WSPChecksum(), score=1/len(message_indices),
|
||||
field_type="checksum", message_indices={index})
|
||||
try:
|
||||
present = next(c for c in checksums_for_length if c == checksum_range)
|
||||
present.message_indices.add(index)
|
||||
except StopIteration:
|
||||
checksums_for_length.append(checksum_range)
|
||||
continue
|
||||
|
||||
crc_object, data_start, data_stop, crc_start, crc_stop = crc.guess_all(bits,
|
||||
ignore_positions=self.already_labeled_cols)
|
||||
|
||||
if (crc_object, data_start, data_stop, crc_start, crc_stop) != (0, 0, 0, 0, 0):
|
||||
checksum_range = ChecksumRange(start=crc_start, length=crc_stop - crc_start,
|
||||
data_range_start=data_start, data_range_end=data_stop,
|
||||
crc=copy.copy(crc_object), score=1 / len(message_indices),
|
||||
field_type="checksum", message_indices={index}
|
||||
)
|
||||
|
||||
try:
|
||||
present = next(rng for rng in checksums_for_length if rng == checksum_range)
|
||||
present.message_indices.add(index)
|
||||
continue
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
checksums_for_length.append(checksum_range)
|
||||
|
||||
matching = awre_util.check_crc_for_messages(message_indices, self.bitvectors,
|
||||
data_start, data_stop,
|
||||
crc_start, crc_stop,
|
||||
*crc_object.get_parameters())
|
||||
|
||||
checksum_range.message_indices.update(matching)
|
||||
|
||||
# Score ranges
|
||||
for rng in checksums_for_length:
|
||||
rng.score = len(rng.message_indices) / len(message_indices)
|
||||
|
||||
try:
|
||||
result.append(max(checksums_for_length, key=lambda x: x.score))
|
||||
except ValueError:
|
||||
pass # no checksums found for this length
|
||||
|
||||
self._debug("Found Checksums", result)
|
||||
try:
|
||||
max_scored = max(filter(lambda x: len(x.message_indices) >= 2 and x.score >= self.minimum_score, result),
|
||||
key=lambda x: x.score)
|
||||
except ValueError:
|
||||
return []
|
||||
|
||||
result = list(filter(lambda x: x.crc == max_scored.crc, result))
|
||||
self._debug("Filtered Checksums", result)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def calc_score(diff_frequencies: dict) -> float:
|
||||
"""
|
||||
Calculate the score based on the distribution of differences
|
||||
1. high if one constant (!= zero) dominates
|
||||
2. Other constants (!= zero) should lower the score, zero means sequence number stays same for some messages
|
||||
|
||||
:param diff_frequencies: Frequencies of decimal differences between columns of subsequent messages
|
||||
e.g. {-255: 3, 1: 1020} means -255 appeared 3 times and 1 appeared 1020 times
|
||||
:return: a score between 0 and 1
|
||||
"""
|
||||
total = sum(diff_frequencies.values())
|
||||
num_zeros = sum(v for k, v in diff_frequencies.items() if k == 0)
|
||||
if num_zeros == total:
|
||||
return 0
|
||||
|
||||
try:
|
||||
most_frequent = ChecksumEngine.get_most_frequent(diff_frequencies)
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
return diff_frequencies[most_frequent] / (total - num_zeros)
|
@ -0,0 +1,85 @@
|
||||
from urh.awre.CommonRange import CommonRange
|
||||
from urh.awre.Histogram import Histogram
|
||||
import numpy as np
|
||||
from urh.cythonext import awre_util
|
||||
import itertools
|
||||
|
||||
|
||||
class Engine(object):
|
||||
_DEBUG_ = False
|
||||
|
||||
def _debug(self, *args):
|
||||
if self._DEBUG_:
|
||||
print("[{}]".format(self.__class__.__name__), *args)
|
||||
|
||||
@staticmethod
|
||||
def find_common_ranges_by_cluster(msg_vectors, clustered_bitvectors, alpha=0.95, range_type="bit"):
|
||||
"""
|
||||
|
||||
:param alpha: How many percent of values must be equal per range?
|
||||
:param range_type: Describes what kind of range this is: bit, hex or byte.
|
||||
Needed for conversion of range start / end later
|
||||
:type msg_vectors: list of np.ndarray
|
||||
:type clustered_bitvectors: dict
|
||||
:rtype: dict[int, list of CommonRange]
|
||||
"""
|
||||
histograms = {
|
||||
cluster: Histogram(msg_vectors, message_indices)
|
||||
for cluster, message_indices in clustered_bitvectors.items()
|
||||
}
|
||||
|
||||
common_ranges_by_cluster = {
|
||||
cluster: histogram.find_common_ranges(alpha=alpha, range_type=range_type)
|
||||
for cluster, histogram in histograms.items()
|
||||
}
|
||||
|
||||
return common_ranges_by_cluster
|
||||
|
||||
@staticmethod
|
||||
def find_common_ranges_exhaustive(msg_vectors, msg_indices, range_type="bit") -> list:
|
||||
result = []
|
||||
|
||||
for i, j in itertools.combinations(msg_indices, 2):
|
||||
for rng in Histogram(msg_vectors, indices=[i, j]).find_common_ranges(alpha=1, range_type=range_type):
|
||||
try:
|
||||
common_range = next(cr for cr in result if cr.start == rng.start and cr.value.tobytes() == rng.value.tobytes())
|
||||
common_range.message_indices.update({i, j})
|
||||
except StopIteration:
|
||||
result.append(rng)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def ignore_already_labeled(common_ranges, already_labeled):
|
||||
"""
|
||||
Shrink the common ranges so that they not overlap with already labeled ranges.
|
||||
Empty common ranges are removed after shrinking
|
||||
|
||||
:type common_ranges: list of CommonRange
|
||||
:type already_labeled: list of tuple
|
||||
:return: list of CommonRange
|
||||
"""
|
||||
result = []
|
||||
for common_range in common_ranges:
|
||||
range_result = [common_range]
|
||||
for start, end in already_labeled:
|
||||
for rng in range_result[:]:
|
||||
range_result.remove(rng)
|
||||
range_result.extend(rng.ensure_not_overlaps(start, end))
|
||||
result.extend(range_result)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def find_longest_common_sub_sequences(seq1, seq2) -> list:
|
||||
result = []
|
||||
if seq1 is None or seq2 is None:
|
||||
return result
|
||||
|
||||
indices = awre_util.find_longest_common_sub_sequence_indices(seq1, seq2)
|
||||
for ind in indices:
|
||||
s = seq1[slice(*ind)]
|
||||
if len(s) > 0:
|
||||
result.append(s)
|
||||
|
||||
return result
|