diff options
Diffstat (limited to 'gsmstack/channel.c')
-rw-r--r-- | gsmstack/channel.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/gsmstack/channel.c b/gsmstack/channel.c new file mode 100644 index 0000000..768ed65 --- /dev/null +++ b/gsmstack/channel.c @@ -0,0 +1,143 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "gsmstack.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) +{ + 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() + } + } + + 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(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 = + break; + case GSM_PCHAN_UNKNOWN: + default: + fprintf(stderr, "unknown pchan config (ts=%u\n)\n", + pchan->timeslot); + return; + break; + } +} |