summaryrefslogtreecommitdiffstats
path: root/src/host
diff options
context:
space:
mode:
Diffstat (limited to 'src/host')
-rw-r--r--src/host/trxcon/Makefile.am1
-rw-r--r--src/host/trxcon/l1ctl_link.c4
-rw-r--r--src/host/trxcon/trx_if.c4
-rw-r--r--src/host/trxcon/trxcon.c80
-rw-r--r--src/host/trxcon/trxcon.h35
-rw-r--r--src/host/trxcon/trxcon_fsm.c123
6 files changed, 161 insertions, 86 deletions
diff --git a/src/host/trxcon/Makefile.am b/src/host/trxcon/Makefile.am
index b51db02f..76254c5e 100644
--- a/src/host/trxcon/Makefile.am
+++ b/src/host/trxcon/Makefile.am
@@ -22,6 +22,7 @@ AM_CFLAGS = \
bin_PROGRAMS = trxcon
trxcon_SOURCES = \
+ trxcon_fsm.c \
l1ctl_link.c \
l1ctl.c \
trx_if.c \
diff --git a/src/host/trxcon/l1ctl_link.c b/src/host/trxcon/l1ctl_link.c
index b7ea262a..0b01d729 100644
--- a/src/host/trxcon/l1ctl_link.c
+++ b/src/host/trxcon/l1ctl_link.c
@@ -176,8 +176,8 @@ static int l1ctl_link_accept(struct osmo_fd *bfd, unsigned int flags)
return -1;
}
- osmo_fsm_inst_dispatch(trxcon_fsm, L1CTL_EVENT_CONNECT, l1l);
osmo_fsm_inst_state_chg(l1l->fsm, L1CTL_STATE_CONNECTED, 0, 0);
+ osmo_fsm_inst_dispatch(trxcon_fsm, TRXCON_EV_L1CTL_CONNECT, NULL);
LOGP(DL1C, LOGL_NOTICE, "L1CTL has a new connection\n");
@@ -223,8 +223,8 @@ int l1ctl_link_close_conn(struct l1ctl_link *l1l)
/* Clear pending messages */
osmo_wqueue_clear(&l1l->wq);
- osmo_fsm_inst_dispatch(trxcon_fsm, L1CTL_EVENT_DISCONNECT, l1l);
osmo_fsm_inst_state_chg(l1l->fsm, L1CTL_STATE_IDLE, 0, 0);
+ osmo_fsm_inst_dispatch(trxcon_fsm, TRXCON_EV_L1CTL_DISCONNECT, NULL);
return 0;
}
diff --git a/src/host/trxcon/trx_if.c b/src/host/trxcon/trx_if.c
index 4c10da6c..79df6873 100644
--- a/src/host/trxcon/trx_if.c
+++ b/src/host/trxcon/trx_if.c
@@ -173,7 +173,7 @@ static void trx_ctrl_timer_cb(void *data)
if (++tcm->retry_cnt > 3) {
LOGP(DTRX, LOGL_NOTICE, "Transceiver offline\n");
osmo_fsm_inst_state_chg(trx->fsm, TRX_STATE_OFFLINE, 0, 0);
- osmo_fsm_inst_dispatch(trxcon_fsm, TRX_EVENT_OFFLINE, trx);
+ osmo_fsm_inst_dispatch(trxcon_fsm, TRXCON_EV_TRX_DISCONNECT, NULL);
return;
}
@@ -514,7 +514,7 @@ static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
rsp_error:
/* Notify higher layers about the problem */
- osmo_fsm_inst_dispatch(trxcon_fsm, TRX_EVENT_RSP_ERROR, trx);
+ osmo_fsm_inst_dispatch(trxcon_fsm, TRXCON_EV_TRX_CTRL_ERROR, NULL);
return -EIO;
}
diff --git a/src/host/trxcon/trxcon.c b/src/host/trxcon/trxcon.c
index 8e371df1..8b177ba5 100644
--- a/src/host/trxcon/trxcon.c
+++ b/src/host/trxcon/trxcon.c
@@ -1,7 +1,7 @@
/*
* OsmocomBB <-> SDR connection bridge
*
- * (C) 2016-2017 by Vadim Yanitskiy <axilirator@gmail.com>
+ * (C) 2016-2019 by Vadim Yanitskiy <axilirator@gmail.com>
*
* All Rights Reserved
*
@@ -77,72 +77,6 @@ static struct {
static void *tall_trxcon_ctx = NULL;
struct osmo_fsm_inst *trxcon_fsm;
-static void trxcon_fsm_idle_action(struct osmo_fsm_inst *fi,
- uint32_t event, void *data)
-{
- if (event == L1CTL_EVENT_CONNECT)
- osmo_fsm_inst_state_chg(trxcon_fsm, TRXCON_STATE_MANAGED, 0, 0);
-}
-
-static void trxcon_fsm_managed_action(struct osmo_fsm_inst *fi,
- uint32_t event, void *data)
-{
- switch (event) {
- case L1CTL_EVENT_DISCONNECT:
- osmo_fsm_inst_state_chg(trxcon_fsm, TRXCON_STATE_IDLE, 0, 0);
-
- if (app_data.trx->fsm->state != TRX_STATE_OFFLINE) {
- /* Reset scheduler and clock counter */
- sched_trx_reset(app_data.trx, true);
-
- /* TODO: implement trx_if_reset() */
- trx_if_cmd_poweroff(app_data.trx);
- trx_if_cmd_echo(app_data.trx);
- }
- break;
- case TRX_EVENT_RSP_ERROR:
- case TRX_EVENT_OFFLINE:
- /* TODO: notify L2 & L3 about that */
- break;
- default:
- LOGPFSML(fi, LOGL_ERROR, "Unhandled event %u\n", event);
- }
-}
-
-static struct osmo_fsm_state trxcon_fsm_states[] = {
- [TRXCON_STATE_IDLE] = {
- .in_event_mask = GEN_MASK(L1CTL_EVENT_CONNECT),
- .out_state_mask = GEN_MASK(TRXCON_STATE_MANAGED),
- .name = "IDLE",
- .action = trxcon_fsm_idle_action,
- },
- [TRXCON_STATE_MANAGED] = {
- .in_event_mask = (
- GEN_MASK(L1CTL_EVENT_DISCONNECT) |
- GEN_MASK(TRX_EVENT_RSP_ERROR) |
- GEN_MASK(TRX_EVENT_OFFLINE)),
- .out_state_mask = GEN_MASK(TRXCON_STATE_IDLE),
- .name = "MANAGED",
- .action = trxcon_fsm_managed_action,
- },
-};
-
-static const struct value_string app_evt_names[] = {
- OSMO_VALUE_STRING(L1CTL_EVENT_CONNECT),
- OSMO_VALUE_STRING(L1CTL_EVENT_DISCONNECT),
- OSMO_VALUE_STRING(TRX_EVENT_OFFLINE),
- OSMO_VALUE_STRING(TRX_EVENT_RSP_ERROR),
- { 0, NULL }
-};
-
-static struct osmo_fsm trxcon_fsm_def = {
- .name = "trxcon_app_fsm",
- .states = trxcon_fsm_states,
- .num_states = ARRAY_SIZE(trxcon_fsm_states),
- .log_subsys = DAPP,
- .event_names = app_evt_names,
-};
-
static void print_usage(const char *app)
{
printf("Usage: %s\n", app);
@@ -273,10 +207,11 @@ int main(int argc, char **argv)
/* Init logging system */
trx_log_init(tall_trxcon_ctx, app_data.debug_mask);
- /* Allocate the application state machine */
- osmo_fsm_register(&trxcon_fsm_def);
- trxcon_fsm = osmo_fsm_inst_alloc(&trxcon_fsm_def, tall_trxcon_ctx,
- NULL, LOGL_DEBUG, "main");
+ /* Allocate a trxcon state machine */
+ trxcon_fsm = osmo_fsm_inst_alloc(&trxcon_fsm_def,
+ tall_trxcon_ctx, NULL, LOGL_DEBUG, "main");
+ if (trxcon_fsm == NULL)
+ goto exit;
/* Init L1CTL server */
app_data.l1l = l1ctl_link_init(tall_trxcon_ctx,
@@ -323,7 +258,8 @@ exit:
trx_if_close(app_data.trx);
/* Shutdown main state machine */
- osmo_fsm_inst_free(trxcon_fsm);
+ if (trxcon_fsm != NULL)
+ osmo_fsm_inst_free(trxcon_fsm);
/* Deinitialize logging */
log_fini();
diff --git a/src/host/trxcon/trxcon.h b/src/host/trxcon/trxcon.h
index f66a6285..0b113915 100644
--- a/src/host/trxcon/trxcon.h
+++ b/src/host/trxcon/trxcon.h
@@ -1,20 +1,35 @@
#pragma once
+#include <osmocom/core/utils.h>
+#include <osmocom/core/fsm.h>
+
#define GEN_MASK(state) (0x01 << state)
+extern const struct value_string trxcon_fsm_event_names[];
extern struct osmo_fsm_inst *trxcon_fsm;
+extern struct osmo_fsm trxcon_fsm_def;
-enum trxcon_fsm_states {
- TRXCON_STATE_IDLE = 0,
- TRXCON_STATE_MANAGED,
+enum trxcon_fsm_state_type {
+ TRXCON_ST_IDLE = 0,
+ TRXCON_ST_MANAGED,
};
-enum trxcon_fsm_events {
- /* L1CTL specific events */
- L1CTL_EVENT_CONNECT,
- L1CTL_EVENT_DISCONNECT,
+enum trxcon_event_type {
+ /* Events coming from L1CTL interface */
+ TRXCON_EV_L1CTL_DISCONNECT, /*!< L1CTL interface has lost a connection */
+ TRXCON_EV_L1CTL_CONNECT, /*!< L1CTL interface has got a connection */
+ TRXCON_EV_L1CTL_REQ, /*!< L1CTL request message from a client */
+
+ /* Events coming from TRX interface */
+ TRXCON_EV_TRX_DISCONNECT, /*!< TRX interface has lost connection */
+ TRXCON_EV_TRX_CTRL_ERROR, /*!< TRXC (CTRL) error from transceiver */
+ TRXCON_EV_TRX_CTRL_RSP, /*!< TRXC (CTRL) response from transceiver */
+ TRXCON_EV_TRX_DL_BURST, /*!< TRXD (DATA) DL burst from transceiver */
- /* TRX specific events */
- TRX_EVENT_RSP_ERROR,
- TRX_EVENT_OFFLINE,
+ /* Events coming from scheduler */
+ TRXCON_EV_SCHED_CLCK_LOSS, /*!< No more clock from transceiver */
+ TRXCON_EV_SCHED_DL_DF_IND, /*!< DL Data Frame INDication */
+ TRXCON_EV_SCHED_UL_DF_CONF, /*!< UL Data Frame CONFirmation */
+ TRXCON_EV_SCHED_DL_TF_IND, /*!< DL Traffic Frame INDication */
+ TRXCON_EV_SCHED_UL_TF_CONF, /*!< UL Traffic Frame CONFirmation */
};
diff --git a/src/host/trxcon/trxcon_fsm.c b/src/host/trxcon/trxcon_fsm.c
new file mode 100644
index 00000000..69a2da1b
--- /dev/null
+++ b/src/host/trxcon/trxcon_fsm.c
@@ -0,0 +1,123 @@
+/*
+ * OsmocomBB <-> SDR connection bridge
+ * trxcon state machine definition
+ *
+ * (C) 2019 by Vadim Yanitskiy <axilirator@gmail.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/fsm.h>
+
+#include <logging.h>
+#include <trxcon.h>
+
+static void trxcon_fsm_idle_action(struct osmo_fsm_inst *fi,
+ uint32_t event, void *data)
+{
+ switch ((enum trxcon_event_type) event) {
+ case TRXCON_EV_L1CTL_CONNECT:
+ osmo_fsm_inst_state_chg(fi, TRXCON_ST_MANAGED, 0, 0);
+ break;
+ default:
+ LOGPFSML(fi, LOGL_ERROR, "Unhandled event '%s'\n",
+ osmo_fsm_event_name(&trxcon_fsm_def, event));
+ }
+}
+
+static void trxcon_fsm_managed_action(struct osmo_fsm_inst *fi,
+ uint32_t event, void *data)
+{
+ switch ((enum trxcon_event_type) event) {
+ case TRXCON_EV_L1CTL_DISCONNECT:
+ /* TODO: reset TRX interface */
+ osmo_fsm_inst_state_chg(fi, TRXCON_ST_IDLE, 0, 0);
+ break;
+ case TRXCON_EV_TRX_DISCONNECT:
+ /* TODO: notify L1CTL interface */
+ osmo_fsm_inst_state_chg(fi, TRXCON_ST_IDLE, 0, 0);
+ break;
+ default:
+ LOGPFSML(fi, LOGL_ERROR, "Unhandled event '%s'\n",
+ osmo_fsm_event_name(&trxcon_fsm_def, event));
+ }
+}
+
+/* Generates mask for a single state or event */
+#define S(x) (1 << x)
+
+static const struct osmo_fsm_state trxcon_fsm_states[] = {
+ [TRXCON_ST_IDLE] = {
+ .name = "IDLE",
+ .out_state_mask = S(TRXCON_ST_MANAGED),
+ .in_event_mask = S(TRXCON_EV_L1CTL_CONNECT),
+ .action = &trxcon_fsm_idle_action,
+ },
+ [TRXCON_ST_MANAGED] = {
+ .name = "MANAGED",
+ .out_state_mask = S(TRXCON_ST_IDLE),
+ .in_event_mask = S(TRXCON_EV_L1CTL_DISCONNECT)
+ | S(TRXCON_EV_L1CTL_CONNECT)
+ | S(TRXCON_EV_L1CTL_REQ)
+ | S(TRXCON_EV_TRX_DISCONNECT)
+ | S(TRXCON_EV_TRX_CTRL_ERROR)
+ | S(TRXCON_EV_TRX_CTRL_RSP)
+ | S(TRXCON_EV_TRX_DL_BURST)
+ | S(TRXCON_EV_SCHED_CLCK_LOSS)
+ | S(TRXCON_EV_SCHED_DL_DF_IND)
+ | S(TRXCON_EV_SCHED_UL_DF_CONF)
+ | S(TRXCON_EV_SCHED_DL_TF_IND)
+ | S(TRXCON_EV_SCHED_UL_TF_CONF)
+ ,
+ .action = &trxcon_fsm_managed_action,
+ },
+};
+
+const struct value_string trxcon_fsm_event_names[] = {
+ OSMO_VALUE_STRING(TRXCON_EV_L1CTL_DISCONNECT),
+ OSMO_VALUE_STRING(TRXCON_EV_L1CTL_CONNECT),
+ OSMO_VALUE_STRING(TRXCON_EV_L1CTL_REQ),
+
+ OSMO_VALUE_STRING(TRXCON_EV_TRX_DISCONNECT),
+ OSMO_VALUE_STRING(TRXCON_EV_TRX_CTRL_ERROR),
+ OSMO_VALUE_STRING(TRXCON_EV_TRX_CTRL_RSP),
+ OSMO_VALUE_STRING(TRXCON_EV_TRX_DL_BURST),
+
+ OSMO_VALUE_STRING(TRXCON_EV_SCHED_CLCK_LOSS),
+ OSMO_VALUE_STRING(TRXCON_EV_SCHED_DL_DF_IND),
+ OSMO_VALUE_STRING(TRXCON_EV_SCHED_UL_DF_CONF),
+ OSMO_VALUE_STRING(TRXCON_EV_SCHED_DL_TF_IND),
+ OSMO_VALUE_STRING(TRXCON_EV_SCHED_UL_TF_CONF),
+
+ { 0, NULL }
+};
+
+struct osmo_fsm trxcon_fsm_def = {
+ .name = "trxcon_fsm",
+ .states = trxcon_fsm_states,
+ .num_states = ARRAY_SIZE(trxcon_fsm_states),
+ .event_names = trxcon_fsm_event_names,
+ .log_subsys = DAPP,
+};
+
+static __attribute__((constructor)) void on_dso_load(void)
+{
+ /* Register our FSM */
+ OSMO_ASSERT(osmo_fsm_register(&trxcon_fsm_def) == 0);
+}