summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-02-27 16:05:13 +0100
committerSteve Markgraf <steve@steve-m.de>2021-10-23 18:51:19 +0200
commit4ca765187b26e73f3fc1c1bfa27f803349f5ee8e (patch)
tree7f13fece9507c4c79834ab0263e329cee8ce7cf2
parent48c76f0f65087323753405da2a56acc615efcf3f (diff)
Allow transceiver application to handle multiple TRX and multiple phones
There is no more one-to-one relation between application state, trx instance and l1ctl link to the phone. An application can have many trx instances and many l1ctl links to phones. Additionally each trx can have up to 8 relations to one or different l1ctl links, one for each time slot. This allows to split one TRX into several phones. (use only one ARFCN) Also it allows to use multiple phones for multiple TRX. (use multiple ARFCN)
-rw-r--r--src/host/layer23/src/transceiver/app.h4
-rw-r--r--src/host/layer23/src/transceiver/l1ctl.c40
-rw-r--r--src/host/layer23/src/transceiver/l1ctl.h6
-rw-r--r--src/host/layer23/src/transceiver/l1ctl_link.h6
-rw-r--r--src/host/layer23/src/transceiver/main.c11
-rw-r--r--src/host/layer23/src/transceiver/trx.c57
-rw-r--r--src/host/layer23/src/transceiver/trx.h11
7 files changed, 83 insertions, 52 deletions
diff --git a/src/host/layer23/src/transceiver/app.h b/src/host/layer23/src/transceiver/app.h
index ba72f266..7b8e25c7 100644
--- a/src/host/layer23/src/transceiver/app.h
+++ b/src/host/layer23/src/transceiver/app.h
@@ -41,10 +41,10 @@ struct app_state
struct log_target *stderr_target;
/* L1CTL link */
- struct l1ctl_link l1l;
+ struct l1ctl_link l1l[2];
/* TRX link to OpenBTS */
- struct trx *trx;
+ struct trx *trx[2];
/* Signal processing */
struct osmo_gmsk_state *gs;
diff --git a/src/host/layer23/src/transceiver/l1ctl.c b/src/host/layer23/src/transceiver/l1ctl.c
index afdeb171..52ea80b0 100644
--- a/src/host/layer23/src/transceiver/l1ctl.c
+++ b/src/host/layer23/src/transceiver/l1ctl.c
@@ -112,9 +112,9 @@ l1ctl_tx_fbsb_req(struct l1ctl_link *l1l,
}
int
-l1ctl_tx_bts_mode(struct l1ctl_link *l1l,
- uint8_t enabled, uint8_t *type, uint8_t bsic,
- uint16_t band_arfcn, int gain)
+l1ctl_tx_bts_mode(struct l1ctl_link *l1l, uint8_t enabled, uint8_t *type,
+ uint8_t bsic, uint16_t band_arfcn, int gain, uint8_t tx_mask,
+ uint8_t rx_mask)
{
struct msgb *msg;
struct l1ctl_bts_mode *be;
@@ -134,6 +134,8 @@ l1ctl_tx_bts_mode(struct l1ctl_link *l1l,
be->bsic = bsic;
be->band_arfcn = htons(band_arfcn);
be->gain = gain;
+ be->tx_mask = tx_mask;
+ be->rx_mask = rx_mask;
return l1l_send(l1l, msg);
}
@@ -168,7 +170,7 @@ l1ctl_tx_bts_burst_req(struct l1ctl_link *l1l,
/* ------------------------------------------------------------------------ */
static int
-_l1ctl_rx_bts_burst_nb_ind(struct app_state *as, struct msgb *msg)
+_l1ctl_rx_bts_burst_nb_ind(struct l1ctl_link *l1l, struct msgb *msg)
{
struct l1ctl_bts_burst_nb_ind *bi;
uint32_t fn;
@@ -205,7 +207,7 @@ _l1ctl_rx_bts_burst_nb_ind(struct app_state *as, struct msgb *msg)
for (i=0; i<148; i++)
data[i] = data[i] ? -127 : 127;
- trx_data_ind(as->trx, fn, bi->tn, data, toa, rssi);
+ trx_data_ind(l1l->trx, fn, bi->tn, data, toa, rssi);
exit:
msgb_free(msg);
@@ -214,7 +216,7 @@ exit:
}
static int
-_l1ctl_rx_bts_burst_ab_ind(struct app_state *as, struct msgb *msg)
+_l1ctl_rx_bts_burst_ab_ind(struct l1ctl_link *l1l, struct msgb *msg)
{
struct l1ctl_bts_burst_ab_ind *bi;
uint32_t fn;
@@ -233,7 +235,7 @@ _l1ctl_rx_bts_burst_ab_ind(struct app_state *as, struct msgb *msg)
fn = ntohl(bi->fn);
- rc = gsm_ab_ind_process(as, bi, data, &toa);
+ rc = gsm_ab_ind_process(l1l->as, bi, data, &toa);
if (rc < 0)
goto exit;
@@ -241,7 +243,7 @@ _l1ctl_rx_bts_burst_ab_ind(struct app_state *as, struct msgb *msg)
LOGP(DL1C, LOGL_INFO, "Access Burst Indication (fn=%d iq toa=%f)\n", fn, toa);
- trx_data_ind(as->trx, fn, 0, data, toa, 0);
+ trx_data_ind(l1l->trx, fn, 0, data, toa, 0);
exit:
msgb_free(msg);
@@ -249,7 +251,7 @@ exit:
}
static int
-_l1ctl_rx_data_ind(struct app_state *as, struct msgb *msg)
+_l1ctl_rx_data_ind(struct l1ctl_link *l1l, struct msgb *msg)
{
struct l1ctl_info_dl *dl;
struct l1ctl_data_ind *di;
@@ -284,7 +286,9 @@ _l1ctl_rx_data_ind(struct app_state *as, struct msgb *msg)
}
#endif
- rc = trx_clk_ind(as->trx, ntohl(dl->frame_nr));
+ /* forward clock of fist l1ctl_link instance only */
+ if (l1l == &l1l->as->l1l[0])
+ rc = trx_clk_ind(l1l->trx, ntohl(dl->frame_nr));
exit:
msgb_free(msg);
@@ -293,7 +297,7 @@ exit:
}
static int
-_l1ctl_rx_fbsb_conf(struct app_state *as, struct msgb *msg)
+_l1ctl_rx_fbsb_conf(struct l1ctl_link *l1l, struct msgb *msg)
{
struct l1ctl_info_dl *dl;
struct l1ctl_fbsb_conf *sc;
@@ -319,7 +323,7 @@ _l1ctl_rx_fbsb_conf(struct app_state *as, struct msgb *msg)
if (sc->result != 0) {
LOGP(DAPP, LOGL_INFO, "Sync failed, retrying ... \n");
- rc = l1ctl_tx_fbsb_req(&as->l1l, as->arfcn_sync, L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_NONE);
+ rc = l1ctl_tx_fbsb_req(l1l, l1l->as->arfcn_sync, L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_NONE);
} else {
LOGP(DAPP, LOGL_INFO, "Sync acquired, wait for BCCH ...\n");
}
@@ -335,7 +339,7 @@ exit:
int
l1ctl_recv(void *data, struct msgb *msg)
{
- struct app_state *as = data;
+ struct l1ctl_link *l1l = data;
struct l1ctl_hdr *l1h;
int rc = 0;
@@ -347,25 +351,25 @@ l1ctl_recv(void *data, struct msgb *msg)
/* Act */
switch (l1h->msg_type) {
case L1CTL_BTS_BURST_AB_IND:
- rc = _l1ctl_rx_bts_burst_ab_ind(as, msg);
+ rc = _l1ctl_rx_bts_burst_ab_ind(l1l, msg);
break;
case L1CTL_BTS_BURST_NB_IND:
- rc = _l1ctl_rx_bts_burst_nb_ind(as, msg);
+ rc = _l1ctl_rx_bts_burst_nb_ind(l1l, msg);
break;
case L1CTL_DATA_IND:
- rc = _l1ctl_rx_data_ind(as, msg);
+ rc = _l1ctl_rx_data_ind(l1l, msg);
break;
case L1CTL_FBSB_CONF:
- rc = _l1ctl_rx_fbsb_conf(as, msg);
+ rc = _l1ctl_rx_fbsb_conf(l1l, msg);
break;
case L1CTL_RESET_IND:
case L1CTL_RESET_CONF:
LOGP(DAPP, LOGL_INFO, "Reset received: Starting sync.\n");
- l1ctl_tx_fbsb_req(&as->l1l, as->arfcn_sync, L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_NONE);
+ l1ctl_tx_fbsb_req(l1l, l1l->as->arfcn_sync, L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_NONE);
msgb_free(msg);
break;
diff --git a/src/host/layer23/src/transceiver/l1ctl.h b/src/host/layer23/src/transceiver/l1ctl.h
index 74d074b6..31d69037 100644
--- a/src/host/layer23/src/transceiver/l1ctl.h
+++ b/src/host/layer23/src/transceiver/l1ctl.h
@@ -38,9 +38,9 @@ int l1ctl_tx_reset_req(struct l1ctl_link *l1l, uint8_t type);
int l1ctl_tx_fbsb_req(struct l1ctl_link *l1l,
uint16_t arfcn, uint8_t flags, uint16_t timeout,
uint8_t sync_info_idx, uint8_t ccch_mode);
-int l1ctl_tx_bts_mode(struct l1ctl_link *l1l,
- uint8_t enabled, uint8_t *type, uint8_t bsic, uint16_t band_arfcn,
- int gain);
+int l1ctl_tx_bts_mode(struct l1ctl_link *l1l, uint8_t enabled, uint8_t *type,
+ uint8_t bsic, uint16_t band_arfcn, int gain, uint8_t tx_mask,
+ uint8_t rx_mask);
int l1ctl_tx_bts_burst_req(struct l1ctl_link *l1l,
uint32_t fn, uint8_t tn, struct burst_data *burst);
diff --git a/src/host/layer23/src/transceiver/l1ctl_link.h b/src/host/layer23/src/transceiver/l1ctl_link.h
index e53bd829..15960242 100644
--- a/src/host/layer23/src/transceiver/l1ctl_link.h
+++ b/src/host/layer23/src/transceiver/l1ctl_link.h
@@ -36,6 +36,12 @@ struct l1ctl_link
l1ctl_cb_t cb;
void *cb_data;
+
+ struct app_state *as;
+
+ struct trx *trx;
+
+ uint8_t tx_mask, rx_mask;
};
diff --git a/src/host/layer23/src/transceiver/main.c b/src/host/layer23/src/transceiver/main.c
index 8c97f64b..c2a8748b 100644
--- a/src/host/layer23/src/transceiver/main.c
+++ b/src/host/layer23/src/transceiver/main.c
@@ -155,17 +155,22 @@ int main(int argc, char *argv[])
exit(-1);
/* TRX interface with OpenBTS */
- as->trx = trx_alloc("127.0.0.1", 5700, &as->l1l);
+ as->trx[0] = trx_alloc("127.0.0.1", 5700, as, 1);
if (!as->trx)
exit(-1);
/* Establish l1ctl link */
- rv = l1l_open(&as->l1l, "/tmp/osmocom_l2", l1ctl_recv, as);
+ rv = l1l_open(&as->l1l[0], "/tmp/osmocom_l2", l1ctl_recv, &as->l1l[0]);
if (rv)
exit(-1);
+ as->l1l[0].trx = as->trx[0];
+ as->l1l[0].as = as;
+ as->l1l[0].tx_mask = 0xe3; /* TS 5,6,7,0,1 */
+ as->l1l[0].rx_mask = 0x01; /* TS 0 */
+ as->trx[0]->l1l[0] = &as->l1l[0];
/* Reset phone */
- l1ctl_tx_reset_req(&as->l1l, L1CTL_RES_T_FULL);
+ l1ctl_tx_reset_req(&as->l1l[0], L1CTL_RES_T_FULL);
if (daemonize) {
rv = osmo_daemonize();
diff --git a/src/host/layer23/src/transceiver/trx.c b/src/host/layer23/src/transceiver/trx.c
index 3dd0cb6c..b82c80bd 100644
--- a/src/host/layer23/src/transceiver/trx.c
+++ b/src/host/layer23/src/transceiver/trx.c
@@ -44,6 +44,7 @@
#include <osmocom/bb/common/logging.h>
+#include "app.h"
#include "l1ctl.h"
#include "l1ctl_link.h"
#include "trx.h"
@@ -115,7 +116,7 @@ err:
}
struct trx *
-trx_alloc(const char *addr, uint16_t base_port, struct l1ctl_link *l1l)
+trx_alloc(const char *addr, uint16_t base_port, struct app_state *as, int clock)
{
struct trx *trx;
int rv;
@@ -131,20 +132,22 @@ trx_alloc(const char *addr, uint16_t base_port, struct l1ctl_link *l1l)
trx->gain = 0; /* Best test results for broadest range of RX levels */
/* L1 link */
- trx->l1l = l1l;
+ trx->as = as;
/* Clock */
- rv = _trx_udp_init(trx, &trx->ofd_clk, addr, base_port, _trx_clk_read_cb);
- if (rv)
- goto err;
+ if (clock) {
+ rv = _trx_udp_init(trx, &trx->ofd_clk, addr, base_port++, _trx_clk_read_cb);
+ if (rv)
+ goto err;
+ }
/* Control */
- rv = _trx_udp_init(trx, &trx->ofd_ctrl, addr, base_port+1, _trx_ctrl_read_cb);
+ rv = _trx_udp_init(trx, &trx->ofd_ctrl, addr, base_port++, _trx_ctrl_read_cb);
if (rv)
goto err;
/* Data */
- rv = _trx_udp_init(trx, &trx->ofd_data, addr, base_port+2, _trx_data_read_cb);
+ rv = _trx_udp_init(trx, &trx->ofd_data, addr, base_port++, _trx_data_read_cb);
if (rv)
goto err;
@@ -228,8 +231,12 @@ _trx_ctrl_send_resp(struct trx *trx, const char *cmd, const char *fmt, ...)
static int
_trx_ctrl_cmd_poweroff(struct trx *trx, const char *cmd, const char *args)
{
- l1ctl_tx_bts_mode(trx->l1l, 0, trx->type, 0, 0, 0);
+ int i;
+
trx->power = 0;
+ for (i = 0; i < 8; i++)
+ if (trx->l1l[i])
+ l1ctl_tx_bts_mode(trx->l1l[i], 0, trx->type, 0, 0, 0, 0, 0);
return _trx_ctrl_send_resp(trx, cmd, "%d", 0);
}
@@ -237,15 +244,18 @@ _trx_ctrl_cmd_poweroff(struct trx *trx, const char *cmd, const char *args)
static int
_trx_ctrl_cmd_poweron(struct trx *trx, const char *cmd, const char *args)
{
- int rv;
+ int rv = 0;
+ int i;
if (trx->bsic == BSIC_INVAL || trx->arfcn == ARFCN_INVAL) {
LOGP(DTRX, LOGL_ERROR,
"TRX received POWERON when not fully configured\n");
rv = -EINVAL;
} else {
- rv = l1ctl_tx_bts_mode(trx->l1l, 1, trx->type, trx->bsic, trx->arfcn, trx->gain);
trx->power = 1;
+ for (i = 0; i < 8; i++)
+ if (trx->l1l[i])
+ l1ctl_tx_bts_mode(trx->l1l[i], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[i]->tx_mask, trx->l1l[i]->rx_mask);
}
return _trx_ctrl_send_resp(trx, cmd, "%d", rv);
@@ -280,6 +290,7 @@ static int
_trx_ctrl_cmd_setrxgain(struct trx *trx, const char *cmd, const char *args)
{
int db = atoi(args);
+ int i;
if (db < 0 || db > 63) {
LOGP(DTRX, LOGL_ERROR, "Invalid gain received\n");
@@ -288,9 +299,11 @@ _trx_ctrl_cmd_setrxgain(struct trx *trx, const char *cmd, const char *args)
trx->gain = db;
- if (trx->power)
- l1ctl_tx_bts_mode(trx->l1l, 1, trx->type, trx->bsic, trx->arfcn,
- trx->gain);
+ if (trx->power) {
+ for (i = 0; i < 8; i++)
+ if (trx->l1l[i])
+ l1ctl_tx_bts_mode(trx->l1l[i], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[i]->tx_mask, trx->l1l[i]->rx_mask);
+ }
return _trx_ctrl_send_resp(trx, cmd, "%d %d", 0, db);
}
@@ -315,6 +328,7 @@ static int
_trx_ctrl_cmd_setslot(struct trx *trx, const char *cmd, const char *args)
{
int n, tn, type;
+ int i;
n = sscanf(args, "%d %d", &tn, &type);
@@ -323,9 +337,8 @@ _trx_ctrl_cmd_setslot(struct trx *trx, const char *cmd, const char *args)
trx->type[tn] = type;
- if (trx->power)
- l1ctl_tx_bts_mode(trx->l1l, 1, trx->type, trx->bsic, trx->arfcn,
- trx->gain);
+ if (trx->l1l[i])
+ l1ctl_tx_bts_mode(trx->l1l[i], 1, trx->type, trx->bsic, trx->arfcn, trx->gain, trx->l1l[i]->tx_mask, trx->l1l[i]->rx_mask);
return _trx_ctrl_send_resp(trx, cmd, "%d %d", 0, type);
}
@@ -505,6 +518,10 @@ _trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
pwr_att = buf[5];
data = buf+6;
+ /* Ignore unallocated time slots */
+ if (!trx->l1l[tn])
+ goto skip;
+
/* Ignore FCCH and SCH completely, they're handled internally */
if ((trx->type[tn] >> 1) == 2 && ((fn % 51) % 10) < 2)
goto skip;
@@ -523,13 +540,11 @@ _trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
osmo_ubit2pbit_ext(burst->data, 58, data, 87, 58, 0);
/* Send to L1 */
- if (tn == 0)
- l1ctl_tx_bts_burst_req(trx->l1l, fn, tn, burst);
+ l1ctl_tx_bts_burst_req(trx->l1l[tn], fn, tn, burst);
/* Debug */
- if (tn == 0)
- LOGP(DTRX, LOGL_DEBUG, "TRX Data %u:%d:%d:%s\n",
- fn, tn, pwr_att, osmo_hexdump_nospc(burst->data, 15));
+ LOGP(DTRX, LOGL_DEBUG, "TRX Data %u:%d:%d:%s\n",
+ fn, tn, pwr_att, osmo_hexdump_nospc(burst->data, 15));
/* Done ! */
skip:
diff --git a/src/host/layer23/src/transceiver/trx.h b/src/host/layer23/src/transceiver/trx.h
index 754f2d69..65816c6d 100644
--- a/src/host/layer23/src/transceiver/trx.h
+++ b/src/host/layer23/src/transceiver/trx.h
@@ -35,8 +35,6 @@
#define ARFCN_INVAL 0xffff
#define BSIC_INVAL 0xff
-struct l1ctl_link;
-
struct trx {
/* UDP sockets */
@@ -44,8 +42,11 @@ struct trx {
struct osmo_fd ofd_ctrl;
struct osmo_fd ofd_data;
- /* Link to L1CTL */
- struct l1ctl_link *l1l;
+ /* Link to app state */
+ struct app_state *as;
+
+ /* Link to L1CTL for each TN */
+ struct l1ctl_link *l1l[8];
/* TRX configuration */
int power;
@@ -57,7 +58,7 @@ struct trx {
struct trx *trx_alloc(const char *addr, uint16_t base_port,
- struct l1ctl_link *l1l);
+ struct app_state *as, int clock);
void trx_free(struct trx *trx);
int trx_clk_ind(struct trx *trx, uint32_t fn);