summaryrefslogtreecommitdiff
path: root/gsmstack/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'gsmstack/channel.c')
-rw-r--r--gsmstack/channel.c143
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;
+ }
+}
personal git repositories of Harald Welte. Your mileage may vary