trxcon: move l1sched/phyif shim API to libtrxcon.la

Change-Id: I56701b471a6f1c30ffd107037c2b1aed65621b2c
Related: OS#5599
This commit is contained in:
Vadim Yanitskiy 2022-11-12 21:33:30 +07:00
parent 54a2ee5cef
commit 269fe14045
6 changed files with 273 additions and 239 deletions

View File

@ -89,8 +89,8 @@ struct phyif_burst_ind {
};
int phyif_handle_burst_ind(void *phyif, const struct phyif_burst_ind *bi);
int phyif_handle_burst_ind(void *priv, const struct phyif_burst_ind *bi);
int phyif_handle_burst_req(void *phyif, const struct phyif_burst_req *br);
int phyif_handle_cmd(void *phyif, const struct phyif_cmd *cmd);
int phyif_handle_rsp(void *phyif, const struct phyif_rsp *rsp);
int phyif_handle_rsp(void *priv, const struct phyif_rsp *rsp);
void phyif_close(void *phyif);

View File

@ -13,6 +13,9 @@ struct trxcon_inst {
/* Logging context for sched and l1c */
const char *log_prefix;
/* GSMTAP instance (optional) */
struct gsmtap_inst *gsmtap;
/* The L1 scheduler */
struct l1sched_state *sched;
/* PHY interface (e.g. TRXC/TRXD) */

View File

@ -40,6 +40,7 @@ noinst_LTLIBRARIES += libtrxcon.la
libtrxcon_la_SOURCES = \
trxcon_inst.c \
trxcon_fsm.c \
trxcon_shim.c \
l1ctl.c \
$(NULL)

View File

@ -390,7 +390,7 @@ static void trx_if_measure_rsp_cb(struct trx_instance *trx, char *resp)
},
};
phyif_handle_rsp(trx, &rsp);
phyif_handle_rsp(trx->priv, &rsp);
}
/*
@ -675,7 +675,7 @@ static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)
"RX burst tn=%u fn=%u rssi=%d toa=%d\n",
bi.tn, bi.fn, bi.rssi, bi.toa256);
return phyif_handle_burst_ind(trx, &bi);
return phyif_handle_burst_ind(trx->priv, &bi);
}
int trx_if_handle_phyif_burst_req(struct trx_instance *trx,

View File

@ -48,7 +48,6 @@
#include <osmocom/bb/trxcon/logging.h>
#include <osmocom/bb/trxcon/l1ctl.h>
#include <osmocom/bb/trxcon/l1ctl_server.h>
#include <osmocom/bb/l1sched/l1sched.h>
#define COPYRIGHT \
"Copyright (C) 2016-2022 by Vadim Yanitskiy <axilirator@gmail.com>\n" \
@ -87,87 +86,6 @@ static struct {
static void *tall_trxcon_ctx = NULL;
static void trxcon_gsmtap_send(const struct l1sched_lchan_desc *lchan_desc,
uint32_t fn, uint8_t tn, uint16_t band_arfcn,
int8_t signal_dbm, uint8_t snr,
const uint8_t *data, size_t data_len)
{
/* GSMTAP logging may be not enabled */
if (app_data.gsmtap == NULL)
return;
/* Omit frames with unknown channel type */
if (lchan_desc->gsmtap_chan_type == GSMTAP_CHANNEL_UNKNOWN)
return;
/* TODO: distinguish GSMTAP_CHANNEL_PCH and GSMTAP_CHANNEL_AGCH */
gsmtap_send(app_data.gsmtap, band_arfcn, tn, lchan_desc->gsmtap_chan_type,
lchan_desc->ss_nr, fn, signal_dbm, snr, data, data_len);
}
/* External L1 API for the scheduler */
int l1sched_handle_config_req(struct l1sched_state *sched,
const struct l1sched_config_req *cr)
{
struct trxcon_inst *trxcon = sched->priv;
switch (cr->type) {
case L1SCHED_CFG_PCHAN_COMB:
{
struct trxcon_param_set_phy_config_req req = {
.type = TRXCON_PHY_CFGT_PCHAN_COMB,
.pchan_comb = {
.tn = cr->pchan_comb.tn,
.pchan = cr->pchan_comb.pchan,
},
};
return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_SET_PHY_CONFIG_REQ, &req);
}
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled config request (type 0x%02x)\n", cr->type);
return -ENODEV;
}
}
int l1sched_handle_burst_req(struct l1sched_state *sched,
const struct l1sched_burst_req *br)
{
struct trxcon_inst *trxcon = sched->priv;
const struct phyif_burst_req phybr = {
.fn = br->fn,
.tn = br->tn,
.pwr = br->pwr,
.burst = &br->burst[0],
.burst_len = br->burst_len,
};
return phyif_handle_burst_req(trxcon->phyif, &phybr);
}
/* External L1 API for the PHYIF */
int phyif_handle_burst_ind(void *phyif, const struct phyif_burst_ind *bi)
{
struct trx_instance *trx = phyif;
struct trxcon_inst *trxcon = trx->priv;
const struct l1sched_meas_set meas = {
.fn = bi->fn,
.toa256 = bi->toa256,
.rssi = bi->rssi,
};
/* Poke scheduler */
l1sched_handle_rx_burst(trxcon->sched, bi->tn, bi->fn,
bi->burst, bi->burst_len, &meas);
/* Correct local clock counter */
if (bi->fn % 51 == 0)
l1sched_clck_handle(trxcon->sched, bi->fn);
return 0;
}
int phyif_handle_burst_req(void *phyif, const struct phyif_burst_req *br)
{
return trx_if_handle_phyif_burst_req(phyif, br);
@ -178,164 +96,11 @@ int phyif_handle_cmd(void *phyif, const struct phyif_cmd *cmd)
return trx_if_handle_phyif_cmd(phyif, cmd);
}
int phyif_handle_rsp(void *phyif, const struct phyif_rsp *rsp)
{
struct trx_instance *trx = phyif;
struct trxcon_inst *trxcon = trx->priv;
switch (rsp->type) {
case PHYIF_CMDT_MEASURE:
{
const struct phyif_rspp_measure *meas = &rsp->param.measure;
struct trxcon_param_full_power_scan_res res = {
.band_arfcn = meas->band_arfcn,
.dbm = meas->dbm,
};
return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_FULL_POWER_SCAN_RES, &res);
}
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled PHYIF response (type 0x%02x)\n", rsp->type);
return -ENODEV;
}
}
void phyif_close(void *phyif)
{
trx_if_close(phyif);
}
/* External L2 API for the scheduler */
int l1sched_handle_data_ind(struct l1sched_lchan_state *lchan,
const uint8_t *data, size_t data_len,
int n_errors, int n_bits_total,
enum l1sched_data_type dt)
{
const struct l1sched_meas_set *meas = &lchan->meas_avg;
const struct l1sched_lchan_desc *lchan_desc;
struct l1sched_state *sched = lchan->ts->sched;
struct trxcon_inst *trxcon = sched->priv;
int rc;
lchan_desc = &l1sched_lchan_desc[lchan->type];
struct trxcon_param_rx_data_ind ind = {
/* .traffic is set below */
.chan_nr = lchan_desc->chan_nr | lchan->ts->index,
.link_id = lchan_desc->link_id,
.band_arfcn = trxcon->l1p.band_arfcn,
.frame_nr = meas->fn,
.toa256 = meas->toa256,
.rssi = meas->rssi,
.n_errors = n_errors,
.n_bits_total = n_bits_total,
.data_len = data_len,
.data = data,
};
switch (dt) {
case L1SCHED_DT_PACKET_DATA:
case L1SCHED_DT_TRAFFIC:
ind.traffic = true;
/* fall-through */
case L1SCHED_DT_SIGNALING:
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_RX_DATA_IND, &ind);
break;
case L1SCHED_DT_OTHER:
if (lchan->type == L1SCHED_SCH) {
if (trxcon->fi->state != TRXCON_ST_FBSB_SEARCH)
return 0;
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_FBSB_SEARCH_RES, NULL);
break;
}
/* fall through */
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled L2 DATA.ind (type 0x%02x)\n", dt);
return -ENODEV;
}
if (data != NULL && data_len > 0) {
trxcon_gsmtap_send(lchan_desc, meas->fn, lchan->ts->index,
trxcon->l1p.band_arfcn, meas->rssi, 0,
data, data_len);
}
return rc;
}
int l1sched_handle_data_cnf(struct l1sched_lchan_state *lchan,
uint32_t fn, enum l1sched_data_type dt)
{
const struct l1sched_lchan_desc *lchan_desc;
struct l1sched_state *sched = lchan->ts->sched;
struct trxcon_inst *trxcon = sched->priv;
bool is_traffic = false;
const uint8_t *data;
uint8_t ra_buf[2];
size_t data_len;
int rc;
lchan_desc = &l1sched_lchan_desc[lchan->type];
switch (dt) {
case L1SCHED_DT_TRAFFIC:
case L1SCHED_DT_PACKET_DATA:
is_traffic = true;
/* fall-through */
case L1SCHED_DT_SIGNALING:
{
struct trxcon_param_tx_data_cnf cnf = {
.traffic = is_traffic,
.chan_nr = lchan_desc->chan_nr | lchan->ts->index,
.link_id = lchan_desc->link_id,
.band_arfcn = trxcon->l1p.band_arfcn,
.frame_nr = fn,
};
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_DATA_CNF, &cnf);
data_len = lchan->prim->payload_len;
data = lchan->prim->payload;
break;
}
case L1SCHED_DT_OTHER:
if (L1SCHED_PRIM_IS_RACH(lchan->prim)) {
const struct l1sched_ts_prim_rach *rach;
struct trxcon_param_tx_access_burst_cnf cnf = {
.band_arfcn = trxcon->l1p.band_arfcn,
.frame_nr = fn,
};
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_ACCESS_BURST_CNF, &cnf);
rach = (struct l1sched_ts_prim_rach *)lchan->prim->payload;
if (lchan->prim->type == L1SCHED_PRIM_RACH11) {
ra_buf[0] = (uint8_t)(rach->ra >> 3);
ra_buf[1] = (uint8_t)(rach->ra & 0x07);
data = &ra_buf[0];
data_len = 2;
} else {
ra_buf[0] = (uint8_t)(rach->ra);
data = &ra_buf[0];
data_len = 1;
}
break;
}
/* fall through */
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled L2 DATA.cnf (type 0x%02x)\n", dt);
return -ENODEV;
}
trxcon_gsmtap_send(lchan_desc, fn, lchan->ts->index,
trxcon->l1p.band_arfcn | ARFCN_UPLINK,
0, 0, data, data_len);
return rc;
}
void trxcon_l1ctl_close(struct trxcon_inst *trxcon)
{
/* Avoid use-after-free: both *fi and *trxcon are children of
@ -391,6 +156,8 @@ static void l1ctl_conn_accept_cb(struct l1ctl_client *l1c)
osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_PHYIF_FAILURE, NULL);
return;
}
trxcon->gsmtap = app_data.gsmtap;
}
static void l1ctl_conn_close_cb(struct l1ctl_client *l1c)

View File

@ -0,0 +1,263 @@
/*
* OsmocomBB <-> SDR connection bridge
*
* (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <stdint.h>
#include <errno.h>
#include <osmocom/core/fsm.h>
#include <osmocom/core/gsmtap_util.h>
#include <osmocom/core/gsmtap.h>
#include <osmocom/bb/trxcon/trxcon.h>
#include <osmocom/bb/trxcon/trxcon_fsm.h>
#include <osmocom/bb/trxcon/phyif.h>
#include <osmocom/bb/l1sched/l1sched.h>
static void trxcon_gsmtap_send(struct gsmtap_inst *gi, uint8_t chan_type,
uint32_t fn, uint8_t tn, uint8_t ss,
uint16_t band_arfcn,
int8_t signal_dbm, uint8_t snr,
const uint8_t *data, size_t data_len)
{
/* Omit frames with unknown channel type */
if (chan_type == GSMTAP_CHANNEL_UNKNOWN)
return;
/* TODO: distinguish GSMTAP_CHANNEL_PCH and GSMTAP_CHANNEL_AGCH */
gsmtap_send(gi, band_arfcn, tn, chan_type, ss, fn, signal_dbm, snr, data, data_len);
}
/* External L1 API for the scheduler */
int l1sched_handle_config_req(struct l1sched_state *sched,
const struct l1sched_config_req *cr)
{
struct trxcon_inst *trxcon = sched->priv;
switch (cr->type) {
case L1SCHED_CFG_PCHAN_COMB:
{
struct trxcon_param_set_phy_config_req req = {
.type = TRXCON_PHY_CFGT_PCHAN_COMB,
.pchan_comb = {
.tn = cr->pchan_comb.tn,
.pchan = cr->pchan_comb.pchan,
},
};
return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_SET_PHY_CONFIG_REQ, &req);
}
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled config request (type 0x%02x)\n", cr->type);
return -ENODEV;
}
}
int l1sched_handle_burst_req(struct l1sched_state *sched,
const struct l1sched_burst_req *br)
{
struct trxcon_inst *trxcon = sched->priv;
const struct phyif_burst_req phybr = {
.fn = br->fn,
.tn = br->tn,
.pwr = br->pwr,
.burst = &br->burst[0],
.burst_len = br->burst_len,
};
return phyif_handle_burst_req(trxcon->phyif, &phybr);
}
/* External L2 API for the scheduler */
int l1sched_handle_data_ind(struct l1sched_lchan_state *lchan,
const uint8_t *data, size_t data_len,
int n_errors, int n_bits_total,
enum l1sched_data_type dt)
{
const struct l1sched_meas_set *meas = &lchan->meas_avg;
const struct l1sched_lchan_desc *lchan_desc;
struct l1sched_state *sched = lchan->ts->sched;
struct trxcon_inst *trxcon = sched->priv;
int rc;
lchan_desc = &l1sched_lchan_desc[lchan->type];
struct trxcon_param_rx_data_ind ind = {
/* .traffic is set below */
.chan_nr = lchan_desc->chan_nr | lchan->ts->index,
.link_id = lchan_desc->link_id,
.band_arfcn = trxcon->l1p.band_arfcn,
.frame_nr = meas->fn,
.toa256 = meas->toa256,
.rssi = meas->rssi,
.n_errors = n_errors,
.n_bits_total = n_bits_total,
.data_len = data_len,
.data = data,
};
switch (dt) {
case L1SCHED_DT_PACKET_DATA:
case L1SCHED_DT_TRAFFIC:
ind.traffic = true;
/* fall-through */
case L1SCHED_DT_SIGNALING:
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_RX_DATA_IND, &ind);
break;
case L1SCHED_DT_OTHER:
if (lchan->type == L1SCHED_SCH) {
if (trxcon->fi->state != TRXCON_ST_FBSB_SEARCH)
return 0;
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_FBSB_SEARCH_RES, NULL);
break;
}
/* fall through */
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled L2 DATA.ind (type 0x%02x)\n", dt);
return -ENODEV;
}
if (trxcon->gsmtap != NULL && data != NULL && data_len > 0) {
trxcon_gsmtap_send(trxcon->gsmtap, lchan_desc->gsmtap_chan_type,
meas->fn, lchan->ts->index, lchan_desc->ss_nr,
trxcon->l1p.band_arfcn, meas->rssi, 0,
data, data_len);
}
return rc;
}
int l1sched_handle_data_cnf(struct l1sched_lchan_state *lchan,
uint32_t fn, enum l1sched_data_type dt)
{
const struct l1sched_lchan_desc *lchan_desc;
struct l1sched_state *sched = lchan->ts->sched;
struct trxcon_inst *trxcon = sched->priv;
bool is_traffic = false;
const uint8_t *data;
uint8_t ra_buf[2];
size_t data_len;
int rc;
lchan_desc = &l1sched_lchan_desc[lchan->type];
switch (dt) {
case L1SCHED_DT_TRAFFIC:
case L1SCHED_DT_PACKET_DATA:
is_traffic = true;
/* fall-through */
case L1SCHED_DT_SIGNALING:
{
struct trxcon_param_tx_data_cnf cnf = {
.traffic = is_traffic,
.chan_nr = lchan_desc->chan_nr | lchan->ts->index,
.link_id = lchan_desc->link_id,
.band_arfcn = trxcon->l1p.band_arfcn,
.frame_nr = fn,
};
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_DATA_CNF, &cnf);
data_len = lchan->prim->payload_len;
data = lchan->prim->payload;
break;
}
case L1SCHED_DT_OTHER:
if (L1SCHED_PRIM_IS_RACH(lchan->prim)) {
const struct l1sched_ts_prim_rach *rach;
struct trxcon_param_tx_access_burst_cnf cnf = {
.band_arfcn = trxcon->l1p.band_arfcn,
.frame_nr = fn,
};
rc = osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_TX_ACCESS_BURST_CNF, &cnf);
rach = (struct l1sched_ts_prim_rach *)lchan->prim->payload;
if (lchan->prim->type == L1SCHED_PRIM_RACH11) {
ra_buf[0] = (uint8_t)(rach->ra >> 3);
ra_buf[1] = (uint8_t)(rach->ra & 0x07);
data = &ra_buf[0];
data_len = 2;
} else {
ra_buf[0] = (uint8_t)(rach->ra);
data = &ra_buf[0];
data_len = 1;
}
break;
}
/* fall through */
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled L2 DATA.cnf (type 0x%02x)\n", dt);
return -ENODEV;
}
if (trxcon->gsmtap != NULL) {
trxcon_gsmtap_send(trxcon->gsmtap, lchan_desc->gsmtap_chan_type,
fn, lchan->ts->index, lchan_desc->ss_nr,
trxcon->l1p.band_arfcn | ARFCN_UPLINK,
0, 0, data, data_len);
}
return rc;
}
/* External L1 API for the PHYIF */
int phyif_handle_burst_ind(void *priv, const struct phyif_burst_ind *bi)
{
struct trxcon_inst *trxcon = priv;
const struct l1sched_meas_set meas = {
.fn = bi->fn,
.toa256 = bi->toa256,
.rssi = bi->rssi,
};
/* Poke scheduler */
l1sched_handle_rx_burst(trxcon->sched, bi->tn, bi->fn,
bi->burst, bi->burst_len, &meas);
/* Correct local clock counter */
if (bi->fn % 51 == 0)
l1sched_clck_handle(trxcon->sched, bi->fn);
return 0;
}
int phyif_handle_rsp(void *priv, const struct phyif_rsp *rsp)
{
struct trxcon_inst *trxcon = priv;
switch (rsp->type) {
case PHYIF_CMDT_MEASURE:
{
const struct phyif_rspp_measure *meas = &rsp->param.measure;
struct trxcon_param_full_power_scan_res res = {
.band_arfcn = meas->band_arfcn,
.dbm = meas->dbm,
};
return osmo_fsm_inst_dispatch(trxcon->fi, TRXCON_EV_FULL_POWER_SCAN_RES, &res);
}
default:
LOGPFSML(trxcon->fi, LOGL_ERROR,
"Unhandled PHYIF response (type 0x%02x)\n", rsp->type);
return -ENODEV;
}
}