[PATCH 2/3] layer23 smscb: reassemble blocks and pass them up to L3
Alex Badea
vamposdecampos at gmail.com
Sun Nov 28 15:07:28 CET 2010
We (re)construct an equivalent RSL_MT_SMS_BC_CMD from
received frames.
Signed-off-by: Alex Badea <vamposdecampos at gmail.com>
---
src/host/layer23/include/osmocom/bb/common/smscb.h | 5 +
src/host/layer23/src/common/smscb.c | 177 +++++++++++++++++++-
2 files changed, 176 insertions(+), 6 deletions(-)
diff --git a/src/host/layer23/include/osmocom/bb/common/smscb.h b/src/host/layer23/include/osmocom/bb/common/smscb.h
index d689cd7..a475a78 100644
--- a/src/host/layer23/include/osmocom/bb/common/smscb.h
+++ b/src/host/layer23/include/osmocom/bb/common/smscb.h
@@ -7,7 +7,12 @@ struct osmocom_ms;
struct msgb;
struct l1ctl_info_dl;
+#define SMSCB_MAX_BLOCKS 4
+
struct smscb_entity {
+ uint8_t seq_next;
+ uint8_t sched:1;
+ struct msgb *blocks[SMSCB_MAX_BLOCKS];
struct osmocom_ms *ms;
};
diff --git a/src/host/layer23/src/common/smscb.c b/src/host/layer23/src/common/smscb.c
index 31a5752..f520f25 100644
--- a/src/host/layer23/src/common/smscb.c
+++ b/src/host/layer23/src/common/smscb.c
@@ -21,26 +21,191 @@
*/
#include <osmocom/bb/common/smscb.h>
+#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
#include <osmocore/msgb.h>
+#include <osmocore/rsl.h>
+#include <osmocore/tlv.h>
+#include <osmocore/gsm_utils.h>
+#include <osmocore/protocol/gsm_04_12.h>
+#include <osmocore/protocol/gsm_08_58.h>
+
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#define SMSCB_LPD 1
+
+#define SMSCB_ALLOC_SIZE 256
+#define SMSCB_ALLOC_HEADROOM 64
+
+static void smscb_reset(struct smscb_entity *se)
+{
+ int k;
+
+ for (k = 0; k < SMSCB_MAX_BLOCKS; k++) {
+ msgb_free(se->blocks[k]);
+ se->blocks[k] = NULL;
+ }
+ se->sched = 0;
+ se->seq_next = 0;
+}
void smscb_init(struct smscb_entity *se, struct osmocom_ms *ms)
{
+ memset(se, 0, sizeof(*se));
se->ms = ms;
}
void smscb_exit(struct smscb_entity *se)
{
+ smscb_reset(se);
+}
+
+static int smscb_rx_msg(struct smscb_entity *se, const struct l1ctl_info_dl *l1i)
+{
+ struct msgb *msg;
+ struct abis_rsl_cchan_hdr *ch;
+ int k;
+ uint8_t msglen, *tlv;
+ struct gsm_time tm;
+ struct rsl_ie_cb_cmd_type cmd_type = {};
+
+ msg = msgb_alloc_headroom(
+ SMSCB_ALLOC_HEADROOM + SMSCB_ALLOC_SIZE,
+ SMSCB_ALLOC_HEADROOM, "smscb_data");
+ if (!msg)
+ return -ENOMEM;
+
+ msg->l2h = msgb_put(msg, sizeof(*ch));
+ ch = (struct abis_rsl_cchan_hdr *) msg->l2h;
+ rsl_init_cchan_hdr(ch, RSL_MT_SMS_BC_CMD);
+ ch->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
+ ch->chan_nr = l1i->chan_nr;
+
+ cmd_type.command =
+ se->sched ? RSL_CB_CMD_TYPE_SCHEDULE :
+ RSL_CB_CMD_TYPE_NORMAL;
+ cmd_type.last_block =
+ se->blocks[3] ? RSL_CB_CMD_LASTBLOCK_4 :
+ se->blocks[2] ? RSL_CB_CMD_LASTBLOCK_3 :
+ se->blocks[1] ? RSL_CB_CMD_LASTBLOCK_2 :
+ RSL_CB_CMD_LASTBLOCK_1;
+ msgb_tv_put(msg, RSL_IE_CB_CMD_TYPE, *((uint8_t *) &cmd_type));
+
+ for (k = 0, msglen = 0; se->blocks[k] && k < SMSCB_MAX_BLOCKS; k++)
+ msglen += se->blocks[k]->len;
+ tlv = msgb_put(msg, TLV_GROSS_LEN(msglen));
+ *tlv++ = RSL_IE_SMSCB_MSG;
+ *tlv++ = msglen;
+ for (k = 0; se->blocks[k] && k < SMSCB_MAX_BLOCKS; k++) {
+ memcpy(tlv, se->blocks[k]->data, se->blocks[k]->len);
+ tlv += se->blocks[k]->len;
+ }
+
+ /*
+ * TS 05.02 chapter 6.5.4: basic vs. extended CBCH
+ * is indicated by multiframe number
+ */
+ gsm_fn2gsmtime(&tm, ntohl(l1i->frame_nr));
+ msgb_tv_put(msg, RSL_IE_SMSCB_CHAN_INDICATOR, !(tm.tc < 4));
+
+ return rslms_sendmsg(msg, se->ms);
+}
+
+static int smscb_rx_null_msg(struct smscb_entity *se, const struct l1ctl_info_dl *l1i)
+{
+ struct msgb *msg;
+ struct abis_rsl_cchan_hdr *ch;
+ struct gsm_time tm;
+ struct rsl_ie_cb_cmd_type cmd_type = {};
+
+ msg = msgb_alloc_headroom(
+ SMSCB_ALLOC_HEADROOM + SMSCB_ALLOC_SIZE,
+ SMSCB_ALLOC_HEADROOM, "smscb_data");
+ if (!msg)
+ return -ENOMEM;
+
+ msg->l2h = msgb_put(msg, sizeof(*ch));
+ ch = (struct abis_rsl_cchan_hdr *) msg->l2h;
+ rsl_init_cchan_hdr(ch, RSL_MT_SMS_BC_CMD);
+ ch->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
+ ch->chan_nr = l1i->chan_nr;
+
+ cmd_type.command = RSL_CB_CMD_TYPE_NULL;
+ msgb_tv_put(msg, RSL_IE_CB_CMD_TYPE, *((uint8_t *) &cmd_type));
+ msgb_tlv_put(msg, RSL_IE_SMSCB_MSG, 0, NULL);
+
+ gsm_fn2gsmtime(&tm, ntohl(l1i->frame_nr));
+ msgb_tv_put(msg, RSL_IE_SMSCB_CHAN_INDICATOR, !(tm.tc < 4));
+
+ return rslms_sendmsg(msg, se->ms);
}
int smscb_ph_data_ind(struct smscb_entity *se, struct msgb *msg, struct l1ctl_info_dl *l1i)
{
- uint8_t addr = msg->l2h[0];
- uint8_t seq = addr & 0x0f;
+ struct gsm412_block_type *bt = (struct gsm412_block_type *) msg->l2h;
+ uint8_t seq;
+ uint8_t last;
+
+ LOGP(DLAPDM, LOGL_NOTICE, "SMSCB: received message: len=%d"
+ " seq=%d lb=%d lpd=%d spare=%d\n",
+ msg->len, bt->seq_nr, bt->lb, bt->lpd, bt->spare);
+
+ if (bt->lpd != SMSCB_LPD) {
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+ msgb_pull(msg, sizeof(*bt));
+
+ seq = bt->seq_nr & 3;
+ last = bt->lb;
+
+ if (bt->seq_nr == GSM412_SEQ_NULL_MSG) {
+ smscb_rx_null_msg(se, l1i);
+ smscb_reset(se);
+ msgb_free(msg);
+ return 0;
+ }
+
+ if (seq != se->seq_next) {
+ LOGP(DLAPDM, LOGL_ERROR, "SMSCB: got sequence %d (expected %d)\n",
+ bt->seq_nr, se->seq_next);
+ smscb_reset(se);
+ if (seq) {
+ msgb_free(msg);
+ return -EINVAL;
+ }
+ }
- LOGP(DLAPDM, LOGL_NOTICE, "SMSCB: received message: seq=%d len=%d\n",
- seq, msg->len);
+ switch (bt->seq_nr) {
+ case GSM412_SEQ_FST_SCHED_BLOCK:
+ se->sched = 1;
+ break;
+ case GSM412_SEQ_FTH_BLOCK:
+ last = 1;
+ break;
+ }
- msgb_free(msg);
- return 0;
+ switch (bt->seq_nr) {
+ case GSM412_SEQ_FST_SCHED_BLOCK:
+ case GSM412_SEQ_FST_BLOCK:
+ case GSM412_SEQ_SND_BLOCK:
+ case GSM412_SEQ_TRD_BLOCK:
+ case GSM412_SEQ_FTH_BLOCK:
+ msgb_free(se->blocks[seq]);
+ se->blocks[seq] = msg;
+ se->seq_next = seq + 1;
+ if (!last)
+ return 0;
+ smscb_rx_msg(se, l1i);
+ smscb_reset(se);
+ return 0;
+ default:
+ LOGP(DLAPDM, LOGL_ERROR, "SMSCB: unhandled sequence number %d\n",
+ bt->seq_nr);
+ msgb_free(msg);
+ return -EINVAL;
+ }
}
--
1.7.0.4
More information about the baseband-devel
mailing list