summaryrefslogtreecommitdiff
path: root/gsmstack
diff options
context:
space:
mode:
Diffstat (limited to 'gsmstack')
-rw-r--r--gsmstack/README25
-rw-r--r--gsmstack/cch.h41
-rw-r--r--gsmstack/channel.c42
-rw-r--r--gsmstack/get_lctype.c6
-rw-r--r--gsmstack/gsmstack.c2
-rw-r--r--gsmstack/gsmstack.h6
-rw-r--r--gsmstack/gsmtap.h3
-rw-r--r--gsmstack/source_pcap_burst.c15
-rw-r--r--gsmstack/tch.c2
-rw-r--r--gsmstack/tch.h16
10 files changed, 132 insertions, 26 deletions
diff --git a/gsmstack/README b/gsmstack/README
new file mode 100644
index 0000000..54c26ed
--- /dev/null
+++ b/gsmstack/README
@@ -0,0 +1,25 @@
+gsmstack - A GSM Um Layer 1 implementation
+(C) 2008 by Harald Welte <laforge@gnumonks.org>, portions from gsm-tvoid
+========================================================================
+
+This is a GSM Layer 1 implementation mainly aimed at the requirements of
+a GSM protocol analyzer. It starts off where the demodulation ends: With
+the raw bits of the differential-decoded GSM Um burst.
+
+Based on that input, the stack takes care of demultiplexing the bursts into the
+various physical and logical channels, decoding the various burst types,
+convolutional decode and parity checking (where applicable).
+
+For the CCCH, it includes FCH and SCH processing. Frequency correction
+informaiton can be signalled to the decoder/demodulator by callback functions.
+
+The recovereed TDMA Frame Number will be passed along with all MAC blocks
+to the Layer2 protocol instance on top.
+
+The output of this Layer1 stack are the 23byte MAC blocks for control
+channels, and the 260bits (32.5byte) speech frames for TCH/F channels
+
+The codebase is currently unfinished and highly experimental.
+
+Patches/contributions are welcome, please send them to laforge@gnumonks.org
+
diff --git a/gsmstack/cch.h b/gsmstack/cch.h
new file mode 100644
index 0000000..71308c4
--- /dev/null
+++ b/gsmstack/cch.h
@@ -0,0 +1,41 @@
+
+#ifndef __GSMSTACK_CCH_H__
+#define __GSMSTACK_CCH_H__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gsmstack.h"
+
+/*
+ * decode_cch
+ *
+ * Decode a "common" control channel. Most control channels use
+ * the same burst, interleave, Viterbi and parity configuration.
+ * The documentation for the control channels defines SACCH first
+ * and then just keeps referring to that.
+ *
+ * The current (investigated) list is as follows:
+ *
+ * BCCH Norm
+ * BCCH Ext
+ * PCH
+ * AGCH
+ * CBCH (SDCCH/4)
+ * CBCH (SDCCH/8)
+ * SDCCH/4
+ * SACCH/C4
+ * SDCCH/8
+ * SACCH/C8
+ *
+ * We provide two functions, one for where all four bursts are
+ * contiguous, and one where they aren't.
+ */
+unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gsmstack/channel.c b/gsmstack/channel.c
index 768ed65..6bd61e5 100644
--- a/gsmstack/channel.c
+++ b/gsmstack/channel.c
@@ -1,7 +1,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include "gsmstack.h"
+#include "cch.h"
+#include "tch.h"
/* convert an 18byte 8-bit-per-byte burst to a 142byte 1bit-per-byte */
static void bit_per_byte(unsigned char *dest, const unsigned char *src)
@@ -21,26 +24,34 @@ static void bit_per_byte(unsigned char *dest, const unsigned char *src)
static int add_burst_to_lchan(struct gsm_logi_chan *lchan,
struct gsm_burst *burst)
{
+ struct gsm_phys_chan *pchan = burst->pchan;
int rc = 0;
/* copy burst to burst buffer */
memcpy(lchan->burst_buf[lchan->next_burst], burst, sizeof(*burst));
lchan->next_burst++;
- switch (lchan->type) {
- case GSM_LCHAN_TCH_F:
- /* FIXME */
- break;
- case GSM_LCHAN_TCH_H:
- /* FIXME */
- default:
- if (lchan->next_burst == 4) {
- lchan->next_burst = 0;
- /* FIXME: decode the four bursts into a MAC block */
-
- /* pass the resulting MAC block up the stack */
- rc = gsm_lchan_macblock()
+ if (lchan->next_burst == 4) {
+ lchan->next_burst = 0;
+ /* decode the four bursts into a MAC block */
+ switch (pchan->config) {
+ case GSM_PCHAN_TCH_H:
+ /* FIXME */
+ break;
+ case GSM_PCHAN_TCH_F:
+ rc = tch_decode();
+ break;
+ case GSM_PCHAN_CCCH:
+ case GSM_PCHAN_SDCCH8_SACCH8C:
+ rc = cch_decode();
+ break;
+ default:
+ fprintf(stderr, "unknown pchan config %u\n",
+ pchan->config);
}
+ /* pass the resulting MAC block up the stack */
+ if (rc)
+ rc = gsm_lchan_macblock()
}
return rc;
@@ -65,7 +76,7 @@ static int gsm_rx_sdcch8(struct gsm_burst *burst)
return add_burst_to_lchan(lchan, burst);
}
-static int gsm_rx_tch(struct gsm_burst *burst)
+static int gsm_rx_tch_f(struct gsm_burst *burst)
{
struct gsm_phys_chan *pchan = burst->gsm_pchan;
struct gsm_logi_chan *lchan;
@@ -131,8 +142,9 @@ int gsm_rx_burst(struct gsm_burst *burst, int bits)
rc = gsm_rx_sdcch8(burst);
break;
case GSM_PCHAN_TCH_F:
- rc =
+ rc = gsm_rx_tch_h(burst);
break;
+ case GSM_PCHAN_TCH_H:
case GSM_PCHAN_UNKNOWN:
default:
fprintf(stderr, "unknown pchan config (ts=%u\n)\n",
diff --git a/gsmstack/get_lctype.c b/gsmstack/get_lctype.c
index 953b56d..fcffaa1 100644
--- a/gsmstack/get_lctype.c
+++ b/gsmstack/get_lctype.c
@@ -81,6 +81,8 @@ static int get_lctype_for_tch_f(unsigned int fnr)
return lc_type;
}
+/* get the logical channel type based on frame number and
+ * physical channel configuration */
int get_lctype(struct gsm_phys_chan *pchan, int fnr)
{
switch (pchan->config) {
@@ -98,8 +100,10 @@ int get_lctype(struct gsm_phys_chan *pchan, int fnr)
return -EINVAL;
}
+/* get a pointer to the logical channel structure based on frame number
+ * and physical channel configuration */
struct gsm_logi_chan *get_lchan(struct gsm_phys_chan *pchan, int fnr)
{
int lctype = get_lctype(pchan, fnr);
- return pchan->logi_chan[lctype];
+ return &pchan->logi_chan[lctype];
}
diff --git a/gsmstack/gsmstack.c b/gsmstack/gsmstack.c
index 1690d15..5e69e93 100644
--- a/gsmstack/gsmstack.c
+++ b/gsmstack/gsmstack.c
@@ -22,7 +22,7 @@ struct gsm_rf_chan *gsm_init_rfchan(unsigned int arfcn)
for (i = 0; i < NR_TIMESLOTS; i++) {
struct gsm_phys_chan *pchan;
- pchan = rf->phys_chan[i];
+ pchan = &rf->phys_chan[i];
pchan->timeslot = i;
pchan->rf_chan = rf;
}
diff --git a/gsmstack/gsmstack.h b/gsmstack/gsmstack.h
index 9986dff..d73a156 100644
--- a/gsmstack/gsmstack.h
+++ b/gsmstack/gsmstack.h
@@ -4,13 +4,14 @@
#define NR_TIMESLOTS 8
#define NR_ARFCN 1024
+#define USEFUL_BITS 142
#define BURST_BITS (USEFUL_BITS/8 + 1)
#include "gsmtap.h"
enum gsm_burst_type {
GSM_BURST_UNKNOWN = GSMTAP_BURST_UNKNOWN,
GSM_BURST_FCCH = GSMTAP_BURST_FCCH,
- GSM_BURST_PARTIAL_FCCH = GSMTAP_BURST_PARTIAL_FCCH,
+ GSM_BURST_PARTIAL_SCH = GSMTAP_BURST_PARTIAL_SCH,
GSM_BURST_SCH = GSMTAP_BURST_SCH,
GSM_BURST_CTS_SCH = GSMTAP_BURST_CTS_SCH,
GSM_BURST_COMPACT_SCH = GSMTAP_BURST_COMPACT_SCH,
@@ -72,7 +73,8 @@ enum gsm_logical_channel_type {
GSM_LCHAN_SACCH8C, /* Slow Associated Control CH */
/* TCH */
- GSM_LCHAN_TCH, /* Traffic CH */
+ GSM_LCHAN_TCH_F, /* Traffic CH */
+ GSM_LCHAN_TCH_H, /* Traffic CH */
GSM_LCHAN_SACCH, /* Slow Associated Control CH */
/* uplink */
diff --git a/gsmstack/gsmtap.h b/gsmstack/gsmtap.h
index 20a6074..316e73d 100644
--- a/gsmstack/gsmtap.h
+++ b/gsmstack/gsmtap.h
@@ -43,6 +43,9 @@ struct gsmtap_hdr {
/* PCAP related definitions */
#define TCPDUMP_MAGIC 0xa1b2c3d4
+#ifndef LINKTYPE_GSMTAP
+#define LINKTYPE_GSMTAP 2342
+#endif
struct pcap_timeval {
int32_t tv_sec;
int32_t tv_usec;
diff --git a/gsmstack/source_pcap_burst.c b/gsmstack/source_pcap_burst.c
index bb340e7..0956c19 100644
--- a/gsmstack/source_pcap_burst.c
+++ b/gsmstack/source_pcap_burst.c
@@ -1,6 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
#include <pcap.h>
#include "gsmstack.h"
@@ -16,7 +19,7 @@
*/
-static struct gsm_rf_chan rfchans[NR_ARFCN];
+static struct gsm_rf_chan *rfchans[NR_ARFCN];
static int read_pcap_hdr(int fd)
{
@@ -59,7 +62,7 @@ static int send_burst(struct gsmtap_hdr *gh, int burst_len,
}
rfchan = rfchans[arfcn];
- pchan = rfchan->phys_chan[gh->timeslot];
+ pchan = &rfchan->phys_chan[gh->timeslot];
memset(&burst, 0, sizeof(burst));
burst.phys_chan = pchan;
@@ -95,11 +98,11 @@ static int read_one_pkt(int fd, unsigned char *buf, int bufsize,
return -4;
if (tv) {
- tv.tv_sec = pkthdr.tv_sec;
- tv.tv_usec = pkthdr.tv_usec;
+ tv->tv_sec = pkthdr.ts.tv_sec;
+ tv->tv_usec = pkthdr.ts.tv_usec;
}
- len = read(fd, buf, pkthdr.caplen)
+ len = read(fd, buf, pkthdr.caplen);
if (len < pkthdr.caplen)
return -5;
@@ -138,7 +141,7 @@ int main(int argc, char **argv)
unsigned char buf[1024];
struct timeval tv;
int burst_len;
- burst_len = read_one_pkt(fd, &tv, sbuf, sizeof(buf));
+ burst_len = read_one_pkt(fd, buf, sizeof(buf), &tv);
if (burst_len < 0) {
fprintf(stderr, "read_one_pkt() = %d\n", burst_len);
exit(3);
diff --git a/gsmstack/tch.c b/gsmstack/tch.c
index f8b4329..068d1cd 100644
--- a/gsmstack/tch.c
+++ b/gsmstack/tch.c
@@ -13,7 +13,7 @@
#include <ctype.h>
#include <math.h>
-#include "burst_types.h"
+//#include "burst_types.h"
#include "tch.h"
//#include "fire_crc.h"
diff --git a/gsmstack/tch.h b/gsmstack/tch.h
new file mode 100644
index 0000000..c27d633
--- /dev/null
+++ b/gsmstack/tch.h
@@ -0,0 +1,16 @@
+#ifndef __GSMSTACK_TCH_H__
+#define __GSMSTACK_TCH_H__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gsmstack.h"
+
+unsigned char *decode_tch(GS_CTX *ctx, unsigned char *burst, unsigned int *len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
personal git repositories of Harald Welte. Your mileage may vary