From 51eaba28a3d4c83ecee4ca98544635d47c771380 Mon Sep 17 00:00:00 2001
From: Harald Welte <laforge@gnumonks.org>
Date: Sat, 29 Nov 2008 13:48:12 +0530
Subject: [gsm-tvoid] new gsmtap header, raw burst pcap support

* split burst decoding context out of GS_ctx and have one for each TS
* add PCAP output for GSMTAP_TYPE_UM_BURST (142 bit burst per packet)
---
 gsm-tvoid/src/lib/gsmstack.c | 96 +++++++++++++++++++++++++++++++-------------
 gsm-tvoid/src/lib/gsmstack.h | 12 ++++--
 gsm-tvoid/src/lib/gsmtap.h   | 23 +++++++++--
 gsm-tvoid/src/lib/out_pcap.c | 14 +++++--
 gsm-tvoid/src/lib/out_pcap.h |  4 +-
 5 files changed, 110 insertions(+), 39 deletions(-)

(limited to 'gsm-tvoid/src')

diff --git a/gsm-tvoid/src/lib/gsmstack.c b/gsm-tvoid/src/lib/gsmstack.c
index c0f422e..a46bc87 100644
--- a/gsm-tvoid/src/lib/gsmstack.c
+++ b/gsm-tvoid/src/lib/gsmstack.c
@@ -17,6 +17,28 @@
 
 static void out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len);
 
+/* encode a decoded burst (1 bit per byte) into 8-bit-per-byte */
+static void burst_octify(unsigned char *dest, 
+			 const unsigned char *data, int length)
+{
+	int bitpos = 0;
+
+	while (bitpos < USEFUL_BITS) {
+		unsigned char tbyte;
+		int i; 
+
+		tbyte = 0;
+		for (i = 0; (i < 8) && (bitpos < length); i++) {
+			tbyte <<= 1;
+			tbyte |= data[bitpos++];
+		}
+		if (i < 8)
+			tbyte <<= 8 - i;
+		*dest++ = tbyte;
+	}	
+}
+
+
 #if 0
 static void
 diff_decode(char *dst, char *src, int len)
@@ -58,9 +80,14 @@ GS_new(GS_CTX *ctx)
 	if (ctx->pcap_fd < 0)
 		fprintf(stderr, "cannot open PCAP file: %s\n", strerror(errno));
 
+	ctx->burst_pcap_fd = open_pcap_file("tvoid-burst.pcap");
+	if (ctx->burst_pcap_fd < 0)
+		fprintf(stderr, "cannot open burst PCAP file: %s\n", strerror(errno));
+
 	return 0;
 }
 
+#define BURST_BYTES	((USEFUL_BITS/8)+1)
 /*
  * 142 bit
  */
@@ -72,7 +99,17 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src)
 	int ret;
 	unsigned char *data;
 	int len;
+	struct gs_ts_ctx *ts_ctx = &ctx->ts_ctx[ts];
+	unsigned char octified[BURST_BYTES];
 
+	memset(ctx->msg, 0, sizeof(ctx->msg));
+
+	/* write burst to burst PCAP file */
+	burst_octify(octified, src, USEFUL_BITS);
+	write_pcap_packet(ctx->burst_pcap_fd, 0 /* arfcn */, ts, ctx->fn,
+			  1, type, octified, BURST_BYTES);
+	
+#if 0
 	if (ts != 0) {
 		/* non-0 timeslots should end up in PCAP */
 		data = decode_cch(ctx, ctx->burst, &len);
@@ -81,51 +118,56 @@ GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src)
 		write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, data, len);
 		return;
 	}
+#endif
 
-	if (type == SCH)
-	{
-		ret = decode_sch(src, &fn, &bsic);
-		if (ret != 0)
+	if (ts == 0) {
+		if (type == SCH) {
+			ret = decode_sch(src, &fn, &bsic);
+			if (ret != 0)
+				return 0;
+			if ((ctx->bsic > 0) && (bsic != ctx->bsic))
+				fprintf(stderr, "WARN: BSIC changed.\n");
+			//DEBUGF("FN %d, BSIC %d\n", fn, bsic);
+			ctx->fn = fn;
+			ctx->bsic = bsic;
+			/* Reset message concatenator */
+			ts_ctx->burst_count = 0;
 			return 0;
-		if ((ctx->bsic > 0) && (bsic != ctx->bsic))
-			fprintf(stderr, "WARN: BSIC changed.\n");
-		//DEBUGF("FN %d, BSIC %d\n", fn, bsic);
-		ctx->fn = fn;
-		ctx->bsic = bsic;
-		/* Reset message concatenator */
-		ctx->burst_count = 0;
-		return 0;
-	}
+		}
 
-	/* If we did not get Frame Number yet then return */
-	if (ctx->fn < 0)
-		return 0;
+		/* If we did not get Frame Number yet then return */
+		if (ctx->fn < 0)
+			return 0;
 
-	ctx->fn++;
-	if (type == NORMAL)
-	{
+		ctx->fn++;
+	}
+
+	if (type == NORMAL) {
 		/* Interested in these frame numbers (cch)
  		 * 2-5, 12-15, 22-25, 23-35, 42-45
  		 * 6-9, 16-19, 26-29, 36-39, 46-49
  		 */
 		/* Copy content data into new array */
 		//DEBUGF("burst count %d\n", ctx->burst_count);
-		memcpy(ctx->burst + (116 * ctx->burst_count), src, 58);
-		memcpy(ctx->burst + (116 * ctx->burst_count) + 58, src + 58 + 26, 58);
-		ctx->burst_count++;
+		memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count), src, 58);
+		memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count) + 58, src + 58 + 26, 58);
+		ts_ctx->burst_count++;
 		/* Return if not enough bursts for a full gsm message */
-		if (ctx->burst_count < 4)
+		if (ts_ctx->burst_count < 4)
 			return 0;
 
-		ctx->burst_count = 0;
-		data = decode_cch(ctx, ctx->burst, &len);
-		if (data == NULL)
+		ts_ctx->burst_count = 0;
+		data = decode_cch(ctx, ts_ctx->burst, &len);
+		if (data == NULL) {
+			DEBUGF("cannot decode fnr=0x%08x ts=%d\n", ctx->fn, ts);
 			return -1;
+		}
 		//DEBUGF("OK TS %d, len %d\n", ts, len);
 
 		out_gsmdecode(0, 0, ts, ctx->fn - 4, data, len);
 		write_interface(ctx->tun_fd, data+1, len-1, ctx->ether_addr);
-		write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, data, len);
+		write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn,
+				  0, NORMAL, data, len);
 #if 0
 		if (ctx->fn % 51 != 0) && ( (((ctx->fn % 51 + 5) % 10 == 0) || (((ctx->fn % 51) + 1) % 10 ==0) ) )
 			ready = 1;
diff --git a/gsm-tvoid/src/lib/gsmstack.h b/gsm-tvoid/src/lib/gsmstack.h
index b4a5c96..a9da102 100644
--- a/gsm-tvoid/src/lib/gsmstack.h
+++ b/gsm-tvoid/src/lib/gsmstack.h
@@ -9,22 +9,28 @@ extern "C" {
 #include <linux/if_ether.h>
 #include "interleave.h"
 
+struct gs_ts_ctx {
+	/* FIXME: later do this per each ts per each arfcn */
+	unsigned char burst[4 * 58 * 2];
+	int burst_count;
+};
+
 typedef struct
 {
 	int flags;
 	int fn;
 	int bsic;
 	char msg[23];	/* last decoded message */
+
 	INTERLEAVE_CTX interleave_ctx;
 
-	/* FIXME: later do this per each ts per each arfcn */
-	unsigned char burst[4 * 58 * 2];
-	int burst_count;
+	struct gs_ts_ctx ts_ctx[8];
 
 	int tun_fd;
 	unsigned char ether_addr[ETH_ALEN];
 
 	int pcap_fd;
+	int burst_pcap_fd;
 } GS_CTX;
 
 int GS_new(GS_CTX *ctx);
diff --git a/gsm-tvoid/src/lib/gsmtap.h b/gsm-tvoid/src/lib/gsmtap.h
index 6676d9a..1022194 100644
--- a/gsm-tvoid/src/lib/gsmtap.h
+++ b/gsm-tvoid/src/lib/gsmtap.h
@@ -5,10 +5,21 @@
 
 #include <sys/types.h>
 
-#define GSMTAP_VERSION		0x02
+#define GSMTAP_VERSION		0x01
 
 #define GSMTAP_TYPE_UM		0x01
 #define GSMTAP_TYPE_ABIS	0x02
+#define GSMTAP_TYPE_UM_BURST	0x03	/* raw burst bits */
+
+#define GSMTAP_BURST_UNKNOWN		0x00
+#define GSMTAP_BURST_FCCH		0x01
+#define GSMTAP_BURST_PARTIAL_SCH	0x02
+#define GSMTAP_BURST_SCH		0x03
+#define GSMTAP_BURST_CTS_SCH		0x04
+#define GSMTAP_BURST_COMPACT_SCH	0x05
+#define GSMTAP_BURST_NORMAL		0x06
+#define GSMTAP_BURST_DUMMY		0x07
+#define GSMTAP_BURST_ACCESS		0x08
 
 struct gsmtap_hdr {
 	u_int8_t version;		/* version, set to 0x01 currently */
@@ -17,10 +28,14 @@ struct gsmtap_hdr {
 	u_int8_t timeslot;		/* timeslot (0..7 on Um) */
 
 	u_int16_t arfcn;		/* ARFCN (frequency) */
-	u_int8_t noise_db;
-	u_int8_t signal_db;
+	u_int8_t noise_db;		/* noise figure in dB */
+	u_int8_t signal_db;		/* signal level in dB */
 
-	u_int32_t frame_number;
+	u_int32_t frame_number;		/* GSM Frame Number (FN) */
+
+	u_int8_t burst_type;		/* Type of burst, see above */
+	u_int8_t antenna_nr;		/* Antenna Number */
+	u_int16_t res;			/* reserved for future use (RFU) */
 
 } __attribute__((packed));
 #endif /* _GSMTAP_H */
diff --git a/gsm-tvoid/src/lib/out_pcap.c b/gsm-tvoid/src/lib/out_pcap.c
index 95f24f5..4da5fd6 100644
--- a/gsm-tvoid/src/lib/out_pcap.c
+++ b/gsm-tvoid/src/lib/out_pcap.c
@@ -67,7 +67,8 @@ int open_pcap_file(char *fname)
 }
 
 int write_pcap_packet(int fd, int arfcn, int ts, int fn,
-		      char *data, unsigned int len)
+		      int burst, int burst_type,
+		      const unsigned char *data, unsigned int len)
 {
 	unsigned char buf[8192];
 	struct pcap_sf_pkthdr *ph;
@@ -75,7 +76,8 @@ int write_pcap_packet(int fd, int arfcn, int ts, int fn,
 	struct timeval tv;
 	int rc;
 
-	printf("writing pcap packet fd=%d len=%d\n", fd, len);
+	if (fd < 0)
+		return -EINVAL;
 
 	ph = (struct pcap_sf_pkthdr *) &buf[0];
 	gh = (struct gsmtap_hdr *) &buf[sizeof(struct pcap_sf_pkthdr)];
@@ -88,18 +90,22 @@ int write_pcap_packet(int fd, int arfcn, int ts, int fn,
 
 	gh->version = GSMTAP_VERSION;
 	gh->hdr_len = sizeof(struct gsmtap_hdr)>>2;
-	gh->type = GSMTAP_TYPE_UM;
+	if (burst)
+		gh->type = GSMTAP_TYPE_UM_BURST;
+	else
+		gh->type = GSMTAP_TYPE_UM;
 	gh->timeslot = ts;
 	gh->arfcn = htons(arfcn);
 	/* we don't support signal/noise yet */
 	gh->noise_db = gh->signal_db = 0;
 	gh->frame_number = htonl(fn);
+	gh->burst_type = burst_type & 0xff;
 
 	memcpy(buf + sizeof(*ph) + sizeof(*gh), data, len);
 	
 	rc = write(fd, buf, sizeof(*ph) + sizeof(*gh) + len);
 
-	fsync(fd);
+	//fsync(fd);
 
 	return rc;
 }
diff --git a/gsm-tvoid/src/lib/out_pcap.h b/gsm-tvoid/src/lib/out_pcap.h
index e8d4b3c..5ae5e3c 100644
--- a/gsm-tvoid/src/lib/out_pcap.h
+++ b/gsm-tvoid/src/lib/out_pcap.h
@@ -2,6 +2,8 @@
 #define _PCAP_IF_H
 
 extern int open_pcap_file(char *fname);
-int write_pcap_packet(int fd, int arfcn, int ts, int fn, char *data, unsigned int len);
 
+int write_pcap_packet(int fd, int arfcn, int ts, int fn,
+		      int burst, int burst_type,
+		      const unsigned char *data, unsigned int len);
 #endif
-- 
cgit v1.2.3