From a6c837cd982dcd7075ff022ae58f71520b148b75 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 2 Feb 2024 04:45:43 +0700 Subject: [PATCH] l1gprs: implement UL BLOCK.cnf (L1CTL_GPRS_UL_BLOCK_CNF) Change-Id: I56e0b5631c7446390adbfc5664e56f56ebb88cc1 --- include/l1ctl_proto.h | 8 ++++++++ include/l1gprs.h | 4 ++++ src/shared/l1gprs.c | 41 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/include/l1ctl_proto.h b/include/l1ctl_proto.h index 941a947a2..79feabab1 100644 --- a/include/l1ctl_proto.h +++ b/include/l1ctl_proto.h @@ -60,6 +60,7 @@ enum { /* Extended (11-bit) RACH (see 3GPP TS 05.02, section 5.2.7) */ L1CTL_EXT_RACH_REQ = 0x24, L1CTL_GPRS_RTS_IND = 0x25, + L1CTL_GPRS_UL_BLOCK_CNF = 0x26, }; enum ccch_mode { @@ -401,4 +402,11 @@ struct l1ctl_gprs_rts_ind { uint8_t usf; } __attribute__((packed)); +/* payload of L1CTL_GPRS_UL_BLOCK_CNF */ +struct l1ctl_gprs_ul_block_cnf { + uint32_t fn; + uint8_t tn; + uint8_t data[0]; +} __attribute__((packed)); + #endif /* __L1CTL_PROTO_H__ */ diff --git a/include/l1gprs.h b/include/l1gprs.h index 57380d3f8..6a18da1f2 100644 --- a/include/l1gprs.h +++ b/include/l1gprs.h @@ -111,6 +111,10 @@ struct l1gprs_prim_dl_block_ind { int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs, struct l1gprs_prim_ul_block_req *req, const struct msgb *msg); +struct msgb *l1gprs_handle_ul_block_cnf(struct l1gprs_state *gprs, + uint32_t fn, uint8_t tn, + const uint8_t *data, + size_t data_len); struct msgb *l1gprs_handle_dl_block_ind(struct l1gprs_state *gprs, const struct l1gprs_prim_dl_block_ind *ind, uint8_t *usf); struct msgb *l1gprs_handle_rts_ind(struct l1gprs_state *gprs, uint32_t fn, uint8_t tn, uint8_t usf); diff --git a/src/shared/l1gprs.c b/src/shared/l1gprs.c index 1da227677..2bf759d58 100644 --- a/src/shared/l1gprs.c +++ b/src/shared/l1gprs.c @@ -1,7 +1,7 @@ /* * l1gprs - GPRS layer 1 implementation * - * (C) 2022-2023 by sysmocom - s.f.m.c. GmbH + * (C) 2022-2024 by sysmocom - s.f.m.c. GmbH * Author: Vadim Yanitskiy * * All Rights Reserved @@ -656,6 +656,45 @@ int l1gprs_handle_ul_block_req(struct l1gprs_state *gprs, return 0; } +struct msgb *l1gprs_handle_ul_block_cnf(struct l1gprs_state *gprs, + uint32_t fn, uint8_t tn, + const uint8_t *data, + size_t data_len) +{ + const struct l1gprs_pdch *pdch = NULL; + struct l1ctl_gprs_ul_block_cnf *l1bc; + struct msgb *msg; + + OSMO_ASSERT(tn < ARRAY_SIZE(gprs->pdch)); + pdch = &gprs->pdch[tn]; + + LOGP_PDCH(pdch, LOGL_DEBUG, "Rx UL BLOCK.cnf (fn=%u)\n", fn); + + if (pdch->ul_tbf_count + pdch->dl_tbf_count == 0) { + LOGP_PDCH(pdch, LOGL_ERROR, + "Rx UL BLOCK.cnf (fn=%u), but this PDCH has no active TBFs\n", + fn); + return NULL; + } + + msg = l1gprs_l1ctl_msgb_alloc(L1CTL_GPRS_UL_BLOCK_CNF); + if (OSMO_UNLIKELY(msg == NULL)) { + LOGP_GPRS(gprs, LOGL_ERROR, "l1gprs_l1ctl_msgb_alloc() failed\n"); + return NULL; + } + + l1bc = (void *)msgb_put(msg, sizeof(*l1bc)); + *l1bc = (struct l1ctl_gprs_ul_block_cnf) { + .fn = htonl(fn), + .tn = tn, + }; + + if (data != NULL && data_len > 0) + memcpy(msgb_put(msg, data_len), data, data_len); + + return msg; +} + /* Check if a Downlink block is a PTCCH/D (see 3GPP TS 45.002, table 6) */ #define BLOCK_IND_IS_PTCCH(ind) \ (((ind)->hdr.fn % 104) == 12)