diff options
-rw-r--r-- | gsmstack/README | 25 | ||||
-rw-r--r-- | gsmstack/cch.h | 41 | ||||
-rw-r--r-- | gsmstack/channel.c | 42 | ||||
-rw-r--r-- | gsmstack/get_lctype.c | 6 | ||||
-rw-r--r-- | gsmstack/gsmstack.c | 2 | ||||
-rw-r--r-- | gsmstack/gsmstack.h | 6 | ||||
-rw-r--r-- | gsmstack/gsmtap.h | 3 | ||||
-rw-r--r-- | gsmstack/source_pcap_burst.c | 15 | ||||
-rw-r--r-- | gsmstack/tch.c | 2 | ||||
-rw-r--r-- | gsmstack/tch.h | 16 |
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 |