diff options
author | Vadim Yanitskiy <axilirator@gmail.com> | 2019-01-17 11:45:22 +0700 |
---|---|---|
committer | Vadim Yanitskiy <axilirator@gmail.com> | 2019-02-21 17:25:00 +0700 |
commit | 8fdcd52dacb9a020358790318f6c3cdf9906ce14 (patch) | |
tree | 7e63d0ca4e92ddffc7cf3159297543e4a07f3701 /src | |
parent | 947369922990195bccb59cae88cccbd7eefac9c8 (diff) |
trxcon: refactor trxcon_fsm finite state machine
Change-Id: I035b2cb701e2d0b3fedec4d569507b79d400df5b
Diffstat (limited to 'src')
-rw-r--r-- | src/host/trxcon/Makefile.am | 1 | ||||
-rw-r--r-- | src/host/trxcon/l1ctl_link.c | 4 | ||||
-rw-r--r-- | src/host/trxcon/trx_if.c | 4 | ||||
-rw-r--r-- | src/host/trxcon/trxcon.c | 80 | ||||
-rw-r--r-- | src/host/trxcon/trxcon.h | 35 | ||||
-rw-r--r-- | src/host/trxcon/trxcon_fsm.c | 123 |
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); +} |