mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4924bd249a | ||
|
|
a5e000a14c | ||
|
|
53eaccc892 | ||
|
|
e95cd4dd3a | ||
|
|
48b0c4025b | ||
|
|
2171df515d | ||
|
|
83d7460a0b | ||
|
|
38ad11dbef | ||
|
|
eddd6cb8b1 |
@@ -52,14 +52,13 @@ git_describe(GIT_TAG)
|
||||
|
||||
find_package(LibSndFile REQUIRED)
|
||||
find_package(MBE REQUIRED)
|
||||
find_package(ITPP REQUIRED)
|
||||
find_package(RTLSDR)
|
||||
find_package(Curses REQUIRED)
|
||||
find_package(PulseAudio REQUIRED)
|
||||
find_package(CODEC2)
|
||||
|
||||
include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${ITPP_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIRS})
|
||||
set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${ITPP_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${PULSEAUDIO_LIBRARY} ${CURSES_LIBRARIES})
|
||||
include_directories(SYSTEM ${LIBSNDFILE_INCLUDE_DIR} ${MBE_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIRS} ${CURSES_INCLUDE_DIRS})
|
||||
set(LIBS ${MBE_LIBRARY} ${LIBSNDFILE_LIBRARY} ${PULSEAUDIO_SIMPLE_LIBRARY} ${PULSEAUDIO_LIBRARY} ${CURSES_LIBRARIES})
|
||||
|
||||
if(RTLSDR_FOUND)
|
||||
find_package(Threads)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# - Try to find ITPP
|
||||
# Once done this will define
|
||||
#
|
||||
# ITPP_FOUND - System has ITPP
|
||||
# ITPP_INCLUDE_DIR - The ITPP include directory
|
||||
# ITPP_LIBRARY - The library needed to use ITPP
|
||||
#
|
||||
|
||||
find_path(ITPP_INCLUDE_DIR itpp/itcomm.h)
|
||||
|
||||
set(ITPP_NAMES ${ITPP_NAMES} itpp libitpp libitpp.dll)
|
||||
FIND_LIBRARY(ITPP_LIBRARY NAMES ${ITPP_NAMES})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ITPP DEFAULT_MSG ITPP_LIBRARY ITPP_INCLUDE_DIR)
|
||||
@@ -61,10 +61,6 @@ if [ "$RELEASE" = "y" ]; then
|
||||
#start copying things to the lib folder
|
||||
cp -r /lib/pulseaudio/ dsd-fme-portable/lib/
|
||||
|
||||
#support for LAPACK, BLAS, and FFTW3 (SIMD math libraries and dependencies)
|
||||
cp /lib/lapack/* dsd-fme-portable/dsd-fme/
|
||||
cp /bin/cyggfortran* dsd-fme-portable/dsd-fme/
|
||||
|
||||
#start copying things into the dsd-fme folder
|
||||
cp dsd-fme/build/dsd-fme.exe dsd-fme-portable/dsd-fme/
|
||||
cp -r dsd-fme/examples dsd-fme-portable/dsd-fme/
|
||||
@@ -98,7 +94,6 @@ if [ "$RELEASE" = "y" ]; then
|
||||
|
||||
#compiled items into release dsd-fme folder
|
||||
cp codec2/build/src/cygcodec2* dsd-fme-portable/dsd-fme/
|
||||
cp itpp-4.3.1/build/itpp/cygitpp* dsd-fme-portable/dsd-fme/
|
||||
cp rtl-sdr/build/src/cyg* dsd-fme-portable/dsd-fme/
|
||||
cp mbelib/build/cygmbe* dsd-fme-portable/dsd-fme/
|
||||
|
||||
|
||||
@@ -17,11 +17,6 @@ if [ "$ANSWER" = "y" ]; then
|
||||
sudo pacman -Syu #always run a full update first, partial upgrades aren't supported in Arch -- including downloading dependencies, that may require an updated dependency, and breaks same dependency on another package, a.k.a, dependency hell
|
||||
sudo pacman -S libpulse cmake ncurses lapack perl fftw rtl-sdr codec2 base-devel libsndfile git wget
|
||||
|
||||
printf "Installing itpp 4.3.1 from Arch Strike --Tested on Arch 2023.08.01 and Manjaro XFCE 22.1.3 Minimal\n"
|
||||
wget https://mirror.archstrike.org/x86_64/archstrike/itpp-4.3.1-3-x86_64.pkg.tar.xz
|
||||
sudo pacman -U itpp-4.3.1-3-x86_64.pkg.tar.xz
|
||||
sudo rm -R itpp-4.3.1-3-x86_64.pkg.tar.xz
|
||||
|
||||
git clone https://github.com/lwvmobile/mbelib
|
||||
cd mbelib
|
||||
git checkout ambe_tones
|
||||
|
||||
@@ -19,22 +19,6 @@ if [ "$ANSWER" = "y" ]; then
|
||||
export LD_LIBRARY_PATH
|
||||
echo $LD_LIBRARY_PATH
|
||||
|
||||
#ITPP
|
||||
cd $cdir
|
||||
printf "Installing itpp 4.3.1 from source http://sourceforge.net/projects/itpp/files/latest/download?source=files\n Please wait!\n"
|
||||
wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files
|
||||
tar xjf itpp-latest.tar.bz2
|
||||
cd itpp-4.3.1/
|
||||
#newer Cygwin has Cmake 4.1.3 (or newer) so we need to replace the line with cmake_minimum_required to a newer version
|
||||
#this doesn't seem to break anything, its just that cmake will refuse to run properly without a newer min version in it
|
||||
#I'm just going to use the version that is used for most all my other cmake projects, seems to still be okay with new cmake
|
||||
sed -i '/^cmake_minimum_required *( *VERSION *2\.8\.6 *)$/c\cmake_minimum_required(VERSION 3.10.2)' CMakeLists.txt
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j $(nproc)
|
||||
make install
|
||||
|
||||
#MBELIB
|
||||
cd $cdir
|
||||
printf "Installing mbelib\n Please wait!\n"
|
||||
|
||||
@@ -12,13 +12,7 @@ read -p "Have you viewed the patent notice? y/N " ANSWER
|
||||
ANSWER=$(printf "$ANSWER"|tr '[:upper:]' '[:lower:]')
|
||||
if [ "$ANSWER" = "y" ]; then
|
||||
sudo apt update
|
||||
sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncurses-dev libncurses6 libcodec2-dev
|
||||
chkitpp=$(dpkg -l libitpp-dev 2>/dev/null | awk '/^ii/ {print 1} END {if (NR == 0) print 0}')
|
||||
if [ "$chkitpp" -lt "1" ];then
|
||||
printf "\nFor some reason, ITPP did NOT install!\nYou may have to manually install it.\n\n"
|
||||
read -p "Press Enter to exit..." x
|
||||
exit 1
|
||||
fi
|
||||
sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncurses-dev libncurses6 libcodec2-dev
|
||||
git clone https://github.com/lwvmobile/mbelib
|
||||
cd mbelib
|
||||
git checkout ambe_tones
|
||||
|
||||
@@ -12,13 +12,7 @@ read -p "Have you viewed the patent notice? y/N " ANSWER
|
||||
ANSWER=$(printf "$ANSWER"|tr '[:upper:]' '[:lower:]')
|
||||
if [ "$ANSWER" = "y" ]; then
|
||||
sudo apt update
|
||||
sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev libcodec2-dev
|
||||
chkitpp=$(dpkg -l libitpp-dev 2>/dev/null | awk '/^ii/ {print 1} END {if (NR == 0) print 0}')
|
||||
if [ "$chkitpp" -lt "1" ];then
|
||||
printf "\nFor some reason, ITPP did NOT install!\nYou may have to manually install it.\n\n"
|
||||
read -p "Press Enter to exit..." x
|
||||
exit 1
|
||||
fi
|
||||
sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncursesw5-dev libcodec2-dev
|
||||
git clone https://github.com/lwvmobile/mbelib
|
||||
cd mbelib
|
||||
git checkout ambe_tones
|
||||
|
||||
@@ -43,9 +43,9 @@ Debian/Mint/Ubuntu/Pi
|
||||
```
|
||||
sudo apt update
|
||||
#Ubuntu 22.04 lts / Debian 11 and lower
|
||||
sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libcodec2-dev
|
||||
sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libcodec2-dev
|
||||
#Ubuntu 24.04 lts / Debian 12
|
||||
#sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncurses-dev libncurses6 libcodec2-dev
|
||||
#sudo apt install libpulse-dev pavucontrol libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncurses-dev libncurses6 libcodec2-dev
|
||||
```
|
||||
|
||||
Fedora 36/37 -- from https://github.com/lwvmobile/dsd-fme/issues/99
|
||||
@@ -60,8 +60,6 @@ Arch -- https://github.com/lwvmobile/dsd-fme/issues/153 and https://github.com/l
|
||||
```
|
||||
sudo pacman -Syu
|
||||
sudo pacman -S libpulse cmake ncurses lapack perl fftw rtl-sdr codec2 base-devel libsndfile git wget rtl-sdr
|
||||
wget https://mirror.archstrike.org/x86_64/archstrike/itpp-4.3.1-3-x86_64.pkg.tar.xz
|
||||
sudo pacman -U itpp-4.3.1-3-x86_64.pkg.tar.xz
|
||||
```
|
||||
|
||||
## Headless Ubuntu Server/Pi
|
||||
@@ -69,24 +67,7 @@ sudo pacman -U itpp-4.3.1-3-x86_64.pkg.tar.xz
|
||||
If running headless, swap out pavucontrol for pulsemixer, and also install pulseaudio as well. Attempting to install pavucontrol in a headless environment may attempt to install a minimal desktop environment. Note: Default behavior of pulseaudio in a headless environment may be to be muted, so check by opening pulsemixer and unmuting and routing audio appropriately.
|
||||
|
||||
```
|
||||
sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libitpp-dev libncursesw5-dev pulsemixer pulseaudio libcodec2-dev
|
||||
```
|
||||
|
||||
### Build and Install ITPP - ONLY IF NOT IN REPO!!
|
||||
|
||||
```
|
||||
wget -O itpp-latest.tar.bz2 http://sourceforge.net/projects/itpp/files/latest/download?source=files
|
||||
tar xjf itpp*
|
||||
#if you can't cd into this folder, double check folder name first
|
||||
cd itpp-4.3.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j `nproc`
|
||||
sudo make install
|
||||
sudo ldconfig
|
||||
cd ..
|
||||
cd ..
|
||||
sudo apt install libpulse-dev libsndfile1-dev libfftw3-dev liblapack-dev socat libusb-1.0-0-dev libncurses5 libncurses5-dev rtl-sdr librtlsdr-dev libusb-1.0-0-dev cmake git wget make build-essential libncursesw5-dev pulsemixer pulseaudio libcodec2-dev
|
||||
```
|
||||
|
||||
MBELib is considered a requirement in this build. You must read this notice prior to continuing. [MBElib Patent Notice](https://github.com/lwvmobile/mbelib#readme "MBElib Patent Notice")
|
||||
@@ -135,7 +116,7 @@ Open Windows PowerShell (not Command Prompt) and copy and paste all of this in a
|
||||
|
||||
```
|
||||
Invoke-WebRequest https://cygwin.com/setup-x86_64.exe -OutFile setup-x86_64.exe
|
||||
.\setup-x86_64.exe --packages nano,libpulse-devel,libpulse-mainloop-glib0,libpulse-simple0,libpulse0,pulseaudio,pulseaudio-debuginfo,pulseaudio-equalizer,pulseaudio-module-x11,pulseaudio-module-zeroconf,pulseaudio-utils,sox-fmt-pulseaudio,libusb0,libusb1.0,libusb1.0-debuginfo,libusb1.0-devel,libncurses++w10,libncurses-devel,libncursesw10,ncurses,cmake,gcc-core,gcc-debuginfo,gcc-objc,git,make,socat,sox,sox-fmt-ao,zip,unzip,wget,gcc-g++,libsndfile-devel,libopenblas,liblapack-devel,libfftw3-devel
|
||||
.\setup-x86_64.exe --packages nano,libpulse-devel,libpulse-mainloop-glib0,libpulse-simple0,libpulse0,pulseaudio,pulseaudio-debuginfo,pulseaudio-equalizer,pulseaudio-module-x11,pulseaudio-module-zeroconf,pulseaudio-utils,sox-fmt-pulseaudio,libusb0,libusb1.0,libusb1.0-debuginfo,libusb1.0-devel,libncurses++w10,libncurses-devel,libncursesw10,ncurses,cmake,gcc-core,gcc-debuginfo,gcc-objc,git,make,socat,sox,sox-fmt-ao,zip,unzip,wget,gcc-g++,libsndfile-devel
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
*
|
||||
* Code adapted from http://www.aqdi.com/golay.htm
|
||||
*
|
||||
* Tried before with the implementation from ITPP library but couldn't make it produce the same outputs
|
||||
* expected from the P25 transmissions that I have tested. This implementation does work.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
/**
|
||||
* Code taken and adapted from www.eccpage.com/rs.c
|
||||
* Credit goes to Mr Simon Rockliff.
|
||||
*
|
||||
* Tried before with the implementation from ITPP library but couldn't make it produce the same outputs
|
||||
* expected from the P25 transmissions that I have tested. This implementation does work.
|
||||
*/
|
||||
|
||||
/* This program is an encoder/decoder for Reed-Solomon codes. Encoding is in
|
||||
|
||||
@@ -59,8 +59,9 @@
|
||||
#include "p25p1_heuristics.h"
|
||||
|
||||
//OSS support
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
#endif
|
||||
#include <pulse/pulseaudio.h> //PULSE AUDIO
|
||||
#include <pulse/simple.h> //PULSE AUDIO
|
||||
#include <pulse/error.h> //PULSE AUDIO
|
||||
@@ -1643,6 +1644,7 @@ unsigned long long int hytera_lfsr(uint8_t * mi, uint8_t * taps, uint8_t len);
|
||||
void hytera_enhanced_alg_refresh(dsd_state * state);
|
||||
|
||||
//LFSR to expand either a DMR 32-bit or P25/NXDN 64-bit MI into a 128-bit IV for AES
|
||||
void lfsr_64_to_128(uint8_t * iv);
|
||||
void LFSR128(dsd_state * state);
|
||||
void LFSR128n(dsd_state * state);
|
||||
void LFSR128d(dsd_state * state);
|
||||
@@ -1669,6 +1671,9 @@ int ez_rs28_facch (int payload[156], int parity[114]); //ezpwd bridge for FME
|
||||
int ez_rs28_sacch (int payload[180], int parity[132]); //ezpwd bridge for FME
|
||||
int isch_lookup (uint64_t isch); //isch map lookup
|
||||
|
||||
//Phase 1 NID Check
|
||||
int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
#ifndef P25P1_CHECK_NID_H_3af071e917ea43fdb51326e2cbfbde0a
|
||||
#define P25P1_CHECK_NID_H_3af071e917ea43fdb51326e2cbfbde0a
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Checks a NID value, returns the fixed NAC, DUID and also an indication if it failed to decode the NID.
|
||||
* \param bch_code Input. An array to the 63 bytes, each containing one bit of the NID. This includes the
|
||||
* NAC (12 bits), DUID (4 bits) and 47 bits of BCH parity.
|
||||
* \param new_nac Output. An address where to store the calculated NAC value after error correction. Should
|
||||
* be large enough to accommodate for an integer.
|
||||
* \param new_duid Output. An address where to store the calculated DUID value after error correction. Should
|
||||
* be able to accommodate 3 chars.
|
||||
* \param parity Input. The parity value read.
|
||||
* \return 0 if there were errors processing the NID.
|
||||
*/
|
||||
int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // P25P1_CHECK_NID_H_3af071e917ea43fdb51326e2cbfbde0a
|
||||
@@ -6,7 +6,6 @@
|
||||
, ncurses
|
||||
, pulseaudio
|
||||
, rtl-sdr
|
||||
, itpp
|
||||
, codec2
|
||||
, portaudioSupport ? true
|
||||
, portaudio ? null
|
||||
@@ -23,7 +22,6 @@ stdenv.mkDerivation {
|
||||
buildInputs = [
|
||||
mbelib
|
||||
libsndfile
|
||||
itpp
|
||||
rtl-sdr
|
||||
ncurses.dev
|
||||
pulseaudio.dev
|
||||
@@ -39,7 +37,7 @@ stdenv.mkDerivation {
|
||||
tap audio and synthesize the decoded speech. Speech synthesis requires
|
||||
mbelib, which is a separate package.
|
||||
'';
|
||||
homepage = "https://github.com/szechyjs/dsd";
|
||||
homepage = "https://github.com/lwvmobile/dsd-fme";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
|
||||
@@ -189,6 +189,14 @@ void parse_pulse_output_string (dsd_opts * opts, char * input)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
// macOS does not support OSS (/dev/dsp).
|
||||
// Provide a stub so callers can link while using Pulse/CoreAudio backends.
|
||||
void openOSSOutput(dsd_opts *opts)
|
||||
{
|
||||
(void)opts;
|
||||
}
|
||||
#else
|
||||
void openOSSOutput (dsd_opts * opts)
|
||||
{
|
||||
int fmt;
|
||||
@@ -207,6 +215,7 @@ void openOSSOutput (dsd_opts * opts)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
fmt = 0;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
|
||||
{
|
||||
@@ -303,6 +312,7 @@ void openOSSOutput (dsd_opts * opts)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
processAudio (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
263
src/dsd_file.c
263
src/dsd_file.c
@@ -18,6 +18,7 @@
|
||||
#include "dsd.h"
|
||||
#include "p25p1_const.h" //for imbe fr (7200)
|
||||
#include "dmr_const.h" //for ambe+2 fr
|
||||
#include "bp.h" //for bp key table
|
||||
|
||||
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
|
||||
{
|
||||
@@ -928,9 +929,12 @@ uint16_t parse_raw_user_string (char * input, uint8_t * output)
|
||||
return len;
|
||||
}
|
||||
|
||||
//DMRA late entry items
|
||||
static int ambe2_counter;
|
||||
static int dmra_le;
|
||||
|
||||
uint16_t ambe2_str_to_decode(dsd_opts * opts, dsd_state * state, char * ambe_str, uint8_t * ks, uint16_t ks_idx, uint8_t dmra, uint8_t is_enc, uint8_t ks_available)
|
||||
{
|
||||
UNUSED(opts);
|
||||
|
||||
char ambe_fr[4][24]; memset (ambe_fr, 0, sizeof(ambe_fr));
|
||||
uint8_t dibit_pair = 0;
|
||||
@@ -976,6 +980,39 @@ uint16_t ambe2_str_to_decode(dsd_opts * opts, dsd_state * state, char * ambe_str
|
||||
|
||||
}
|
||||
|
||||
//if using DMRA Late Entry IV mechanics, evaluate for IV
|
||||
if (dmra_le)
|
||||
{
|
||||
|
||||
//make a copy of ambe_fr codeword 3 (MI fragment)
|
||||
uint8_t c3[24]; memset (c3, 0, sizeof(c3));
|
||||
for (int i = 0; i < 24; i++)
|
||||
c3[i] = ambe_fr[3][i];
|
||||
|
||||
//force slot to 0
|
||||
state->currentslot = 0;
|
||||
|
||||
uint8_t c3_hex = (uint64_t)ConvertBitIntoBytes(c3, 4);
|
||||
|
||||
//debug
|
||||
// fprintf (stderr, "\n AMBE#: %02d / %d / %d; F: %X;", ambe2_counter, ambe2_counter/3, ambe2_counter%3, c3_hex);
|
||||
|
||||
//use div and mod 3 to set current storage fragment
|
||||
state->late_entry_mi_fragment[0][(ambe2_counter/3)+1][ambe2_counter%3] = c3_hex;
|
||||
|
||||
//run LFSR evaluate stored codewords for matching IV or replace if not match or not set
|
||||
if (ambe2_counter == 17)
|
||||
{
|
||||
if (state->payload_mi != 0)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
LFSR(state);
|
||||
}
|
||||
fprintf (stderr, "\n");
|
||||
dmr_late_entry_mi (opts, state);
|
||||
}
|
||||
}
|
||||
|
||||
char ambe_d[49]; memset(ambe_d, 0, sizeof(ambe_d));
|
||||
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
||||
state->errs2 = state->errs;
|
||||
@@ -1052,7 +1089,6 @@ uint16_t ambe2_str_to_decode(dsd_opts * opts, dsd_state * state, char * ambe_str
|
||||
|
||||
uint16_t imbe_str_to_decode(dsd_opts * opts, dsd_state * state, char * imbe_str, uint8_t * ks, uint16_t ks_idx, uint8_t is_enc, uint8_t ks_available)
|
||||
{
|
||||
UNUSED(opts);
|
||||
|
||||
char imbe_fr[8][23]; memset (imbe_fr, 0, sizeof(imbe_fr));
|
||||
uint8_t dibit_pair = 0;
|
||||
@@ -1199,6 +1235,16 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
state->synctype = -1;
|
||||
state->lastsynctype = -1;
|
||||
|
||||
//reset encryption variables
|
||||
state->payload_mi = 0;
|
||||
state->payload_algid = 0;
|
||||
state->payload_keyid = 0;
|
||||
if (state->keyloader == 1)
|
||||
{
|
||||
state->R = 0;
|
||||
state->aes_key_loaded[0] = 0;
|
||||
}
|
||||
|
||||
//watchdog for event history
|
||||
watchdog_event_history(opts, state, 0);
|
||||
watchdog_event_current(opts, state, 0);
|
||||
@@ -1210,6 +1256,12 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
uint8_t ks_i[3000]; memset (ks_i, 0, sizeof(ks_i));
|
||||
uint16_t ks_idx_i = 808; //keystream index value IMBE (start at 808 for out of order ESS)
|
||||
int imbe_counter = 0; //count IMBE frames for when to skip 2 bytes of ks and juggle keystreams
|
||||
|
||||
//Used in conjunction with DMR's DMRA Late Entry IV
|
||||
ambe2_counter = 0; //count AMBE+2 frames for DMRA late entry IV mechanics (static)
|
||||
dmra_le = 0; //whether or not to attempt looking for the DMRA Late Entry
|
||||
if (state->forced_alg_id != 0)
|
||||
state->payload_mi = 0;
|
||||
|
||||
source_size = fread (source_str, 1, 0x100000, opts->mbe_in_f);
|
||||
|
||||
@@ -1344,6 +1396,77 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
}
|
||||
|
||||
//if forcing a DMRA EP mode, turn on dmra_le and set alg here
|
||||
if (state->forced_alg_id >= 0x21 && state->forced_alg_id <= 0x25)
|
||||
{
|
||||
is_dmra = 1;
|
||||
dmra_le = 1;
|
||||
is_enc = 1;
|
||||
alg_id = state->forced_alg_id;
|
||||
state->payload_algid = alg_id;
|
||||
rc4_db = 256;
|
||||
rc4_mod = 9;
|
||||
|
||||
//since we can't keyring on a forced alg, we can perhaps look it up
|
||||
//via the TO field for the TG value, as long as it isn't greated than 0x1FFFF (upper bound of the array)
|
||||
if (state->keyloader == 1 && state->lasttg != 0 && state->lasttg < 0x1FFFF && state->rkey_array[state->lasttg] != 0)
|
||||
state->R = state->rkey_array[state->lasttg];
|
||||
|
||||
if (alg_id == 0x21 && state->R != 0 && state->payload_mi != 0)
|
||||
{
|
||||
|
||||
//test when we don't have an encryption_mi in the .mbe file for DMR
|
||||
//TODO: Handle multi keystream creation with a new function
|
||||
uint8_t ks_bytes[375]; memset(ks_bytes, 0, sizeof(ks_bytes));
|
||||
uint8_t kiv[32]; memset(kiv, 0, sizeof(kiv));
|
||||
|
||||
//load key into key portion of kiv
|
||||
kiv[0] = ((state->R & 0xFF00000000) >> 32);
|
||||
kiv[1] = ((state->R & 0xFF000000) >> 24);
|
||||
kiv[2] = ((state->R & 0xFF0000) >> 16);
|
||||
kiv[3] = ((state->R & 0xFF00) >> 8);
|
||||
kiv[4] = ((state->R & 0xFF) >> 0);
|
||||
|
||||
//load IV from late entry state->payload_mi
|
||||
kiv[5] = ((state->payload_mi & 0xFF000000) >> 24);
|
||||
kiv[6] = ((state->payload_mi & 0xFF0000) >> 16);
|
||||
kiv[7] = ((state->payload_mi & 0xFF00) >> 8);
|
||||
kiv[8] = ((state->payload_mi & 0xFF) >> 0);
|
||||
|
||||
rc4_block_output (rc4_db, rc4_mod, 200, kiv, ks_bytes);
|
||||
unpack_byte_array_into_bit_array(ks_bytes, ks, 200);
|
||||
|
||||
ks_available = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//TODO: This
|
||||
else if (state->forced_alg_id == 1) //Basic Privacy
|
||||
{
|
||||
//This is where the key loaded comes into play for moto vs hytera vs scrambler
|
||||
if (state->K != 0)
|
||||
{
|
||||
uint64_t k = 0;
|
||||
k = BPK[state->K];
|
||||
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
||||
k <<= 1;
|
||||
k += (k >> 48) & 1;
|
||||
|
||||
//load that into ks
|
||||
for (int i = 0; i < 18*49; i++)
|
||||
ks[i] = (k >> (i%49)) & 1;
|
||||
}
|
||||
else if (state->H != 0)
|
||||
{
|
||||
//Hytera BP
|
||||
}
|
||||
else if (state->R != 0)
|
||||
{
|
||||
//NXDN Scrambler
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp ("to", str_buffer, 2) == 0)
|
||||
{
|
||||
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
|
||||
@@ -1445,9 +1568,9 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
//TODO: Handle multi keystream creation with a new function
|
||||
uint8_t ks_bytes[375]; memset(ks_bytes, 0, sizeof(ks_bytes));
|
||||
uint8_t kiv[15]; memset(kiv, 0, sizeof(kiv));
|
||||
uint8_t kiv[32]; memset(kiv, 0, sizeof(kiv));
|
||||
|
||||
//Test: Setup a simple RC4 for now (working)
|
||||
//RC4 (v1 tested and working on P25, v2 should be okay now)
|
||||
if ( (alg_id == 0xAA || alg_id == 0x21) && state->R != 0 )
|
||||
{
|
||||
|
||||
@@ -1480,19 +1603,113 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
ks_available = 1;
|
||||
|
||||
}
|
||||
|
||||
} //end test
|
||||
//P25 DES (v1 tested and working on P1, v2 should be okay now)
|
||||
else if (alg_id == 0x81 && state->R != 0)
|
||||
{
|
||||
|
||||
//NOTE: Regarding SDRTrunk .mbe format, the ESS Encryption Sync
|
||||
//is in the correct location on P25p2, but for P25p1, the ESS
|
||||
//information preceeds LDU2, but should be AFTER the LDU2 IMBE frames,
|
||||
//so, for now, we utilize a reverse lfsr function (Crypthings coming in handy)
|
||||
//and recover the previous LFSR and make two keystreams in order
|
||||
//to properly decrypt the initial frame, and then juggle the
|
||||
//keystreams in code to provide a smooth decryption session of P25p1.
|
||||
des_multi_keystream_output(iv_hex, state->R, ks_bytes, 1, 32); //32*8=256
|
||||
|
||||
//Update: There is a pull request available now, and using a version value,
|
||||
//we will be able to do either format (ESS out of order vs ESS in correct order)
|
||||
if (protocol == 1) //Phase 1 IMBE start on 19 for DES-OFB (8 discard + 9 LCW + 2 reserved)
|
||||
unpack_byte_array_into_bit_array(ks_bytes+19, ks, 256-19); //unpack starting after discard
|
||||
else if (protocol == 2) //Phase 2 AMBE+2 start on 8 after discard round for DES-OFB
|
||||
unpack_byte_array_into_bit_array(ks_bytes+8, ks, 256-8); //unpack starting after discard
|
||||
|
||||
//reverse lfsr on IV and create keystream with that as well
|
||||
//due to out of order execution on P25p1 ESS sync.
|
||||
if (protocol == 1 && version == 1)
|
||||
{
|
||||
|
||||
//load the str_buffer into the IV portion of kiv (just borrowing for DES)
|
||||
parse_raw_user_string(str_buffer, kiv+5);
|
||||
|
||||
reverse_lfsr_64_to_len (opts, kiv+5, 64);
|
||||
|
||||
//convert bytes back into value
|
||||
iv_hex = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
iv_hex <<= 8;
|
||||
iv_hex |= kiv[i+5];
|
||||
}
|
||||
|
||||
memset(ks_bytes, 0, sizeof(ks_bytes));
|
||||
|
||||
des_multi_keystream_output(iv_hex, state->R, ks_bytes, 1, 32); //32*8=256
|
||||
|
||||
unpack_byte_array_into_bit_array(ks_bytes+19, ks_i, 256-19); //unpack starting after discard
|
||||
}
|
||||
|
||||
ks_available = 1;
|
||||
|
||||
}
|
||||
|
||||
//P25 AES (v1 and v2 tested working on P1)
|
||||
else if ( (alg_id == 0x84 || alg_id == 0x89) && state->aes_key_loaded[0] == 1 )
|
||||
{
|
||||
|
||||
uint8_t aes_key[32];
|
||||
memset(aes_key, 0, sizeof(aes_key));
|
||||
|
||||
//Load key from A1 - A4
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
aes_key[i+0] = (state->A1[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+8] = (state->A2[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+16] = (state->A3[0] >> (56-(i*8))) & 0xFF;
|
||||
aes_key[i+24] = (state->A4[0] >> (56-(i*8))) & 0xFF;
|
||||
}
|
||||
|
||||
uint8_t aes_iv[16];
|
||||
memset(aes_iv, 0, sizeof(aes_iv));
|
||||
|
||||
//load the str_buffer into the IV portion of aes_iv
|
||||
parse_raw_user_string(str_buffer, aes_iv);
|
||||
|
||||
//backup copy of current IV to reverse and expand, if needed
|
||||
uint8_t aes_last_iv[16];
|
||||
memset(aes_last_iv, 0, sizeof(aes_last_iv));
|
||||
for (int i = 0; i < 8; i++)
|
||||
aes_last_iv[i] = aes_iv[i];
|
||||
|
||||
//Resolve the longer IV from the shorter one
|
||||
lfsr_64_to_128(aes_iv);
|
||||
|
||||
if (alg_id == 0x89) //128, or 256
|
||||
aes_ofb_keystream_output(aes_iv, aes_key, ks_bytes, 0, 16); //16*16=256
|
||||
else aes_ofb_keystream_output(aes_iv, aes_key, ks_bytes, 2, 16); //16*16=256
|
||||
|
||||
if (protocol == 1) //Phase 1 IMBE start on 27 for AES-OFB (16 discard + 9 LCW + 2 reserved)
|
||||
unpack_byte_array_into_bit_array(ks_bytes+27, ks, 256-27); //unpack starting after discard
|
||||
else if (protocol == 2) //Phase 2 AMBE+2 start on 16 after discard round for AES-OFB
|
||||
unpack_byte_array_into_bit_array(ks_bytes+16, ks, 256-16); //unpack starting after discard
|
||||
|
||||
//reverse lfsr on IV and create keystream with that as well
|
||||
//due to out of order execution on P25p1 ESS sync.
|
||||
if (protocol == 1 && version == 1)
|
||||
{
|
||||
|
||||
reverse_lfsr_64_to_len (opts, aes_last_iv, 64);
|
||||
|
||||
//Resolve the longer IV from the shorter one
|
||||
lfsr_64_to_128(aes_last_iv);
|
||||
|
||||
memset(ks_bytes, 0, sizeof(ks_bytes));
|
||||
|
||||
if (alg_id == 0x89) //128, or 256
|
||||
aes_ofb_keystream_output(aes_last_iv, aes_key, ks_bytes, 0, 16); //16*16=256
|
||||
else aes_ofb_keystream_output(aes_last_iv, aes_key, ks_bytes, 2, 16); //16*16=256
|
||||
|
||||
unpack_byte_array_into_bit_array(ks_bytes+27, ks_i, 256-27); //unpack starting after discard
|
||||
}
|
||||
|
||||
ks_available = 1;
|
||||
|
||||
}
|
||||
|
||||
//Pull request: https://github.com/DSheirer/sdrtrunk/pull/2273
|
||||
//Merged into SDRTrunk nightly so should be able to handle this better now
|
||||
|
||||
//reset ks_idx to 0
|
||||
ks_idx = 0;
|
||||
@@ -1516,6 +1733,9 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
imbe_counter++;
|
||||
|
||||
//debug
|
||||
// fprintf (stderr, "\n IMBE# %02d; KS_IDX: %d; KS_IDX_I: %d; ", imbe_counter, ks_idx, ks_idx_i);
|
||||
|
||||
//36 hex characters on 'hex' which is the IMBE interleaved C codewords
|
||||
if (version == 1)
|
||||
ks_idx_i = imbe_str_to_decode(opts, state, str_buffer, ks_i, ks_idx_i, is_enc, ks_available);
|
||||
@@ -1523,7 +1743,10 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
//skip LSD bits in-between these two IMBE voice frames
|
||||
if (imbe_counter == 8 || imbe_counter == 17)
|
||||
{
|
||||
ks_idx_i += 16;
|
||||
ks_idx += 16;
|
||||
}
|
||||
|
||||
//juggle keystreams and reset the I counter (if version 1)
|
||||
if (imbe_counter == 9 && version == 1)
|
||||
@@ -1544,7 +1767,7 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
}
|
||||
|
||||
//debug
|
||||
// fprintf (stderr, " # %02d; KS_IDX_I: %04d;", imbe_counter, ks_idx_i);
|
||||
// fprintf (stderr, "\n IMBE# %02d; KS_IDX: %d; KS_IDX_I: %d; ", imbe_counter, ks_idx, ks_idx_i);
|
||||
|
||||
//debug
|
||||
// if (is_enc == 1 && ks_available == 0)
|
||||
@@ -1567,6 +1790,16 @@ void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
|
||||
// else if (is_enc == 1 && ks_available == 1)
|
||||
// fprintf (stderr, " Enc Play;");
|
||||
|
||||
//increment AMBE+2 counter
|
||||
ambe2_counter++;
|
||||
|
||||
//reset if over for DMR 18 AMBE+2 frames
|
||||
if (dmra_le && ambe2_counter == 18)
|
||||
{
|
||||
ambe2_counter = 0;
|
||||
ks_idx = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#include "p25p1_check_nid.h"
|
||||
|
||||
void
|
||||
printFrameInfo (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
|
||||
@@ -3392,18 +3392,23 @@
|
||||
//to a variable config, it cannot be the input as well
|
||||
|
||||
|
||||
#ifndef __APPLE__
|
||||
if((strncmp(opts.audio_in_dev, "/dev/audio", 10) == 0))
|
||||
{
|
||||
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
|
||||
fprintf (stderr, "Switching to /dev/dsp.\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
if((strncmp(opts.audio_in_dev, "pa", 2) == 0))
|
||||
{
|
||||
sprintf (opts.audio_in_dev, "%s", "/dev/dsp");
|
||||
fprintf (stderr, "Switching to /dev/dsp.\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
speed = 48000; //hardset to 48000
|
||||
if((strncmp(opts.audio_in_dev, "/dev/dsp", 8) == 0))
|
||||
{
|
||||
@@ -3437,24 +3442,31 @@
|
||||
|
||||
opts.audio_in_type = 5; //5 will become OSS input type
|
||||
}
|
||||
#endif
|
||||
|
||||
//check for OSS output
|
||||
#ifndef __APPLE__
|
||||
if((strncmp(opts.audio_out_dev, "/dev/audio", 10) == 0))
|
||||
{
|
||||
sprintf (opts.audio_out_dev, "%s", "/dev/dsp");
|
||||
fprintf (stderr, "Switching to /dev/dsp.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
if((strncmp(opts.audio_out_dev, "pa", 2) == 0))
|
||||
{
|
||||
sprintf (opts.audio_out_dev, "%s", "/dev/dsp");
|
||||
fprintf (stderr, "Switching to /dev/dsp.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
//this will only open OSS output if its listed as a type
|
||||
//changed to this so I could call it freely inside of ncurses terminal
|
||||
#ifndef __APPLE__
|
||||
if (opts.playfiles == 0)
|
||||
openOSSOutput(&opts);
|
||||
#endif
|
||||
|
||||
if (opts.playfiles == 1)
|
||||
{
|
||||
@@ -3466,8 +3478,10 @@
|
||||
opts.pulse_digi_out_channels = 1;
|
||||
if (opts.audio_out_type == 0)
|
||||
openPulseOutput(&opts);
|
||||
#ifndef __APPLE__
|
||||
else if((strncmp(opts.audio_out_dev, "/dev/dsp", 8) == 0))
|
||||
openOSSOutput(&opts); //open after split == 1 so it will open and playback at the proper speed
|
||||
#endif
|
||||
}
|
||||
|
||||
//this particular if-elseif-else could be rewritten to be a lot neater and simpler
|
||||
|
||||
@@ -130,11 +130,13 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
closePulseOutput (opts);
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
//close OSS output
|
||||
if (opts->audio_out_type == 2 || opts->audio_out_type == 5)
|
||||
{
|
||||
close (opts->audio_out_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (opts->audio_in_type == 0) //close pulse input if it is the specified input method
|
||||
{
|
||||
@@ -1585,10 +1587,12 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
openPulseOutput (opts);
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
if (opts->audio_out_type == 2 || opts->audio_out_type == 5)
|
||||
{
|
||||
openOSSOutput (opts);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (opts->audio_in_type == 0) //reopen pulse input if it is the specified input method
|
||||
|
||||
@@ -1,17 +1,138 @@
|
||||
#include <itpp/itcomm.h>
|
||||
// BCH decoder implementation from OP25 (Copyright 2010, KA1RBI, GPL license)
|
||||
#include "dsd.h"
|
||||
|
||||
#include "p25p1_check_nid.h"
|
||||
#include <vector>
|
||||
typedef std::vector<bool> bit_vector;
|
||||
|
||||
static const int bchGFexp[64] = {
|
||||
1, 2, 4, 8, 16, 32, 3, 6, 12, 24, 48, 35, 5, 10, 20, 40,
|
||||
19, 38, 15, 30, 60, 59, 53, 41, 17, 34, 7, 14, 28, 56, 51, 37,
|
||||
9, 18, 36, 11, 22, 44, 27, 54, 47, 29, 58, 55, 45, 25, 50, 39,
|
||||
13, 26, 52, 43, 21, 42, 23, 46, 31, 62, 63, 61, 57, 49, 33, 0
|
||||
};
|
||||
|
||||
static const int bchGFlog[64] = {
|
||||
-1, 0, 1, 6, 2, 12, 7, 26, 3, 32, 13, 35, 8, 48, 27, 18,
|
||||
4, 24, 33, 16, 14, 52, 36, 54, 9, 45, 49, 38, 28, 41, 19, 56,
|
||||
5, 62, 25, 11, 34, 31, 17, 47, 15, 23, 53, 51, 37, 44, 55, 40,
|
||||
10, 61, 46, 30, 50, 22, 39, 43, 29, 60, 42, 21, 20, 59, 57, 58
|
||||
};
|
||||
|
||||
using namespace itpp;
|
||||
int bchDec(bit_vector& Codeword)
|
||||
{
|
||||
int elp[24][22], S[23];
|
||||
int D[23], L[24], uLu[24];
|
||||
int locn[11], reg[12];
|
||||
int i, j, U, q, count;
|
||||
int SynError, CantDecode;
|
||||
|
||||
// Ideas taken from http://op25.osmocom.org/trac/wiki.png/browser/op25/gr-op25/lib/decoder_ff_impl.cc
|
||||
// See also p25_training_guide.pdf page 48.
|
||||
// See also tia-102-baaa-a-project_25-fdma-common_air_interface.pdf page 40.
|
||||
// BCH encoder/decoder implementation from IT++. GNU GPL 3 license.
|
||||
SynError = 0; CantDecode = 0;
|
||||
|
||||
itpp::BCH bch(63, 16, 11, "6 3 3 1 1 4 1 3 6 7 2 3 5 4 5 3", true);
|
||||
for (i = 1; i <= 22; i++) {
|
||||
S[i] = 0;
|
||||
for (j = 0; j <= 62; j++) {
|
||||
if (Codeword[j]) {
|
||||
S[i] = S[i] ^ bchGFexp[(i * j) % 63];
|
||||
}
|
||||
}
|
||||
if (S[i]) { SynError = 1; }
|
||||
S[i] = bchGFlog[S[i]];
|
||||
}
|
||||
|
||||
if (SynError) { // if there are errors, try to correct them
|
||||
L[0] = 0; uLu[0] = -1; D[0] = 0; elp[0][0] = 0;
|
||||
L[1] = 0; uLu[1] = 0; D[1] = S[1]; elp[1][0] = 1;
|
||||
for (i = 1; i <= 21; i++) {
|
||||
elp[0][i] = -1; elp[1][i] = 0;
|
||||
}
|
||||
U = 0;
|
||||
|
||||
do {
|
||||
U = U + 1;
|
||||
if (D[U] == -1) {
|
||||
L[U + 1] = L[U];
|
||||
for (i = 0; i <= L[U]; i++) {
|
||||
elp[U + 1][i] = elp[U][i];
|
||||
elp[U][i] = bchGFlog[elp[U][i]];
|
||||
}
|
||||
} else {
|
||||
q = U - 1;
|
||||
while ((D[q] == -1) && (q > 0)) { q = q - 1; }
|
||||
if (q > 0) {
|
||||
j = q;
|
||||
do { j = j - 1; if ((D[j] != -1) && (uLu[q] < uLu[j])) { q = j; }
|
||||
} while (j > 0);
|
||||
}
|
||||
|
||||
if (L[U] > L[q] + U - q) {
|
||||
L[U + 1] = L[U];
|
||||
} else {
|
||||
L[U + 1] = L[q] + U - q;
|
||||
}
|
||||
|
||||
for (i = 0; i <= 21; i++) {
|
||||
elp[U + 1][i] = 0;
|
||||
}
|
||||
for (i = 0; i <= L[q]; i++) {
|
||||
if (elp[q][i] != -1) {
|
||||
elp[U + 1][i + U - q] = bchGFexp[(D[U] + 63 - D[q] + elp[q][i]) % 63];
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= L[U]; i++) {
|
||||
elp[U + 1][i] = elp[U + 1][i] ^ elp[U][i];
|
||||
elp[U][i] = bchGFlog[elp[U][i]];
|
||||
}
|
||||
}
|
||||
uLu[U + 1] = U - L[U + 1];
|
||||
|
||||
if (U < 22) {
|
||||
if (S[U + 1] != -1) { D[U + 1] = bchGFexp[S[U + 1]]; } else { D[U + 1] = 0; }
|
||||
for (i = 1; i <= L[U + 1]; i++) {
|
||||
if ((S[U + 1 - i] != -1) && (elp[U + 1][i] != 0)) {
|
||||
D[U + 1] = D[U + 1] ^ bchGFexp[(S[U + 1 - i] + bchGFlog[elp[U + 1][i]]) % 63];
|
||||
}
|
||||
}
|
||||
D[U + 1] = bchGFlog[D[U + 1]];
|
||||
}
|
||||
} while ((U < 22) && (L[U + 1] <= 11));
|
||||
|
||||
U = U + 1;
|
||||
if (L[U] <= 11) {
|
||||
for (i = 0; i <= L[U]; i++) {
|
||||
elp[U][i] = bchGFlog[elp[U][i]];
|
||||
}
|
||||
|
||||
for (i = 1; i <= L[U]; i++) {
|
||||
reg[i] = elp[U][i];
|
||||
}
|
||||
count = 0;
|
||||
for (i = 1; i <= 63; i++) {
|
||||
q = 1;
|
||||
for (j = 1; j <= L[U]; j++) {
|
||||
if (reg[j] != -1) {
|
||||
reg[j] = (reg[j] + j) % 63;
|
||||
q = q ^ bchGFexp[reg[j]];
|
||||
}
|
||||
}
|
||||
if (q == 0) {
|
||||
locn[count] = 63 - i;
|
||||
count = count + 1;
|
||||
}
|
||||
}
|
||||
if (count == L[U]) {
|
||||
for (i = 0; i <= L[U] - 1; i++) {
|
||||
Codeword[locn[i]] = Codeword[locn[i]] ^ 1;
|
||||
}
|
||||
CantDecode = count;
|
||||
} else {
|
||||
CantDecode = -1;
|
||||
}
|
||||
} else {
|
||||
CantDecode = -2;
|
||||
}
|
||||
}
|
||||
return CantDecode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class to calculate the parity of the DUID values. Keeps a table with the expected outcomes
|
||||
@@ -24,13 +145,13 @@ private:
|
||||
|
||||
unsigned char get_index(unsigned char x, unsigned char y)
|
||||
{
|
||||
return (x<<2) + y;
|
||||
return (x << 2) + y;
|
||||
}
|
||||
|
||||
public:
|
||||
ParityTable()
|
||||
{
|
||||
for (unsigned int i=0; i<sizeof(table); i++) {
|
||||
for (unsigned int i = 0; i < sizeof(table); i++) {
|
||||
table[i] = 0;
|
||||
}
|
||||
table[get_index(1,1)] = 1;
|
||||
@@ -39,9 +160,8 @@ public:
|
||||
|
||||
unsigned char get_value(unsigned char x, unsigned char y)
|
||||
{
|
||||
return table[get_index(x,y)];
|
||||
return table[get_index(x, y)];
|
||||
}
|
||||
|
||||
} parity_table;
|
||||
|
||||
int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity)
|
||||
@@ -49,31 +169,38 @@ int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity
|
||||
int result;
|
||||
|
||||
// Fill up with the given input
|
||||
bvec input(63);
|
||||
for(unsigned int i=0; i<63; i++) {
|
||||
input[i] = bch_code[i];
|
||||
bit_vector codeword(63);
|
||||
for (unsigned int i = 0; i < 63; i++) {
|
||||
codeword[i] = bch_code[62-i];
|
||||
}
|
||||
|
||||
// Decode it
|
||||
bvec decoded, cw_isvalid;
|
||||
bool ok = bch.decode(input, decoded, cw_isvalid);
|
||||
int errors = bchDec(codeword);
|
||||
bool ok = (errors >= 0);
|
||||
|
||||
if (!ok) {
|
||||
// Decode failed
|
||||
// fprintf (stderr, "NID ERR: %d; ", errors);
|
||||
result = 0;
|
||||
} else {
|
||||
//reload the codeword back into correct bit order
|
||||
for (unsigned int i = 0; i < 63; i++) {
|
||||
bch_code[i] = codeword[62-i];
|
||||
}
|
||||
for (unsigned int i = 0; i < 63; i++) {
|
||||
codeword[i] = bch_code[i];
|
||||
}
|
||||
// Take the NAC from the decoded output. It's a 12 bit number starting from position 0.
|
||||
// Just convert the output from a binary sequence to an integer.
|
||||
int nac = 0;
|
||||
for (int i=0; i<12; i++) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
nac <<= 1;
|
||||
nac |= (int)decoded[i];
|
||||
nac |= (int)codeword[i];
|
||||
}
|
||||
*new_nac = nac;
|
||||
|
||||
// Take the fixed DUID from the encoded output. 4 bit value starting at position 12.
|
||||
unsigned char new_duid_0 = (((int)decoded[12])<<1) + ((int)decoded[13]);
|
||||
unsigned char new_duid_1 = (((int)decoded[14])<<1) + ((int)decoded[15]);
|
||||
unsigned char new_duid_0 = (((int)codeword[12]) << 1) + ((int)codeword[13]);
|
||||
unsigned char new_duid_1 = (((int)codeword[14]) << 1) + ((int)codeword[15]);
|
||||
new_duid[0] = new_duid_0 + '0';
|
||||
new_duid[1] = new_duid_1 + '0';
|
||||
new_duid[2] = 0; // Null terminate
|
||||
@@ -82,12 +209,12 @@ int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity
|
||||
unsigned char expected_parity = parity_table.get_value(new_duid_0, new_duid_1);
|
||||
|
||||
if (expected_parity != parity) {
|
||||
// Ignore, not sure what to do
|
||||
//fprintf (stderr, "Error in parity detected?");
|
||||
// Parity mismatch – optional handling
|
||||
// fprintf(stderr, "Error in parity detected?\n");
|
||||
}
|
||||
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user