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
This commit is contained in:
Andreas Eversberg 2023-06-17 19:31:40 +02:00
parent 0a2b0a20b3
commit ba5d2e4a5f
3 changed files with 81 additions and 0 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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)) {