summaryrefslogtreecommitdiff
path: root/gsmstack/get_lctype.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2008-12-01 01:19:19 +0530
committerHarald Welte <laforge@gnumonks.org>2008-12-01 01:19:19 +0530
commitfd405f799425b6832a0c9cc7a56b07f43288b8b1 (patch)
treec02cdfa014a63339950a98ef7e3bdbebb44adbf5 /gsmstack/get_lctype.c
parent753c2fc0f6861f6a3dcf6e5520343d93b5ed2317 (diff)
gsmstack: add new unfinished GSM burst/channel demultiplex
This is some unfinished work on a new codebase for 'proper' demultiplex of all the various physical and logical channel types. Basically this includes everything needed to get from the differential-decoded bursts up to the MAC blocks that can be passed up to layer 2.
Diffstat (limited to 'gsmstack/get_lctype.c')
-rw-r--r--gsmstack/get_lctype.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/gsmstack/get_lctype.c b/gsmstack/get_lctype.c
new file mode 100644
index 0000000..953b56d
--- /dev/null
+++ b/gsmstack/get_lctype.c
@@ -0,0 +1,105 @@
+
+/* helper routines to determine the logical channel type based on
+ * physical channel configuration and frame number */
+
+#include "gsmstack.h"
+#include "get_lctype.h"
+
+#define GSM_FN_51 (fn / 51)
+
+#define GSM_TC(fn) ((fn / 51) % 8)
+
+
+/* parameters determined from CCCH_CONF (octet 2 of control channel description
+ * in System Information Type 3:
+ * BS_CC_CHANS defines if we have CCCH on ts 2/4/6
+ * BS_CCCH_SDCCH_COMB defines if we have SDCCH/8 SACCH/C8 on TS0
+ * BS_AG_BLKS_RES defines which CCCH blocks are reserved for AGCH
+ * if BCCH Ext. is used, BS_AS_BLKS_RES has to be non-zero
+ */
+
+static int get_lctype_for_ccch(unsigned int fnr)
+{
+ unsigned int fnr51 = GSM_FN_51(fnr);
+ int lc_type;
+
+ if (fnr51 % 10 == 0)
+ lc_type = GSM_LCHAN_FCCH;
+ else if (fnr51 % 10 == 1)
+ lc_type = GSM_LCHAN_SCH;
+ else if (fnr51 >= 2 && fnr_mod_51 <= 5)
+ lc_type = GSM_LCHAN_BCCH;
+ else if (fnr51 >= 6 && fnr51 <= 9) {
+ if (flags & CCCH_F_BCCH_EXT)
+ lc_type = GSM_LCHAN_BCCH;
+ else
+ lc_ctype = GSM_LCHAN_PCH;
+ } else
+ lc_ctype = GSM_LCHAN_PCH;
+
+ /* FIXME: what about AGCH ? */
+ /* FIXME: what about NCH ? */
+ /* FIXME: what about CBCH ? */
+
+ return lc_ctype;
+}
+
+static int get_lctype_for_sdcch8(unsigned int fnr)
+{
+ unsigned int fnr51 = GSM_FN_51(fnr);
+ unsigned int fnr102 = fnr % 102;
+ int lc_type;
+
+ /* the lower 32 bursts are evenly divided between SDCCH8 0..7 */
+ if (fnr51 % < 32) {
+ lc_type = GSM_LCHAN_SDCCH8;
+ subc = fnr51 / 4;
+ } else {
+ /* the upper 16 bursts are bundles of four bursts for
+ * alternating either SACCH0..3 or SACCH4..7 */
+ lc_type = GSM_LCHAN_SACCH8C;
+ subc = (fnr51 - 32) / 4;
+ if (fnr102 > 50)
+ subc += 4;
+ }
+
+ return lc_type;
+}
+
+static int get_lctype_for_tch_f(unsigned int fnr)
+{
+ unsigned int fnr52 = fnr % 52;
+ int lc_type = GSM_LCHAN_TCH;
+
+ /* only burst number 12 and 51 are be SACCH */
+ if (fnr52 == 12 || fnr52 == 51)
+ lc_ctype = GSM_LCHAN_SACCH;
+ /* burst number 26 and 39 are empty (for measurements) */
+ else if (fnr52 == 26 || fnr52 == 39)
+ lc_ctype = GSM_LCHAN_NONE;
+
+ return lc_type;
+}
+
+int get_lctype(struct gsm_phys_chan *pchan, int fnr)
+{
+ switch (pchan->config) {
+ case GSM_PCHAN_CCCH:
+ return get_lctype_for_ccch(fnr);
+ break;
+ case GSM_PCHAN_TCH_F:
+ return get_lctype_for_tch_f(fnr);
+ break;
+ case GSM_PCHAN_SDCCH8_SACCH8C:
+ return get_lctype_for_sdcch8(fnr);
+ break;
+ }
+
+ return -EINVAL;
+}
+
+struct gsm_logi_chan *get_lchan(struct gsm_phys_chan *pchan, int fnr)
+{
+ int lctype = get_lctype(pchan, fnr);
+ return pchan->logi_chan[lctype];
+}
personal git repositories of Harald Welte. Your mileage may vary