summaryrefslogtreecommitdiffstats
path: root/src/host/trxcon/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/host/trxcon/include')
-rw-r--r--src/host/trxcon/include/Makefile.am3
-rw-r--r--src/host/trxcon/include/osmocom/Makefile.am3
-rw-r--r--src/host/trxcon/include/osmocom/bb/Makefile.am9
l---------src/host/trxcon/include/osmocom/bb/l1ctl_proto.h1
l---------src/host/trxcon/include/osmocom/bb/l1gprs.h1
-rw-r--r--src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am5
-rw-r--r--src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h417
-rw-r--r--src/host/trxcon/include/osmocom/bb/l1sched/logging.h37
-rw-r--r--src/host/trxcon/include/osmocom/bb/l1sched/prim.h132
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/Makefile.am9
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h22
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_server.h67
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/logging.h16
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/phyif.h120
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/trx_if.h61
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h64
-rw-r--r--src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h169
17 files changed, 1136 insertions, 0 deletions
diff --git a/src/host/trxcon/include/Makefile.am b/src/host/trxcon/include/Makefile.am
new file mode 100644
index 00000000..9d963a02
--- /dev/null
+++ b/src/host/trxcon/include/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+ osmocom \
+ $(NULL)
diff --git a/src/host/trxcon/include/osmocom/Makefile.am b/src/host/trxcon/include/osmocom/Makefile.am
new file mode 100644
index 00000000..83c6385c
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+ bb \
+ $(NULL)
diff --git a/src/host/trxcon/include/osmocom/bb/Makefile.am b/src/host/trxcon/include/osmocom/bb/Makefile.am
new file mode 100644
index 00000000..4a575ffb
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/Makefile.am
@@ -0,0 +1,9 @@
+SUBDIRS = \
+ l1sched \
+ trxcon \
+ $(NULL)
+
+noinst_HEADERS = \
+ l1ctl_proto.h \
+ l1gprs.h \
+ $(NULL)
diff --git a/src/host/trxcon/include/osmocom/bb/l1ctl_proto.h b/src/host/trxcon/include/osmocom/bb/l1ctl_proto.h
new file mode 120000
index 00000000..ee19b80e
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/l1ctl_proto.h
@@ -0,0 +1 @@
+../../../../../../include/l1ctl_proto.h \ No newline at end of file
diff --git a/src/host/trxcon/include/osmocom/bb/l1gprs.h b/src/host/trxcon/include/osmocom/bb/l1gprs.h
new file mode 120000
index 00000000..3bf85176
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/l1gprs.h
@@ -0,0 +1 @@
+../../../../../../include/l1gprs.h \ No newline at end of file
diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am b/src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am
new file mode 100644
index 00000000..39c32ba0
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/l1sched/Makefile.am
@@ -0,0 +1,5 @@
+noinst_HEADERS = \
+ l1sched.h \
+ logging.h \
+ prim.h \
+ $(NULL)
diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
new file mode 100644
index 00000000..6c5a31e8
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h
@@ -0,0 +1,417 @@
+#pragma once
+
+#include <time.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <arpa/inet.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/gsm0502.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/timer.h>
+
+#include <osmocom/bb/l1sched/prim.h>
+
+#define GPRS_L2_MAX_LEN 54
+#define EDGE_L2_MAX_LEN 155
+
+#define L1SCHED_CH_LID_DEDIC 0x00
+#define L1SCHED_CH_LID_SACCH 0x40
+
+/* Osmocom-specific extension for PTCCH (see 3GPP TS 45.002, section 3.3.4.2).
+ * Shall be used to distinguish PTCCH and PDTCH channels on a PDCH time-slot. */
+#define L1SCHED_CH_LID_PTCCH 0x80
+
+/* Is a channel related to PDCH (GPRS) */
+#define L1SCHED_CH_FLAG_PDCH (1 << 0)
+/* Should a channel be activated automatically */
+#define L1SCHED_CH_FLAG_AUTO (1 << 1)
+
+#define MAX_A5_KEY_LEN (128 / 8)
+#define TRX_TS_COUNT 8
+
+struct l1sched_lchan_state;
+struct l1sched_meas_set;
+struct l1sched_state;
+struct l1sched_ts;
+
+enum l1sched_burst_type {
+ L1SCHED_BURST_GMSK,
+ L1SCHED_BURST_8PSK,
+};
+
+/**
+ * These types define the different channels on a multiframe.
+ * Each channel has queues and can be activated individually.
+ */
+enum l1sched_lchan_type {
+ L1SCHED_IDLE = 0,
+ L1SCHED_FCCH,
+ L1SCHED_SCH,
+ L1SCHED_BCCH,
+ L1SCHED_RACH,
+ L1SCHED_CCCH,
+ L1SCHED_TCHF,
+ L1SCHED_TCHH_0,
+ L1SCHED_TCHH_1,
+ L1SCHED_SDCCH4_0,
+ L1SCHED_SDCCH4_1,
+ L1SCHED_SDCCH4_2,
+ L1SCHED_SDCCH4_3,
+ L1SCHED_SDCCH8_0,
+ L1SCHED_SDCCH8_1,
+ L1SCHED_SDCCH8_2,
+ L1SCHED_SDCCH8_3,
+ L1SCHED_SDCCH8_4,
+ L1SCHED_SDCCH8_5,
+ L1SCHED_SDCCH8_6,
+ L1SCHED_SDCCH8_7,
+ L1SCHED_SACCHTF,
+ L1SCHED_SACCHTH_0,
+ L1SCHED_SACCHTH_1,
+ L1SCHED_SACCH4_0,
+ L1SCHED_SACCH4_1,
+ L1SCHED_SACCH4_2,
+ L1SCHED_SACCH4_3,
+ L1SCHED_SACCH8_0,
+ L1SCHED_SACCH8_1,
+ L1SCHED_SACCH8_2,
+ L1SCHED_SACCH8_3,
+ L1SCHED_SACCH8_4,
+ L1SCHED_SACCH8_5,
+ L1SCHED_SACCH8_6,
+ L1SCHED_SACCH8_7,
+ L1SCHED_PDTCH,
+ L1SCHED_PTCCH,
+ L1SCHED_SDCCH4_CBCH,
+ L1SCHED_SDCCH8_CBCH,
+ _L1SCHED_CHAN_MAX
+};
+
+/* Represents a burst to be transmitted */
+struct l1sched_burst_req {
+ uint32_t fn;
+ uint8_t tn;
+ uint8_t pwr;
+
+ /* Internally used by the scheduler */
+ uint8_t bid;
+
+ ubit_t burst[GSM_NBITS_NB_8PSK_BURST];
+ size_t burst_len;
+};
+
+/* Represents a received burst */
+struct l1sched_burst_ind {
+ uint32_t fn;
+ uint8_t tn;
+
+ /*! ToA256 (Timing of Arrival, 1/256 of a symbol) */
+ int16_t toa256;
+ /*! RSSI (Received Signal Strength Indication) */
+ int8_t rssi;
+
+ /* Internally used by the scheduler */
+ uint8_t bid;
+
+ sbit_t burst[GSM_NBITS_NB_8PSK_BURST];
+ size_t burst_len;
+};
+
+/* Probed lchan is active */
+#define L1SCHED_PROBE_F_ACTIVE (1 << 0)
+
+/* RTR (Ready-to-Receive) probe */
+struct l1sched_probe {
+ uint32_t flags; /* see L1SCHED_PROBE_F_* above */
+ uint32_t fn;
+ uint8_t tn;
+};
+
+typedef int l1sched_lchan_rx_func(struct l1sched_lchan_state *lchan,
+ const struct l1sched_burst_ind *bi);
+
+typedef int l1sched_lchan_tx_func(struct l1sched_lchan_state *lchan,
+ struct l1sched_burst_req *br);
+
+struct l1sched_lchan_desc {
+ /*! Human-readable name */
+ const char *name;
+ /*! Human-readable description */
+ const char *desc;
+
+ /*! Channel Number (like in RSL) */
+ uint8_t chan_nr;
+ /*! Link ID (like in RSL) */
+ uint8_t link_id;
+
+ /*! How much memory do we need to store bursts */
+ size_t burst_buf_size;
+ /*! Channel specific flags */
+ uint8_t flags;
+
+ /*! Function to call when burst received from PHY */
+ l1sched_lchan_rx_func *rx_fn;
+ /*! Function to call when data received from L2 */
+ l1sched_lchan_tx_func *tx_fn;
+};
+
+struct l1sched_tdma_frame {
+ /*! Downlink channel (slot) type */
+ enum l1sched_lchan_type dl_chan;
+ /*! Downlink block ID */
+ uint8_t dl_bid;
+ /*! Uplink channel (slot) type */
+ enum l1sched_lchan_type ul_chan;
+ /*! Uplink block ID */
+ uint8_t ul_bid;
+};
+
+struct l1sched_tdma_multiframe {
+ /*! Channel combination */
+ enum gsm_phys_chan_config chan_config;
+ /*! Human-readable name */
+ const char *name;
+ /*! Repeats how many frames */
+ uint8_t period;
+ /*! Applies to which timeslots */
+ uint8_t slotmask;
+ /*! Contains which lchans */
+ uint64_t lchan_mask;
+ /*! Pointer to scheduling structure */
+ const struct l1sched_tdma_frame *frames;
+};
+
+struct l1sched_meas_set {
+ /*! TDMA frame number of the first burst this set belongs to */
+ uint32_t fn;
+ /*! ToA256 (Timing of Arrival, 1/256 of a symbol) */
+ int16_t toa256;
+ /*! RSSI (Received Signal Strength Indication) */
+ int8_t rssi;
+};
+
+/* Simple ring buffer (up to 24 unique measurements) */
+struct l1sched_lchan_meas_hist {
+ struct l1sched_meas_set buf[24];
+ struct l1sched_meas_set *head;
+};
+
+/* States each channel on a multiframe */
+struct l1sched_lchan_state {
+ /*! Channel type */
+ enum l1sched_lchan_type type;
+ /*! Channel status */
+ uint8_t active;
+ /*! Link to a list of channels */
+ struct llist_head list;
+
+ /*! Burst type: GMSK or 8PSK */
+ enum l1sched_burst_type burst_type;
+ /*! Mask of received bursts */
+ uint32_t rx_burst_mask;
+ /*! Mask of transmitted bursts */
+ uint32_t tx_burst_mask;
+ /*! Burst buffer for RX */
+ sbit_t *rx_bursts;
+ /*! Burst buffer for TX */
+ ubit_t *tx_bursts;
+
+ /*! Queue of Tx primitives */
+ struct llist_head tx_prims;
+ /*! Tx primitive being sent */
+ struct msgb *prim;
+
+ /*! Mode for TCH channels (see GSM48_CMODE_*) */
+ uint8_t tch_mode;
+ /*! Training Sequence Code */
+ uint8_t tsc;
+
+ /*! FACCH/H on downlink */
+ bool dl_ongoing_facch;
+ /*! pending FACCH/H blocks on Uplink */
+ uint8_t ul_facch_blocks;
+
+ /*! Downlink measurements history */
+ struct l1sched_lchan_meas_hist meas_hist;
+ /*! AVG measurements of the last received block */
+ struct l1sched_meas_set meas_avg;
+
+ /*! TDMA loss detection state */
+ struct {
+ /*! Last processed TDMA frame number */
+ uint32_t last_proc;
+ /*! Number of processed TDMA frames */
+ unsigned long num_proc;
+ /*! Number of lost TDMA frames */
+ unsigned long num_lost;
+ } tdma;
+
+ /*! SACCH state */
+ struct {
+ /*! Cached measurement report (last received) */
+ uint8_t mr_cache[GSM_MACBLOCK_LEN];
+ /*! Cache usage counter */
+ uint8_t mr_cache_usage;
+ /*! Was a MR transmitted last time? */
+ bool mr_tx_last;
+ } sacch;
+
+ /* AMR specific */
+ struct {
+ /*! 4 possible codecs for AMR */
+ uint8_t codec[4];
+ /*! Number of possible codecs */
+ uint8_t codecs;
+ /*! Current uplink FT index */
+ uint8_t ul_ft;
+ /*! Current downlink FT index */
+ uint8_t dl_ft;
+ /*! Current uplink CMR index */
+ uint8_t ul_cmr;
+ /*! Current downlink CMR index */
+ uint8_t dl_cmr;
+ /*! If AMR loop is enabled */
+ uint8_t amr_loop;
+ /*! Number of bit error rates */
+ uint8_t ber_num;
+ /*! Sum of bit error rates */
+ float ber_sum;
+ /* last received dtx frame type */
+ uint8_t last_dtx;
+ } amr;
+
+ /*! A5/X encryption state */
+ struct {
+ uint8_t key[MAX_A5_KEY_LEN];
+ uint8_t key_len;
+ uint8_t algo;
+ } a5;
+
+ /* TS that this lchan belongs to */
+ struct l1sched_ts *ts;
+};
+
+struct l1sched_ts {
+ /*! Timeslot index within a frame (0..7) */
+ uint8_t index;
+
+ /*! Pointer to multiframe layout */
+ const struct l1sched_tdma_multiframe *mf_layout;
+ /*! Channel states for logical channels */
+ struct llist_head lchans;
+ /*! Backpointer to the scheduler */
+ struct l1sched_state *sched;
+};
+
+/*! Scheduler configuration */
+struct l1sched_cfg {
+ /*! Logging context (used as prefix for messages) */
+ const char *log_prefix;
+};
+
+/*! One scheduler instance */
+struct l1sched_state {
+ /*! List of timeslots maintained by this scheduler */
+ struct l1sched_ts *ts[TRX_TS_COUNT];
+ /*! SACCH cache (common for all lchans) */
+ uint8_t sacch_cache[GSM_MACBLOCK_LEN];
+ /*! BSIC value learned from SCH bursts */
+ uint8_t bsic;
+ /*! Logging context (used as prefix for messages) */
+ const char *log_prefix;
+ /*! Some private data */
+ void *priv;
+};
+
+extern const struct l1sched_lchan_desc l1sched_lchan_desc[_L1SCHED_CHAN_MAX];
+const struct l1sched_tdma_multiframe *
+l1sched_mframe_layout(enum gsm_phys_chan_config config, uint8_t tn);
+
+/* Scheduler management functions */
+struct l1sched_state *l1sched_alloc(void *ctx, const struct l1sched_cfg *cfg, void *priv);
+void l1sched_reset(struct l1sched_state *sched, bool reset_clock);
+void l1sched_free(struct l1sched_state *sched);
+
+/* Timeslot management functions */
+struct l1sched_ts *l1sched_add_ts(struct l1sched_state *sched, int tn);
+void l1sched_del_ts(struct l1sched_state *sched, int tn);
+int l1sched_reset_ts(struct l1sched_state *sched, int tn);
+int l1sched_configure_ts(struct l1sched_state *sched, int tn,
+ enum gsm_phys_chan_config config);
+int l1sched_start_ciphering(struct l1sched_ts *ts, uint8_t algo,
+ const uint8_t *key, uint8_t key_len);
+
+/* Logical channel management functions */
+enum gsm_phys_chan_config l1sched_chan_nr2pchan_config(uint8_t chan_nr);
+
+void l1sched_deactivate_all_lchans(struct l1sched_ts *ts);
+int l1sched_set_lchans(struct l1sched_ts *ts, uint8_t chan_nr,
+ int active, uint8_t tch_mode, uint8_t tsc);
+int l1sched_lchan_set_amr_cfg(struct l1sched_lchan_state *lchan,
+ uint8_t codecs_bitmask, uint8_t start_codec);
+int l1sched_activate_lchan(struct l1sched_ts *ts, enum l1sched_lchan_type chan);
+int l1sched_deactivate_lchan(struct l1sched_ts *ts, enum l1sched_lchan_type chan);
+struct l1sched_lchan_state *l1sched_find_lchan_by_type(struct l1sched_ts *ts,
+ enum l1sched_lchan_type type);
+struct l1sched_lchan_state *l1sched_find_lchan_by_chan_nr(struct l1sched_state *sched,
+ uint8_t chan_nr, uint8_t link_id);
+
+#define L1SCHED_TCH_MODE_IS_SPEECH(mode) \
+ (mode == GSM48_CMODE_SPEECH_V1 \
+ || mode == GSM48_CMODE_SPEECH_EFR \
+ || mode == GSM48_CMODE_SPEECH_AMR)
+
+#define L1SCHED_TCH_MODE_IS_DATA(mode) \
+ (mode == GSM48_CMODE_DATA_14k5 \
+ || mode == GSM48_CMODE_DATA_12k0 \
+ || mode == GSM48_CMODE_DATA_6k0 \
+ || mode == GSM48_CMODE_DATA_3k6)
+
+#define L1SCHED_CHAN_IS_TCH(chan) \
+ (chan == L1SCHED_TCHF || chan == L1SCHED_TCHH_0 || chan == L1SCHED_TCHH_1)
+
+#define L1SCHED_CHAN_IS_SACCH(chan) \
+ (l1sched_lchan_desc[chan].link_id & L1SCHED_CH_LID_SACCH)
+
+int l1sched_handle_rx_burst(struct l1sched_state *sched,
+ struct l1sched_burst_ind *bi);
+int l1sched_handle_rx_probe(struct l1sched_state *sched,
+ struct l1sched_probe *probe);
+int l1sched_handle_burst_req(struct l1sched_state *sched,
+ const struct l1sched_burst_req *br);
+
+/* Shared declarations for lchan handlers */
+extern const uint8_t l1sched_nb_training_bits[8][26];
+
+const char *l1sched_burst_mask2str(const uint32_t *mask, int bits);
+
+/* Interleaved TCH/H block TDMA frame mapping */
+bool l1sched_tchh_block_map_fn(enum l1sched_lchan_type chan,
+ uint32_t fn, bool ul, bool facch, bool start);
+
+#define l1sched_tchh_traffic_start(chan, fn, ul) \
+ l1sched_tchh_block_map_fn(chan, fn, ul, 0, 1)
+#define l1sched_tchh_traffic_end(chan, fn, ul) \
+ l1sched_tchh_block_map_fn(chan, fn, ul, 0, 0)
+
+#define l1sched_tchh_facch_start(chan, fn, ul) \
+ l1sched_tchh_block_map_fn(chan, fn, ul, 1, 1)
+#define l1sched_tchh_facch_end(chan, fn, ul) \
+ l1sched_tchh_block_map_fn(chan, fn, ul, 1, 0)
+
+/* Measurement history */
+void l1sched_lchan_meas_push(struct l1sched_lchan_state *lchan,
+ const struct l1sched_burst_ind *bi);
+void l1sched_lchan_meas_avg(struct l1sched_lchan_state *lchan, unsigned int n);
+
+/* Clock and Downlink scheduling trigger */
+int l1sched_clck_handle(struct l1sched_state *sched, uint32_t fn);
+void l1sched_clck_reset(struct l1sched_state *sched);
+
+void l1sched_pull_burst(struct l1sched_state *sched, struct l1sched_burst_req *br);
+void l1sched_pull_send_frame(struct l1sched_state *sched);
diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/logging.h b/src/host/trxcon/include/osmocom/bb/l1sched/logging.h
new file mode 100644
index 00000000..21be9955
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/l1sched/logging.h
@@ -0,0 +1,37 @@
+#pragma once
+
+extern int l1sched_log_cat_common;
+extern int l1sched_log_cat_data;
+
+void l1sched_logging_init(int log_cat_common, int log_cat_data);
+
+/* Messages using l1sched_state as the context */
+#define LOGP_SCHED_CAT(sched, cat, level, fmt, args...) \
+ LOGP(l1sched_log_cat_##cat, level, "%s" fmt, \
+ (sched)->log_prefix, ## args)
+
+/* Common messages using l1sched_state as the context */
+#define LOGP_SCHEDC(sched, level, fmt, args...) \
+ LOGP_SCHED_CAT(sched, common, level, fmt, ## args)
+
+/* Data messages using l1sched_state as the context */
+#define LOGP_SCHEDD(sched, level, fmt, args...) \
+ LOGP_SCHED_CAT(sched, data, level, fmt, ## args)
+
+
+#define LOGP_LCHAN_NAME_FMT "TS%u-%s"
+#define LOGP_LCHAN_NAME_ARGS(lchan) \
+ (lchan)->ts->index, l1sched_lchan_desc[(lchan)->type].name
+
+/* Messages using l1sched_lchan_state as the context */
+#define LOGP_LCHAN_CAT(lchan, cat, level, fmt, args...) \
+ LOGP_SCHED_CAT((lchan)->ts->sched, cat, level, LOGP_LCHAN_NAME_FMT " " fmt, \
+ LOGP_LCHAN_NAME_ARGS(lchan), ## args)
+
+/* Common messages using l1sched_lchan_state as the context */
+#define LOGP_LCHANC(lchan, level, fmt, args...) \
+ LOGP_LCHAN_CAT(lchan, common, level, fmt, ## args)
+
+/* Data messages using l1sched_lchan_state as the context */
+#define LOGP_LCHAND(lchan, level, fmt, args...) \
+ LOGP_LCHAN_CAT(lchan, data, level, fmt, ## args)
diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/prim.h b/src/host/trxcon/include/osmocom/bb/l1sched/prim.h
new file mode 100644
index 00000000..a9187c2a
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/l1sched/prim.h
@@ -0,0 +1,132 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/prim.h>
+#include <osmocom/core/utils.h>
+
+#define l1sched_prim_from_msgb(msg) \
+ ((struct l1sched_prim *)(msg)->l1h)
+
+#define l1sched_prim_data_from_msgb(msg) \
+ ((uint8_t *)msgb_l2(msg))
+
+#define l1sched_prim_type_from_msgb(msg) \
+ l1sched_prim_from_msgb(msg)->oph.primitive
+
+#define L1SCHED_PRIM_STR_FMT "%s.%s"
+#define L1SCHED_PRIM_STR_ARGS(prim) \
+ l1sched_prim_type_name((prim)->oph.primitive), \
+ osmo_prim_operation_name((prim)->oph.operation)
+
+enum l1sched_prim_type {
+ L1SCHED_PRIM_T_DATA, /* Req | Ind | Cnf */
+ L1SCHED_PRIM_T_RACH, /* Req | Cnf */
+ L1SCHED_PRIM_T_SCH, /* Ind */
+ L1SCHED_PRIM_T_PCHAN_COMB, /* Ind */
+};
+
+extern const struct value_string l1sched_prim_type_names[];
+static inline const char *l1sched_prim_type_name(enum l1sched_prim_type val)
+{
+ return get_value_string(l1sched_prim_type_names, val);
+}
+
+/*! Common header for L1SCHED_PRIM_T_{DATA,RACH} */
+struct l1sched_prim_chdr {
+ /*! TDMA Frame Number */
+ uint32_t frame_nr;
+ /*! RSL Channel Number */
+ uint8_t chan_nr;
+ /*! RSL Link Identifier */
+ uint8_t link_id;
+ /*! Traffic or signalling */
+ bool traffic;
+};
+
+/*! Payload of L1SCHED_PRIM_T_DATA | Ind */
+struct l1sched_prim_data_ind {
+ /*! Common sub-header */
+ struct l1sched_prim_chdr chdr;
+ int16_t toa256;
+ int8_t rssi;
+ int n_errors;
+ int n_bits_total;
+};
+
+/*! Payload of L1SCHED_PRIM_T_RACH | {Req,Cnf} */
+struct l1sched_prim_rach {
+ /*! Common sub-header */
+ struct l1sched_prim_chdr chdr;
+ /*! Training Sequence (only for 11-bit RA) */
+ uint8_t synch_seq;
+ /*! Transmission offset (how many frames to skip) */
+ uint8_t offset;
+ /*! RA value is 11 bit */
+ bool is_11bit;
+ /*! RA value */
+ uint16_t ra;
+};
+
+struct l1sched_prim {
+ /*! Primitive header */
+ struct osmo_prim_hdr oph;
+ /*! Type specific header */
+ union {
+ /*! L1SCHED_PRIM_T_DATA | Req */
+ struct l1sched_prim_chdr data_req;
+ /*! L1SCHED_PRIM_T_DATA | Cnf */
+ struct l1sched_prim_chdr data_cnf;
+ /*! L1SCHED_PRIM_T_DATA | Ind */
+ struct l1sched_prim_data_ind data_ind;
+
+ /*! L1SCHED_PRIM_T_RACH | Req */
+ struct l1sched_prim_rach rach_req;
+ /*! L1SCHED_PRIM_T_RACH | Cnf */
+ struct l1sched_prim_rach rach_cnf;
+
+ /*! L1SCHED_PRIM_T_SCH | Ind */
+ struct {
+ /*! TDMA frame number */
+ uint32_t frame_nr;
+ /*! BSIC */
+ uint8_t bsic;
+ } sch_ind;
+
+ /*! L1SCHED_PRIM_T_PCHAN_COMB | Ind */
+ struct {
+ /*! Timeslot number */
+ uint8_t tn;
+ /*! Channel combination for a timeslot */
+ enum gsm_phys_chan_config pchan;
+ } pchan_comb_ind;
+ };
+};
+
+
+struct l1sched_state;
+struct l1sched_lchan_state;
+
+void l1sched_prim_init(struct msgb *msg,
+ enum l1sched_prim_type type,
+ enum osmo_prim_operation op);
+
+struct msgb *l1sched_prim_alloc(enum l1sched_prim_type type,
+ enum osmo_prim_operation op);
+
+bool l1sched_lchan_amr_prim_is_valid(struct l1sched_lchan_state *lchan,
+ struct msgb *msg, bool is_cmr);
+struct msgb *l1sched_lchan_prim_dequeue_sacch(struct l1sched_lchan_state *lchan);
+struct msgb *l1sched_lchan_prim_dequeue_tch(struct l1sched_lchan_state *lchan, bool facch);
+struct msgb *l1sched_lchan_prim_dummy_lapdm(const struct l1sched_lchan_state *lchan);
+
+int l1sched_lchan_emit_data_ind(struct l1sched_lchan_state *lchan,
+ const uint8_t *data, size_t data_len,
+ int n_errors, int n_bits_total, bool traffic);
+int l1sched_lchan_emit_data_cnf(struct l1sched_lchan_state *lchan,
+ struct msgb *msg, uint32_t fn);
+
+int l1sched_prim_from_user(struct l1sched_state *sched, struct msgb *msg);
+int l1sched_prim_to_user(struct l1sched_state *sched, struct msgb *msg);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/Makefile.am b/src/host/trxcon/include/osmocom/bb/trxcon/Makefile.am
new file mode 100644
index 00000000..ad1e89a0
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/Makefile.am
@@ -0,0 +1,9 @@
+noinst_HEADERS = \
+ l1ctl_server.h \
+ l1ctl.h \
+ phyif.h \
+ trx_if.h \
+ logging.h \
+ trxcon.h \
+ trxcon_fsm.h \
+ $(NULL)
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h
new file mode 100644
index 00000000..7e2fa6a5
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <stdint.h>
+
+struct msgb;
+struct trxcon_param_rx_data_ind;
+struct trxcon_param_tx_data_cnf;
+struct trxcon_param_tx_access_burst_cnf;
+
+int l1ctl_tx_fbsb_conf(struct trxcon_inst *trxcon, uint16_t band_arfcn, uint8_t bsic);
+int l1ctl_tx_fbsb_fail(struct trxcon_inst *trxcon, uint16_t band_arfcn);
+int l1ctl_tx_ccch_mode_conf(struct trxcon_inst *trxcon, uint8_t mode);
+int l1ctl_tx_pm_conf(struct trxcon_inst *trxcon, uint16_t band_arfcn, int dbm, int last);
+int l1ctl_tx_reset_conf(struct trxcon_inst *trxcon, uint8_t type);
+int l1ctl_tx_reset_ind(struct trxcon_inst *trxcon, uint8_t type);
+
+int l1ctl_tx_dt_ind(struct trxcon_inst *trxcon,
+ const struct trxcon_param_rx_data_ind *ind);
+int l1ctl_tx_dt_conf(struct trxcon_inst *trxcon,
+ const struct trxcon_param_tx_data_cnf *cnf);
+int l1ctl_tx_rach_conf(struct trxcon_inst *trxcon,
+ const struct trxcon_param_tx_access_burst_cnf *cnf);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_server.h b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_server.h
new file mode 100644
index 00000000..83c61f02
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_server.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/msgb.h>
+
+#define L1CTL_LENGTH 512
+#define L1CTL_HEADROOM 32
+
+/**
+ * Each L1CTL message gets its own length pushed
+ * as two bytes in front before sending.
+ */
+#define L1CTL_MSG_LEN_FIELD 2
+
+struct l1ctl_client;
+
+typedef int l1ctl_conn_data_func(struct l1ctl_client *, struct msgb *);
+typedef void l1ctl_conn_state_func(struct l1ctl_client *);
+
+struct l1ctl_server_cfg {
+ /* UNIX socket path to listen on */
+ const char *sock_path;
+ /* maximum number of connected clients */
+ unsigned int num_clients_max;
+ /* functions to be called on various events */
+ l1ctl_conn_data_func *conn_read_cb; /* mandatory */
+ l1ctl_conn_state_func *conn_accept_cb; /* optional */
+ l1ctl_conn_state_func *conn_close_cb; /* optional */
+};
+
+struct l1ctl_server {
+ /* list of connected clients */
+ struct llist_head clients;
+ /* number of connected clients */
+ unsigned int num_clients;
+ /* used for client ID generation */
+ unsigned int next_client_id;
+ /* socket on which we listen for connections */
+ struct osmo_fd ofd;
+ /* server configuration */
+ const struct l1ctl_server_cfg *cfg;
+};
+
+struct l1ctl_client {
+ /* list head in l1ctl_server.clients */
+ struct llist_head list;
+ /* struct l1ctl_server we belong to */
+ struct l1ctl_server *server;
+ /* client's write queue */
+ struct osmo_wqueue wq;
+ /* logging context (used as prefix for messages) */
+ const char *log_prefix;
+ /* unique client ID */
+ unsigned int id;
+ /* some private data */
+ void *priv;
+};
+
+struct l1ctl_server *l1ctl_server_alloc(void *ctx, const struct l1ctl_server_cfg *cfg);
+void l1ctl_server_free(struct l1ctl_server *server);
+
+int l1ctl_client_send(struct l1ctl_client *client, struct msgb *msg);
+void l1ctl_client_conn_close(struct l1ctl_client *client);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/logging.h b/src/host/trxcon/include/osmocom/bb/trxcon/logging.h
new file mode 100644
index 00000000..ce149926
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/logging.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <osmocom/core/logging.h>
+
+enum {
+ DAPP,
+ DL1C,
+ DL1D,
+ DTRXC,
+ DTRXD,
+ DSCH,
+ DSCHD,
+ DGPRS,
+};
+
+int trxcon_logging_init(void *tall_ctx, const char *category_mask);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/phyif.h b/src/host/trxcon/include/osmocom/bb/trxcon/phyif.h
new file mode 100644
index 00000000..2ad7a678
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/phyif.h
@@ -0,0 +1,120 @@
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+
+/* PHYIF command type */
+enum trxcon_phyif_cmd_type {
+ TRXCON_PHYIF_CMDT_RESET,
+ TRXCON_PHYIF_CMDT_POWERON,
+ TRXCON_PHYIF_CMDT_POWEROFF,
+ TRXCON_PHYIF_CMDT_MEASURE,
+ TRXCON_PHYIF_CMDT_SETFREQ_H0,
+ TRXCON_PHYIF_CMDT_SETFREQ_H1,
+ TRXCON_PHYIF_CMDT_SETSLOT,
+ TRXCON_PHYIF_CMDT_SETTA,
+};
+
+/* param of TRXCON_PHYIF_CMDT_SETFREQ_H0 */
+struct trxcon_phyif_cmdp_setfreq_h0 {
+ uint16_t band_arfcn;
+};
+
+/* param of TRXCON_PHYIF_CMDT_SETFREQ_H1 */
+struct trxcon_phyif_cmdp_setfreq_h1 {
+ uint8_t hsn;
+ uint8_t maio;
+ const uint16_t *ma;
+ unsigned int ma_len;
+};
+
+/* param of TRXCON_PHYIF_CMDT_SETSLOT */
+struct trxcon_phyif_cmdp_setslot {
+ uint8_t tn;
+ uint8_t pchan; /* enum gsm_phys_chan_config */
+};
+
+/* param of TRXCON_PHYIF_CMDT_SETTA */
+struct trxcon_phyif_cmdp_setta {
+ int8_t ta; /* intentionally signed */
+};
+
+/* param of TRXCON_PHYIF_CMDT_MEASURE (command) */
+struct trxcon_phyif_cmdp_measure {
+ uint16_t band_arfcn;
+};
+
+/* param of TRXCON_PHYIF_CMDT_MEASURE (response) */
+struct trxcon_phyif_rspp_measure {
+ uint16_t band_arfcn;
+ int dbm;
+};
+
+struct trxcon_phyif_cmd {
+ enum trxcon_phyif_cmd_type type;
+ union {
+ struct trxcon_phyif_cmdp_setfreq_h0 setfreq_h0;
+ struct trxcon_phyif_cmdp_setfreq_h1 setfreq_h1;
+ struct trxcon_phyif_cmdp_setslot setslot;
+ struct trxcon_phyif_cmdp_setta setta;
+ struct trxcon_phyif_cmdp_measure measure;
+ } param;
+};
+
+struct trxcon_phyif_rsp {
+ enum trxcon_phyif_cmd_type type;
+ union {
+ struct trxcon_phyif_rspp_measure measure;
+ } param;
+};
+
+/* RTS.ind - Ready-to-Send indication */
+struct trxcon_phyif_rts_ind {
+ uint32_t fn;
+ uint8_t tn;
+};
+
+/* RTR.ind - Ready-to-Receive indicaton */
+struct trxcon_phyif_rtr_ind {
+ uint32_t fn;
+ uint8_t tn;
+};
+
+/* The probed lchan is active */
+#define TRXCON_PHYIF_RTR_F_ACTIVE (1 << 0)
+
+/* RTR.rsp - Ready-to-Receive response */
+struct trxcon_phyif_rtr_rsp {
+ uint32_t flags; /* see TRXCON_PHYIF_RTR_F_* above */
+};
+
+/* BURST.req - a burst to be transmitted */
+struct trxcon_phyif_burst_req {
+ uint32_t fn;
+ uint8_t tn;
+ uint8_t pwr;
+ const ubit_t *burst;
+ unsigned int burst_len;
+};
+
+/* BURST.ind - a received burst */
+struct trxcon_phyif_burst_ind {
+ uint32_t fn;
+ uint8_t tn;
+ int16_t toa256;
+ int8_t rssi;
+ const sbit_t *burst;
+ unsigned int burst_len;
+};
+
+int trxcon_phyif_handle_burst_req(void *phyif, const struct trxcon_phyif_burst_req *br);
+int trxcon_phyif_handle_burst_ind(void *priv, const struct trxcon_phyif_burst_ind *bi);
+
+int trxcon_phyif_handle_rts_ind(void *priv, const struct trxcon_phyif_rts_ind *rts);
+int trxcon_phyif_handle_rtr_ind(void *priv, const struct trxcon_phyif_rtr_ind *ind,
+ struct trxcon_phyif_rtr_rsp *rsp);
+
+int trxcon_phyif_handle_cmd(void *phyif, const struct trxcon_phyif_cmd *cmd);
+int trxcon_phyif_handle_rsp(void *priv, const struct trxcon_phyif_rsp *rsp);
+void trxcon_phyif_close(void *phyif);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trx_if.h b/src/host/trxcon/include/osmocom/bb/trxcon/trx_if.h
new file mode 100644
index 00000000..e564fd8e
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/trx_if.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/fsm.h>
+
+#include <osmocom/bb/trxcon/phyif.h>
+
+#define TRXC_BUF_SIZE 1024
+#define TRXD_BUF_SIZE 512
+
+enum trx_fsm_states {
+ TRX_STATE_OFFLINE = 0,
+ TRX_STATE_IDLE,
+ TRX_STATE_ACTIVE,
+ TRX_STATE_RSP_WAIT,
+};
+
+struct trx_instance {
+ struct osmo_fd trx_ofd_ctrl;
+ struct osmo_fd trx_ofd_data;
+
+ struct osmo_timer_list trx_ctrl_timer;
+ struct llist_head trx_ctrl_list;
+ struct osmo_fsm_inst *fi;
+ uint32_t fn_advance;
+
+ /* HACK: we need proper state machines */
+ uint32_t prev_state;
+ bool powered_up;
+
+ /* Some private data */
+ void *priv;
+};
+
+struct trx_ctrl_msg {
+ struct llist_head list;
+ char cmd[TRXC_BUF_SIZE];
+ int retry_cnt;
+ int critical;
+ int cmd_len;
+};
+
+struct trx_if_params {
+ const char *local_host;
+ const char *remote_host;
+ uint16_t base_port;
+ uint32_t fn_advance;
+ uint8_t instance;
+
+ struct osmo_fsm_inst *parent_fi;
+ uint32_t parent_term_event;
+ void *priv;
+};
+
+struct trx_instance *trx_if_open(const struct trx_if_params *params);
+void trx_if_close(struct trx_instance *trx);
+
+int trx_if_handle_phyif_burst_req(struct trx_instance *trx, const struct trxcon_phyif_burst_req *br);
+int trx_if_handle_phyif_cmd(struct trx_instance *trx, const struct trxcon_phyif_cmd *cmd);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
new file mode 100644
index 00000000..ff54e785
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <stdint.h>
+
+struct osmo_fsm_inst;
+struct l1sched_state;
+struct l1gprs_state;
+struct msgb;
+
+struct trxcon_inst {
+ struct osmo_fsm_inst *fi;
+ unsigned int id;
+
+ /* Logging context for sched and l1c */
+ const char *log_prefix;
+
+ /* GSMTAP instance (optional) */
+ struct gsmtap_inst *gsmtap;
+
+ /* The L1 scheduler */
+ struct l1sched_state *sched;
+ /* GPRS state (MAC layer) */
+ struct l1gprs_state *gprs;
+
+ /* PHY interface (e.g. TRXC/TRXD) */
+ void *phyif;
+ /* L2 interface (e.g. L1CTL) */
+ void *l2if;
+
+ /* State specific data of trxcon_fsm */
+ void *fi_data;
+
+ /* L1 parameters */
+ struct {
+ uint16_t band_arfcn;
+ uint8_t tx_power;
+ uint8_t tsc; /* only valid for DCCH/PDCH */
+ int8_t ta;
+ } l1p;
+
+ /* PHY specific quirks */
+ struct {
+ /* FBSB timeout extension (in TDMA FNs) */
+ unsigned int fbsb_extend_fns;
+ } phy_quirks;
+};
+
+enum trxcon_log_cat {
+ TRXCON_LOGC_FSM, /* trxcon_fsm */
+ TRXCON_LOGC_L1C, /* L1CTL control */
+ TRXCON_LOGC_L1D, /* L1CTL data */
+ TRXCON_LOGC_SCHC, /* l1sched control */
+ TRXCON_LOGC_SCHD, /* l1sched data */
+ TRXCON_LOGC_GPRS, /* l1gprs logging */
+};
+
+void trxcon_set_log_cfg(const int *logc, unsigned int logc_num);
+
+struct trxcon_inst *trxcon_inst_alloc(void *ctx, unsigned int id);
+void trxcon_inst_free(struct trxcon_inst *trxcon);
+
+int trxcon_l1ctl_receive(struct trxcon_inst *trxcon, struct msgb *msg);
+int trxcon_l1ctl_send(struct trxcon_inst *trxcon, struct msgb *msg);
+void trxcon_l1ctl_close(struct trxcon_inst *trxcon);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h
new file mode 100644
index 00000000..9eba4fde
--- /dev/null
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon_fsm.h
@@ -0,0 +1,169 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <osmocom/core/fsm.h>
+
+extern struct osmo_fsm trxcon_fsm_def;
+
+enum trxcon_fsm_states {
+ TRXCON_ST_RESET,
+ TRXCON_ST_FULL_POWER_SCAN,
+ TRXCON_ST_FBSB_SEARCH,
+ TRXCON_ST_BCCH_CCCH,
+ TRXCON_ST_DEDICATED,
+ TRXCON_ST_PACKET_DATA,
+};
+
+enum trxcon_fsm_events {
+ TRXCON_EV_PHYIF_FAILURE,
+ TRXCON_EV_L2IF_FAILURE,
+ TRXCON_EV_RESET_FULL_REQ,
+ TRXCON_EV_RESET_SCHED_REQ,
+ TRXCON_EV_FULL_POWER_SCAN_REQ,
+ TRXCON_EV_FULL_POWER_SCAN_RES,
+ TRXCON_EV_FBSB_SEARCH_REQ,
+ TRXCON_EV_FBSB_SEARCH_RES,
+ TRXCON_EV_SET_CCCH_MODE_REQ,
+ TRXCON_EV_SET_TCH_MODE_REQ,
+ TRXCON_EV_SET_PHY_CONFIG_REQ,
+ TRXCON_EV_TX_ACCESS_BURST_REQ,
+ TRXCON_EV_TX_ACCESS_BURST_CNF,
+ TRXCON_EV_UPDATE_SACCH_CACHE_REQ,
+ TRXCON_EV_DCH_EST_REQ,
+ TRXCON_EV_DCH_REL_REQ,
+ TRXCON_EV_TX_DATA_REQ,
+ TRXCON_EV_TX_DATA_CNF,
+ TRXCON_EV_RX_DATA_IND,
+ TRXCON_EV_CRYPTO_REQ,
+ TRXCON_EV_GPRS_UL_TBF_CFG_REQ, /* param: L1CTL msgb */
+ TRXCON_EV_GPRS_DL_TBF_CFG_REQ, /* param: L1CTL msgb */
+ TRXCON_EV_GPRS_UL_BLOCK_REQ, /* param: L1CTL msgb */
+};
+
+/* param of TRXCON_EV_FULL_POWER_SCAN_REQ */
+struct trxcon_param_full_power_scan_req {
+ uint16_t band_arfcn_start;
+ uint16_t band_arfcn_stop;
+};
+
+/* param of TRXCON_EV_FULL_POWER_SCAN_RES */
+struct trxcon_param_full_power_scan_res {
+ uint16_t band_arfcn;
+ int dbm;
+};
+
+/* param of TRXCON_EV_FBSB_SEARCH_REQ */
+struct trxcon_param_fbsb_search_req {
+ uint16_t band_arfcn;
+ uint16_t timeout_fns; /* in TDMA Fn periods */
+ uint8_t pchan_config;
+};
+
+/* param of TRXCON_EV_SET_{CCCH,TCH}_MODE_REQ */
+struct trxcon_param_set_ccch_tch_mode_req {
+ uint8_t mode;
+ struct {
+ uint8_t start_codec;
+ uint8_t codecs_bitmask;
+ } amr;
+ bool applied;
+};
+
+/* param of TRXCON_EV_SET_PHY_CONFIG_REQ */
+struct trxcon_param_set_phy_config_req {
+ enum {
+ TRXCON_PHY_CFGT_PCHAN_COMB,
+ TRXCON_PHY_CFGT_TX_PARAMS,
+ } type;
+ union {
+ struct {
+ uint8_t tn;
+ uint8_t pchan;
+ } pchan_comb;
+ struct {
+ uint8_t timing_advance;
+ uint8_t tx_power;
+ } tx_params;
+ };
+};
+
+/* param of TRXCON_EV_TX_DATA_REQ */
+struct trxcon_param_tx_data_req {
+ bool traffic;
+ uint8_t chan_nr;
+ uint8_t link_id;
+ size_t data_len;
+ const uint8_t *data;
+};
+
+/* param of TRXCON_EV_TX_DATA_CNF */
+struct trxcon_param_tx_data_cnf {
+ bool traffic;
+ uint8_t chan_nr;
+ uint8_t link_id;
+ uint16_t band_arfcn;
+ uint32_t frame_nr;
+ size_t data_len;
+ const uint8_t *data;
+};
+
+/* param of TRXCON_EV_RX_DATA_IND */
+struct trxcon_param_rx_data_ind {
+ bool traffic;
+ uint8_t chan_nr;
+ uint8_t link_id;
+ uint16_t band_arfcn;
+ uint32_t frame_nr;
+ int16_t toa256;
+ int8_t rssi;
+ int n_errors;
+ int n_bits_total;
+ size_t data_len;
+ const uint8_t *data;
+};
+
+/* param of TRXCON_EV_TX_ACCESS_BURST_REQ */
+struct trxcon_param_tx_access_burst_req {
+ uint8_t chan_nr;
+ uint8_t link_id;
+ uint8_t offset;
+ uint8_t synch_seq;
+ uint16_t ra;
+ bool is_11bit;
+};
+
+/* param of TRXCON_EV_TX_ACCESS_BURST_CNF */
+struct trxcon_param_tx_access_burst_cnf {
+ uint16_t band_arfcn;
+ uint32_t frame_nr;
+};
+
+/* param of TRXCON_EV_DCH_EST_REQ */
+struct trxcon_param_dch_est_req {
+ uint8_t chan_nr;
+ uint8_t tch_mode;
+ uint8_t tsc;
+
+ bool hopping;
+ union {
+ struct { /* hopping=false */
+ uint16_t band_arfcn;
+ } h0;
+ struct { /* hopping=true */
+ uint8_t hsn;
+ uint8_t maio;
+ uint8_t n;
+ uint16_t ma[64];
+ } h1;
+ };
+};
+
+/* param of TRXCON_EV_CRYPTO_REQ */
+struct trxcon_param_crypto_req {
+ uint8_t chan_nr;
+ uint8_t a5_algo; /* 0 is A5/0 */
+ uint8_t key_len;
+ const uint8_t *key;
+};