aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/bsc/lchan_fsm.h
blob: 8734e57f9fa3abb53b08f088549e775617076ef0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/* osmo-bsc API to manage lchans, logical channels in GSM cells. */
#pragma once

#include <osmocom/bsc/gsm_data.h>

#define LOG_ADD_NEWLINE(fmt) ((!fmt || !*fmt || fmt[strlen(fmt)-1] != '\n') ? "\n" : "")

/* This macro automatically includes a final \n, if omitted. */
#define LOG_LCHAN(lchan, level, fmt, args...) do { \
	if (lchan->fi) \
		LOGPFSML(lchan->fi, level, "(type=%s) " fmt "%s", gsm_lchant_name(lchan->type), \
			 ## args, LOG_ADD_NEWLINE(fmt)); \
	else \
		LOGP(DRSL, level, "%s (not initialized) " fmt "%s", gsm_lchan_name(lchan), \
		     ## args, LOG_ADD_NEWLINE(fmt)); \
	} while(0)

enum lchan_fsm_state {
	LCHAN_ST_UNUSED,
	LCHAN_ST_WAIT_TS_READY,
	LCHAN_ST_WAIT_ACTIV_ACK,
	LCHAN_ST_WAIT_RLL_ESTABLISH,
	LCHAN_ST_WAIT_MGW_ENDPOINT_AVAILABLE,
	LCHAN_ST_WAIT_IPACC_CRCX_ACK,
	LCHAN_ST_WAIT_IPACC_MDCX_ACK,
	LCHAN_ST_WAIT_MGW_ENDPOINT_CONFIGURED,
	LCHAN_ST_ACTIVE,
	LCHAN_ST_WAIT_SAPIS_RELEASED,
	LCHAN_ST_WAIT_BEFORE_RF_RELEASE,
	LCHAN_ST_WAIT_RF_RELEASE_ACK,
	LCHAN_ST_WAIT_AFTER_ERROR,
	LCHAN_ST_BORKEN,
};

enum lchan_fsm_event {
	LCHAN_EV_ACTIVATE,
	LCHAN_EV_TS_READY,
	LCHAN_EV_TS_ERROR,
	LCHAN_EV_RSL_CHAN_ACTIV_ACK,
	LCHAN_EV_RSL_CHAN_ACTIV_NACK,
	LCHAN_EV_RLL_ESTABLISH_IND,
	LCHAN_EV_MGW_ENDPOINT_AVAILABLE,
	LCHAN_EV_MGW_ENDPOINT_CONFIGURED,
	LCHAN_EV_MGW_ENDPOINT_ERROR,
	LCHAN_EV_IPACC_CRCX_ACK,
	LCHAN_EV_IPACC_CRCX_NACK,
	LCHAN_EV_IPACC_MDCX_ACK,
	LCHAN_EV_IPACC_MDCX_NACK,
	LCHAN_EV_RLL_REL_IND,
	LCHAN_EV_RLL_REL_CONF,
	LCHAN_EV_RSL_RF_CHAN_REL_ACK,
	LCHAN_EV_RLL_ERR_IND,

	/* FIXME: not yet implemented: Chan Mode Modify */
	LCHAN_EV_CHAN_MODE_MODIF_ACK,
	LCHAN_EV_CHAN_MODE_MODIF_ERROR,
};

void lchan_fsm_alloc(struct gsm_lchan *lchan);
void lchan_release(struct gsm_lchan *lchan, bool sacch_deact,
		   bool err, enum gsm48_rr_cause cause_rr);

struct lchan_activate_info {
	enum lchan_activate_mode activ_for;
	struct gsm_subscriber_connection *for_conn;
	/* This always is for a specific lchan, so its lchan->type indicates full or half rate.
	 * When a dyn TS was selected, the lchan->type has been set to the desired rate. */
	enum gsm48_chan_mode chan_mode;
	bool requires_voice_stream;
	struct gsm_lchan *old_lchan;
};

void lchan_activate(struct gsm_lchan *lchan, struct lchan_activate_info *info);

static inline const char *lchan_state_name(struct gsm_lchan *lchan)
{
	return lchan->fi ? osmo_fsm_inst_state_name(lchan->fi) : "NULL";
}

static inline bool lchan_state_is(struct gsm_lchan *lchan, uint32_t state)
{
	return lchan->fi && lchan->fi->state == state;
}

bool lchan_may_receive_data(struct gsm_lchan *lchan);

void lchan_forgetx_conn(struct gsm_lchan *lchan);
void lchan_forgetx_mgw_endpoint(struct gsm_lchan *lchan);