From fd405f799425b6832a0c9cc7a56b07f43288b8b1 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 1 Dec 2008 01:19:19 +0530 Subject: 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. --- gsmstack/get_lctype.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 gsmstack/get_lctype.c (limited to 'gsmstack/get_lctype.c') 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]; +} -- cgit v1.2.3