airprobe/gsmstack/channel.c

156 lines
3.3 KiB
C

#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)
{
int bit, byte;
for (byte = 0; byte < BURST_BYTES; src++) {
for (bit = 0; bit < 8; bit++) {
if (src[byte] >> bit &= 0x01)
*dest++ = 0x01;
else
*dest++ = 0x00;
}
}
}
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++;
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;
}
static int gsm_rx_sdcch8(struct gsm_burst *burst)
{
struct gsm_phys_chan *pchan = burst->gsm_pchan;
int rc = -EINVAL;
if (burst_type == GSM_BURST_DUMMY)
return;
if (burst->type != GSM_BURST_NORMAL) {
fprintf(stderr, "Burst type %u not allowed in SDCCH8\n",
burst->type);
/* FIXME: statistics */
return rc;
}
lchan = get_lchan(pchan, burst->fnr);
return add_burst_to_lchan(lchan, burst);
}
static int gsm_rx_tch_f(struct gsm_burst *burst)
{
struct gsm_phys_chan *pchan = burst->gsm_pchan;
struct gsm_logi_chan *lchan;
int rc = -EINVAL;
if (burst->type != GSM_BURST_NORMAL)
return rc;
lchan = get_lchan(pchan, fnr);
return add_burst_to_lchan(lchan, burst);
}
/* input a new GSM Um burst on a CCCH */
static int gsm_rx_ccch(struct gsm_burst *burst)
{
struct gsm_phys_chan *pchan = burst->gsm_pchan;
struct gsm_logi_chan *lchan;
int rc = -EINVAL;
switch (burst->type) {
case GSM_BURST_FCCH:
/* FIXME */
/* obtain the frequency offset and report to caller */
break;
case GSM_BURST_SCH:
/* obtain the RFN from the SCH burst */
/* FIXME */
break;
case GSM_BURST_NORMAL:
/* determine logical channel and append burst */
lchan = get_lchan(pchan, burst->fnr);
rc = add_burst_to_lchan(lchan, burst);
break;
default:
break;
};
return rc;
}
/* input a new GSM Um interface burst into the stack */
int gsm_rx_burst(struct gsm_burst *burst, int bits)
{
struct gsm_phys_chan *pchan;
int rc = -EINVAL;
/* we assume the following fields have already been
* filled-in by the caller:
* phys_chan, rx_time, rx_frame_nr, decoded/decoded_bits */
pchan = burst->phys_chan;
if (!bits)
bit_per_byte(burst->decoded_bits, burst->decoded);
pchan->stats.rx_total++;
pchan->stats.rx_type[burst->type]++;
switch (pchan->config) {
case GSM_PCHAN_CCCH:
rc = gsm_rx_ccch(burst);
break;
case GSM_PCHAN_SDCCH8_SACCH8C:
rc = gsm_rx_sdcch8(burst);
break;
case GSM_PCHAN_TCH_F:
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",
pchan->timeslot);
return;
break;
}
}