From 49d993e4abdd8fac8b111e92078563fd9bb28df1 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 12 Jan 2023 17:25:21 +0600 Subject: [PATCH] modem: request an Uplink TBF, match Immediate Assignment Change-Id: Iec0dcc629d29dec270649cf7428f71af0dfd2dbb Related: SYS#5500 --- src/host/layer23/src/modem/app_modem.c | 96 +++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/host/layer23/src/modem/app_modem.c b/src/host/layer23/src/modem/app_modem.c index c135ff32a..ec267e582 100644 --- a/src/host/layer23/src/modem/app_modem.c +++ b/src/host/layer23/src/modem/app_modem.c @@ -45,8 +45,28 @@ static struct { enum ccch_mode ccch_mode; struct gsm48_sysinfo si; + + /* TODO: use mobile->rrlayer API instead */ + struct { + bool ref_valid; + struct gsm48_req_ref ref; + } chan_req; } app_data; +/* Generate a 8-bit CHANNEL REQUEST message as per 3GPP TS 44.018, 9.1.8 */ +static uint8_t gen_chan_req(bool single_block) +{ + uint8_t rnd = (uint8_t)rand(); + + if (single_block) /* 01110xxx */ + return 0x70 | (rnd & 0x07); + + /* 011110xx or 01111x0x or 01111xx0 */ + if ((rnd & 0x07) == 0x07) + return 0x78; + return 0x78 | (rnd & 0x07); +} + static int handle_si1(struct osmocom_ms *ms, struct msgb *msg) { int rc; @@ -127,6 +147,7 @@ static int handle_si4(struct osmocom_ms *ms, struct msgb *msg) static int handle_si13(struct osmocom_ms *ms, struct msgb *msg) { + struct gsm48_rrlayer *rr = &ms->rrlayer; int rc; if (msgb_l3len(msg) != GSM_MACBLOCK_LEN) @@ -138,6 +159,20 @@ static int handle_si13(struct osmocom_ms *ms, struct msgb *msg) if (rc != 0) return rc; + /* HACK: request an Uplink TBF here (one phase access) */ + if (rr->state == GSM48_RR_ST_IDLE) { + if (!app_data.si.si1) + return 0; + if (!app_data.si.gprs.supported) + return 0; + + rr->cr_ra = gen_chan_req(false); + LOGP(DRR, LOGL_NOTICE, "Sending CHANNEL REQUEST (0x%02x)\n", rr->cr_ra); + l1ctl_tx_rach_req(ms, RSL_CHAN_RACH, 0x00, rr->cr_ra, 0, + app_data.ccch_mode == CCCH_MODE_COMBINED); + rr->state = GSM48_RR_ST_CONN_PEND; + } + return 0; } @@ -166,6 +201,7 @@ static int modem_rx_bcch(struct osmocom_ms *ms, struct msgb *msg) static int modem_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg) { const struct gsm48_imm_ass *ia = msgb_l3(msg); + struct gsm48_rrlayer *rr = &ms->rrlayer; uint8_t ch_type, ch_subch, ch_ts; int rc; @@ -173,6 +209,13 @@ static int modem_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg) if ((ia->page_mode >> 4) == 0) return 0; + if (rr->state != GSM48_RR_ST_CONN_PEND) + return 0; + if (!app_data.chan_req.ref_valid) + return 0; + if (memcmp(&ia->req_ref, &app_data.chan_req.ref, sizeof(ia->req_ref))) + return 0; + if (rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts) != 0) { LOGP(DRR, LOGL_ERROR, "%s(): rsl_dec_chan_nr(chan_nr=0x%02x) failed\n", @@ -190,9 +233,13 @@ static int modem_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg) "ARFCN=%u, TS=%u, SS=%u, TSC=%u)\n", ia->req_ref.ra, ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch, ia->chan_desc.h0.tsc); + + l1ctl_tx_dm_est_req_h0(ms, arfcn, RSL_CHAN_OSMO_PDCH, + ia->chan_desc.h0.tsc, GSM48_CMODE_SIGN, 0); } else { /* Hopping */ - uint8_t maio, hsn; + uint8_t maio, hsn, ma_len; + uint16_t ma[64]; hsn = ia->chan_desc.h1.hsn; maio = ia->chan_desc.h1.maio_low | (ia->chan_desc.h1.maio_high << 2); @@ -201,6 +248,22 @@ static int modem_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg) "HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u)\n", ia->req_ref.ra, ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch, ia->chan_desc.h1.tsc); + + for (unsigned int i = 1, j = 0; i <= 1024; i++) { + unsigned int arfcn = i & 1023; + unsigned int k; + + if (~app_data.si.freq[arfcn].mask & 0x01) + continue; + + k = ia->mob_alloc_len - (j >> 3) - 1; + if (ia->mob_alloc[k] & (1 << (j & 7))) + ma[ma_len++] = arfcn; + j++; + } + + l1ctl_tx_dm_est_req_h1(ms, maio, hsn, &ma[0], ma_len, RSL_CHAN_OSMO_PDCH, + ia->chan_desc.h1.tsc, GSM48_CMODE_SIGN, 0); } const uint8_t *data = msgb_l3(msg) + sizeof(*ia) + ia->mob_alloc_len; @@ -213,6 +276,9 @@ static int modem_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg) return rc; } + /* TODO: deliver decoded params to the RLC/MAC layer */ + + rr->state = GSM48_RR_ST_DEDICATED; return 0; } @@ -313,6 +379,31 @@ static int modem_rx_rslms_rll(struct osmocom_ms *ms, struct msgb *msg) } } +static int modem_rx_rslms_cchan(struct osmocom_ms *ms, struct msgb *msg) +{ + const struct abis_rsl_cchan_hdr *ch = msgb_l2(msg); + struct gsm48_rrlayer *rr = &ms->rrlayer; + + switch (ch->c.msg_type) { + case RSL_MT_CHAN_CONF: /* RACH.conf */ + if (rr->state == GSM48_RR_ST_CONN_PEND) { + const struct gsm48_req_ref *ref = (void *)&ch->data[1]; + LOGP(DRSL, LOGL_NOTICE, + "Rx RACH.conf (RA=0x%02x, T1=%u, T3=%u, T2=%u)\n", + rr->cr_ra, ref->t1, ref->t3_high << 3 | ref->t3_low, ref->t2); + memcpy(&app_data.chan_req.ref, ref, sizeof(*ref)); + app_data.chan_req.ref.ra = rr->cr_ra; + app_data.chan_req.ref_valid = true; + return 0; + } + /* fall-through */ + default: + LOGP(DRSL, LOGL_NOTICE, "Unhandled RSLms CCHAN message " + "(msg_type 0x%02x)\n", ch->c.msg_type); + return -EINVAL; + } +} + static int modem_rslms_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx) { const struct abis_rsl_common_hdr *rslh = msgb_l2(msg); @@ -322,6 +413,9 @@ static int modem_rslms_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx) case ABIS_RSL_MDISC_RLL: rc = modem_rx_rslms_rll((struct osmocom_ms *)ctx, msg); break; + case ABIS_RSL_MDISC_COM_CHAN: + rc = modem_rx_rslms_cchan((struct osmocom_ms *)ctx, msg); + break; default: LOGP(DRSL, LOGL_NOTICE, "Unhandled RSLms message " "(msg_discr 0x%02x)\n", rslh->msg_discr);