Add README, various compile fixes
This commit is contained in:
parent
10f2fcca8d
commit
602a3c8aa8
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -1,7 +1,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "gsmstack.h"
|
#include "gsmstack.h"
|
||||||
|
#include "cch.h"
|
||||||
|
#include "tch.h"
|
||||||
|
|
||||||
/* convert an 18byte 8-bit-per-byte burst to a 142byte 1bit-per-byte */
|
/* 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)
|
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,
|
static int add_burst_to_lchan(struct gsm_logi_chan *lchan,
|
||||||
struct gsm_burst *burst)
|
struct gsm_burst *burst)
|
||||||
{
|
{
|
||||||
|
struct gsm_phys_chan *pchan = burst->pchan;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/* copy burst to burst buffer */
|
/* copy burst to burst buffer */
|
||||||
memcpy(lchan->burst_buf[lchan->next_burst], burst, sizeof(*burst));
|
memcpy(lchan->burst_buf[lchan->next_burst], burst, sizeof(*burst));
|
||||||
lchan->next_burst++;
|
lchan->next_burst++;
|
||||||
|
|
||||||
switch (lchan->type) {
|
if (lchan->next_burst == 4) {
|
||||||
case GSM_LCHAN_TCH_F:
|
lchan->next_burst = 0;
|
||||||
/* FIXME */
|
/* decode the four bursts into a MAC block */
|
||||||
break;
|
switch (pchan->config) {
|
||||||
case GSM_LCHAN_TCH_H:
|
case GSM_PCHAN_TCH_H:
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
default:
|
break;
|
||||||
if (lchan->next_burst == 4) {
|
case GSM_PCHAN_TCH_F:
|
||||||
lchan->next_burst = 0;
|
rc = tch_decode();
|
||||||
/* FIXME: decode the four bursts into a MAC block */
|
break;
|
||||||
|
case GSM_PCHAN_CCCH:
|
||||||
/* pass the resulting MAC block up the stack */
|
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||||
rc = gsm_lchan_macblock()
|
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;
|
return rc;
|
||||||
|
@ -65,7 +76,7 @@ static int gsm_rx_sdcch8(struct gsm_burst *burst)
|
||||||
return add_burst_to_lchan(lchan, 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_phys_chan *pchan = burst->gsm_pchan;
|
||||||
struct gsm_logi_chan *lchan;
|
struct gsm_logi_chan *lchan;
|
||||||
|
@ -131,8 +142,9 @@ int gsm_rx_burst(struct gsm_burst *burst, int bits)
|
||||||
rc = gsm_rx_sdcch8(burst);
|
rc = gsm_rx_sdcch8(burst);
|
||||||
break;
|
break;
|
||||||
case GSM_PCHAN_TCH_F:
|
case GSM_PCHAN_TCH_F:
|
||||||
rc =
|
rc = gsm_rx_tch_h(burst);
|
||||||
break;
|
break;
|
||||||
|
case GSM_PCHAN_TCH_H:
|
||||||
case GSM_PCHAN_UNKNOWN:
|
case GSM_PCHAN_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown pchan config (ts=%u\n)\n",
|
fprintf(stderr, "unknown pchan config (ts=%u\n)\n",
|
||||||
|
|
|
@ -81,6 +81,8 @@ static int get_lctype_for_tch_f(unsigned int fnr)
|
||||||
return lc_type;
|
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)
|
int get_lctype(struct gsm_phys_chan *pchan, int fnr)
|
||||||
{
|
{
|
||||||
switch (pchan->config) {
|
switch (pchan->config) {
|
||||||
|
@ -98,8 +100,10 @@ int get_lctype(struct gsm_phys_chan *pchan, int fnr)
|
||||||
return -EINVAL;
|
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)
|
struct gsm_logi_chan *get_lchan(struct gsm_phys_chan *pchan, int fnr)
|
||||||
{
|
{
|
||||||
int lctype = get_lctype(pchan, fnr);
|
int lctype = get_lctype(pchan, fnr);
|
||||||
return pchan->logi_chan[lctype];
|
return &pchan->logi_chan[lctype];
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct gsm_rf_chan *gsm_init_rfchan(unsigned int arfcn)
|
||||||
for (i = 0; i < NR_TIMESLOTS; i++) {
|
for (i = 0; i < NR_TIMESLOTS; i++) {
|
||||||
struct gsm_phys_chan *pchan;
|
struct gsm_phys_chan *pchan;
|
||||||
|
|
||||||
pchan = rf->phys_chan[i];
|
pchan = &rf->phys_chan[i];
|
||||||
pchan->timeslot = i;
|
pchan->timeslot = i;
|
||||||
pchan->rf_chan = rf;
|
pchan->rf_chan = rf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
#define NR_TIMESLOTS 8
|
#define NR_TIMESLOTS 8
|
||||||
#define NR_ARFCN 1024
|
#define NR_ARFCN 1024
|
||||||
|
|
||||||
|
#define USEFUL_BITS 142
|
||||||
#define BURST_BITS (USEFUL_BITS/8 + 1)
|
#define BURST_BITS (USEFUL_BITS/8 + 1)
|
||||||
|
|
||||||
#include "gsmtap.h"
|
#include "gsmtap.h"
|
||||||
enum gsm_burst_type {
|
enum gsm_burst_type {
|
||||||
GSM_BURST_UNKNOWN = GSMTAP_BURST_UNKNOWN,
|
GSM_BURST_UNKNOWN = GSMTAP_BURST_UNKNOWN,
|
||||||
GSM_BURST_FCCH = GSMTAP_BURST_FCCH,
|
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_SCH = GSMTAP_BURST_SCH,
|
||||||
GSM_BURST_CTS_SCH = GSMTAP_BURST_CTS_SCH,
|
GSM_BURST_CTS_SCH = GSMTAP_BURST_CTS_SCH,
|
||||||
GSM_BURST_COMPACT_SCH = GSMTAP_BURST_COMPACT_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 */
|
GSM_LCHAN_SACCH8C, /* Slow Associated Control CH */
|
||||||
|
|
||||||
/* TCH */
|
/* 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 */
|
GSM_LCHAN_SACCH, /* Slow Associated Control CH */
|
||||||
|
|
||||||
/* uplink */
|
/* uplink */
|
||||||
|
|
|
@ -43,6 +43,9 @@ struct gsmtap_hdr {
|
||||||
|
|
||||||
/* PCAP related definitions */
|
/* PCAP related definitions */
|
||||||
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||||
|
#ifndef LINKTYPE_GSMTAP
|
||||||
|
#define LINKTYPE_GSMTAP 2342
|
||||||
|
#endif
|
||||||
struct pcap_timeval {
|
struct pcap_timeval {
|
||||||
int32_t tv_sec;
|
int32_t tv_sec;
|
||||||
int32_t tv_usec;
|
int32_t tv_usec;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
|
|
||||||
#include "gsmstack.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)
|
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];
|
rfchan = rfchans[arfcn];
|
||||||
pchan = rfchan->phys_chan[gh->timeslot];
|
pchan = &rfchan->phys_chan[gh->timeslot];
|
||||||
|
|
||||||
memset(&burst, 0, sizeof(burst));
|
memset(&burst, 0, sizeof(burst));
|
||||||
burst.phys_chan = pchan;
|
burst.phys_chan = pchan;
|
||||||
|
@ -95,11 +98,11 @@ static int read_one_pkt(int fd, unsigned char *buf, int bufsize,
|
||||||
return -4;
|
return -4;
|
||||||
|
|
||||||
if (tv) {
|
if (tv) {
|
||||||
tv.tv_sec = pkthdr.tv_sec;
|
tv->tv_sec = pkthdr.ts.tv_sec;
|
||||||
tv.tv_usec = pkthdr.tv_usec;
|
tv->tv_usec = pkthdr.ts.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = read(fd, buf, pkthdr.caplen)
|
len = read(fd, buf, pkthdr.caplen);
|
||||||
if (len < pkthdr.caplen)
|
if (len < pkthdr.caplen)
|
||||||
return -5;
|
return -5;
|
||||||
|
|
||||||
|
@ -138,7 +141,7 @@ int main(int argc, char **argv)
|
||||||
unsigned char buf[1024];
|
unsigned char buf[1024];
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int burst_len;
|
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) {
|
if (burst_len < 0) {
|
||||||
fprintf(stderr, "read_one_pkt() = %d\n", burst_len);
|
fprintf(stderr, "read_one_pkt() = %d\n", burst_len);
|
||||||
exit(3);
|
exit(3);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "burst_types.h"
|
//#include "burst_types.h"
|
||||||
#include "tch.h"
|
#include "tch.h"
|
||||||
//#include "fire_crc.h"
|
//#include "fire_crc.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
|
Loading…
Reference in New Issue