/*! \file gsm0502.c * Paging helper code */ /* * (C) 2009 by Holger Hans Peter Freyther * All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #include #include #include unsigned int gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_t imsi) { int ccch_conf; int bs_cc_chans; int blocks; unsigned int group; ccch_conf = chan_desc->ccch_conf; bs_cc_chans = rsl_ccch_conf_to_bs_cc_chans(ccch_conf); /* code word + 2, as 2 channels equals 0x0 */ blocks = gsm48_number_of_paging_subchannels(chan_desc); group = gsm0502_get_paging_group(imsi, bs_cc_chans, blocks); return group; } /* Clause 7 Table 1 of 5 Mapping of logical channels onto physical channels */ #define TCH_REPEAT_LENGTH 13 #define FACCH_F_REPEAT_LENGTH 13 #define FACCH_H_REPEAT_LENGTH 26 static const uint8_t gsm0502_tch_f_traffic_block_map[3][8] = { {0, 1, 2, 3, 4, 5, 6, 7}, {4, 5, 6, 7, 8, 9, 10, 11}, {8, 9, 10, 11, 0, 1, 2, 3} }; static const uint8_t gsm0502_tch_h0_traffic_block_map[3][4] = { {0, 2, 4, 6}, {4, 6, 8, 10}, {8, 10, 0, 2} }; static const uint8_t gsm0502_tch_h1_traffic_block_map[3][4] = { {1, 3, 5, 7}, {5, 7, 9, 11}, {9, 11, 1, 3} }; static const uint8_t gsm0502_tch_f_facch_block_map[3][8] = { {0, 1, 2, 3, 4, 5, 6, 7}, {4, 5, 6, 7, 8, 9, 10, 11}, {8, 9, 10, 11, 0, 1, 2, 3} }; static const uint8_t gsm0502_tch_h0_facch_block_map[3][6] = { {0, 2, 4, 6, 8, 10}, {8, 10, 13, 15, 17, 19}, {17, 19, 21, 23, 0, 2} }; static const uint8_t gsm0502_tch_h1_facch_block_map[3][6] = { {1, 3, 5, 7, 9, 11}, {9, 11, 14, 16, 18, 20}, {18, 20, 22, 24, 1, 3} }; /* Struct to describe a remapping function for block frame nbumbers. The member * blockend describes the ending of a block for which we want to determine the * beginning frame number. The member distance describes the value we need to * subtract from the blockend frame number in order to get the beginning of the * the block. The member cycle describes the Repeat length in TDMA frames we * are dealing with. For traffic channels this is always 13, for control * channels it is different. The member len simply defines amount of * blockendings and distances we store in the remap table */ struct fn_remap_table { unsigned int cycle; unsigned int len; uint8_t blockend[8]; uint8_t distance[8]; }; /* Memory to hold the remap tables we will automatically generate on startup */ static struct fn_remap_table tch_f_remap_table; static struct fn_remap_table tch_h0_remap_table; static struct fn_remap_table tch_h1_remap_table; static struct fn_remap_table facch_f_remap_table; static struct fn_remap_table facch_h0_remap_table; static struct fn_remap_table facch_h1_remap_table; static struct fn_remap_table *fn_remap_table_ptr[FN_REMAP_MAX]; /* Generate a remap table from a given block map. A block map lists the block * layout as defined in GSM 05.02, Clause 7 Table 1 of 5, one block per row. * Parameters: * table: name of the remap table to output * map: traffic block map input * rows: length of the traffic block map * cols: witdh of the traffic block map * repeat: repeat length in TDMA frames (cycle) */ #define fn_remap_table_from_traffic_block_map(table, map, rows, cols, repeat) \ for(i=0;icycle; for (i = 0; i < table->len; i++) { if (table->blockend[i] == fn_cycle) { sub = table->distance[i]; break; } } if (sub == -1) { LOGP(DLGLOBAL, LOGL_ERROR, "could not remap frame number!, fn=%"PRIu32"\n", fn); return fn; } fn_map = (fn + GSM_MAX_FN - sub) % GSM_MAX_FN; return fn_map; }