lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
gerrit-log@lists.osmocom.org

July 2023

  • 1 participants
  • 3051 discussions
[M] Change in osmo-trx[master]: transceiver: add experimental viterbi equalizer support
by Hoernchen 26 Jul '23

26 Jul '23
Attention is currently required from: Hoernchen. Hello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/osmo-trx/+/33930 to look at the new patch set (#5). Change subject: transceiver: add experimental viterbi equalizer support ...................................................................... transceiver: add experimental viterbi equalizer support The VA is already being used by the ms side and is part of the original gsm design. It only works for gmsk, 4sps, and needs a bit of rx burst scaling and burst shifting. Change-Id: I9d7a4ff72e323832a94d885d5714fcde01ceeb3d --- M CommonLibs/config_defs.h M CommonLibs/trx_vty.c M Transceiver52M/Makefile.am M Transceiver52M/Transceiver.cpp M Transceiver52M/osmo-trx.cpp M Transceiver52M/radioInterface.h 6 files changed, 132 insertions(+), 12 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/30/33930/5 -- To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/33930 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-trx Gerrit-Branch: master Gerrit-Change-Id: I9d7a4ff72e323832a94d885d5714fcde01ceeb3d Gerrit-Change-Number: 33930 Gerrit-PatchSet: 5 Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Attention: Hoernchen <ewild(a)sysmocom.de> Gerrit-MessageType: newpatchset
1 0
0 0
[L] Change in osmo-trx[master]: ms/va: add test tool and data
by Hoernchen 26 Jul '23

26 Jul '23
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-trx/+/33945 ) Change subject: ms/va: add test tool and data ...................................................................... ms/va: add test tool and data Change-Id: Ie38ed4996134e84ad0481872a743299bb442b3db --- M .checkpatch.conf M .gitignore M utils/Makefile.am A utils/va-test/burst-gen.cpp A utils/va-test/demodbits_tsc7.s8 A utils/va-test/nb_chunk_tsc7.cfile 6 files changed, 559 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/45/33945/1 diff --git a/.checkpatch.conf b/.checkpatch.conf index 1e4b479..1699801 100644 --- a/.checkpatch.conf +++ b/.checkpatch.conf @@ -1,4 +1,5 @@ --exclude osmocom-bb/.* --exclude .*h --exclude Transceiver52M/grgsm_vitac/.* +--exclude utils/va-test/.* --ignore FUNCTION_WITHOUT_ARGS \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0b33e0f..02fd7fe 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,7 @@ !contrib/osmo-trx.spec.in utils/osmo-prbs-tool +utils/burst-gen /.qtc_clangd/* /.cache/* /.vscode/* diff --git a/utils/Makefile.am b/utils/Makefile.am index bac9a7f..4a0cfb3 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,5 +1,7 @@ -AM_CPPFLAGS = $(LIBOSMOCODING_CFLAGS) -AM_CFLAGS = -Wall +include $(top_srcdir)/Makefile.common +AM_CPPFLAGS = -Wall $(STD_DEFINES_AND_INCLUDES) -I${srcdir}/../Transceiver52M/arch/common -I${srcdir}/../Transceiver52M/device/common -I${srcdir}/../Transceiver52M +AM_CXXFLAGS = -lpthread $(LIBOSMOCODING_CFLAGS) +AM_CFLAGS = -lpthread $(LIBOSMOCODING_CFLAGS) -Wall EXTRA_DIST = clockdump.sh matlab @@ -7,3 +9,13 @@ osmo_prbs_tool_SOURCES = prbs-tool.c osmo_prbs_tool_LDADD = $(LIBOSMOCODING_LIBS) + +noinst_PROGRAMS += burst-gen + +burst_gen_SOURCES = va-test/burst-gen.cpp ${srcdir}/../Transceiver52M/grgsm_vitac/grgsm_vitac.cpp ${srcdir}/../Transceiver52M/grgsm_vitac/viterbi_detector.cc +burst_gen_LDADD = \ + ${srcdir}/../Transceiver52M/libtransceiver_common.la \ + $(ARCH_LA) \ + $(GSM_LA) \ + $(COMMON_LA) +burst_gen_CPPFLAGS = $(AM_CPPFLAGS) $(UHD_CFLAGS) diff --git a/utils/va-test/burst-gen.cpp b/utils/va-test/burst-gen.cpp new file mode 100644 index 0000000..b2f2c73 --- /dev/null +++ b/utils/va-test/burst-gen.cpp @@ -0,0 +1,534 @@ +/* + * (C) 2023 by sysmocom s.f.m.c. GmbH <info(a)sysmocom.de> + * All Rights Reserved + * + * Author: Eric Wild <ewild(a)sysmocom.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "sigProcLib.h" + +extern "C" { +#include "convert.h" +#include <convolve.h> +} + +#define _CRT_SECURE_NO_WARNINGS +#include <iterator> +#include <filesystem> +//#include <complex> +#include <algorithm> +#include <string.h> +#include <iomanip> +#include <numeric> +#include <vector> +#include <memory> +#include <iostream> +#include <fstream> + +#include <random> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <grgsm_vitac/grgsm_vitac.h> + +#define DO_RACH + +const int SAMPLE_SCALE_FACTOR = 1; + +template <typename DST_T, typename SRC_T, typename ST> +void convert_and_scale(void *dst, void *src, unsigned int src_len, ST scale) +{ + for (unsigned int i = 0; i < src_len; i++) + reinterpret_cast<DST_T *>(dst)[i] = static_cast<DST_T>((reinterpret_cast<SRC_T *>(src)[i]) * scale); +} +template <typename DST_T, typename SRC_T> +void convert_and_scale_default(void *dst, void *src, unsigned int src_len) +{ + return convert_and_scale<DST_T, SRC_T>(dst, src, src_len, SAMPLE_SCALE_FACTOR); +} + +static const unsigned int txFullScale = (float)(1 << 14) - 1; +static const unsigned int rxFullScale = (float)(1 << 14) - 1; + +static const BitVector + gRACHBurstx("0011101001001011011111111001100110101010001111000110111101111110000111001001010110011000"); + +static const BitVector gTrainingSequencex[] = { + BitVector("00100101110000100010010111"), BitVector("00101101110111100010110111"), + BitVector("01000011101110100100001110"), BitVector("01000111101101000100011110"), + BitVector("00011010111001000001101011"), BitVector("01001110101100000100111010"), + BitVector("10100111110110001010011111"), BitVector("11101111000100101110111100"), +}; + +struct mrv { + std::vector<char> bits; + signalVector *rvbuf; + std::unique_ptr<std::vector<std::complex<float>>> convolved; + // mrv(): bits(), demod_bits() {} + CorrType ct; +}; + +static mrv genRandNormalBurstx(int tsc, int sps, int tn) +{ + mrv retstruct; + int i = 0; + BitVector bits(148); + + /* Tail bits */ + for (; i < 3; i++) + bits[i] = 0; + + /* Random bits */ + for (int j = 0; i < 60; i++, j++) + bits[i] = rand() % 2; + + /* Stealing bit */ + bits[i++] = 0; + + /* Training sequence */ + for (int n = 0; i < 87; i++, n++) + bits[i] = gTrainingSequencex[tsc][n]; + + /* Stealing bit */ + bits[i++] = 0; + + /* Random bits */ + for (; i < 145; i++) + bits[i] = rand() % 2; + + /* Tail bits */ + for (; i < 148; i++) + bits[i] = 0; + + int guard = 8 + !(tn % 4); + auto r = modulateBurst(bits, guard, sps); + + retstruct.rvbuf = r; + for (size_t i = 0; i < bits.size(); i++) + retstruct.bits.push_back(bits.bit(i) ? 1 : 0); + return retstruct; +} + +static mrv genRandAccessBurstx(int delay, int sps, int tn) +{ + mrv retstruct; + int i = 0; + BitVector bits(88 + delay); + + /* delay */ + for (; i < delay; i++) + bits[i] = 0; + + /* head and synch bits */ + for (int n = 0; i < 49 + delay; i++, n++) + bits[i] = gRACHBurstx[n]; + + /* Random bits */ + for (int j = 0; i < 85 + delay; i++, j++) + bits[i] = rand() % 2; + + for (; i < 88 + delay; i++) + bits[i] = 0; + + int guard = 68 - delay + !(tn % 4); + auto r = modulateBurst(bits, guard, sps); + + retstruct.rvbuf = r; + for (size_t i = 0; i < bits.size(); i++) + retstruct.bits.push_back(bits.bit(i) ? 1 : 0); + return retstruct; +} + +extern gr_complex d_sync_training_seq[N_ACCESS_BITS]; ///<encoded training sequence of a SCH burst +extern gr_complex d_sch_training_seq[N_SYNC_BITS]; ///<encoded training sequence of a SCH burst +extern gr_complex d_norm_training_seq[TRAIN_SEQ_NUM] + [N_TRAIN_BITS]; ///<encoded training sequences of a normal and dummy burst + +void sv_write_helper(signalVector *burst, std::string fname) +{ + auto start = burst->begin(); + auto n = burst->bytes(); + char *data = reinterpret_cast<char *>(start); + + const int len_in_real = burst->size() * 2; + auto cvrtbuf_tx_a = new int16_t[len_in_real]; + convert_float_short(cvrtbuf_tx_a, (float *)burst->begin(), float(txFullScale), len_in_real); + + std::ofstream fout; + fout.open(fname + ".cfile", std::ios::binary | std::ios::out); + fout.write(data, n); + fout.close(); + + fout.open(fname + ".cs16", std::ios::binary | std::ios::out); + fout.write((char *)cvrtbuf_tx_a, len_in_real * sizeof(uint16_t)); + fout.close(); + delete[] cvrtbuf_tx_a; +} + +// borrowed from a real world burst.. +static std::vector<std::complex<float>> chan_im_resp = { + { 4.1588e-05 + -0.000361925 }, { 0.000112728 + -0.000289796 }, { 0.000162952 + -0.000169028 }, + { 0.000174185 + -2.54575e-05 }, { 0.000142947 + 0.000105992 }, { 8.65919e-05 + 0.000187041 }, + { 4.15799e-05 + 0.000184346 }, { 5.30207e-05 + 7.84921e-05 }, { 0.000158877 + -0.000128058 }, + { 0.000373956 + -0.000407954 }, { 0.000680606 + -0.000712065 }, { 0.00102929 + -0.000979604 }, + { 0.00135049 + -0.00115333 }, { 0.00157434 + -0.0011948 }, { 0.00165098 + -0.00109534 }, + { 0.00156519 + -0.000878794 }, { 0.0013399 + -0.000594285 }, { 0.00102788 + -0.00030189 }, + { 0.000694684 + -5.58912e-05 }, { 0.000399328 + 0.000109463 } +}; + +// as above, downsampled to 1sps + just magnitude +static std::vector<float> chan_im_resp_trunc = { 1., 0.20513351, 0.10020305, 0.11490235 }; + +template <typename A, typename B> +auto conv(const std::vector<A> &a, const std::vector<B> &b) -> std::unique_ptr<std::vector<A>> +{ + int data_len = a.size(); + int conv_len = b.size(); + int conv_size = conv_len + data_len - 1; + auto retv = std::make_unique<std::vector<A>>(conv_size); + + for (int i = 0; i < data_len; ++i) { + for (int j = 0; j < conv_len; ++j) { + (*retv)[i + j] += a[i] * b[j]; + } + } + return retv; +} + +template <typename A> +static auto conv(const A *a, int len, std::vector<float> &b) +{ + std::vector<A> aa(len); + std::copy_n(a, len, aa.begin()); + std::reverse(b.begin(), b.end()); + return conv(aa, b); +} +template <typename A> +static auto conv(const A *a, int len, std::vector<A> &b) +{ + std::vector<A> aa(len); + std::copy_n(a, len, aa.begin()); + std::reverse(b.begin(), b.end()); + return conv(aa, b); +} + +// signalvector is owning despite claiming not to, but we can pretend, too.. +static void dummy_free(void *wData){}; +static void *dummy_alloc(size_t newSize) +{ + return 0; +}; + +template <typename T> +size_t read_from_file(std::string path, std::vector<T> &outvec) +{ + std::ifstream infile; + infile.open(path, std::ios::in | std::ios::binary); + if (infile.fail()) { + std::cout << " not found: " << path << std::endl; + exit(0); + } + infile.seekg(0, std::ios_base::end); + size_t fsize = infile.tellg(); + auto fsize_in_T = fsize / sizeof(T); + infile.seekg(0, std::ios_base::beg); + + outvec.resize(fsize_in_T); + infile.read(reinterpret_cast<char *>(&outvec[0]), fsize); + infile.close(); + std::cout << "Read " << fsize << " from " << path << std::endl; + return fsize; +} +void demod_real_burst(int num = 0) +{ + auto path = "./nb_chunk_tsc7.cfile"; + auto bitfile = "./demodbits_tsc7.s8"; + + std::vector<std::complex<float>> burstdata; + std::vector<char> bitdata; + read_from_file(path, burstdata); + read_from_file(bitfile, bitdata); + + // print "known good" burst bits + std::cerr << "known bits:" << std::endl; + std::cerr << std::setw(5) << 0 << " - "; + for (auto i : bitdata) + std::cout << (i > 0 ? "1" : "0"); + std::cerr << std::endl; + std::cerr << "demod tests sigproclib:" << std::endl; + + auto ct = CorrType::TSC; + auto delay = 0; + auto tsc = 7; + int offset = 0; + auto cplx = reinterpret_cast<complex *>(&burstdata[offset]); + auto stdcplx = reinterpret_cast<std::complex<float> *>(&burstdata[offset]); + signalVector sv(&cplx[0], 0, burstdata.size() - offset, dummy_alloc, dummy_free); + + struct estim_burst_params ebp; + auto rc = detectAnyBurst(sv, tsc, BURST_THRESH, 4, ct, 40, &ebp); + auto rxBurst = demodAnyBurst(sv, (CorrType)rc, 4, &ebp); + + // print osmotrx sigproclib demod result + std::cerr << std::setw(5) << int(ebp.toa) << " o "; + for (size_t i = 0 + delay; i < 148 + delay; i++) + std::cout << (rxBurst->bit(i) ? "1" : "0"); + std::cerr << std::endl; + + std::cerr << "demod test va:" << std::endl; + std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + char demodded_softbits[444]; + + // demod at known offset + { + auto inp = &stdcplx[29]; // known offset + auto normal_burst_startX = get_norm_chan_imp_resp(inp, &chan_imp_resp[0], &ncmax, tsc); + detect_burst_nb(inp, &chan_imp_resp[0], normal_burst_startX, demodded_softbits); + + std::cerr << std::setw(3) << normal_burst_startX << " v "; + for (size_t i = 0; i < 148; i++) + std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + std::cerr << std::endl; + } + { + std::cerr << "-- va start offset loop --" << std::endl; + std::cerr << "offset/det offset/#errors/known^demod bits" << std::endl; + for (int i = 0; i < 34; i++) { + auto inp = &stdcplx[i]; + auto conved_beg = inp; + + auto me = get_norm_chan_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, tsc); + detect_burst_nb(conved_beg, &chan_imp_resp[0], me, demodded_softbits); + auto bitdiffarr = std::make_unique<char[]>(148); + for (size_t i = 0; i < 148; i++) + bitdiffarr.get()[i] = (demodded_softbits[i] < 0 ? 1 : 0) ^ (bitdata[i] > 0 ? 1 : 0); + auto ber = std::accumulate(bitdiffarr.get(), bitdiffarr.get() + 148, 0); + + std::cerr << std::setw(3) << i << ": " << std::setw(3) << me << " v " << std::setw(3) << ber + << " "; + for (size_t i = 0; i < 148; i++) + std::cerr << (bitdiffarr[i] ? "1" : "0"); + std::cerr << std::endl; + // std::cerr << std::setw(4) << i << " (" << std::setw(4) << 29 - i << "):" << std::setw(4) << org + // << " " << std::setw(4) << me << " y " << std::endl; + } + } +} + +auto gen_burst(CorrType t, int delay, int tsc) +{ + mrv rs; + if (t == CorrType::RACH) { + rs = genRandAccessBurstx(delay, 4, tsc); + + } else if (t == CorrType::TSC) { + rs = genRandNormalBurstx(tsc, 4, 0); + } else { + std::cerr << "wtf?" << std::endl; + exit(0); + } + rs.ct = t; + + signalVector *burst = rs.rvbuf; + // sv_write_helper(burst, std::to_string(num)); + // scaleVector(*burst, {1, 0}); + const int len_in_real = burst->size() * 2; + auto cvrtbuf_tx_a = std::make_unique<short[]>(len_in_real); + auto cvrtbuf_rx_a = std::make_unique<float[]>(len_in_real); + auto rx_cfloat = reinterpret_cast<std::complex<float> *>(&cvrtbuf_rx_a[0]); + + convert_float_short(cvrtbuf_tx_a.get(), (float *)burst->begin(), float(txFullScale), len_in_real); + convert_short_float(cvrtbuf_rx_a.get(), cvrtbuf_tx_a.get(), len_in_real); + for (int i = 0; i < len_in_real; i++) // scale properly! + cvrtbuf_rx_a[i] *= 1. / txFullScale; + auto conved = conv(rx_cfloat, burst->size(), chan_im_resp); + + std::cerr << "-- generated " << (t == CorrType::RACH ? "RACH" : "TSC") << " burst --" << std::endl; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (rs.bits[i] ? "1" : "0"); + std::cerr << std::endl; + delete burst; + rs.convolved = std::move(conved); + return rs; +} + +void demod_generated_burst(CorrType t) +{ + int tsc = 0; + int delay = 0; + auto rs = gen_burst(t, delay, tsc); + auto conved_beg = &(*rs.convolved)[0]; + + if (rs.ct == CorrType::RACH) { + std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + char demodded_softbits[444]; + int normal_burst_start = 0; + normal_burst_start = get_access_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, 0); + normal_burst_start = std::max(normal_burst_start, 0); + for (int j = 0; j < 4; j++) { + for (int start_val = 0; start_val < 16; start_val++) { + auto bitdiffarr = std::make_unique<char[]>(rs.bits.size()); + detect_burst_access_burst(conved_beg, &chan_imp_resp[0], normal_burst_start + j, + demodded_softbits, start_val); + + for (size_t i = 0; i < rs.bits.size(); i++) + bitdiffarr.get()[i] = (demodded_softbits[i] < 0 ? 1 : 0) ^ rs.bits[i]; + auto ber = std::accumulate(bitdiffarr.get(), bitdiffarr.get() + rs.bits.size(), 0); + + std::cerr << "ber " << std::setw(4) << ber << " bo:" << std::setw(4) << j + << " vas:" << std::setw(4) << start_val << " "; + // for (size_t i = 0; i < rs.num_bits; i++) + // std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + // std::cerr << std::endl; + // std::cerr << "d " << std::setw(4) << ber << " "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (bitdiffarr.get()[i] ? "1" : "0"); + std::cerr << std::endl; + + // std::cerr << "v " << std::setw(4) << j << std::setw(4) << start_val << " "; + // for (size_t i = 0; i < rs.num_bits; i++) + // std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + // std::cerr << std::endl; + // std::cerr << "d " << std::setw(4) << ber << " "; + // for (size_t i = 0; i < rs.num_bits; i++) + // std::cerr << (ptr.get()[i] ? "1" : "0"); + // std::cerr << std::endl; + } + } + + } else { + std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + char demodded_softbits[444]; + + auto normal_burst_start = get_norm_chan_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, tsc); + detect_burst_nb(conved_beg, &chan_imp_resp[0], normal_burst_start + 0, demodded_softbits); + std::cerr << "toa " << std::setprecision(2) << normal_burst_start << std::endl; + + std::cerr << "vita "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + std::cerr << std::endl; + std::cerr << "diff "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << ((demodded_softbits[i] < 0 ? 1 : 0) ^ rs.bits[i] ? "1" : "0"); + std::cerr << std::endl; + } + + struct estim_burst_params ebp; + char demodded_softbits[444]; + complex *rx_sigproc_cfloat = reinterpret_cast<complex *>(conved_beg); + signalVector sv(rx_sigproc_cfloat, 0, rs.convolved->size(), dummy_alloc, dummy_free); + + auto rc = detectAnyBurst(sv, tsc, BURST_THRESH, 4, rs.ct, 40, &ebp); + auto rxBurst = std::unique_ptr<SoftVector>(demodAnyBurst(sv, (CorrType)rc, 4, &ebp)); + + std::cerr << "toa " << std::setprecision(2) << ebp.toa << std::endl; + + for (size_t i = 0; i < delay; i++) // maybe pad rach op? + demodded_softbits[i] = 0; + for (size_t i = 0 + delay; i < rs.bits.size() + delay; i++) + demodded_softbits[i] = (rxBurst->bit(i) ? 1 : 0); + + std::cerr << "sigp "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (demodded_softbits[i] ? "1" : "0"); + std::cerr << std::endl; + + std::cerr << "diff "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (demodded_softbits[i] ^ rs.bits[i] ? "1" : "0"); + std::cerr << std::endl; +} + +void demod_test_offsets() +{ + const int tsc = 0; + const int delaybuffer_realoffset = 100; + + { + auto rs = gen_burst(CorrType::RACH, 0, tsc); + typeof(*rs.convolved) delay_buffer(rs.convolved->size() * 2); // plenty of space.. + + for (int delay = -10; delay < 60; delay++) { + std::fill(delay_buffer.begin(), delay_buffer.end(), 0); + std::copy(rs.convolved->begin(), rs.convolved->end(), + delay_buffer.begin() + delaybuffer_realoffset + delay); + + auto conved_beg = &delay_buffer[delaybuffer_realoffset]; + + std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + auto va_burst_start = get_access_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, 60); + + complex *rx_sigproc_cfloat = reinterpret_cast<complex *>(conved_beg); + struct estim_burst_params ebp; + signalVector sv(rx_sigproc_cfloat, 0, rs.convolved->size(), dummy_alloc, dummy_free); + detectAnyBurst(sv, tsc, BURST_THRESH, 4, rs.ct, 60, &ebp); + std::cerr << "delay:" << std::setw(3) << std::setprecision(2) << delay; + std::cerr << " va: " << std::setw(3) << std::setprecision(2) << va_burst_start; + std::cerr << " sg: " << std::setw(3) << std::setprecision(2) << ebp.toa; + std::cerr << " d: " << std::setw(3) << std::setprecision(2) << (ebp.toa * 4) - va_burst_start; + std::cerr << " ! " << float(va_burst_start + 13) / 4 << std::endl; + } + } + { + auto rs = gen_burst(CorrType::TSC, 0, tsc); + typeof(*rs.convolved) delay_buffer(rs.convolved->size() * 2); // plenty of space.. + + for (int delay = -10; delay < 10; delay++) { + std::fill(delay_buffer.begin(), delay_buffer.end(), 0); + std::copy(rs.convolved->begin(), rs.convolved->end(), + delay_buffer.begin() + delaybuffer_realoffset + delay); + + auto conved_beg = &delay_buffer[delaybuffer_realoffset]; + + std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + auto va_burst_start = get_norm_chan_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, tsc); + + complex *rx_sigproc_cfloat = reinterpret_cast<complex *>(conved_beg); + struct estim_burst_params ebp; + signalVector sv(rx_sigproc_cfloat, 0, rs.convolved->size(), dummy_alloc, dummy_free); + detectAnyBurst(sv, tsc, BURST_THRESH, 4, rs.ct, 60, &ebp); + std::cerr << "delay:" << std::setw(3) << std::setprecision(2) << delay; + std::cerr << " va: " << std::setw(3) << std::setprecision(2) << va_burst_start; + std::cerr << " sg: " << std::setw(3) << std::setprecision(2) << ebp.toa; + std::cerr << " d: " << std::setw(3) << std::setprecision(2) << (ebp.toa * 4) - va_burst_start; + std::cerr << " ! " << float(va_burst_start + 19) / 4 << std::endl; + } + } +} + +int main() +{ + convolve_init(); + convert_init(); + sigProcLibSetup(); + initvita(); + + for (int i = 0; i < 1; i++) { + demod_real_burst(i); + demod_generated_burst(CorrType::RACH); + demod_generated_burst(CorrType::TSC); + demod_test_offsets(); + } +} diff --git a/utils/va-test/demodbits_tsc7.s8 b/utils/va-test/demodbits_tsc7.s8 new file mode 100644 index 0000000..c91cd6c --- /dev/null +++ b/utils/va-test/demodbits_tsc7.s8 Binary files differ diff --git a/utils/va-test/nb_chunk_tsc7.cfile b/utils/va-test/nb_chunk_tsc7.cfile new file mode 100644 index 0000000..67e577e --- /dev/null +++ b/utils/va-test/nb_chunk_tsc7.cfile Binary files differ -- To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/33945 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-trx Gerrit-Branch: master Gerrit-Change-Id: Ie38ed4996134e84ad0481872a743299bb442b3db Gerrit-Change-Number: 33945 Gerrit-PatchSet: 1 Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[L] Change in osmo-trx[master]: ms/va: add test tool and data
by Hoernchen 26 Jul '23

26 Jul '23
Attention is currently required from: Hoernchen. Hello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/osmo-trx/+/33929 to look at the new patch set (#4). Change subject: ms/va: add test tool and data ...................................................................... ms/va: add test tool and data Change-Id: Ie38ed4996134e84ad0481872a743299bb442b3db move burstgen Change-Id: Ie2cf3066500062920201c6fa4c2a4286fd5bbcb0 --- M .checkpatch.conf M .gitignore M utils/Makefile.am A utils/va-test/burst-gen.cpp A utils/va-test/demodbits_tsc7.s8 A utils/va-test/nb_chunk_tsc7.cfile 6 files changed, 563 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/29/33929/4 -- To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/33929 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-trx Gerrit-Branch: master Gerrit-Change-Id: Ie2cf3066500062920201c6fa4c2a4286fd5bbcb0 Gerrit-Change-Number: 33929 Gerrit-PatchSet: 4 Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Attention: Hoernchen <ewild(a)sysmocom.de> Gerrit-MessageType: newpatchset
1 0
0 0
[L] Change in osmo-trx[master]: ms: restructure the va code to add rach support
by Hoernchen 26 Jul '23

26 Jul '23
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-trx/+/33944 ) Change subject: ms: restructure the va code to add rach support ...................................................................... ms: restructure the va code to add rach support Change-Id: I7275a647428661a788646fec10af429fcdcf577e new bb Change-Id: I36dbed6394243c8c2b5e14acbade7b1b82d0708c XX va trials Change-Id: Id1de531249922315da35d2d01778a7611879fb92 fugg Change-Id: Ibe5d538e9970e590877d2a901165defa6dc972fe tx->va needs scaling by 0.1 Change-Id: Ic3cc5748e00584971c4bd509eed7db9d5f09201c sch Change-Id: I41fabcdd5b4a5eb8cff4e42676438b0bffa2e1b9 va1 Change-Id: I93ab3cb8f91bf6e496175ae70e5da0323cabe911 xx Change-Id: I26b5957f80be02df913e31a370e1e7910f4484df va2 Change-Id: I09d6b560241e6797a533e7f8e68e899c42517baa va: max elemn fix max elem returns the first largest element - but the true value is skewed to the right in our case. Change-Id: I1de9b7e280d8723ce9876bef20c790383070e958 SDSD Change-Id: Ie32fc753548583896be9eef486346617ea8b9e88 adsad Change-Id: I3a9a2569c2057feae196b182f6e812edd08ccfa4 make ubsan happy Change-Id: Ic6ddfcf826539dd227e76e8054d3f3d777c97d5e wtf wip Change-Id: I0f465da6d17bf91f24a68b3ec2075995478b5fad a bit of channel impulse resp makes it work (?!) Change-Id: I2ab1d6bdf89a0d950ebe38b1fd5efb9764c9ba4f shp Change-Id: I7f936dd22b55145bd182f3b5e51b9c183ab1725f finally works as intended.. maybe. Change-Id: I2af965ab20af74b38975c645093626a81b7fdf72 cleanup Change-Id: If36f15a5f32465ce04113a669e3875dc19c69d6b cleanup Change-Id: I1163a6194570cdce93d46e40e4b710ad5239cce7 iomanip Change-Id: I20453a5381afcf8a7875b6e82805f7e8595163b2 cleanup3 Change-Id: I8e66f2a447984a1fd5a20814eca3ee019ba59717 cleanup3 Change-Id: Ib499fe0a5d42afd9198da96dbcba2a42705bbe73 use short inted burst Change-Id: I0bc7a7b35da474bce74f8a36834a22d5885bbdbc add burst dump Change-Id: I0ca9114b6a02cac7fb628ac47db2554b3ff3b967 cleanup va Change-Id: I1697925b0f0f36aaa05ee170a9483750611aef5d all tests Change-Id: Ie2db803ccb789699cdfaf82e74acba42123d961a transceiver: add va This needs slightly shifted rx windows that need to include the beginning ot the burst. Change-Id: I64f4f596875434bf3e7201ddbbe58924482f4559 va offset pretty #1 Change-Id: Ibb6d3b351bfd915d4bfc2587c5f5c47d129de360 va pretty #2 Change-Id: I8bd2cb9dbe449324be64d8514593815c0ca24c0b makeu Change-Id: I13ccc55a6f5c0438236490bb1e75f93a0e20fe2e xx mergeme Change-Id: Id8edf31fe1bf72a2f254e634edc7c12b3bba8833 sign comp Change-Id: I4a5cedc8c9a3289c75ce7b914eac286e601ebed0 --- M Transceiver52M/grgsm_vitac/constants.h M Transceiver52M/grgsm_vitac/grgsm_vitac.cpp M Transceiver52M/grgsm_vitac/grgsm_vitac.h M Transceiver52M/ms/ms_rx_lower.cpp M Transceiver52M/ms/ms_upper.cpp 5 files changed, 255 insertions(+), 96 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/44/33944/1 diff --git a/Transceiver52M/grgsm_vitac/constants.h b/Transceiver52M/grgsm_vitac/constants.h index 07f2290..27bf6f4 100644 --- a/Transceiver52M/grgsm_vitac/constants.h +++ b/Transceiver52M/grgsm_vitac/constants.h @@ -38,6 +38,7 @@ #define STEALING_BIT 1 #define N_TRAIN_BITS 26 #define N_SYNC_BITS 64 +#define N_ACCESS_BITS 41 #define USEFUL_BITS 142 //(2*(DATA_BITS+STEALING_BIT) + N_TRAIN_BITS ) #define FCCH_BITS USEFUL_BITS #define BURST_SIZE (USEFUL_BITS+2*TAIL_BITS) @@ -73,6 +74,12 @@ 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 }; +static const unsigned char ACCESS_BITS [] = { + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0 +}; + const unsigned FCCH_FRAMES[] = { 0, 10, 20, 30, 40 }; const unsigned SCH_FRAMES[] = { 1, 11, 21, 31, 41 }; diff --git a/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp b/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp index 836c555..00e3d5a 100644 --- a/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp +++ b/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp @@ -39,13 +39,13 @@ #include "viterbi_detector.h" #include "grgsm_vitac.h" -//signalVector mChanResp; +gr_complex d_sync_training_seq[N_ACCESS_BITS]; ///<encoded training sequence of a SCH burst gr_complex d_sch_training_seq[N_SYNC_BITS]; ///<encoded training sequence of a SCH burst gr_complex d_norm_training_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS]; ///<encoded training sequences of a normal and dummy burst const int d_chan_imp_length = CHAN_IMP_RESP_LENGTH; -void initvita() { - +void initvita() +{ /** * Prepare SCH sequence bits * @@ -53,59 +53,73 @@ * Burst and two guard periods * (one guard period is an arbitrary overlap) */ - gmsk_mapper(SYNC_BITS, N_SYNC_BITS, - d_sch_training_seq, gr_complex(0.0, -1.0)); + gmsk_mapper(SYNC_BITS, N_SYNC_BITS, d_sch_training_seq, gr_complex(0.0, -1.0)); for (auto &i : d_sch_training_seq) i = conj(i); + /* ab */ + gmsk_mapper(ACCESS_BITS, N_ACCESS_BITS, d_sync_training_seq, gr_complex(0.0, -1.0)); + for (auto &i : d_sync_training_seq) + i = conj(i); + /* Prepare bits of training sequences */ for (int i = 0; i < TRAIN_SEQ_NUM; i++) { /** * If first bit of the sequence is 0 * => first symbol is 1, else -1 */ - gr_complex startpoint = train_seq[i][0] == 0 ? - gr_complex(1.0, 0.0) : gr_complex(-1.0, 0.0); - gmsk_mapper(train_seq[i], N_TRAIN_BITS, - d_norm_training_seq[i], startpoint); + gr_complex startpoint = train_seq[i][0] == 0 ? gr_complex(1.0, 0.0) : gr_complex(-1.0, 0.0); + gmsk_mapper(train_seq[i], N_TRAIN_BITS, d_norm_training_seq[i], startpoint); for (auto &i : d_norm_training_seq[i]) i = conj(i); } - } -MULTI_VER_TARGET_ATTR NO_UBSAN -void detect_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary) +template <unsigned int burst_size> +NO_UBSAN static void detect_burst_generic(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, + char *output_binary, int ss) { std::vector<gr_complex> rhh_temp(CHAN_IMP_RESP_LENGTH * d_OSR); unsigned int stop_states[2] = { 4, 12 }; - gr_complex filtered_burst[BURST_SIZE]; + gr_complex filtered_burst[burst_size]; gr_complex rhh[CHAN_IMP_RESP_LENGTH]; - float output[BURST_SIZE]; - int start_state = 3; - - // if(burst_start < 0 ||burst_start > 10) - // fprintf(stderr, "bo %d\n", burst_start); - - // burst_start = burst_start >= 0 ? burst_start : 0; + float output[burst_size]; + int start_state = ss; autocorrelation(chan_imp_resp, &rhh_temp[0], d_chan_imp_length * d_OSR); for (int ii = 0; ii < d_chan_imp_length; ii++) rhh[ii] = conj(rhh_temp[ii * d_OSR]); - mafi(&input[burst_start], BURST_SIZE, chan_imp_resp, - d_chan_imp_length * d_OSR, filtered_burst); + mafi(&input[burst_start], burst_size, chan_imp_resp, d_chan_imp_length * d_OSR, filtered_burst); - viterbi_detector(filtered_burst, BURST_SIZE, rhh, - start_state, stop_states, 2, output); + viterbi_detector(filtered_burst, burst_size, rhh, start_state, stop_states, 2, output); - for (int i = 0; i < BURST_SIZE; i++) - output_binary[i] = output[i] * -127; // pre flip bits! + for (unsigned int i = 0; i < burst_size; i++) + output_binary[i] = (char)(output[i] * -127); // pre flip bits! } -void -gmsk_mapper(const unsigned char* input, - int nitems, gr_complex* gmsk_output, gr_complex start_point) +NO_UBSAN void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary, + int ss) +{ + return detect_burst_generic<BURST_SIZE>(input, chan_imp_resp, burst_start, output_binary, ss); +} +NO_UBSAN void detect_burst_access_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, + char *output_binary, int ss) +{ + return detect_burst_generic<8 + 41 + 36 + 3>(input, chan_imp_resp, burst_start, output_binary, ss); +} + +NO_UBSAN void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary) +{ + return detect_burst_nb(input, chan_imp_resp, burst_start, output_binary, 3); +} +NO_UBSAN void detect_burst_access_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, + char *output_binary) +{ + return detect_burst_access_burst(input, chan_imp_resp, burst_start, output_binary, 3); +} + +void gmsk_mapper(const unsigned char *input, int nitems, gr_complex *gmsk_output, gr_complex start_point) { gr_complex j = gr_complex(0.0, 1.0); gmsk_output[0] = start_point; @@ -122,16 +136,13 @@ encoded_symbol = current_symbol * previous_symbol; /* And do GMSK mapping */ - gmsk_output[i] = j * gr_complex(encoded_symbol, 0.0) - * gmsk_output[i - 1]; + gmsk_output[i] = j * gr_complex(encoded_symbol, 0.0) * gmsk_output[i - 1]; previous_symbol = current_symbol; } } -gr_complex -correlate_sequence(const gr_complex* sequence, - int length, const gr_complex* input) +gr_complex correlate_sequence(const gr_complex *sequence, int length, const gr_complex *input) { gr_complex result(0.0, 0.0); @@ -142,9 +153,7 @@ } /* Computes autocorrelation for positive arguments */ -inline void -autocorrelation(const gr_complex* input, - gr_complex* out, int nitems) +inline void autocorrelation(const gr_complex *input, gr_complex *out, int nitems) { for (int k = nitems - 1; k >= 0; k--) { out[k] = gr_complex(0, 0); @@ -153,9 +162,7 @@ } } -inline void -mafi(const gr_complex* input, int nitems, - gr_complex* filter, int filter_length, gr_complex* output) +inline void mafi(const gr_complex *input, int nitems, gr_complex *filter, int filter_length, gr_complex *output) { for (int n = 0; n < nitems; n++) { int a = n * d_OSR; @@ -170,66 +177,45 @@ } } -int get_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, int search_center, int search_start_pos, - int search_stop_pos, gr_complex *tseq, int tseqlen, float *corr_max) +int get_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, int search_start_pos, int search_stop_pos, + gr_complex *tseq, int tseqlen, float *corr_max) { - std::vector<gr_complex> correlation_buffer; + const int num_search_windows = search_stop_pos - search_start_pos; + const int power_search_window_len = d_chan_imp_length * d_OSR; std::vector<float> window_energy_buffer; std::vector<float> power_buffer; + std::vector<gr_complex> correlation_buffer; - for (int ii = search_start_pos; ii < search_stop_pos; ii++) { - gr_complex correlation = correlate_sequence(tseq, tseqlen, &input[ii]); + power_buffer.reserve(num_search_windows); + correlation_buffer.reserve(num_search_windows); + window_energy_buffer.reserve(num_search_windows); + + for (int ii = 0; ii < num_search_windows; ii++) { + gr_complex correlation = correlate_sequence(tseq, tseqlen, &input[search_start_pos + ii]); correlation_buffer.push_back(correlation); power_buffer.push_back(std::pow(abs(correlation), 2)); } - int strongest_corr_nr = max_element(power_buffer.begin(), power_buffer.end()) - power_buffer.begin(); - /* Compute window energies */ - auto window_energy_start_offset = strongest_corr_nr - 6 * d_OSR; - window_energy_start_offset = window_energy_start_offset < 0 ? 0 : window_energy_start_offset; //can end up out of range.. - auto window_energy_end_offset = strongest_corr_nr + 6 * d_OSR + d_chan_imp_length * d_OSR; - auto iter = power_buffer.begin() + window_energy_start_offset; - auto iter_end = power_buffer.begin() + window_energy_end_offset; - while (iter != iter_end) { - std::vector<float>::iterator iter_ii = iter; - bool loop_end = false; - float energy = 0; + float windowSum = 0; - int len = d_chan_imp_length * d_OSR; - for (int ii = 0; ii < len; ii++, iter_ii++) { - if (iter_ii == power_buffer.end()) { - loop_end = true; - break; - } + // first window + for (int i = 0; i < power_search_window_len; i++) { + windowSum += power_buffer[i]; + } + window_energy_buffer.push_back(windowSum); - energy += (*iter_ii); - } - - if (loop_end) - break; - - window_energy_buffer.push_back(energy); - iter++; + // slide windows + for (int i = power_search_window_len; i < num_search_windows; i++) { + windowSum += power_buffer[i] - power_buffer[i - power_search_window_len]; + window_energy_buffer.push_back(windowSum); } - /* Calculate the strongest window number */ - int strongest_window_nr = window_energy_start_offset + - max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - + int strongest_window_nr = std::max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin(); - // auto window_search_start = window_energy_buffer.begin() + strongest_corr_nr - 5* d_OSR; - // auto window_search_end = window_energy_buffer.begin() + strongest_corr_nr + 10* d_OSR; - // window_search_end = window_search_end >= window_energy_buffer.end() ? window_energy_buffer.end() : window_search_end; - - // /* Calculate the strongest window number */ - // int strongest_window_nr = max_element(window_search_start, window_search_end /* - d_chan_imp_length * d_OSR*/) - window_energy_buffer.begin(); - - // if (strongest_window_nr < 0) - // strongest_window_nr = 0; - float max_correlation = 0; - for (int ii = 0; ii < d_chan_imp_length * d_OSR; ii++) { + for (int ii = 0; ii < power_search_window_len; ii++) { gr_complex correlation = correlation_buffer[strongest_window_nr + ii]; if (abs(correlation) > max_correlation) max_correlation = abs(correlation); @@ -242,7 +228,27 @@ * Compute first sample position, which corresponds * to the first sample of the impulse response */ - return search_start_pos + strongest_window_nr - search_center * d_OSR; + return search_start_pos + strongest_window_nr; +} + +/* +8 ext tail bits +41 sync seq +36 encrypted bits +3 tail bits +68.25 extended tail bits (!) + +center at 8+5 (actually known tb -> known isi, start at 8?) FIXME +*/ +int get_access_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, float *corr_max, int max_delay) +{ + const int search_center = 8 + 5; + const int search_start_pos = (search_center - 5) * d_OSR + 1; + const int search_stop_pos = (search_center + 5 + d_chan_imp_length + max_delay) * d_OSR; + const auto tseq = &d_sync_training_seq[TRAIN_BEGINNING]; + const auto tseqlen = N_ACCESS_BITS - (2 * TRAIN_BEGINNING); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, corr_max) - + search_center * d_OSR; } /* @@ -260,8 +266,8 @@ const int search_stop_pos = (search_center + 5 + d_chan_imp_length) * d_OSR; const auto tseq = &d_norm_training_seq[bcc][TRAIN_BEGINNING]; const auto tseqlen = N_TRAIN_BITS - (2 * TRAIN_BEGINNING); - return get_chan_imp_resp(input, chan_imp_resp, search_center, search_start_pos, search_stop_pos, tseq, tseqlen, - corr_max); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, corr_max) - + search_center * d_OSR; } /* @@ -281,8 +287,9 @@ // strongest_window_nr + chan_imp_resp_center + SYNC_POS *d_OSR - 48 * d_OSR - 2 * d_OSR + 2 ; float corr_max; - return get_chan_imp_resp(input, chan_imp_resp, search_center, search_start_pos, search_stop_pos, tseq, tseqlen, - &corr_max); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, &corr_max) - + search_center * d_OSR; + ; } int get_sch_buffer_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, unsigned int len, float *corr_max) @@ -291,9 +298,9 @@ const int search_center = SYNC_POS + TRAIN_BEGINNING; const int search_start_pos = 0; // FIXME: proper end offset - const int search_stop_pos = len - (N_SYNC_BITS*8); + const int search_stop_pos = len - (N_SYNC_BITS * 8); auto tseq = &d_sch_training_seq[TRAIN_BEGINNING]; - return get_chan_imp_resp(input, chan_imp_resp, search_center, search_start_pos, search_stop_pos, tseq, tseqlen, - corr_max); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, corr_max) - + search_center * d_OSR; } \ No newline at end of file diff --git a/Transceiver52M/grgsm_vitac/grgsm_vitac.h b/Transceiver52M/grgsm_vitac/grgsm_vitac.h index 2c89d8c..9d4c300 100644 --- a/Transceiver52M/grgsm_vitac/grgsm_vitac.h +++ b/Transceiver52M/grgsm_vitac/grgsm_vitac.h @@ -58,8 +58,13 @@ int process_vita_burst(gr_complex *input, int tsc, unsigned char *output_binary); int process_vita_sc_burst(gr_complex *input, int tsc, unsigned char *output_binary, int *offset); -MULTI_VER_TARGET_ATTR_CLANGONLY -void detect_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary); +void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary, int ss); +void detect_burst_access_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary, + int ss); +void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary); +void detect_burst_access_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, + char *output_binary); + void gmsk_mapper(const unsigned char *input, int nitems, gr_complex *gmsk_output, gr_complex start_point); gr_complex correlate_sequence(const gr_complex *sequence, int length, const gr_complex *input); inline void autocorrelation(const gr_complex *input, gr_complex *out, int nitems); @@ -67,6 +72,7 @@ int get_sch_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp); int get_norm_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, float *corr_max, int bcc); int get_sch_buffer_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, unsigned int len, float *corr_max); +int get_access_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, float *corr_max, int max_delay); enum class btype { NB, SCH }; struct fdata { diff --git a/Transceiver52M/ms/ms_rx_lower.cpp b/Transceiver52M/ms/ms_rx_lower.cpp index 5a07df5..c2adda3 100644 --- a/Transceiver52M/ms/ms_rx_lower.cpp +++ b/Transceiver52M/ms/ms_rx_lower.cpp @@ -170,7 +170,7 @@ start = start < 39 ? start : 39; start = start > -39 ? start : -39; } - detect_burst(&ss[start], &channel_imp_resp[0], 0, sch_demod_bits); + detect_burst_nb(&ss[start], &channel_imp_resp[0], 0, sch_demod_bits); auto sch_decode_success = decode_sch(sch_demod_bits, is_first_sch_acq); diff --git a/Transceiver52M/ms/ms_upper.cpp b/Transceiver52M/ms/ms_upper.cpp index 21f70bb..6a83f2a 100644 --- a/Transceiver52M/ms/ms_upper.cpp +++ b/Transceiver52M/ms/ms_upper.cpp @@ -196,7 +196,7 @@ // fprintf(stderr, "%s %d\n", (is_nb ? "N":"D"), burst_time.FN()); // if (is_nb) #endif - detect_burst(ss, &chan_imp_resp[0], normal_burst_start, demodded_softbits); + detect_burst_nb(ss, &chan_imp_resp[0], normal_burst_start, demodded_softbits); #ifdef DBGXX // else // detect_burst(ss, &chan_imp_resp2[0], dummy_burst_start, outbin); -- To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/33944 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-trx Gerrit-Branch: master Gerrit-Change-Id: I4a5cedc8c9a3289c75ce7b914eac286e601ebed0 Gerrit-Change-Number: 33944 Gerrit-PatchSet: 1 Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de> Gerrit-MessageType: newchange
1 0
0 0
[L] Change in osmo-tetra[master]: Added first steps towards tetra crypto support
by wbokslag 26 Jul '23

26 Jul '23
Attention is currently required from: wbokslag. Hello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 to look at the new patch set (#3). Change subject: Added first steps towards tetra crypto support ...................................................................... Added first steps towards tetra crypto support A crypto folder has been added containing only a single c and h file at the moment. These files contain structs and high level functionality pertaining to TETRA crypto support which can be added in future patches. Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 --- M src/Makefile A src/crypto/tetra_crypto.c A src/crypto/tetra_crypto.h 3 files changed, 416 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/osmo-tetra refs/changes/43/33943/3 -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 Gerrit-Change-Number: 33943 Gerrit-PatchSet: 3 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Reviewer: Jenkins Builder Gerrit-Attention: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-MessageType: newpatchset
1 0
0 0
[L] Change in osmo-tetra[master]: Added first steps towards tetra crypto support
by Jenkins Builder 26 Jul '23

26 Jul '23
Attention is currently required from: wbokslag. Jenkins Builder has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-tetra/+/33943 ) Change subject: Added first steps towards tetra crypto support ...................................................................... Patch Set 2: (1 comment) File src/crypto/tetra_crypto.c: Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10059): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/2aa9522c_b044e47b PS2, Line 46: if (tea_type >= TEA_PROPRIETARY) trailing whitespace -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 Gerrit-Change-Number: 33943 Gerrit-PatchSet: 2 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Reviewer: Jenkins Builder Gerrit-Attention: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Comment-Date: Wed, 26 Jul 2023 15:56:38 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-tetra[master]: Added first steps towards tetra crypto support
by wbokslag 26 Jul '23

26 Jul '23
Attention is currently required from: wbokslag. Hello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 to look at the new patch set (#2). Change subject: Added first steps towards tetra crypto support ...................................................................... Added first steps towards tetra crypto support A crypto folder has been added containing only a single c and h file at the moment. These files contain structs and high level functionality pertaining to TETRA crypto support which can be added in future patches. Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 --- M src/Makefile A src/crypto/tetra_crypto.c A src/crypto/tetra_crypto.h 3 files changed, 416 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/osmo-tetra refs/changes/43/33943/2 -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 Gerrit-Change-Number: 33943 Gerrit-PatchSet: 2 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Reviewer: Jenkins Builder Gerrit-Attention: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-MessageType: newpatchset
1 0
0 0
[L] Change in osmo-tetra[master]: Added first steps towards tetra crypto support
by Jenkins Builder 26 Jul '23

26 Jul '23
Jenkins Builder has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-tetra/+/33943 ) Change subject: Added first steps towards tetra crypto support ...................................................................... Patch Set 1: (12 comments) File src/crypto/tetra_crypto.h: Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/227e4cd5_1b634f19 PS1, Line 98: void tetra_crypto_init(); Bad function definition - void tetra_crypto_init() should probably be void tetra_crypto_init(void) Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/4224422e_0a259b3d PS1, Line 112: void update_current_cck(); Bad function definition - void update_current_cck() should probably be void update_current_cck(void) File src/crypto/tetra_crypto.c: Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/29f1db8b_ac8bda28 PS1, Line 46: if (tea_type > 7) { braces {} are not necessary for any arm of this statement Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/153f6c0c_ce5e4715 PS1, Line 67: void tetra_crypto_init() Bad function definition - void tetra_crypto_init() should probably be void tetra_crypto_init(void) Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/dd7a2431_0bb330ff PS1, Line 98: if (k->key_type & (KEYTYPE_DCK | KEYTYPE_MGCK)) { braces {} are not necessary for single statement blocks Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/d6b92260_251f93a1 PS1, Line 101: if (k->key_type & (KEYTYPE_CCK | KEYTYPE_SCK)) { braces {} are not necessary for single statement blocks Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/e98f2fdc_65308100 PS1, Line 106: for (int i = 0; i < 10; i++) { braces {} are not necessary for single statement blocks Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/5a1efc88_338960ad PS1, Line 163: if (addr >= tcdb->ranges[i].start && addr < tcdb->ranges[i].end) { braces {} are not necessary for single statement blocks Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/d928f9c9_0305e15c PS1, Line 217: if (!tcs->network) { braces {} are not necessary for single statement blocks Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/444700d2_05f2db1b PS1, Line 223: if (is_issi(addr)) { braces {} are not necessary for single statement blocks Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/e406ba8d_412f5db4 PS1, Line 262: void update_current_cck() Bad function definition - void update_current_cck() should probably be void update_current_cck(void) Robot Comment from checkpatch (run ID jenkins-gerrit-lint-10057): https://gerrit.osmocom.org/c/osmo-tetra/+/33943/comment/8ba9ce29_424802cc PS1, Line 284: if (tcdb->nets[i].mcc == mcc && tcdb->nets[i].mnc == mnc) { braces {} are not necessary for single statement blocks -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 Gerrit-Change-Number: 33943 Gerrit-PatchSet: 1 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-CC: Jenkins Builder Gerrit-Comment-Date: Wed, 26 Jul 2023 15:48:17 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-tetra[master]: Added first steps towards tetra crypto support
by wbokslag 26 Jul '23

26 Jul '23
wbokslag has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-tetra/+/33943 ) Change subject: Added first steps towards tetra crypto support ...................................................................... Added first steps towards tetra crypto support A crypto folder has been added containing only a single c and h file at the moment. These files contain structs and high level functionality pertaining to TETRA crypto support which can be added in future patches. Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 --- M src/Makefile A src/crypto/tetra_crypto.c A src/crypto/tetra_crypto.h 3 files changed, 424 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/osmo-tetra refs/changes/43/33943/1 diff --git a/src/Makefile b/src/Makefile index 41250a9..9b12484 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,11 +16,14 @@ libosmo-tetra-mac.a: lower_mac/tetra_conv_enc.o lower_mac/tch_reordering.o tetra_tdma.o lower_mac/tetra_scramb.o lower_mac/tetra_rm3014.o lower_mac/tetra_interleave.o lower_mac/crc_simple.o tetra_common.o lower_mac/viterbi.o lower_mac/viterbi_cch.o lower_mac/viterbi_tch.o lower_mac/tetra_lower_mac.o tetra_upper_mac.o tetra_mac_pdu.o tetra_llc_pdu.o tetra_llc.o tetra_mle_pdu.o tetra_mle.o tetra_mm_pdu.o tetra_cmce_pdu.o tetra_sndcp_pdu.o tetra_gsmtap.o tuntap.o $(AR) r $@ $^ +libosmo-tetra-crypto.a: crypto/tetra_crypto.o + $(AR) r $@ $^ + float_to_bits: float_to_bits.o crc_test: crc_test.o tetra_common.o libosmo-tetra-mac.a -tetra-rx: tetra-rx.o libosmo-tetra-phy.a libosmo-tetra-mac.a +tetra-rx: tetra-rx.o libosmo-tetra-phy.a libosmo-tetra-mac.a libosmo-tetra-crypto.a conv_enc_test: conv_enc_test.o testpdu.o libosmo-tetra-phy.a libosmo-tetra-mac.a diff --git a/src/crypto/tetra_crypto.c b/src/crypto/tetra_crypto.c new file mode 100644 index 0000000..c5e78e6 --- /dev/null +++ b/src/crypto/tetra_crypto.c @@ -0,0 +1,289 @@ +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include <osmocom/core/utils.h> +#include <tetra_mac_pdu.h> +#include <phy/tetra_burst.h> + +#include "tetra_crypto.h" + +struct tetra_crypto_database _tcdb, *tcdb = &_tcdb; +struct tetra_crypto_state _tcs, *tcs = &_tcs; + +static const struct value_string tetra_key_types[] = { + { KEYTYPE_UNDEFINED, "UNDEFINED" }, + { KEYTYPE_DCK, "DCK" }, + { KEYTYPE_MGCK, "MGCK" }, + { KEYTYPE_SCK, "SCK" }, + { KEYTYPE_CCK, "CCK" }, + { KEYTYPE_GCK, "GCK" }, + { 0, NULL } +}; + +const char *tetra_get_key_type_name(int key_type) +{ + return get_value_string(tetra_key_types, key_type); +} + +static const struct value_string tetra_tea_types[] = { + { UNKNOWN, "UNKNOWN" }, + { TEA1, "TEA1" }, + { TEA2, "TEA2" }, + { TEA3, "TEA3" }, + { TEA4, "TEA4" }, + { TEA5, "TEA5" }, + { TEA6, "TEA6" }, + { TEA7, "TEA7" }, + { PROPRIETARY, "PROPRIETARY" }, + { 0, NULL } +}; + +const char *tetra_get_tea_type_name(int tea_type) +{ + if (tea_type > 7) { + return tetra_tea_types[PROPRIETARY].str; // proprietary + } else { + return get_value_string(tetra_tea_types, tea_type); + } +} + +static const struct value_string tetra_security_classes[] = { + { NETWORK_CLASS_UNDEFINED, "CLASS_UNDEFINED" }, + { NETWORK_CLASS_1, "CLASS_1" }, + { NETWORK_CLASS_2, "CLASS_2" }, + { NETWORK_CLASS_3, "CLASS_3" }, + { NETWORK_CLASS_3G, "CLASS_3G" }, + { 0, NULL } +}; + +const char *tetra_get_security_class_name(uint8_t pdut) +{ + return get_value_string(tetra_security_classes, pdut); +} + +void tetra_crypto_init() +{ + /* Initialize tetra_crypto_state */ + tcs->mnc = -1; + tcs->mcc = -1; + tcs->network = 0; + tcs->cck_id = -1; + tcs->cck = 0; + tcs->hn = -1; + tcs->la = -1; + tcs->cc = -1; + + /* Initialize tetra_crypto_database */ + tcdb->num_keys = 0; + tcdb->num_nets = 0; + tcdb->num_ranges = 0; + tcdb->keys = calloc(TCDB_ALLOC_BLOCK_SIZE, sizeof(struct tetra_key)); + tcdb->nets = calloc(TCDB_ALLOC_BLOCK_SIZE, sizeof(struct network_info)); + tcdb->ranges = calloc(TCDB_ALLOC_BLOCK_SIZE, sizeof(struct address_range)); + if (!tcdb->keys || !tcdb->nets || !tcdb->ranges) { + fprintf(stderr, "couldn't allocate memory for tetra_crypto_database\n"); + exit(1); + } +} + +char *dump_key(struct tetra_key *k) +{ + static char pbuf[1024]; + + int c = snprintf(pbuf, sizeof(pbuf), "MCC %4d MNC %4d key_type %02X", + k->mcc, k->mnc, k->key_type); + if (k->key_type & (KEYTYPE_DCK | KEYTYPE_MGCK)) { + c += snprintf(pbuf + c, sizeof(pbuf) - c, " addr: %8d", k->addr); + } + if (k->key_type & (KEYTYPE_CCK | KEYTYPE_SCK)) { + c += snprintf(pbuf + c, sizeof(pbuf) - c, " key_num: %4d", k->key_num); + } + + c += snprintf(pbuf + c, sizeof(pbuf) - c, ": "); + for (int i = 0; i < 10; i++) { + snprintf(pbuf + c + 2*i, sizeof(pbuf)-c-2*i, "%02X", k->key[i]); + } + return pbuf; +} + +char *dump_network_info(struct network_info *network) +{ + static char pbuf[1024]; + snprintf(pbuf, sizeof(pbuf), "MCC %4d MNC %4d tea_type %d security_class %d", network->mcc, network->mnc, network->tea_type, network->security_class); + return pbuf; +} + +uint32_t tea_build_iv(struct tetra_tdma_time *tm, uint16_t hn, uint8_t dir) +{ + assert(1 <= tm->tn && tm->tn <= 4); + assert(1 <= tm->fn && tm->fn <= 18); + assert(1 <= tm->mn && tm->mn <= 60); + assert(0 <= tm->hn && tm->hn <= 0xFFFF); + assert(0 <= dir && dir <= 1); // 0 = downlink, 1 = uplink + return ((tm->tn - 1) | (tm->fn << 2) | (tm->mn << 7) | ((hn & 0x7FFF) << 13) | (dir << 28)); +} + +int decrypt_identity(struct tetra_addr *addr) +{ + return 0; +} + +int decrypt_mac_element(struct tetra_tmvsap_prim *tmvp, struct tetra_key *key, int l1_len, int tmpdu_offset) +{ + return 0; +} + +int decrypt_voice_timeslot(struct tetra_tdma_time *tdma_time, int16_t *type1_block) +{ + return 0; +} + +int load_keystore(char *tetra_keyfile) +{ + return 0; +} + +void unload_keystore(void) +{ + /* Free database and set ptr to null */ + free(tcdb->keys); + free(tcdb->nets); + free(tcdb->ranges); + + /* Reset any lingering pointers */ + tetra_crypto_init(); +} + +int is_gssi(int addr) +{ + for (int i = 0; i < tcdb->num_ranges; i++) { + if (addr >= tcdb->ranges[i].start && addr < tcdb->ranges[i].end) { + return 1; + } + } + return 0; +} + +int is_issi(int addr) +{ + return !is_gssi(addr); +} + +struct tetra_key *get_key_by_addr(int addr, enum tetra_key_type key_type) +{ + for (int i = 0; i < tcdb->num_keys; i++) { + struct tetra_key *key = &tcdb->keys[i]; + if (key->mnc == tcs->mnc && + key->mcc == tcs->mcc && + key->addr == addr && + (key->key_type & key_type)) { + return key; + } + } + return 0; +} + +struct tetra_key *get_tea_key(int addr) +{ + /* TETRA standard part 7 Clause 6.2: + Class 1: + Shall not use encryption + May use authentication + + Class 2: SCK Mode + Shall use SCK encryption + Shall use ESI with SCK + May use MGCK encryption + May use authentication + + Class 3: DCK Mode + Shall use authentication + Shall use DCK, CCK and/or MGCK encryption + Shall use ESI with CCK + + An address may be an: + - ISSI (individual), + - ASSI (not considered as of yet), + - GSSI (group) + + According to part 1 Clause 7.2.5: + The SSIs (ISSI, ASSI or GSSI) shall be allocated by the network operator. + As such, we do not know what SSI type we get. Also, we get an encrypted identity. + */ + + if (!tcs->network) { + return 0; + } + + if (tcs->network->security_class == NETWORK_CLASS_3G) { + /* This network uses DCKs. Check if individually addressed */ + if (is_issi(addr)) { + return get_key_by_addr(addr, KEYTYPE_DCK); + } + } + + if (is_gssi(addr)) { + /* Group addressed. Let's assume we use MGCKs on this network */ + /* FIXME: check if indeed MGCK used */ + /* FIXME: select MGCK if required */ + // return get_key_by_addr(addr, KEYTYPE_MGCK); + } + + // Individually addressed using CCK or SCK + return tcs->cck; +} + +void update_current_network(int mcc, int mnc) +{ + if (tcs->mnc != mcc || tcs->mcc != mnc) { + + // Update globals + tcs->mcc = mcc; + tcs->mnc = mnc; + + // Network changed, update reference to current network + tcs->network = 0; + for (int i = 0; i < tcdb->num_nets; i++) { + struct network_info *network = &tcdb->nets[i]; + if (network->mnc == tcs->mnc && network->mcc == tcs->mcc) { + tcs->network = network; + break; + } + } + + } + + update_current_cck(); +} + +void update_current_cck() +{ + printf("\ntetra_crypto: update_current_cck invoked cck %d mcc %d mnc %d\n", tcs->cck_id, tcs->mcc, tcs->mnc); + tcs->cck = 0; + + for (int i = 0; i < tcdb->num_keys; i++) { + struct tetra_key *key = &tcdb->keys[i]; + /* TODO FIXME consider selecting CCK or SCK key type based on network config */ + if (key->mcc == tcs->mcc && key->mnc == tcs->mnc && key->key_num == tcs->cck_id) { + if (key->key_type == KEYTYPE_SCK || key->key_type == KEYTYPE_CCK) { + // Best case: full SCK or CCK + tcs->cck = key; + printf("tetra_crypto: Set new current_cck %d (type: full)\n", i); + break; + } + } + } +} + +struct network_info *get_network_info(int mcc, int mnc) +{ + for (int i = 0; i < tcdb->num_nets; i++) { + if (tcdb->nets[i].mcc == mcc && tcdb->nets[i].mnc == mnc) { + return &tcdb->nets[i]; + } + } + return 0; +} diff --git a/src/crypto/tetra_crypto.h b/src/crypto/tetra_crypto.h new file mode 100644 index 0000000..745f824 --- /dev/null +++ b/src/crypto/tetra_crypto.h @@ -0,0 +1,120 @@ +#ifndef TETRA_CRYPTO_H +#define TETRA_CRYPTO_H + +#include <inttypes.h> +#include <stdbool.h> + +#include "../tetra_prim.h" +#include "../tetra_tdma.h" +#include "../tetra_mac_pdu.h" + +#define TCDB_ALLOC_BLOCK_SIZE 1 + +enum tetra_key_type { + KEYTYPE_UNDEFINED = 0x00, + + /* Keytypes usable as ECK after applying TB5 */ + KEYTYPE_DCK = 0x01, + KEYTYPE_MGCK = 0x02, + KEYTYPE_SCK = 0x04, + KEYTYPE_CCK = 0x08, + + /* Can be combined with SCK/CCK to get MGCK */ + KEYTYPE_GCK = 0x20, +}; + +enum tetra_tea_type { + UNKNOWN = 0, + TEA1 = 1, /* KSG number value 0 */ + TEA2 = 2, /* KSG number value 1 */ + TEA3 = 3, /* KSG number value 2 */ + TEA4 = 4, /* KSG number value 3 */ + TEA5 = 5, /* KSG number value 4 */ + TEA6 = 6, /* KSG number value 5 */ + TEA7 = 7, /* KSG number value 6 */ + PROPRIETARY = 8, /* KSG number values 9-15 */ +}; + +enum tetra_security_class { + NETWORK_CLASS_UNDEFINED = 0, + NETWORK_CLASS_1 = 1, + NETWORK_CLASS_2 = 2, + NETWORK_CLASS_3 = 3, + NETWORK_CLASS_3G = 4, /* Class 3 with GCK */ +}; + +struct network_info { + int mcc; + int mnc; + enum tetra_tea_type tea_type; /* KSG used in this network */ + enum tetra_security_class security_class; /* Security class this network employs */ +}; + +struct address_range { + int is_gssi_range; + int start; + int end; +}; + +struct tetra_key { + uint32_t index; /* position in key list */ + uint32_t mnc; + uint32_t mcc; + enum tetra_key_type key_type; + uint32_t key_num; /* key_vn or whatever key numbering system is relevant for this key type */ + uint32_t addr; /* ISSI, GSSI, or whatever address is relevant for this key type */ + uint8_t key[16]; /* Depending on key type, only first part may be used */ + struct network_info *network_info; /* Network with which the key is associated */ +}; + +struct tetra_crypto_database { + int num_keys; + struct tetra_key *keys; + int num_nets; + struct network_info *nets; + int num_ranges; + struct address_range *ranges; +}; +extern struct tetra_crypto_database *tcdb; + +struct tetra_crypto_state { + int mnc; /* Network info for selecting keys */ + int mcc; /* Network info for selecting keys */ + int cck_id; /* CCK id for key selection (from SYSINFO) */ + int hn; /* Hyperframe number for IV (from SYSINFO) */ + int la; /* location area for TB5 */ + int cn; /* carrier number for TB5 */ + int cc; /* colour code for TB5 */ + struct network_info *network; /* pointer to network info struct loaded from file */ + struct tetra_key *cck; /* pointer to CCK or SCK for this network and version (from SYSINFO) */ +}; +extern struct tetra_crypto_state *tcs; + +const char *tetra_get_key_type_name(int key_type); +const char *tetra_get_tea_type_name(int tea_type); +const char *tetra_get_security_class_name(uint8_t pdut); + +/* Key loading / unloading */ +void tetra_crypto_init(); +int load_keystore(char *filename); +void unload_keystore(void); + +/* Keystream generation and decryption functions */ +uint32_t tea_build_iv(struct tetra_tdma_time *tm, uint16_t hn, uint8_t dir); +int decrypt_identity(struct tetra_addr *addr); +int decrypt_mac_element(struct tetra_tmvsap_prim *tmvp, struct tetra_key *key, int l1_len, int tmpdu_offset); +int decrypt_voice_timeslot(struct tetra_tdma_time *tdma_time, int16_t *type1_bits); + +/* Key selection and crypto state management */ +struct tetra_key *get_tea_key(int addr); +struct network_info *get_network_info(int mcc, int mnc); +void update_current_network(int mcc, int mnc); +void update_current_cck(); + +int is_gssi(int addr); +int is_issi(int addr); + +char *dump_network_info(struct network_info *network); +char *dump_key(struct tetra_key *k); + +#endif /* TETRA_CRYPTO_H */ -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33943 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I63bc712630ae5dbaa049c129d456f7aef5bda863 Gerrit-Change-Number: 33943 Gerrit-PatchSet: 1 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-MessageType: newchange
1 0
0 0
[S] Change in osmo-tetra[master]: Added support for slot stealing
by wbokslag 26 Jul '23

26 Jul '23
Attention is currently required from: wbokslag. Hello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/osmo-tetra/+/33942 to look at the new patch set (#2). Change subject: Added support for slot stealing ...................................................................... Added support for slot stealing Slot stealing is how a traffic slot can be partially or fully "stolen" by a control channel. This patch adds support for that and maintains the stealing status in the tetra_mac_state. This can be used to prevent passing a signalling half slot to the voice decoder. Change-Id: I01a112e6e74f75401649d358b8f98c6248d2522b --- M src/lower_mac/tetra_lower_mac.c M src/tetra_common.h 2 files changed, 28 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/osmo-tetra refs/changes/42/33942/2 -- To view, visit https://gerrit.osmocom.org/c/osmo-tetra/+/33942 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-tetra Gerrit-Branch: master Gerrit-Change-Id: I01a112e6e74f75401649d358b8f98c6248d2522b Gerrit-Change-Number: 33942 Gerrit-PatchSet: 2 Gerrit-Owner: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-Reviewer: Jenkins Builder Gerrit-Attention: wbokslag <w.bokslag(a)midnightblue.nl> Gerrit-MessageType: newpatchset
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • ...
  • 306
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.