aboutsummaryrefslogtreecommitdiffstats
path: root/src/bts.cpp
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2019-10-05 23:45:31 +0700
committerVadim Yanitskiy <axilirator@gmail.com>2019-11-23 17:42:45 +0700
commitffebd244567196c248d31f37241c82d18cb96ac1 (patch)
tree3343de26bc8401f08f94be8125213f2853c290c2 /src/bts.cpp
parent17954da56c2642229068da93b00b92a30e7a7be3 (diff)
PTCCH: properly handle RACH.ind for PCU_IF_SAPI_PTCCH
Diffstat (limited to 'src/bts.cpp')
-rw-r--r--src/bts.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 24666af0..c8b63750 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -842,6 +842,53 @@ int BTS::rcv_rach(uint16_t ra, uint32_t Fn, int16_t qta, bool is_11bit,
return rc;
}
+/* PTCCH/U sub-slot / frame-number mapping (see 3GPP TS 45.002, table 6) */
+static uint32_t ptcch_slot_map[PTCCH_TAI_NUM] = {
+ 12, 38, 64, 90,
+ 116, 142, 168, 194,
+ 220, 246, 272, 298,
+ 324, 350, 376, 402,
+};
+
+int BTS::rcv_ptcch_rach(uint8_t trx_nr, uint8_t ts_nr, uint32_t fn, int16_t qta)
+{
+ struct gprs_rlcmac_bts *bts = bts_data();
+ struct gprs_rlcmac_pdch *pdch;
+ uint32_t fn416 = fn % 416;
+ uint8_t ss;
+
+ /* Prevent buffer overflow */
+ if (trx_nr >= ARRAY_SIZE(bts->trx) || ts_nr >= 8) {
+ LOGP(DRLCMAC, LOGL_ERROR, "Malformed RACH.ind message "
+ "(TRX=%u TS=%u FN=%u)\n", trx_nr, ts_nr, fn);
+ return -EINVAL;
+ }
+
+ /* Make sure PDCH time-slot is enabled */
+ pdch = &bts->trx[trx_nr].pdch[ts_nr];
+ if (!pdch->m_is_enabled) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "Rx PTCCH RACH.ind for inactive PDCH "
+ "(TRX=%u TS=%u FN=%u)\n", trx_nr, ts_nr, fn);
+ return -EAGAIN;
+ }
+
+ /* Convert TDMA frame-number to PTCCH/U sub-slot number */
+ for (ss = 0; ss < PTCCH_TAI_NUM; ss++)
+ if (ptcch_slot_map[ss] == fn416)
+ break;
+ if (ss == PTCCH_TAI_NUM) {
+ LOGP(DRLCMAC, LOGL_ERROR, "Failed to map PTCCH/U sub-slot for fn=%u\n", fn);
+ return -ENODEV;
+ }
+
+ /* Apply the new Timing Advance value */
+ LOGP(DRLCMAC, LOGL_INFO, "Continuous Timing Advance update "
+ "for TAI %u, new TA is %u\n", ss, qta2ta(qta));
+ pdch->update_ta(ss, qta2ta(qta));
+
+ return 0;
+}
+
void BTS::snd_dl_ass(gprs_rlcmac_tbf *tbf, bool poll, const char *imsi)
{
int plen;