aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2023-06-17 19:31:40 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2023-07-21 13:20:10 +0200
commitba5d2e4a5f0e967043b5116831e58bd99581c6bd (patch)
tree720d1b71236aa33cc9383a0068bacdb4d04e1f3b
parent0a2b0a20b3de24b6c93ce2551f0e08c23c2f62db (diff)
ASCI: Add Notification/FACCH support
When a VGCS/VBS call is established in a cell, NCH is used to notify about ongoing calls to idle subscribers. Additionally Notification/FACCH is used to notify subscribers in dedicated mode. This is performed by broadcasting this messages to all active dedicated channels. The mobile station can then indicate the call, so the user can join the call. More importaint is the notification of the calling subscriber's MS, which initiated the call. This is done on the early assigned channel. The MS must know on which channel the call is placed. After leaving the uplink, it must know where to access the uplink the next time. Change-Id: I3ed14fa54a907891e492a7ada8e745a2c56cd46d Related: OS#4851, OS#5781
-rw-r--r--include/osmo-bts/notification.h2
-rw-r--r--src/common/notification.c31
-rw-r--r--src/common/rsl.c48
3 files changed, 81 insertions, 0 deletions
diff --git a/include/osmo-bts/notification.h b/include/osmo-bts/notification.h
index f8a7b480..e53d718b 100644
--- a/include/osmo-bts/notification.h
+++ b/include/osmo-bts/notification.h
@@ -57,3 +57,5 @@ const struct asci_notification *bts_asci_notification_get_next(struct gsm_bts *b
void append_group_call_information(struct bitvec *bv, const uint8_t *gcr, const uint8_t *ch_desc, uint8_t ch_desc_len);
int bts_asci_notify_nch_gen_msg(struct gsm_bts *bts, uint8_t *out_buf);
+int bts_asci_notify_facch_gen_msg(struct gsm_bts *bts, uint8_t *out_buf, const uint8_t *group_call_ref,
+ const uint8_t *chan_desc, uint8_t chan_desc_len);
diff --git a/src/common/notification.c b/src/common/notification.c
index 35dc65f9..9351ec04 100644
--- a/src/common/notification.c
+++ b/src/common/notification.c
@@ -223,3 +223,34 @@ int bts_asci_notify_nch_gen_msg(struct gsm_bts *bts, uint8_t *out_buf)
return GSM_MACBLOCK_LEN;
}
+
+int bts_asci_notify_facch_gen_msg(struct gsm_bts *bts, uint8_t *out_buf, const uint8_t *group_call_ref,
+ const uint8_t *chan_desc, uint8_t chan_desc_len)
+{
+ struct gsm48_hdr_sh *sh = (struct gsm48_hdr_sh *) out_buf;
+ unsigned int ro_len;
+
+ *sh = (struct gsm48_hdr_sh) {
+ .rr_short_pd = GSM48_PDISC_SH_RR,
+ .msg_type = GSM48_MT_RR_SH_FACCH,
+ .l2_header = 0,
+ };
+
+ /* Pad remaining octets with constant '2B'O */
+ ro_len = GSM_MACBLOCK_LEN - (sh->data - out_buf);
+ memset(sh->data, GSM_MACBLOCK_PADDING, ro_len);
+
+ struct bitvec bv = {
+ .data_len = ro_len,
+ .data = sh->data,
+ };
+
+ /* 0 < Group Call information > */
+ bitvec_set_bit(&bv, 0);
+ append_group_call_information(&bv, group_call_ref, chan_desc, chan_desc_len);
+
+ /* TODO: Additions in Release 6 */
+ /* TODO: Additions in Release 7 */
+
+ return GSM_MACBLOCK_LEN;
+}
diff --git a/src/common/rsl.c b/src/common/rsl.c
index c7450c57..d47ba99d 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -811,6 +811,51 @@ static int rsl_rx_sms_bcast_cmd(struct gsm_bts_trx *trx, struct msgb *msg)
return 0;
}
+/* Broadcast notification about new VGCS/VBS call on every dedicated channel.
+ * This is required for MSs that are currently in dedicated mode that there is an ongoing call and on which channel
+ * the call is active. Most MSs in dedicated mode may not be able to receive the NCH otherwise.
+ * MSs that do not support ASCI will ignore it, as it is an unsupported message for them.
+ */
+static int asci_broadcast_facch(struct gsm_bts *bts, const uint8_t *group_call_ref, const uint8_t *chan_desc,
+ uint8_t chan_desc_len, unsigned int count)
+{
+ uint8_t notif[23];
+ struct msgb *msg, *cmsg;
+ struct gsm_bts_trx *trx;
+ struct gsm_lchan *lchan;
+ unsigned int tn, ln, n;
+ int rc;
+
+ rc = bts_asci_notify_facch_gen_msg(bts, notif, group_call_ref, chan_desc, chan_desc_len);
+ if (rc < 0)
+ return rc;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
+ for (ln = 0; ln < ARRAY_SIZE(trx->ts[tn].lchan); ln++) {
+ lchan = &trx->ts[tn].lchan[ln];
+ if (!lchan_is_dcch(lchan))
+ continue;
+ if (lchan->state != LCHAN_S_ACTIVE)
+ continue;
+ msg = rsl_rll_simple(RSL_MT_UNIT_DATA_REQ, gsm_lchan2chan_nr(lchan), 0x00, 0);
+ msg->l3h = msg->tail; /* emulate rsl_rx_rll() behaviour */
+ msgb_tl16v_put(msg, RSL_IE_L3_INFO, sizeof(notif), (uint8_t *) &notif);
+ for (n = 1; n < count; n++) {
+ cmsg = msgb_copy(msg, "FACCH copy");
+ lapdm_rslms_recvmsg(cmsg, &lchan->lapdm_ch);
+ }
+ lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Number of times to broadcast ASCI call on every dedicated channel. */
+#define ASCI_BROADCAST_NUM 3
+
/* 8.5.10 NOTIFICATION COMMAND */
static int rsl_rx_notification_cmd(struct gsm_bts_trx *trx, struct msgb *msg)
{
@@ -841,6 +886,9 @@ static int rsl_rx_notification_cmd(struct gsm_bts_trx *trx, struct msgb *msg)
rc = bts_asci_notification_add(trx->bts, TLVP_VAL(&tp, RSL_IE_GROUP_CALL_REF),
TLVP_VAL(&tp, RSL_IE_CHAN_DESC), TLVP_LEN(&tp, RSL_IE_CHAN_DESC),
(struct rsl_ie_nch_drx_info *) TLVP_VAL(&tp, RSL_IE_NCH_DRX_INFO));
+ /* Broadcast to FACCH */
+ asci_broadcast_facch(trx->bts, TLVP_VAL(&tp, RSL_IE_GROUP_CALL_REF), TLVP_VAL(&tp, RSL_IE_CHAN_DESC),
+ TLVP_LEN(&tp, RSL_IE_CHAN_DESC), ASCI_BROADCAST_NUM);
break;
case RSL_CMD_INDICATOR_STOP:
if (!TLVP_PRES_LEN(&tp, RSL_IE_GROUP_CALL_REF, 5)) {