From 59e06e22ee584a7884f339183472ce75b4068008 Mon Sep 17 00:00:00 2001 From: luckyhacky Date: Mon, 30 Dec 2013 20:32:09 +0100 Subject: [PATCH 01/11] added basic hyperframe support for output --- src/tetra_tdma.c | 3 +-- src/tetra_tdma.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tetra_tdma.c b/src/tetra_tdma.c index 8fffa39..e138f49 100644 --- a/src/tetra_tdma.c +++ b/src/tetra_tdma.c @@ -95,6 +95,5 @@ char *tetra_tdma_time_dump(const struct tetra_tdma_time *tm) uint32_t tetra_tdma_time2fn(struct tetra_tdma_time *tm) { - /* FIXME: add hyperframe number !! */ - return (tm->mn *18) + tm->fn; + return (((tm->hn * 60) + tm->mn) * 18) + tm->fn; } diff --git a/src/tetra_tdma.h b/src/tetra_tdma.h index 86c17af..01519ee 100644 --- a/src/tetra_tdma.h +++ b/src/tetra_tdma.h @@ -4,6 +4,7 @@ #include struct tetra_tdma_time { + uint16_t hn; /* hyperframe number (1 ... 65535) */ uint32_t sn; /* symbol number (1 ... 255) */ uint32_t tn; /* timeslot number (1 .. 4) */ uint32_t fn; /* frame number (1 .. 18) */ From 6dcdb8945482554160ccade3a68cf23770d11fea Mon Sep 17 00:00:00 2001 From: luckyhacky Date: Mon, 30 Dec 2013 20:58:30 +0100 Subject: [PATCH 02/11] set hyperframe number in struct tdma_time --- src/tetra_upper_mac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tetra_upper_mac.c b/src/tetra_upper_mac.c index e5b9f30..fdc8c73 100644 --- a/src/tetra_upper_mac.c +++ b/src/tetra_upper_mac.c @@ -49,6 +49,7 @@ static void rx_bcast(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms memset(&sid, 0, sizeof(sid)); macpdu_decode_sysinfo(&sid, msg->l1h); + tmvp->u.unitdata.tdma_time.hn = sid.hyperframe_number; dl_freq = tetra_dl_carrier_hz(sid.freq_band, sid.main_carrier, From 165bf705a2a8546f17e40ddd9b82e88c979ae17c Mon Sep 17 00:00:00 2001 From: luckyhacky Date: Mon, 30 Dec 2013 23:02:41 +0100 Subject: [PATCH 03/11] fixed typo --- src/tetra_prim.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tetra_prim.h b/src/tetra_prim.h index 9bbb830..8913187 100644 --- a/src/tetra_prim.h +++ b/src/tetra_prim.h @@ -9,7 +9,7 @@ enum tetra_saps { TETRA_SAP_TP, /* between PHY and lower MAC */ - TETRA_SAP_TMV, /* beetween lower and upper MAC */ + TETRA_SAP_TMV, /* between lower and upper MAC */ TETRA_SAP_TMA, TETRA_SAP_TMB, TETRA_SAP_TMD, From 732d06d531a3bb43ca6bd489da09bade6295ef55 Mon Sep 17 00:00:00 2001 From: luckyhacky Date: Mon, 30 Dec 2013 23:18:11 +0100 Subject: [PATCH 04/11] align for better readability --- src/tetra_mac_pdu.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tetra_mac_pdu.c b/src/tetra_mac_pdu.c index 70b5ec9..ec31e4f 100644 --- a/src/tetra_mac_pdu.c +++ b/src/tetra_mac_pdu.c @@ -41,19 +41,19 @@ static void decode_d_mle_sysinfo(struct tetra_mle_si_decoded *msid, const uint8_ void macpdu_decode_sysinfo(struct tetra_si_decoded *sid, const uint8_t *si_bits) { - const uint8_t *cur = si_bits + 4; + const uint8_t *cur = si_bits + 4; - sid->main_carrier = bits_to_uint(cur, 12); cur += 12; - sid->freq_band = bits_to_uint(cur, 4); cur += 4; - sid->freq_offset = bits_to_uint(cur, 2); cur += 2; - sid->duplex_spacing = bits_to_uint(cur, 3); cur += 3; + sid->main_carrier = bits_to_uint(cur, 12); cur += 12; + sid->freq_band = bits_to_uint(cur, 4); cur += 4; + sid->freq_offset = bits_to_uint(cur, 2); cur += 2; + sid->duplex_spacing = bits_to_uint(cur, 3); cur += 3; sid->reverse_operation = *cur++; - sid->num_of_csch = bits_to_uint(cur, 2); cur +=2; - sid->ms_txpwr_max_cell = bits_to_uint(cur, 3); cur += 3; - sid->rxlev_access_min = bits_to_uint(cur, 4); cur += 4; - sid->access_parameter = bits_to_uint(cur, 4); cur += 4; - sid->radio_dl_timeout = bits_to_uint(cur, 4); cur += 4; - sid->cck_valid_no_hf = *cur++; + sid->num_of_csch = bits_to_uint(cur, 2); cur += 2; + sid->ms_txpwr_max_cell = bits_to_uint(cur, 3); cur += 3; + sid->rxlev_access_min = bits_to_uint(cur, 4); cur += 4; + sid->access_parameter = bits_to_uint(cur, 4); cur += 4; + sid->radio_dl_timeout = bits_to_uint(cur, 4); cur += 4; + sid->cck_valid_no_hf = *cur++; if (sid->cck_valid_no_hf) sid->cck_id = bits_to_uint(cur, 16); else From 83140af8d0cf66b8ebf7c414f4ed8ef561f4fec2 Mon Sep 17 00:00:00 2001 From: luckyhacky Date: Mon, 30 Dec 2013 23:42:36 +0100 Subject: [PATCH 05/11] extended sysinfo as described in section 21.4.4.1 now every transmitted field in sysinfo is analyzed --- src/tetra_mac_pdu.c | 25 +++++++++++++++++++++---- src/tetra_mac_pdu.h | 6 ++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/tetra_mac_pdu.c b/src/tetra_mac_pdu.c index ec31e4f..f1fed10 100644 --- a/src/tetra_mac_pdu.c +++ b/src/tetra_mac_pdu.c @@ -39,9 +39,12 @@ static void decode_d_mle_sysinfo(struct tetra_mle_si_decoded *msid, const uint8_ msid->bs_service_details = bits_to_uint(cur, 12); cur += 12; } +/* see 21.4.4.1 */ void macpdu_decode_sysinfo(struct tetra_si_decoded *sid, const uint8_t *si_bits) { - const uint8_t *cur = si_bits + 4; + const uint8_t *cur = si_bits; + cur += 2; // skip Broadcast PDU header + cur += 2; // skip Sysinfo PDU header sid->main_carrier = bits_to_uint(cur, 12); cur += 12; sid->freq_band = bits_to_uint(cur, 4); cur += 4; @@ -58,9 +61,23 @@ void macpdu_decode_sysinfo(struct tetra_si_decoded *sid, const uint8_t *si_bits) sid->cck_id = bits_to_uint(cur, 16); else sid->hyperframe_number = bits_to_uint(cur, 16); - cur += 16; - /* FIXME: more */ - decode_d_mle_sysinfo(&sid->mle_si, si_bits + 124-42); + + sid->option_field = bits_to_uint(cur, 2); cur += 2; + switch(sid->option_field) + { + case 0x00: // Even multiframe definition for TS mode + case 0x01: // Odd multiframe definition for TS mode + sid->frame_bitmap = bits_to_uint(cur, 20); cur += 20; + break; + case 0x02: // Default definition for access code A + sid->access_code = bits_to_uint(cur, 20); cur += 20; + break; + case 0x04: // Extended services broadcast + sid->ext_service = bits_to_uint(cur, 20); cur += 20; + break; + } + + decode_d_mle_sysinfo(&sid->mle_si, si_bits + 124-42); // could be also cur due to previous fixes } static const uint8_t addr_len_by_type[] = { diff --git a/src/tetra_mac_pdu.h b/src/tetra_mac_pdu.h index 74608a6..b0244ff 100644 --- a/src/tetra_mac_pdu.h +++ b/src/tetra_mac_pdu.h @@ -60,6 +60,12 @@ struct tetra_si_decoded { uint16_t cck_id; uint16_t hyperframe_number; }; + uint8_t option_field; + union { + uint32_t frame_bitmap; + uint32_t access_code; + uint32_t ext_service; + }; struct tetra_mle_si_decoded mle_si; }; From 6f78d76052034e655b6c5672fe7ed0ab27e24c39 Mon Sep 17 00:00:00 2001 From: luckyhacky Date: Mon, 30 Dec 2013 23:58:58 +0100 Subject: [PATCH 06/11] removed hard coded values - exchanged it with enum for better readability --- src/tetra_mac_pdu.c | 8 ++++---- src/tetra_mac_pdu.h | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/tetra_mac_pdu.c b/src/tetra_mac_pdu.c index f1fed10..b395b7c 100644 --- a/src/tetra_mac_pdu.c +++ b/src/tetra_mac_pdu.c @@ -65,14 +65,14 @@ void macpdu_decode_sysinfo(struct tetra_si_decoded *sid, const uint8_t *si_bits) sid->option_field = bits_to_uint(cur, 2); cur += 2; switch(sid->option_field) { - case 0x00: // Even multiframe definition for TS mode - case 0x01: // Odd multiframe definition for TS mode + case TETRA_MAC_OPT_FIELD_EVEN_MULTIFRAME: // Even multiframe definition for TS mode + case TETRA_MAC_OPT_FIELD_ODD_MULTIFRAME: // Odd multiframe definition for TS mode sid->frame_bitmap = bits_to_uint(cur, 20); cur += 20; break; - case 0x02: // Default definition for access code A + case TETRA_MAC_OPT_FIELD_ACCESS_CODE: // Default definition for access code A sid->access_code = bits_to_uint(cur, 20); cur += 20; break; - case 0x04: // Extended services broadcast + case TETRA_MAC_OPT_FIELD_EXT_SERVICES: // Extended services broadcast sid->ext_service = bits_to_uint(cur, 20); cur += 20; break; } diff --git a/src/tetra_mac_pdu.h b/src/tetra_mac_pdu.h index b0244ff..051e47a 100644 --- a/src/tetra_mac_pdu.h +++ b/src/tetra_mac_pdu.h @@ -36,6 +36,13 @@ enum tetra_bs_serv_details { BS_SERVDET_ADV_LINK = (1 << 0), }; +enum tetra_mac_optional_field_flags { + TETRA_MAC_OPT_FIELD_EVEN_MULTIFRAME = 0, + TETRA_MAC_OPT_FIELD_ODD_MULTIFRAME = 1, + TETRA_MAC_OPT_FIELD_ACCESS_CODE = 2, + TETRA_MAC_OPT_FIELD_EXT_SERVICES = 3 +}; + const char *tetra_get_bs_serv_det_name(uint32_t pdu_type); struct tetra_mle_si_decoded { From c065f9214c758ead2c746b5ef7d57837bcc6edd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pinkava?= Date: Fri, 3 Oct 2014 14:56:52 +0200 Subject: [PATCH 07/11] speed up float_to_bits Reduce overhead caused by inefficient call of read for each float. Increases speed about 50x. --- src/float_to_bits.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/float_to_bits.c b/src/float_to_bits.c index 3fed32b..9ececa0 100644 --- a/src/float_to_bits.c +++ b/src/float_to_bits.c @@ -71,6 +71,9 @@ static void sym_int2bits(int sym, uint8_t *ret) } } +// size of IO buffers (number of elements) +#define BUF_SIZE 1024 + int main(int argc, char **argv) { int fd, fd_out, opt; @@ -104,21 +107,27 @@ int main(int argc, char **argv) } while (1) { int rc; - float fl; - uint8_t bits[2]; - rc = read(fd, &fl, sizeof(fl)); + float fl[BUF_SIZE]; + uint8_t bits[2*BUF_SIZE]; + rc = read(fd, fl, sizeof(*fl) * BUF_SIZE); if (rc < 0) { perror("read"); exit(1); - } else if (rc == 0) + } else if (rc == 0) { break; - rc = process_sym_fl(fl); - sym_int2bits(rc, bits); - //printf("%2d %1u %1u %f\n", rc, bits[0], bits[1], fl); - if (opt_verbose) - printf("%1u%1u", bits[0], bits[1]); + } + rc /= sizeof(*fl); + int i; + for (i = 0; i < rc; ++i) { + int sym = process_sym_fl(fl[i]); + sym_int2bits(sym, bits + i*2); + //printf("%2d %1u %1u %f\n", rc, bits[0], bits[1], fl); + if (opt_verbose) { + printf("%1u%1u", bits[2*i + 0], bits[2*i + 1]); + } + } - rc = write(fd_out, bits, 2); + rc = write(fd_out, bits, rc * 2); if (rc < 0) { perror("write"); exit(1); From 89f01f35013094ba5fbc2f7bbcd70601bc562824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pinkava?= Date: Fri, 3 Oct 2014 16:12:10 +0200 Subject: [PATCH 08/11] fix debug build --- src/phy/tetra_burst_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phy/tetra_burst_sync.c b/src/phy/tetra_burst_sync.c index 0cf86d0..ae210dc 100644 --- a/src/phy/tetra_burst_sync.c +++ b/src/phy/tetra_burst_sync.c @@ -112,7 +112,7 @@ int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int /* we have successfully received (at least) one frame */ tetra_tdma_time_add_tn(&t_phy_state.time, 1); printf("\nBURST"); - DEBUGP(": %s", ubit_dump(trs->bitbuf, TETRA_BITS_PER_TS)); + DEBUGP(": %s", osmo_ubit_dump(trs->bitbuf, TETRA_BITS_PER_TS)); printf("\n"); rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf, (1 << TETRA_TRAIN_NORM_1)| From 7d6f7287d7b8a7db5aa6f172b06b1f51fe198283 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 3 Jul 2012 23:43:08 +0200 Subject: [PATCH 09/11] osmosdr-tetra_demod_fft.py: More verbose fine-tuning messages --- src/demod/python/osmosdr-tetra_demod_fft.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/demod/python/osmosdr-tetra_demod_fft.py b/src/demod/python/osmosdr-tetra_demod_fft.py index 2b2918a..c8585bf 100755 --- a/src/demod/python/osmosdr-tetra_demod_fft.py +++ b/src/demod/python/osmosdr-tetra_demod_fft.py @@ -169,8 +169,8 @@ def fftsink2_callback(x, y): if abs(x / (sample_rate / 2)) > 0.9: set_ifreq(self.ifreq + x / 2) else: - sys.stderr.write("coarse tuned to: %d Hz\n" % x) self.offset = -x + sys.stderr.write("coarse tuned to: %d Hz => %d Hz\n" % (self.offset, (self.ifreq + self.offset))) self.tuner.set_center_freq(self.offset) self.scope = fftsink2.fft_sink_c(self.Main.GetPage(0).GetWin(), @@ -191,7 +191,7 @@ def fftsink2_callback(x, y): def fftsink2_callback2(x, y): self.offset = self.offset - (x / 10) - sys.stderr.write("fine tuned to: %d Hz\n" % self.offset) + sys.stderr.write("fine tuned to: %d Hz => %d Hz\n" % (self.offset, (self.ifreq + self.offset))) self.tuner.set_center_freq(self.offset) self.scope2 = fftsink2.fft_sink_c(self.Main.GetPage(1).GetWin(), From a562b0e9a2af96d731ecdeacf87f320227792fcc Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Tue, 3 Jul 2012 23:43:56 +0200 Subject: [PATCH 10/11] Merged useful extra features osmosdr-tetra_demod_fft.py: Commandline switch -F for frequency offset osmosdr-tetra_demod_fft.py: More verbose fine-tuning messages Conflicts: src/demod/python/osmosdr-tetra_demod_fft.py --- src/demod/python/osmosdr-tetra_demod_fft.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/demod/python/osmosdr-tetra_demod_fft.py b/src/demod/python/osmosdr-tetra_demod_fft.py index c8585bf..d1c941b 100755 --- a/src/demod/python/osmosdr-tetra_demod_fft.py +++ b/src/demod/python/osmosdr-tetra_demod_fft.py @@ -38,6 +38,7 @@ def __init__(self): self.ifreq = options.frequency self.rfgain = options.gain + self.offset = options.frequency_offset self.src = osmosdr.source_c(options.args) self.src.set_center_freq(self.ifreq) @@ -236,6 +237,8 @@ def get_options(): help="set receiver sample rate (default 1800000)") parser.add_option("-f", "--frequency", type="eng_float", default=394.4e6, help="set receiver center frequency") + parser.add_option("-F", "--frequency-offset", type="eng_float", default=0, + help="set receiver offset frequency") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set receiver gain") From bffab641ae47c159f649bff5df94fd00bd32523b Mon Sep 17 00:00:00 2001 From: Jenda Date: Sun, 28 Aug 2016 08:47:30 +0200 Subject: [PATCH 11/11] sniffer (audio and pcap) patch --- src/lower_mac/tetra_lower_mac.c | 54 +++++++++++++++++++++++++++++++++ src/pcap.h | 50 ++++++++++++++++++++++++++++++ src/tetra-rx.c | 52 ++++++++++++++++++++++++++----- src/tetra_gsmtap.c | 48 ++++++++++++++++++++++++++++- src/tetra_upper_mac.c | 11 +++++-- 5 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 src/pcap.h diff --git a/src/lower_mac/tetra_lower_mac.c b/src/lower_mac/tetra_lower_mac.c index 7b62bb4..aef2ec7 100644 --- a/src/lower_mac/tetra_lower_mac.c +++ b/src/lower_mac/tetra_lower_mac.c @@ -39,6 +39,9 @@ #include "tetra_upper_mac.h" #include +extern int ssi; +extern int tsn; + struct tetra_blk_param { const char *name; uint16_t type345_bits; @@ -184,6 +187,57 @@ void tp_sap_udata_ind(enum tp_sap_data_type type, const uint8_t *bits, unsigned DEBUGP("%s %s type4: %s\n", tbp->name, time_str, osmo_ubit_dump(type4, tbp->type345_bits)); + +/* ###### Begin traffic dump patch ###### */ + + extern char *dumpdir; + if ((type == TPSAP_T_SCH_F) && (tms->cur_burst.is_traffic) && dumpdir) { + printf("SAVING FRAME\n"); + char fname[200]; + int16_t block[690]; + FILE *f; + int i; + + /* Open target file */ + //snprintf(fname, 100, "traffic_%d_%d.out", tcd->time.tn, tms->cur_burst.is_traffic); + //snprintf(fname, 100, "traffic_%d.out", tcd->time.tn); + snprintf(fname, 199, "%s/traffic_%d_%d.out", dumpdir, tms->cur_burst.is_traffic, tsn); + f = fopen(fname, "ab"); + + /* Generate a block */ + memset(block, 0x00, sizeof(int16_t) * 690); + for (i=0; i<6; i++) + block[115*i] = 0x6b21 + i; + + for (i=0; i<114; i++) + block[ 1+i] = type4[ i] ? -127 : 127; + + for (i=0; i<114; i++) + block[116+i] = type4[114+i] ? -127 : 127; + + for (i=0; i<114; i++) + block[231+i] = type4[228+i] ? -127 : 127; + + for (i=0; i<90; i++) + block[346+i] = type4[342+i] ? -127 : 127; + + /* Write it */ + fwrite(block, sizeof(int16_t), 690, f); + + /* Close */ + fclose(f); + memset(fname, 0x0, sizeof(char)*200); + snprintf(fname, 199, "%s/traffic_%d_%d.txt", dumpdir, tms->cur_burst.is_traffic, tsn); + /* Write used ssi */ + f=fopen(fname, "a"); + memset(fname, 0x0, sizeof(char)*200); + snprintf(fname, 199, "%d\n", ssi); + fwrite(fname, sizeof(char), strlen(fname), f); + fclose(f); + } + + /* end traffic dump patch */ + if (tbp->interleave_a) { /* Run block deinterleaving: type-3 bits */ block_deinterleave(tbp->type345_bits, tbp->interleave_a, type4, type3); diff --git a/src/pcap.h b/src/pcap.h new file mode 100644 index 0000000..f73259f --- /dev/null +++ b/src/pcap.h @@ -0,0 +1,50 @@ +#ifndef PCAP_H +#define PCAP_H +#include + +typedef uint32_t guint32; +typedef uint16_t guint16; +typedef int32_t gint32; + +typedef struct __attribute__ ((__packed__)) pcap_hdr_s { + guint32 magic_number; /* magic number */ + guint16 version_major; /* major version number */ + guint16 version_minor; /* minor version number */ + gint32 thiszone; /* GMT to local correction */ + guint32 sigfigs; /* accuracy of timestamps */ + guint32 snaplen; /* max length of captured packets, in octets */ + guint32 network; /* data link type */ +} pcap_hdr_t; + +typedef struct __attribute__ ((__packed__)) pcaprec_hdr_s { + guint32 ts_sec; /* timestamp seconds */ + guint32 ts_usec; /* timestamp microseconds */ + guint32 incl_len; /* number of octets of packet saved in file */ + guint32 orig_len; /* actual length of packet */ +} pcaprec_hdr_t; + +#define PCAP_MAGIC 0xa1b2c3d4 +#define PCAP_MAJOR 2 +#define PCAP_MINOR 4 +#define PCAP_SNAPLEN 65535 +#define PCAP_ETHERNET 1 + +unsigned char fake_frame_header[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Ethernet frame, dst and src MAC + 0x08, 0x00, // EtherType 0800 = IPv4 + 0x45, // IPv4 (0x4_), 20B header (0x_5) + 0x00, // no diffserv + 0x00, 0xff, // length + 0xc6, 0xd1, // some random frag + 0x40, 0x00, // don't frag + 0x3f, // TTL + 0x11, // IP proto = UDP + 0x00, 0x00, // checksum + 0x7f, 0x00, 0x00, 0x01, // src = 127.0.0.1 + 0x7f, 0x00, 0x00, 0x01, // dst = 127.0.0.1 + 0xbb, 0x13, // source port + 0x12, 0x79, // dst port = 4729 + 0x00, 0xeb, // length = iplen-20 + 0x00, 0x00 // checksum +}; +#endif diff --git a/src/tetra-rx.c b/src/tetra-rx.c index c751772..47441b0 100644 --- a/src/tetra-rx.c +++ b/src/tetra-rx.c @@ -35,32 +35,70 @@ #include "tetra_gsmtap.h" void *tetra_tall_ctx; +char *dumpdir; + +char *pcap_file_path; +int arfcn; +int ssi; +int tsn; int main(int argc, char **argv) { int fd; + int opt; + struct tetra_rx_state *trs; struct tetra_mac_state *tms; - if (argc < 2) { + char no_udp_tap = 0; + + while ((opt = getopt(argc, argv, "a:t:d:n")) != -1) { + switch (opt) { + case 'a': + arfcn = atoi(optarg); + break; + case 't': + //pcap_file_path = malloc(strlen(optarg)); + //memcpy(pcap_file_path, optarg, strlen(optarg)); + pcap_file_path = optarg; + break; + case 'd': + dumpdir = optarg; + break; + case 'n': + fprintf(stderr, "-n does not work\n"); + exit(1); + no_udp_tap = 1; + break; + default: + fprintf(stderr, "Unknown option %c\n", opt); + exit(2); + } + } + + if (argc <= optind) { + fprintf(stderr, "Usage: %s [-a ARFCN] [-t GSMTAP_PATH] [-d DUMPDIR] [-n] -s [-v] \n", argv[0]); + fprintf(stderr, "Usage: -n .. no UDP GSMTAP messages\n"); fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } - fd = open(argv[1], O_RDONLY); - if (fd < 0) { - perror("open"); - exit(2); + if (no_udp_tap == 0) { + tetra_gsmtap_init("localhost", 0); } - tetra_gsmtap_init("localhost", 0); - tms = talloc_zero(tetra_tall_ctx, struct tetra_mac_state); tetra_mac_state_init(tms); trs = talloc_zero(tetra_tall_ctx, struct tetra_rx_state); trs->burst_cb_priv = tms; + fd = open(argv[optind], O_RDONLY); + if (fd < 0) { + perror("open"); + exit(2); + } + while (1) { uint8_t buf[64]; int len; diff --git a/src/tetra_gsmtap.c b/src/tetra_gsmtap.c index f575c20..4edf20e 100644 --- a/src/tetra_gsmtap.c +++ b/src/tetra_gsmtap.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -14,7 +15,13 @@ #include "tetra_common.h" #include "tetra_tdma.h" +#include "pcap.h" + static struct gsmtap_inst *g_gti = NULL; +FILE *pcap_file; +extern char *pcap_file_path; +extern int arfcn; +extern int tsn; static const uint8_t lchan2gsmtap[] = { [TETRA_LC_SCH_F] = GSMTAP_TETRA_SCH_F, @@ -27,7 +34,6 @@ static const uint8_t lchan2gsmtap[] = { [TETRA_LC_BNCH] = GSMTAP_TETRA_BNCH, }; - struct msgb *tetra_gsmtap_makemsg(struct tetra_tdma_time *tm, enum tetra_log_chan lchan, uint8_t ts, uint8_t ss, int8_t signal_dbm, uint8_t snr, const ubit_t *bitdata, unsigned int bitlen) @@ -47,8 +53,10 @@ struct msgb *tetra_gsmtap_makemsg(struct tetra_tdma_time *tm, enum tetra_log_cha gh->hdr_len = sizeof(*gh)/4; gh->type = GSMTAP_TYPE_TETRA_I1; gh->timeslot = ts; + tsn = ts; gh->sub_slot = ss; gh->snr_db = snr; + gh->arfcn = htons(arfcn); gh->signal_dbm = signal_dbm; gh->frame_number = htonl(fn); gh->sub_type = lchan2gsmtap[lchan]; @@ -61,8 +69,31 @@ struct msgb *tetra_gsmtap_makemsg(struct tetra_tdma_time *tm, enum tetra_log_cha return msg; } +void pcap_pipe(char * buf, size_t n) +{ + if (pcap_file) { + fwrite(buf, n, 1, pcap_file); + fflush(pcap_file); + } +} + int tetra_gsmtap_sendmsg(struct msgb *msg) { + pcaprec_hdr_t hdr; + bzero(&hdr, sizeof(hdr)); + + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + + hdr.ts_sec = now.tv_sec; + hdr.ts_usec = now.tv_nsec/1000; + hdr.incl_len = msg->len + sizeof(fake_frame_header); + hdr.orig_len = hdr.incl_len; + + pcap_pipe((char*)&hdr, sizeof(pcaprec_hdr_t)); + pcap_pipe((char*)&fake_frame_header, sizeof(fake_frame_header)); + pcap_pipe((char*)msg->data, msg->len); + if (g_gti) return gsmtap_sendmsg(g_gti, msg); else @@ -76,5 +107,20 @@ int tetra_gsmtap_init(const char *host, uint16_t port) return -EINVAL; gsmtap_source_add_sink(g_gti); + if (pcap_file_path) { + pcap_hdr_t hdr; + + bzero(&hdr, sizeof(hdr)); + + hdr.magic_number = PCAP_MAGIC; + hdr.version_major = PCAP_MAJOR; + hdr.version_minor = PCAP_MINOR; + hdr.snaplen = PCAP_SNAPLEN; + hdr.network = PCAP_ETHERNET; + + pcap_file = fopen(pcap_file_path, "wb"); + //pcap_pipe((char*)&hdr, sizeof(pcap_hdr_t)); + } + return 0; } diff --git a/src/tetra_upper_mac.c b/src/tetra_upper_mac.c index fdc8c73..eba9d6e 100644 --- a/src/tetra_upper_mac.c +++ b/src/tetra_upper_mac.c @@ -38,6 +38,8 @@ #include "tetra_mle_pdu.h" #include "tetra_gsmtap.h" +extern int ssi; + static int rx_tm_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len); static void rx_bcast(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms) @@ -181,6 +183,8 @@ static void rx_resrc(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms rx_tm_sdu(tms, msg, len_bits); } + ssi = rsd.addr.ssi; + out: printf("\n"); } @@ -240,11 +244,12 @@ static void rx_aach(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms) printf("UL_USAGE: %s ", tetra_get_ul_usage_name(aad.ul_usage)); /* save the state whether the current burst is traffic or not */ - if (aad.dl_usage > 3) + if (aad.dl_usage > 3) { tms->cur_burst.is_traffic = 1; - else + tms->cur_burst.is_traffic = aad.dl_usage; + } else { tms->cur_burst.is_traffic = 0; - + } printf("\n"); }