Import gprsdecode utility from SRLabs
This change introduces a modified version of gprsdecode utility, which is intended to decode the GPRS burst captures and forward decoded packets to the GSMTAP sink. The following modifications were made: - use shared libosmocoding library for GSM 05.03 coding; - use optget for command line options parsing; - use a single application select loop; - use GNU automake as the build system; - add regression tests (GNU autotest); - clean up and comment the code; - add license headers; The code is based on work of SRLabs: https://srlabs.de/ git://git.srlabs.de/gprsdecode.git Related: OS#1672 Change-Id: I12234d37c66b83b8abd60f7511fa1d7837db1856
This commit is contained in:
parent
9fa291dd2b
commit
e357646ed7
15
src/Makefile
15
src/Makefile
|
@ -13,7 +13,7 @@ TOPDIR=$(shell pwd)
|
||||||
|
|
||||||
all: libosmocore-target nofirmware firmware mtk-firmware
|
all: libosmocore-target nofirmware firmware mtk-firmware
|
||||||
|
|
||||||
nofirmware: layer23 osmocon gsmmap virtphy
|
nofirmware: layer23 osmocon gsmmap gprsdecode virtphy
|
||||||
|
|
||||||
libosmocore-target: shared/libosmocore/build-target/src/.libs/libosmocore.a
|
libosmocore-target: shared/libosmocore/build-target/src/.libs/libosmocore.a
|
||||||
|
|
||||||
|
@ -83,6 +83,17 @@ host/layer23/Makefile: host/layer23/configure
|
||||||
host/layer23/layer23: host/layer23/Makefile
|
host/layer23/layer23: host/layer23/Makefile
|
||||||
make -C host/layer23
|
make -C host/layer23
|
||||||
|
|
||||||
|
.PHONY: gprsdecode
|
||||||
|
gprsdecode: host/gprsdecode/gprsdecode
|
||||||
|
|
||||||
|
host/gprsdecode/configure: host/gprsdecode/configure.ac
|
||||||
|
cd host/gprsdecode && autoreconf -i
|
||||||
|
|
||||||
|
host/gprsdecode/Makefile: host/gprsdecode/configure
|
||||||
|
cd host/gprsdecode && ./configure $(HOST_CONFARGS)
|
||||||
|
|
||||||
|
host/gprsdecode/gprsdecode: host/gprsdecode/Makefile
|
||||||
|
make -C host/gprsdecode
|
||||||
|
|
||||||
.PHONY: firmware
|
.PHONY: firmware
|
||||||
firmware: libosmocore-target
|
firmware: libosmocore-target
|
||||||
|
@ -98,6 +109,7 @@ clean:
|
||||||
make -C host/layer23 $@
|
make -C host/layer23 $@
|
||||||
make -C host/osmocon $@
|
make -C host/osmocon $@
|
||||||
make -C host/gsmmap $@
|
make -C host/gsmmap $@
|
||||||
|
make -C host/gprsdecode $@
|
||||||
make -C host/virt_phy $@
|
make -C host/virt_phy $@
|
||||||
make -C target/firmware $@
|
make -C target/firmware $@
|
||||||
make -C target/firmware -f Makefile.mtk $@
|
make -C target/firmware -f Makefile.mtk $@
|
||||||
|
@ -107,6 +119,7 @@ distclean:
|
||||||
make -C host/layer23 $@
|
make -C host/layer23 $@
|
||||||
make -C host/osmocon $@
|
make -C host/osmocon $@
|
||||||
make -C host/gsmmap $@
|
make -C host/gsmmap $@
|
||||||
|
make -C host/gprsdecode $@
|
||||||
make -C host/virt_phy $@
|
make -C host/virt_phy $@
|
||||||
# 'firmware' also handles 'mtk-firmware'
|
# 'firmware' also handles 'mtk-firmware'
|
||||||
make -C target/firmware $@
|
make -C target/firmware $@
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# GNU automake
|
||||||
|
Makefile
|
||||||
|
|
||||||
|
# Final executables
|
||||||
|
gprsdecode
|
||||||
|
|
||||||
|
# GNU autotest
|
||||||
|
tests/package.m4
|
||||||
|
tests/atconfig
|
||||||
|
tests/atlocal
|
||||||
|
tests/testsuite
|
||||||
|
tests/testsuite.dir/
|
||||||
|
tests/testsuite.log
|
|
@ -0,0 +1,36 @@
|
||||||
|
AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
|
||||||
|
SUBDIRS = tests
|
||||||
|
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
$(all_includes) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
AM_CFLAGS = \
|
||||||
|
-Wall -O3 \
|
||||||
|
-Wno-missing-braces \
|
||||||
|
$(LIBOSMOGSM_CFLAGS) \
|
||||||
|
$(LIBOSMOCORE_CFLAGS) \
|
||||||
|
$(LIBOSMOCODING_CFLAGS) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
bin_PROGRAMS = gprsdecode
|
||||||
|
|
||||||
|
gprsdecode_SOURCES = \
|
||||||
|
gsmtap.c \
|
||||||
|
rlcmac.c \
|
||||||
|
gprs.c \
|
||||||
|
main.c \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
noinst_HEADERS = \
|
||||||
|
l1ctl_proto.h \
|
||||||
|
rlcmac.h \
|
||||||
|
gsmtap.h \
|
||||||
|
gprs.h \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
gprsdecode_LDADD = \
|
||||||
|
$(LIBOSMOCODING_LIBS) \
|
||||||
|
$(LIBOSMOCORE_LIBS) \
|
||||||
|
$(LIBOSMOGSM_LIBS) \
|
||||||
|
$(NULL)
|
|
@ -0,0 +1,8 @@
|
||||||
|
GPRS decoder for OsmocomBB
|
||||||
|
|
||||||
|
Usage: ./gprsdecode <burstfile>
|
||||||
|
|
||||||
|
The burstfile should contain samples, captured using burst_ind branch.
|
||||||
|
An example of decoded output as well as few sample capture files could be found in tests/
|
||||||
|
|
||||||
|
Based on the version from git://git.srlabs.de/gprsdecode.git
|
|
@ -0,0 +1,29 @@
|
||||||
|
dnl Process this file with autoconf to produce a configure script
|
||||||
|
AC_INIT([gprsdecode], [0.0.0])
|
||||||
|
AM_INIT_AUTOMAKE
|
||||||
|
|
||||||
|
dnl kernel style compile messages
|
||||||
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
|
dnl Tests
|
||||||
|
AC_CONFIG_TESTDIR(tests)
|
||||||
|
|
||||||
|
dnl checks for programs
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
|
||||||
|
dnl checks for libraries
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm)
|
||||||
|
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding)
|
||||||
|
|
||||||
|
dnl checks for header files
|
||||||
|
AC_HEADER_STDC
|
||||||
|
|
||||||
|
dnl generates the output files
|
||||||
|
AC_OUTPUT(
|
||||||
|
Makefile
|
||||||
|
tests/Makefile
|
||||||
|
)
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* (C) 2017-2018 by sysmocom - s.f.m.c. GmbH, Author: Max <msuraev@sysmocom.de>
|
||||||
|
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
|
||||||
|
* (C) 2011-2012 by Luca Melette <luca@srlabs.de>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/bits.h>
|
||||||
|
#include <osmocom/core/gsmtap.h>
|
||||||
|
#include <osmocom/coding/gsm0503_coding.h>
|
||||||
|
|
||||||
|
#include "l1ctl_proto.h"
|
||||||
|
#include "rlcmac.h"
|
||||||
|
#include "gprs.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We store both DL and UL burst buffers
|
||||||
|
* for all possible timeslots...
|
||||||
|
*/
|
||||||
|
static struct burst_buf burst_buf_dl[8] = { 0 };
|
||||||
|
static struct burst_buf burst_buf_ul[8] = { 0 };
|
||||||
|
|
||||||
|
int process_pdch(struct l1ctl_burst_ind *bi, bool verbose)
|
||||||
|
{
|
||||||
|
int n_errors, n_bits_total, rc, len, i;
|
||||||
|
ubit_t buf[GSM_BURST_PL_LEN];
|
||||||
|
struct gprs_message *gm;
|
||||||
|
struct burst_buf *bb;
|
||||||
|
uint8_t l2[200];
|
||||||
|
uint16_t arfcn;
|
||||||
|
uint32_t fn;
|
||||||
|
uint8_t tn;
|
||||||
|
bool ul;
|
||||||
|
|
||||||
|
/* Get burst parameters */
|
||||||
|
fn = ntohl(bi->frame_nr);
|
||||||
|
arfcn = ntohs(bi->band_arfcn);
|
||||||
|
ul = !!(arfcn & GSMTAP_ARFCN_F_UPLINK);
|
||||||
|
tn = bi->chan_nr & 7;
|
||||||
|
|
||||||
|
/* Select a proper DL / UL buffer */
|
||||||
|
bb = ul ? &burst_buf_ul[tn] : &burst_buf_dl[tn];
|
||||||
|
|
||||||
|
/* Align to first frame */
|
||||||
|
if ((bb->count == 0) && (((fn % 13) % 4) != 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Debug print */
|
||||||
|
if (verbose)
|
||||||
|
printf("Processing %s burst fn=%u, tn=%u\n",
|
||||||
|
ul ? "UL" : "DL", fn, tn);
|
||||||
|
|
||||||
|
/* Unpack hard-bits (1 or 0) */
|
||||||
|
osmo_pbit2ubit_ext(buf, 0, bi->bits, 0, 57, 0);
|
||||||
|
osmo_pbit2ubit_ext(buf, 59, bi->bits, 57, 57, 0);
|
||||||
|
|
||||||
|
/* Set the stealing flags */
|
||||||
|
buf[57] = bi->bits[14] & 0x10;
|
||||||
|
buf[58] = bi->bits[14] & 0x20;
|
||||||
|
|
||||||
|
/* Convert hard-bits (1 or 0) to soft-bits (-127..127) */
|
||||||
|
for (i = 0; i < GSM_BURST_PL_LEN; i++)
|
||||||
|
bb->bursts[GSM_BURST_PL_LEN * bb->count + i] = buf[i] ?
|
||||||
|
-(bi->snr >> 1) : (bi->snr >> 1);
|
||||||
|
|
||||||
|
/* Store the first frame number */
|
||||||
|
if (bb->count == 0)
|
||||||
|
bb->fn_first = fn;
|
||||||
|
|
||||||
|
/* Collect the measurements */
|
||||||
|
bb->rxl[bb->count] = bi->rx_level;
|
||||||
|
bb->snr[bb->count] = bi->snr;
|
||||||
|
|
||||||
|
/* Wait until complete set of bursts (4/4) */
|
||||||
|
if (++bb->count < 4)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Debug print */
|
||||||
|
if (verbose)
|
||||||
|
printf("Collected 4/4 bursts on tn=%u\n", tn);
|
||||||
|
|
||||||
|
/* Flush the burst counter */
|
||||||
|
bb->count = 0;
|
||||||
|
|
||||||
|
/* Attempt to decode */
|
||||||
|
len = gsm0503_pdtch_decode(l2, bb->bursts, NULL,
|
||||||
|
&n_errors, &n_bits_total);
|
||||||
|
|
||||||
|
/* Debug print */
|
||||||
|
if (verbose)
|
||||||
|
printf("GSM 05.03 decoding %s (%s=%d)\n",
|
||||||
|
len <= 0 ? "failed" : "success",
|
||||||
|
len <= 0 ? "rc" : "len", len);
|
||||||
|
|
||||||
|
/* Skip bad blocks... */
|
||||||
|
if (len <= 0)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HACK: for some reason, the handler expects
|
||||||
|
* 53-byte messages, while libosmocoding
|
||||||
|
* generates 54 bytes ?? O_o ??
|
||||||
|
*/
|
||||||
|
len--;
|
||||||
|
|
||||||
|
/* Handle decoded message */
|
||||||
|
gm = (struct gprs_message *) malloc(sizeof(struct gprs_message) + len);
|
||||||
|
if (!gm)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
gm->fn = bb->fn_first;
|
||||||
|
gm->arfcn = arfcn;
|
||||||
|
gm->len = len;
|
||||||
|
gm->tn = tn;
|
||||||
|
|
||||||
|
/* Average the measurements */
|
||||||
|
gm->rxl = MEAS_AVG(bb->rxl);
|
||||||
|
gm->snr = MEAS_AVG(bb->snr);
|
||||||
|
|
||||||
|
/* Copy the message payload */
|
||||||
|
memcpy(gm->msg, l2, len);
|
||||||
|
|
||||||
|
/* Handle the message */
|
||||||
|
rc = rlc_type_handler(gm);
|
||||||
|
free(gm);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define GSM_BURST_PL_LEN 116
|
||||||
|
#define GPRS_BURST_PL_LEN GSM_BURST_PL_LEN
|
||||||
|
|
||||||
|
#define MEAS_AVG(meas) \
|
||||||
|
((meas[0] + meas[1] + meas[2] + meas[3]) / 4)
|
||||||
|
|
||||||
|
/* Burst decoder state */
|
||||||
|
struct burst_buf {
|
||||||
|
unsigned snr[4];
|
||||||
|
unsigned rxl[4];
|
||||||
|
unsigned errors;
|
||||||
|
unsigned count;
|
||||||
|
|
||||||
|
sbit_t bursts[GSM_BURST_PL_LEN * 4];
|
||||||
|
uint32_t fn_first;
|
||||||
|
};
|
||||||
|
|
||||||
|
int process_pdch(struct l1ctl_burst_ind *bi, bool verbose);
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* (C) 2017-2018 by sysmocom - s.f.m.c. GmbH, Author: Max <msuraev@sysmocom.de>
|
||||||
|
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
|
||||||
|
* (C) 2011-2012 by Luca Melette <luca@srlabs.de>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/msgb.h>
|
||||||
|
#include <osmocom/core/gsmtap.h>
|
||||||
|
#include <osmocom/core/gsmtap_util.h>
|
||||||
|
|
||||||
|
#include "l1ctl_proto.h"
|
||||||
|
#include "gsmtap.h"
|
||||||
|
|
||||||
|
static struct gsmtap_inst *gti = NULL;
|
||||||
|
|
||||||
|
int gsmtap_init(const char *addr)
|
||||||
|
{
|
||||||
|
gti = gsmtap_source_init(addr, GSMTAP_UDP_PORT, 0);
|
||||||
|
if (!gti)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
gsmtap_source_add_sink(gti);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gsmtap_send_rlcmac(uint8_t *msg, size_t len, uint8_t ts, bool ul)
|
||||||
|
{
|
||||||
|
if (!gti)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* FIXME: explain params */
|
||||||
|
gsmtap_send(gti,
|
||||||
|
ul ? GSMTAP_ARFCN_F_UPLINK : 0,
|
||||||
|
ts, GSMTAP_CHANNEL_PACCH, 0, 0, 0, 0, msg, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gsmtap_send_llc(uint8_t *data, size_t len, bool ul)
|
||||||
|
{
|
||||||
|
struct gsmtap_hdr *gh;
|
||||||
|
struct msgb *msg;
|
||||||
|
uint8_t *dst;
|
||||||
|
|
||||||
|
if (!gti)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Skip null frames */
|
||||||
|
if ((data[0] == 0x43) &&
|
||||||
|
(data[1] == 0xc0) &&
|
||||||
|
(data[2] == 0x01))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Allocate a new message buffer */
|
||||||
|
msg = msgb_alloc(sizeof(*gh) + len, "gsmtap_tx");
|
||||||
|
if (!msg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Put header in front */
|
||||||
|
gh = (struct gsmtap_hdr *) msgb_put(msg, sizeof(*gh));
|
||||||
|
|
||||||
|
/* Fill in header */
|
||||||
|
gh->version = GSMTAP_VERSION;
|
||||||
|
gh->hdr_len = sizeof(*gh) / 4;
|
||||||
|
gh->type = GSMTAP_TYPE_GB_LLC;
|
||||||
|
gh->timeslot = 0;
|
||||||
|
gh->sub_slot = 0;
|
||||||
|
gh->arfcn = ul ? htons(GSMTAP_ARFCN_F_UPLINK) : 0;
|
||||||
|
gh->snr_db = 0;
|
||||||
|
gh->signal_dbm = 0;
|
||||||
|
gh->frame_number = 0;
|
||||||
|
gh->sub_type = 0;
|
||||||
|
gh->antenna_nr = 0;
|
||||||
|
|
||||||
|
/* Put and fill the payload */
|
||||||
|
dst = msgb_put(msg, len);
|
||||||
|
memcpy(dst, data, len);
|
||||||
|
|
||||||
|
/* Finally, send to the sink */
|
||||||
|
gsmtap_sendmsg(gti, msg);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
int gsmtap_init(const char *addr);
|
||||||
|
void gsmtap_send_rlcmac(uint8_t *msg, size_t len, uint8_t ts, bool ul);
|
||||||
|
void gsmtap_send_llc(uint8_t *data, size_t len, bool ul);
|
|
@ -0,0 +1 @@
|
||||||
|
../../../include/l1ctl_proto.h
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* (C) 2017-2018 by sysmocom - s.f.m.c. GmbH, Author: Max <msuraev@sysmocom.de>
|
||||||
|
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
|
||||||
|
* (C) 2011-2012 by Luca Melette <luca@srlabs.de>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/signal.h>
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
#include <osmocom/core/application.h>
|
||||||
|
|
||||||
|
#include <osmocom/gsm/rsl.h>
|
||||||
|
#include <osmocom/gsm/gsm_utils.h>
|
||||||
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||||
|
|
||||||
|
#include "l1ctl_proto.h"
|
||||||
|
#include "gsmtap.h"
|
||||||
|
#include "gprs.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *capture_file;
|
||||||
|
char *gsmtap_ip;
|
||||||
|
bool verbose;
|
||||||
|
bool quit;
|
||||||
|
} app_data;
|
||||||
|
|
||||||
|
static void burst_handle(struct l1ctl_burst_ind *bi)
|
||||||
|
{
|
||||||
|
uint8_t type, subch, ts;
|
||||||
|
uint32_t fn;
|
||||||
|
|
||||||
|
fn = ntohl(bi->frame_nr);
|
||||||
|
rsl_dec_chan_nr(bi->chan_nr, &type, &subch, &ts);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RSL_CHAN_Bm_ACCHs:
|
||||||
|
/* FIXME: what is (fn % 13) != 12? */
|
||||||
|
/* TODO: use the multiframe layout here */
|
||||||
|
if ((ts > 0) && ((fn % 13) != 12))
|
||||||
|
process_pdch(bi, app_data.verbose);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* We are only interested in GPRS messages */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_help(const char *app)
|
||||||
|
{
|
||||||
|
printf(" Some help...\n\n");
|
||||||
|
|
||||||
|
printf(" Usage: %s [OPTIONS]\n\n", app);
|
||||||
|
|
||||||
|
printf(" -h --help this text\n");
|
||||||
|
printf(" -c --capture The capture file to decode\n");
|
||||||
|
printf(" -i --gsmtap-ip The destination IP used for GSMTAP\n");
|
||||||
|
printf(" -v --verbose Increase the verbosity level\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_options(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Init defaults */
|
||||||
|
app_data.capture_file = NULL;
|
||||||
|
app_data.gsmtap_ip = NULL;
|
||||||
|
app_data.verbose = false;
|
||||||
|
app_data.quit = false;
|
||||||
|
|
||||||
|
/* Parse options */
|
||||||
|
while (1) {
|
||||||
|
int option_index = 0, c;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"help", 0, 0, 'h'},
|
||||||
|
{"verbose", 0, 0, 'v'},
|
||||||
|
{"capture", 1, 0, 'c'},
|
||||||
|
{"gsmtap-ip", 1, 0, 'i'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
c = getopt_long(argc, argv, "c:i:vh",
|
||||||
|
long_options, &option_index);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 1;
|
||||||
|
case 'c':
|
||||||
|
app_data.capture_file = optarg;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
app_data.gsmtap_ip = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
app_data.verbose = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we have the capture file path */
|
||||||
|
if (!app_data.capture_file) {
|
||||||
|
print_help(argv[0]);
|
||||||
|
printf("\nPlease specify the capture file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void signal_handler(int signal)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "signal %d received\n", signal);
|
||||||
|
|
||||||
|
switch (signal) {
|
||||||
|
case SIGINT:
|
||||||
|
app_data.quit = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct l1ctl_burst_ind bi;
|
||||||
|
FILE *burst_fd;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Setup signal handlers */
|
||||||
|
signal(SIGINT, &signal_handler);
|
||||||
|
osmo_init_ignore_signals();
|
||||||
|
|
||||||
|
/* Parse options */
|
||||||
|
rc = handle_options(argc, argv);
|
||||||
|
if (rc)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
/* Attempt to open the capture for reading */
|
||||||
|
burst_fd = fopen(app_data.capture_file, "rb");
|
||||||
|
if (!burst_fd) {
|
||||||
|
printf("Cannot open capture file '%s': %s\n",
|
||||||
|
app_data.capture_file, strerror(errno));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init GSMTAP sink if required */
|
||||||
|
if (app_data.gsmtap_ip != NULL)
|
||||||
|
gsmtap_init(app_data.gsmtap_ip);
|
||||||
|
|
||||||
|
/* Application main loop */
|
||||||
|
while (!app_data.quit) {
|
||||||
|
/* The end of capture file */
|
||||||
|
if (feof(burst_fd))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Read a single burst */
|
||||||
|
rc = fread(&bi, sizeof(bi), 1, burst_fd);
|
||||||
|
if (!rc)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Filter or handle burst */
|
||||||
|
burst_handle(&bi);
|
||||||
|
|
||||||
|
osmo_select_main(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the capture file */
|
||||||
|
fclose(burst_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,418 @@
|
||||||
|
/*
|
||||||
|
* (C) 2017-2018 by sysmocom - s.f.m.c. GmbH, Author: Max <msuraev@sysmocom.de>
|
||||||
|
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
|
||||||
|
* (C) 2011-2012 by Luca Melette <luca@srlabs.de>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/gsmtap.h>
|
||||||
|
|
||||||
|
#include "l1ctl_proto.h"
|
||||||
|
#include "rlcmac.h"
|
||||||
|
#include "gsmtap.h"
|
||||||
|
|
||||||
|
static struct gprs_tbf tbf_table[32 * 2];
|
||||||
|
|
||||||
|
static inline int too_old(uint32_t current_fn, uint32_t test_fn)
|
||||||
|
{
|
||||||
|
uint32_t delta = (current_fn - test_fn) & 0xffffffff;
|
||||||
|
|
||||||
|
/* More and less 30 seconds from now */
|
||||||
|
return abs(delta) > OLD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bsn_is_next(uint8_t first, uint8_t second)
|
||||||
|
{
|
||||||
|
return ((first + 1) % 128) == second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_pkt(uint8_t *msg, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
printf("MSG: ");
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
printf("%.02x", msg[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_blocks(struct gprs_tbf *t, bool ul)
|
||||||
|
{
|
||||||
|
uint8_t llc_data[65536], llc_first_bsn, llc_last_bsn = 0;
|
||||||
|
unsigned skip, llc_len = 0;
|
||||||
|
uint8_t bsn, bsn2, li_off;
|
||||||
|
uint32_t current_fn;
|
||||||
|
struct gprs_frag *f;
|
||||||
|
struct gprs_lime *l;
|
||||||
|
|
||||||
|
/* Get current "time", oldest unreassembled frag */
|
||||||
|
bsn = t->start_bsn;
|
||||||
|
while (t->frags[bsn].len == 0) {
|
||||||
|
bsn = (bsn + 1) % 128;
|
||||||
|
if (bsn == t->start_bsn) {
|
||||||
|
printf("no valid blocks in current TBF!\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_fn = t->frags[bsn].fn;
|
||||||
|
t->start_bsn = bsn;
|
||||||
|
|
||||||
|
/* Walk through fragments, mark reassembled/used blocks */
|
||||||
|
skip = 0;
|
||||||
|
for (bsn = t->start_bsn; bsn != ((t->last_bsn + 1) % 128); bsn = (bsn + 1) % 128) {
|
||||||
|
/* Get fragment descriptor */
|
||||||
|
f = &t->frags[bsn];
|
||||||
|
|
||||||
|
printf(" bsn %d ", bsn);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Already processed or null */
|
||||||
|
if (!f->len) {
|
||||||
|
printf("null\n");
|
||||||
|
fflush(stdout);
|
||||||
|
llc_len = 0;
|
||||||
|
skip = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check fragment age */
|
||||||
|
if (too_old(current_fn, f->fn)) {
|
||||||
|
printf("old segment\n");
|
||||||
|
fflush(stdout);
|
||||||
|
llc_len = 0;
|
||||||
|
skip = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update "time" */
|
||||||
|
current_fn = f->fn;
|
||||||
|
|
||||||
|
if (llc_len && !bsn_is_next(llc_last_bsn, bsn)) {
|
||||||
|
printf("missing bsn, previous %d\n", llc_last_bsn);
|
||||||
|
fflush(stdout);
|
||||||
|
llc_len = 0;
|
||||||
|
skip = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for multiple blocks/parts */
|
||||||
|
if (f->n_blocks == 0) {
|
||||||
|
/* Check if first part of message */
|
||||||
|
if (!llc_len)
|
||||||
|
llc_first_bsn = bsn;
|
||||||
|
|
||||||
|
/* Append data to buffer */
|
||||||
|
memcpy(&llc_data[llc_len], f->data, f->len);
|
||||||
|
|
||||||
|
llc_len += f->len;
|
||||||
|
|
||||||
|
llc_last_bsn = bsn;
|
||||||
|
|
||||||
|
/* Last TBF block? (very rare condition) */
|
||||||
|
if (f->last) {
|
||||||
|
printf("end of TBF\n");
|
||||||
|
fflush(stdout);
|
||||||
|
print_pkt(llc_data, llc_len);
|
||||||
|
|
||||||
|
gsmtap_send_llc(llc_data, llc_len, ul);
|
||||||
|
|
||||||
|
/* Reset all fragments */
|
||||||
|
for (bsn2 = 0; bsn2 < 128; bsn2++) {
|
||||||
|
f = &t->frags[bsn2];
|
||||||
|
f->len = 0;
|
||||||
|
f->n_blocks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset buffer state */
|
||||||
|
llc_len = 0;
|
||||||
|
t->start_bsn = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Multiple data parts */
|
||||||
|
unsigned i;
|
||||||
|
li_off = 0;
|
||||||
|
for (i = 0; i < f->n_blocks; i++) {
|
||||||
|
printf("\nlime %d\n", i);
|
||||||
|
fflush(stdout);
|
||||||
|
l = &f->blocks[i];
|
||||||
|
if (l->used) {
|
||||||
|
if (llc_len) {
|
||||||
|
printf("\nlime error!\n");
|
||||||
|
fflush(stdout);
|
||||||
|
llc_len = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!llc_len)
|
||||||
|
llc_first_bsn = bsn;
|
||||||
|
|
||||||
|
/* Append data to buffer */
|
||||||
|
memcpy(&llc_data[llc_len], &f->data[li_off], l->li);
|
||||||
|
|
||||||
|
llc_len += l->li;
|
||||||
|
|
||||||
|
llc_last_bsn = bsn;
|
||||||
|
|
||||||
|
if (!l->e || !l->m || (l->e && l->m)) {
|
||||||
|
/* Message ends here */
|
||||||
|
printf("end of message reached\n");
|
||||||
|
fflush(stdout);
|
||||||
|
print_pkt(llc_data, llc_len);
|
||||||
|
|
||||||
|
gsmtap_send_llc(llc_data, llc_len, ul);
|
||||||
|
|
||||||
|
/* Mark frags as used */
|
||||||
|
l->used = 1;
|
||||||
|
if (llc_first_bsn != bsn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
llc_len = 0;
|
||||||
|
if (!skip)
|
||||||
|
t->start_bsn = bsn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li_off += l->li;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is spare data valid? */
|
||||||
|
if (l->m) {
|
||||||
|
if (llc_len) {
|
||||||
|
printf("spare and buffer not empty!\n");
|
||||||
|
print_pkt(llc_data, llc_len);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
if ((f->len > li_off) && (f->len-li_off < 65536)) {
|
||||||
|
memcpy(llc_data, &f->data[li_off], f->len-li_off);
|
||||||
|
llc_len = f->len - li_off;
|
||||||
|
llc_first_bsn = bsn;
|
||||||
|
llc_last_bsn = bsn;
|
||||||
|
t->start_bsn = bsn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift window if needed */
|
||||||
|
if (((t->last_bsn - t->start_bsn) % 128) > 64) {
|
||||||
|
t->start_bsn = (t->last_bsn - 64) % 128;
|
||||||
|
printf("shifting window\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlc_data_handler(struct gprs_message *gm)
|
||||||
|
{
|
||||||
|
int ul, off, d_bsn;
|
||||||
|
uint8_t tfi, bsn, cv = 1, fbi = 0;
|
||||||
|
uint32_t d_same_bsn, d_last_bsn;
|
||||||
|
struct gprs_tbf *t, *t_prev;
|
||||||
|
struct gprs_frag *f;
|
||||||
|
struct gprs_lime *l;
|
||||||
|
|
||||||
|
tfi = (gm->msg[1] & 0x3e) >> 1;
|
||||||
|
bsn = (gm->msg[2] & 0xfe) >> 1;
|
||||||
|
|
||||||
|
/* Get "end of TBF" according to direction */
|
||||||
|
ul = !!(gm->arfcn & GSMTAP_ARFCN_F_UPLINK);
|
||||||
|
if (ul) {
|
||||||
|
cv = (gm->msg[0] & 0x3c) >> 2;
|
||||||
|
printf("TFI %d BSN %d CV %d ", tfi, bsn, cv);
|
||||||
|
} else {
|
||||||
|
fbi = (gm->msg[1] & 0x01);
|
||||||
|
printf("TFI %d BSN %d FBI %d ", tfi, bsn, fbi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get TBF descriptor for TFI,UL couple */
|
||||||
|
t = &tbf_table[2 * tfi + ul];
|
||||||
|
|
||||||
|
d_same_bsn = (gm->fn - t->frags[bsn].fn) & 0xffffffff;
|
||||||
|
d_last_bsn = (gm->fn - t->frags[t->last_bsn].fn) & 0xffffffff;
|
||||||
|
d_bsn = (bsn - t->last_bsn) % 128;
|
||||||
|
|
||||||
|
printf("\nfn_same_bsn %d fn_last_bsn %d delta_bsn %d old_len %d\n",
|
||||||
|
d_same_bsn, d_last_bsn, d_bsn, t->frags[bsn].len);
|
||||||
|
|
||||||
|
/* New / old fragment decision */
|
||||||
|
if (d_same_bsn > OLD_TIME) {
|
||||||
|
if (d_last_bsn > OLD_TIME) {
|
||||||
|
/* New TBF is starting, close old one... */
|
||||||
|
t_prev = &tbf_table[2 * ((tfi + 1) % 32) + ul];
|
||||||
|
printf("clearing TBF %d, first %d last %d\n",
|
||||||
|
(tfi + 1) % 32, t_prev->start_bsn, t_prev->last_bsn);
|
||||||
|
f = &t_prev->frags[t_prev->last_bsn];
|
||||||
|
|
||||||
|
/* ...only if data is present */
|
||||||
|
if (f->len) {
|
||||||
|
f->last = 1;
|
||||||
|
process_blocks(t_prev, ul);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("new TBF, starting from %d\n", bsn);
|
||||||
|
t->start_bsn = 0;
|
||||||
|
t->last_bsn = bsn;
|
||||||
|
memset(t->frags, 0, 128 * sizeof(struct gprs_frag));
|
||||||
|
} else {
|
||||||
|
/* Fresh frag, current TBF */
|
||||||
|
if ((d_bsn >= 0) || (d_bsn < -64)) {
|
||||||
|
/* New frag */
|
||||||
|
t->last_bsn = bsn;
|
||||||
|
} else {
|
||||||
|
/* Out of sequence / duplicate */
|
||||||
|
t->frags[bsn].fn = gm->fn;
|
||||||
|
printf("duplicate\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (d_last_bsn > OLD_TIME) {
|
||||||
|
printf("fucking error last_bsn!\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
/* Fresh frag, current TBF */
|
||||||
|
if (d_bsn > 0) {
|
||||||
|
printf("fucking error d_bsn!\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (d_bsn < -64) {
|
||||||
|
/* New frag */
|
||||||
|
t->last_bsn = bsn;
|
||||||
|
} else {
|
||||||
|
/* Duplicate */
|
||||||
|
t->frags[bsn].fn = gm->fn;
|
||||||
|
printf("duplicate2\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get fragment struct for current BSN */
|
||||||
|
f = &t->frags[bsn];
|
||||||
|
|
||||||
|
/* Scan for LI_M_E entries */
|
||||||
|
off = 2;
|
||||||
|
f->n_blocks = 0;
|
||||||
|
while (!(gm->msg[off++] & 0x01)) {
|
||||||
|
l = &f->blocks[f->n_blocks++];
|
||||||
|
l->li = (gm->msg[off] & 0xfc) >> 2;
|
||||||
|
l->m = (gm->msg[off] & 0x02) >> 1;
|
||||||
|
l->e = (gm->msg[off] & 0x01);
|
||||||
|
l->used = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End of TBF? */
|
||||||
|
f->last = (!cv || fbi) ? 1 : 0;
|
||||||
|
|
||||||
|
/* Optional fields for uplink, indicated in TI and PI */
|
||||||
|
if (ul) {
|
||||||
|
if (gm->msg[1] & 0x01) {
|
||||||
|
printf("TLLI 0x%.02x%.02x%.02x%.02x ", gm->msg[off],
|
||||||
|
gm->msg[off+1], gm->msg[off + 2], gm->msg[off + 3]);
|
||||||
|
off += 4;
|
||||||
|
}
|
||||||
|
if (gm->msg[1] & 0x40) {
|
||||||
|
printf("PFI %d ", gm->msg[off]);
|
||||||
|
off += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy data part of message */
|
||||||
|
f->len = gm->len - off;
|
||||||
|
f->fn = gm->fn;
|
||||||
|
memcpy(f->data, &gm->msg[off], f->len);
|
||||||
|
|
||||||
|
process_blocks(t, ul);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rlc_type_handler(struct gprs_message *gm)
|
||||||
|
{
|
||||||
|
bool ul = !!(gm->arfcn & GSMTAP_ARFCN_F_UPLINK);
|
||||||
|
uint8_t rlc_type = (gm->msg[0] & 0xc0) >> 6;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Determine the RLC type */
|
||||||
|
switch (rlc_type) {
|
||||||
|
case 0:
|
||||||
|
printf("TS %d ", gm->tn);
|
||||||
|
|
||||||
|
switch(gm->len) {
|
||||||
|
case 23:
|
||||||
|
printf("CS1 ");
|
||||||
|
break;
|
||||||
|
case 33:
|
||||||
|
printf("CS2 ");
|
||||||
|
break;
|
||||||
|
case 39:
|
||||||
|
printf("CS3 ");
|
||||||
|
break;
|
||||||
|
case 53:
|
||||||
|
printf("CS4 ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unknown (M)CS ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(ul ? "UL " : "DL ");
|
||||||
|
|
||||||
|
gsmtap_send_rlcmac(gm->msg, gm->len, gm->tn, ul);
|
||||||
|
|
||||||
|
printf("DATA ");
|
||||||
|
rlc_data_handler(gm);
|
||||||
|
printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Control block */
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
gsmtap_send_rlcmac(gm->msg, gm->len, gm->tn,
|
||||||
|
!!(gm->arfcn & GSMTAP_ARFCN_F_UPLINK));
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Reserved */
|
||||||
|
case 3:
|
||||||
|
printf("RLC type: reserved\n");
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Unrecognized RLC type: %d\n", rlc_type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define OLD_TIME 2000
|
||||||
|
|
||||||
|
struct gprs_message {
|
||||||
|
uint16_t arfcn;
|
||||||
|
uint32_t fn;
|
||||||
|
uint8_t tn;
|
||||||
|
uint8_t rxl;
|
||||||
|
uint8_t snr;
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t msg[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gprs_lime {
|
||||||
|
uint8_t li:6,
|
||||||
|
m:1,
|
||||||
|
e:1;
|
||||||
|
uint8_t used;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gprs_frag {
|
||||||
|
uint32_t fn;
|
||||||
|
uint8_t last;
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t data[53];
|
||||||
|
uint8_t n_blocks;
|
||||||
|
struct gprs_lime blocks[20];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct gprs_tbf {
|
||||||
|
uint8_t last_bsn;
|
||||||
|
uint8_t start_bsn;
|
||||||
|
struct gprs_frag frags[128];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
void print_pkt(uint8_t *msg, size_t len);
|
||||||
|
void process_blocks(struct gprs_tbf *t, bool ul);
|
||||||
|
void rlc_data_handler(struct gprs_message *gm);
|
||||||
|
int rlc_type_handler(struct gprs_message *gm);
|
|
@ -0,0 +1,48 @@
|
||||||
|
# The `:;' works around a Bash 3.2 bug when the output is not writeable.
|
||||||
|
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
|
||||||
|
:;{ \
|
||||||
|
echo '# Signature of the current package.' && \
|
||||||
|
echo 'm4_define([AT_PACKAGE_NAME],' && \
|
||||||
|
echo ' [$(PACKAGE_NAME)])' && \
|
||||||
|
echo 'm4_define([AT_PACKAGE_TARNAME],' && \
|
||||||
|
echo ' [$(PACKAGE_TARNAME)])' && \
|
||||||
|
echo 'm4_define([AT_PACKAGE_VERSION],' && \
|
||||||
|
echo ' [$(PACKAGE_VERSION)])' && \
|
||||||
|
echo 'm4_define([AT_PACKAGE_STRING],' && \
|
||||||
|
echo ' [$(PACKAGE_STRING)])' && \
|
||||||
|
echo 'm4_define([AT_PACKAGE_BUGREPORT],' && \
|
||||||
|
echo ' [$(PACKAGE_BUGREPORT)])'; \
|
||||||
|
echo 'm4_define([AT_PACKAGE_URL],' && \
|
||||||
|
echo ' [$(PACKAGE_URL)])'; \
|
||||||
|
} >'$(srcdir)/package.m4'
|
||||||
|
|
||||||
|
DISTCLEANFILES = atconfig
|
||||||
|
TESTSUITE = $(srcdir)/testsuite
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
$(srcdir)/package.m4 \
|
||||||
|
testsuite.at \
|
||||||
|
$(TESTSUITE) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
EXTRA_DIST += \
|
||||||
|
cs2.sample \
|
||||||
|
cs3.sample \
|
||||||
|
cs2.decoded \
|
||||||
|
cs3.decoded \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
check-local: atconfig $(TESTSUITE)
|
||||||
|
$(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS)
|
||||||
|
|
||||||
|
installcheck-local: atconfig $(TESTSUITE)
|
||||||
|
$(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' $(TESTSUITEFLAGS)
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
test ! -f '$(TESTSUITE)' || $(SHELL) '$(TESTSUITE)' --clean
|
||||||
|
|
||||||
|
AUTOM4TE = $(SHELL) $(top_srcdir)/missing --run autom4te
|
||||||
|
AUTOTEST = $(AUTOM4TE) --language=autotest
|
||||||
|
$(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4
|
||||||
|
$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at
|
||||||
|
mv $@.tmp $@
|
|
@ -0,0 +1,450 @@
|
||||||
|
TS 7 CS2 UL DATA TFI 21 BSN 0 CV 1
|
||||||
|
fn_same_bsn 494819 fn_last_bsn 494819 delta_bsn 0 old_len 0
|
||||||
|
clearing TBF 22, first 0 last 0
|
||||||
|
new TBF, starting from 0
|
||||||
|
bsn 0
|
||||||
|
TS 7 CS2 UL DATA TFI 21 BSN 1 CV 0
|
||||||
|
fn_same_bsn 494823 fn_last_bsn 4 delta_bsn 1 old_len 0
|
||||||
|
bsn 0 bsn 1
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 01c001080102e5e071070405f41b40072b62f208000100121953422ae57ef909006aa4d594321200d5401716cfabbb
|
||||||
|
|
||||||
|
TS 7 CS2 UL DATA TFI 21 BSN 0 CV 1
|
||||||
|
fn_same_bsn 8 fn_last_bsn 4 delta_bsn -1 old_len 30
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS2 UL DATA TFI 21 BSN 1 CV 0
|
||||||
|
fn_same_bsn 9 fn_last_bsn 9 delta_bsn 0 old_len 29
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS2 UL DATA TFI 21 BSN 0 CV 1
|
||||||
|
fn_same_bsn 9 fn_last_bsn 4 delta_bsn -1 old_len 30
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS2 DL DATA TFI 16 BSN 0 FBI 0
|
||||||
|
fn_same_bsn 494866 fn_last_bsn 494866 delta_bsn 0 old_len 0
|
||||||
|
clearing TBF 17, first 0 last 0
|
||||||
|
new TBF, starting from 0
|
||||||
|
bsn 0
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 01c0010802012a0462f2080001001805f444f70250b6151a
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 1 FBI 0
|
||||||
|
fn_same_bsn 494897 fn_last_bsn 31 delta_bsn 1 old_len 0
|
||||||
|
bsn 0
|
||||||
|
lime 0
|
||||||
|
bsn 1
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b
|
||||||
|
|
||||||
|
lime 1
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 2 FBI 0
|
||||||
|
fn_same_bsn 494914 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 1
|
||||||
|
lime 0
|
||||||
|
|
||||||
|
lime 1
|
||||||
|
bsn 2
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 3 FBI 0
|
||||||
|
fn_same_bsn 494936 fn_last_bsn 22 delta_bsn 1 old_len 0
|
||||||
|
bsn 2
|
||||||
|
lime 0
|
||||||
|
bsn 3
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 UL DATA TFI 20 BSN 0 CV 0
|
||||||
|
fn_same_bsn 494953 fn_last_bsn 494953 delta_bsn 0 old_len 0
|
||||||
|
clearing TBF 21, first 1 last 1
|
||||||
|
bsn 1
|
||||||
|
lime 0
|
||||||
|
new TBF, starting from 0
|
||||||
|
bsn 0
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 01c00508038d8a47
|
||||||
|
|
||||||
|
TS 7 CS4 UL DATA TFI 20 BSN 0 CV 0
|
||||||
|
fn_same_bsn 4 fn_last_bsn 4 delta_bsn 0 old_len 49
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS4 UL DATA TFI 20 BSN 0 CV 0
|
||||||
|
fn_same_bsn 5 fn_last_bsn 5 delta_bsn 0 old_len 49
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS4 UL DATA TFI 20 BSN 0 CV 0
|
||||||
|
fn_same_bsn 4 fn_last_bsn 4 delta_bsn 0 old_len 49
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 4 FBI 0
|
||||||
|
fn_same_bsn 494992 fn_last_bsn 56 delta_bsn 1 old_len 0
|
||||||
|
bsn 3
|
||||||
|
lime 0
|
||||||
|
bsn 4
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 5 FBI 0
|
||||||
|
fn_same_bsn 495009 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 4
|
||||||
|
lime 0
|
||||||
|
bsn 5
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 6 FBI 0
|
||||||
|
fn_same_bsn 495031 fn_last_bsn 22 delta_bsn 1 old_len 0
|
||||||
|
bsn 5
|
||||||
|
lime 0
|
||||||
|
bsn 6
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 UL DATA TFI 19 BSN 0 CV 1
|
||||||
|
fn_same_bsn 495048 fn_last_bsn 495048 delta_bsn 0 old_len 0
|
||||||
|
clearing TBF 20, first 0 last 0
|
||||||
|
bsn 0
|
||||||
|
lime 0
|
||||||
|
new TBF, starting from 0
|
||||||
|
bsn 0
|
||||||
|
TS 7 CS4 UL DATA TFI 19 BSN 1 CV 0
|
||||||
|
fn_same_bsn 495053 fn_last_bsn 5 delta_bsn 1 old_len 0
|
||||||
|
bsn 0 bsn 1
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 01c0090a4105030e00001f10000000000000000000000201212806056a7564666f272680c0230f0100000f04666a6b640567666a6d668021100100001081060000000083060000000032e5d0
|
||||||
|
|
||||||
|
TS 7 CS4 UL DATA TFI 19 BSN 0 CV 1
|
||||||
|
fn_same_bsn 9 fn_last_bsn 4 delta_bsn -1 old_len 50
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS4 UL DATA TFI 19 BSN 1 CV 0
|
||||||
|
fn_same_bsn 8 fn_last_bsn 8 delta_bsn 0 old_len 49
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 7 FBI 0
|
||||||
|
fn_same_bsn 495066 fn_last_bsn 35 delta_bsn 1 old_len 0
|
||||||
|
bsn 6
|
||||||
|
lime 0
|
||||||
|
bsn 7
|
||||||
|
TS 7 CS4 UL DATA TFI 19 BSN 0 CV 1
|
||||||
|
fn_same_bsn 9 fn_last_bsn 5 delta_bsn -1 old_len 50
|
||||||
|
duplicate2
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 8 FBI 0
|
||||||
|
fn_same_bsn 495074 fn_last_bsn 8 delta_bsn 1 old_len 0
|
||||||
|
bsn 6
|
||||||
|
lime 0
|
||||||
|
bsn 7 bsn 8
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 01c0058a42030e23621f72993f3f1143ffff000000002b0601210a00000627148080211002000010810608080808830600000000d68800
|
||||||
|
|
||||||
|
lime 1
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 9 FBI 0
|
||||||
|
fn_same_bsn 495096 fn_last_bsn 22 delta_bsn 1 old_len 0
|
||||||
|
bsn 8
|
||||||
|
lime 0
|
||||||
|
|
||||||
|
lime 1
|
||||||
|
bsn 9
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 10 FBI 0
|
||||||
|
fn_same_bsn 495113 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 9
|
||||||
|
lime 0
|
||||||
|
bsn 10
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 11 FBI 0
|
||||||
|
fn_same_bsn 495131 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 10
|
||||||
|
lime 0
|
||||||
|
bsn 11
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 12 FBI 0
|
||||||
|
fn_same_bsn 495148 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 11
|
||||||
|
lime 0
|
||||||
|
bsn 12
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 13 FBI 0
|
||||||
|
fn_same_bsn 495165 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 12
|
||||||
|
lime 0
|
||||||
|
bsn 13
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 14 FBI 0
|
||||||
|
fn_same_bsn 495183 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 13
|
||||||
|
lime 0
|
||||||
|
bsn 14
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 15 FBI 0
|
||||||
|
fn_same_bsn 495200 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 14
|
||||||
|
lime 0
|
||||||
|
bsn 15
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 16 FBI 0
|
||||||
|
fn_same_bsn 495217 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 15
|
||||||
|
lime 0
|
||||||
|
bsn 16
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 17 FBI 0
|
||||||
|
fn_same_bsn 495235 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 16
|
||||||
|
lime 0
|
||||||
|
bsn 17
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 18 FBI 0
|
||||||
|
fn_same_bsn 495252 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 17
|
||||||
|
lime 0
|
||||||
|
bsn 18
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 19 FBI 0
|
||||||
|
fn_same_bsn 495269 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 18
|
||||||
|
lime 0
|
||||||
|
bsn 19
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 20 FBI 0
|
||||||
|
fn_same_bsn 495287 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 19
|
||||||
|
lime 0
|
||||||
|
bsn 20
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 21 FBI 0
|
||||||
|
fn_same_bsn 495304 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 20
|
||||||
|
lime 0
|
||||||
|
bsn 21
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 22 FBI 0
|
||||||
|
fn_same_bsn 495321 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 21
|
||||||
|
lime 0
|
||||||
|
bsn 22
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 23 FBI 0
|
||||||
|
fn_same_bsn 495339 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 22
|
||||||
|
lime 0
|
||||||
|
bsn 23
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 24 FBI 0
|
||||||
|
fn_same_bsn 495356 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 23
|
||||||
|
lime 0
|
||||||
|
bsn 24
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 25 FBI 0
|
||||||
|
fn_same_bsn 495373 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 24
|
||||||
|
lime 0
|
||||||
|
bsn 25
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 26 FBI 0
|
||||||
|
fn_same_bsn 495391 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 25
|
||||||
|
lime 0
|
||||||
|
bsn 26
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 27 FBI 0
|
||||||
|
fn_same_bsn 495408 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 26
|
||||||
|
lime 0
|
||||||
|
bsn 27
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 28 FBI 0
|
||||||
|
fn_same_bsn 495425 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 27
|
||||||
|
lime 0
|
||||||
|
bsn 28
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 29 FBI 0
|
||||||
|
fn_same_bsn 495443 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 28
|
||||||
|
lime 0
|
||||||
|
bsn 29
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 30 FBI 0
|
||||||
|
fn_same_bsn 495460 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 29
|
||||||
|
lime 0
|
||||||
|
bsn 30
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 31 FBI 0
|
||||||
|
fn_same_bsn 495477 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 30
|
||||||
|
lime 0
|
||||||
|
bsn 31
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 32 FBI 0
|
||||||
|
fn_same_bsn 495495 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 31
|
||||||
|
lime 0
|
||||||
|
bsn 32
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 33 FBI 0
|
||||||
|
fn_same_bsn 495512 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 32
|
||||||
|
lime 0
|
||||||
|
bsn 33
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 34 FBI 0
|
||||||
|
fn_same_bsn 495529 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 33
|
||||||
|
lime 0
|
||||||
|
bsn 34
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 35 FBI 0
|
||||||
|
fn_same_bsn 495547 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 34
|
||||||
|
lime 0
|
||||||
|
bsn 35
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 36 FBI 0
|
||||||
|
fn_same_bsn 495564 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 35
|
||||||
|
lime 0
|
||||||
|
bsn 36
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 37 FBI 0
|
||||||
|
fn_same_bsn 495581 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 36
|
||||||
|
lime 0
|
||||||
|
bsn 37
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 38 FBI 0
|
||||||
|
fn_same_bsn 495599 fn_last_bsn 18 delta_bsn 1 old_len 0
|
||||||
|
bsn 37
|
||||||
|
lime 0
|
||||||
|
bsn 38
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 39 FBI 0
|
||||||
|
fn_same_bsn 495616 fn_last_bsn 17 delta_bsn 1 old_len 0
|
||||||
|
bsn 38
|
||||||
|
lime 0
|
||||||
|
bsn 39
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
||||||
|
TS 7 CS4 DL DATA TFI 16 BSN 40 FBI 1
|
||||||
|
fn_same_bsn 495620 fn_last_bsn 4 delta_bsn 1 old_len 0
|
||||||
|
bsn 39
|
||||||
|
lime 0
|
||||||
|
bsn 40
|
||||||
|
lime 0
|
||||||
|
end of message reached
|
||||||
|
MSG: 43c0012b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,20 @@
|
||||||
|
AT_INIT
|
||||||
|
AT_BANNER([Regression tests.])
|
||||||
|
|
||||||
|
AT_SETUP([sample/cs2])
|
||||||
|
AT_KEYWORDS([cs2])
|
||||||
|
cat $abs_srcdir/cs2.decoded > expout
|
||||||
|
AT_CHECK([
|
||||||
|
$abs_top_builddir/gprsdecode \
|
||||||
|
-c $abs_srcdir/cs2.sample
|
||||||
|
], [0], [expout], [ignore])
|
||||||
|
AT_CLEANUP
|
||||||
|
|
||||||
|
AT_SETUP([sample/cs3])
|
||||||
|
AT_KEYWORDS([cs3])
|
||||||
|
cat $abs_srcdir/cs3.decoded > expout
|
||||||
|
AT_CHECK([
|
||||||
|
$abs_top_builddir/gprsdecode \
|
||||||
|
-c $abs_srcdir/cs3.sample
|
||||||
|
], [0], [expout], [ignore])
|
||||||
|
AT_CLEANUP
|
Loading…
Reference in New Issue