diff --git a/src/demod/python/osmosdr-tetra_demod_fft.py b/src/demod/python/osmosdr-tetra_demod_fft.py index 648d454..6bdd35c 100755 --- a/src/demod/python/osmosdr-tetra_demod_fft.py +++ b/src/demod/python/osmosdr-tetra_demod_fft.py @@ -40,6 +40,7 @@ def __init__(self): self.ifreq = options.frequency self.rfgain = options.gain + self.offset = options.frequency_offset self.src = osmosdr.source(options.args) self.src.set_center_freq(self.ifreq) @@ -173,8 +174,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(), @@ -195,7 +196,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(), @@ -240,6 +241,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") 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"); }