aboutsummaryrefslogtreecommitdiffstats
path: root/include/openbsc
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2008-12-23 20:25:15 +0000
committerHarald Welte <laforge@gnumonks.org>2008-12-23 20:25:15 +0000
commit52b1f9888905df8aa6ecd50af900b63f5273de6a (patch)
treee8d54defa2caba361a847b535f45708cadc0f0e2 /include/openbsc
initial commit of current OpenBSC state
Diffstat (limited to 'include/openbsc')
-rw-r--r--include/openbsc/abis_nm.h316
-rw-r--r--include/openbsc/abis_rsl.h303
-rw-r--r--include/openbsc/debug.h15
-rw-r--r--include/openbsc/gsm_04_08.h238
-rw-r--r--include/openbsc/gsm_data.h74
-rw-r--r--include/openbsc/gsm_subscriber.h16
-rw-r--r--include/openbsc/linuxlist.h360
-rw-r--r--include/openbsc/msgb.h74
-rw-r--r--include/openbsc/select.h17
-rw-r--r--include/openbsc/tlv.h66
10 files changed, 1479 insertions, 0 deletions
diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h
new file mode 100644
index 000000000..1108aa443
--- /dev/null
+++ b/include/openbsc/abis_nm.h
@@ -0,0 +1,316 @@
+/* GSM Network Management messages on the A-bis interface
+ * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
+
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * 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.
+ *
+ */
+
+#ifndef _NM_H
+#define _NM_H
+
+#include <sys/types.h>
+
+/* PRIVATE */
+
+/* generic header in front of every OML message */
+struct abis_om_hdr {
+ u_int8_t mdisc;
+ u_int8_t placement;
+ u_int8_t sequence;
+ u_int8_t length;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+#define ABIS_OM_MDISC_FOM 0x80
+#define ABIS_OM_MDISC_MMI 0x40
+#define ABIS_OM_MDISC_TRAU 0x20
+#define ABIS_OM_MDISC_MANUF 0x10
+#define ABIS_OM_PLACEMENT_ONLY 0x80
+#define ABIS_OM_PLACEMENT_FIRST 0x40
+#define ABIS_OM_PLACEMENT_MIDDLE 0x20
+#define ABIS_OM_PLACEMENT_LAST 0x10
+
+struct abis_om_obj_inst {
+ u_int8_t bts_nr;
+ u_int8_t trx_nr;
+ u_int8_t ts_nr;
+} __attribute__ ((packed));
+
+struct abis_om_fom_hdr {
+ u_int8_t msg_type;
+ u_int8_t obj_class;
+ struct abis_om_obj_inst obj_inst;
+} __attribute__ ((packed));
+
+#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr))
+
+/* Section 9.1: Message Types */
+enum abis_nm_msgtype {
+ /* SW Download Management Messages */
+ NM_MT_LOAD_INIT = 0x01,
+ NM_MT_LOAD_INIT_ACK,
+ NM_MT_LOAD_INIT_NACK,
+ NM_MT_LOAD_SEG,
+ NM_MT_LOAD_SEG_ACK,
+ NM_MT_LOAD_ABORT,
+ NM_MT_LOAD_END,
+ NM_MT_LOAD_END_ACK,
+ NM_MT_LOAD_END_NACK,
+ NM_MT_SW_ACT_REQ, /* BTS->BSC */
+ NM_MT_SW_ACT_REQ_ACK,
+ NM_MT_SW_ACT_REQ_NACK,
+ NM_MT_ACTIVATE_SW, /* BSC->BTS */
+ NM_MT_ACTIVATE_SW_ACK,
+ NM_MT_ACTIVATE_SW_NACK,
+ NM_MT_SW_ACTIVATED_REP, /* 0x10 */
+ /* A-bis Interface Management Messages */
+ NM_MT_ESTABLISH_TEI = 0x21,
+ NM_MT_ESTABLISH_TEI_ACK,
+ NM_MT_ESTABLISH_TEI_NACK,
+ NM_MT_CONN_TERR_SIGN,
+ NM_MT_CONN_TERR_SIGN_ACK,
+ NM_MT_CONN_TERR_SIGN_NACK,
+ NM_MT_DISC_TERR_SIGN,
+ NM_MT_DISC_TERR_SIGN_ACK,
+ NM_MT_DISC_TERR_SIGN_NACK,
+ NM_MT_CONN_TERR_TRAF,
+ NM_MT_CONN_TERR_TRAF_ACK,
+ NM_MT_CONN_TERR_TRAF_NACK,
+ NM_MT_DISC_TERR_TRAF,
+ NM_MT_DISC_TERR_TRAF_ACK,
+ NM_MT_DISC_TERR_TRAF_NACK,
+ /* Transmission Management Messages */
+ NM_MT_CONN_MDROP_LINK = 0x31,
+ NM_MT_CONN_MDROP_LINK_ACK,
+ NM_MT_CONN_MDROP_LINK_NACK,
+ NM_MT_DISC_MDROP_LINK,
+ NM_MT_DISC_MDROP_LINK_ACK,
+ NM_MT_DISC_MDROP_LINK_NACK,
+ /* Air Interface Management Messages */
+ NM_MT_SET_BTS_ATTR = 0x41,
+ NM_MT_SET_BTS_ATTR_ACK,
+ NM_MT_SET_BTS_ATTR_NACK,
+ NM_MT_SET_RADIO_ATTR,
+ NM_MT_SET_RADIO_ATTR_ACK,
+ NM_MT_SET_RADIO_ATTR_NACK,
+ NM_MT_SET_CHAN_ATTR,
+ NM_MT_SET_CHAN_ATTR_ACK,
+ NM_MT_SET_CHAN_ATTR_NACK,
+ /* Test Management Messages */
+ NM_MT_PERF_TEST = 0x51,
+ NM_MT_PERF_TESET_ACK,
+ NM_MT_PERF_TEST_NACK,
+ NM_MT_TEST_REP,
+ NM_MT_SEND_TEST_REP,
+ NM_MT_SEND_TEST_REP_ACK,
+ NM_MT_SEND_TEST_REP_NACK,
+ NM_MT_STOP_TEST,
+ NM_MT_STOP_TEST_ACK,
+ NM_MT_STOP_TEST_NACK,
+ /* State Management and Event Report Messages */
+ NM_MT_STATECHG_EVENT_REP = 0x61,
+ NM_MT_FAILURE_EVENT_REP,
+ NM_MT_STOP_EVENT_REP,
+ NM_MT_STOP_EVENT_REP_ACK,
+ NM_MT_STOP_EVENT_REP_NACK,
+ NM_MT_REST_EVENT_REP,
+ NM_MT_REST_EVENT_REP_ACK,
+ NM_MT_REST_EVENT_REP_NACK,
+ NM_MT_CHG_ADM_STATE,
+ NM_MT_CHG_ADM_STATE_ACK,
+ NM_MT_CHG_ADM_STATE_NACK,
+ NM_MT_CHG_ADM_STATE_REQ,
+ NM_MT_CHG_ADM_STATE_REQ_ACK,
+ NM_MT_CHG_ADM_STATE_REQ_NACK,
+ NM_MT_REP_OUTST_ALARMS = 0x93,
+ NM_MT_REP_OUTST_ALARMS_ACK,
+ NM_MT_REP_OUTST_ALARMS_NACK,
+ /* Equipment Management Messages */
+ NM_MT_CHANGEOVER = 0x71,
+ NM_MT_CHANGEOVER_ACK,
+ NM_MT_CHANGEOVER_NACK,
+ NM_MT_OPSTART,
+ NM_MT_OPSTART_ACK,
+ NM_MT_OPSTART_NACK,
+ NM_MT_REINIT,
+ NM_MT_REINIT_ACK,
+ NM_MT_REINIT_NACK,
+ NM_MT_SET_SITE_OUT,
+ NM_MT_SET_SITE_OUT_ACK,
+ NM_MT_SET_SITE_OUT_NACK,
+ NM_MT_CHG_HW_CONF = 0x90,
+ NM_MT_CHG_HW_CONF_ACK,
+ NM_MT_CHG_HW_CONF_NACK,
+ /* Measurement Management Messages */
+ NM_MT_MEAS_RES_REQ = 0x8a,
+ NM_MT_MEAS_RES_RESP,
+ NM_MT_STOP_MEAS,
+ NM_MT_START_MEAS,
+ /* Other Messages */
+ NM_MT_GET_ATTR = 0x81,
+ NM_MT_GET_ATTR_RESP,
+ NM_MT_GET_ATTR_NACK,
+ NM_MT_SET_ALARM_THRES,
+ NM_MT_SET_ALARM_THRES_ACK,
+ NM_MT_SET_ALARM_THRES_NACK,
+};
+
+/* Section 9.2: Object Class */
+enum abis_nm_obj_class {
+ NM_OC_SITE_MANAGER = 0x00,
+ NM_OC_BTS,
+ NM_OC_RADIO_CARRIER,
+ NM_OC_BASEB_TRANSC,
+ NM_OC_CHANNEL,
+ /* RFU: 05-FE */
+ NM_OC_NULL = 0xff,
+};
+
+/* Section 9.4: Attributes */
+enum abis_nm_attr {
+ NM_ATT_CHANNEL = 0x01,
+ NM_ATT_ADD_INFO,
+ NM_ATT_ADD_TEXT,
+ NM_ATT_ADM_STATE,
+ NM_ATT_ARFCN_LIST,
+ NM_ATT_AUTON_REPORT,
+ NM_ATT_AVAIL_STATUS,
+ NM_ATT_BCCH_ARFCN,
+ NM_ATT_BSIC,
+ NM_ATT_BTS_AIR_TIMER,
+ NM_ATT_CCCH_L_I_P,
+ NM_ATT_CCCH_L_T,
+ NM_ATT_CHAN_COMB,
+ NM_ATT_CONN_FAIL_CRIT,
+ NM_ATT_DEST,
+ /* res */
+ NM_ATT_EVENT_TYPE = 0x11,
+ NM_ATT_FILE_ID,
+ NM_ATT_FILE_VERSION,
+ NM_ATT_GSM_TIME,
+ NM_ATT_HSN,
+ NM_ATT_HW_CONFIG,
+ NM_ATT_HW_DESC,
+ NM_ATT_INTAVE_PARAM,
+ NM_ATT_INTERF_BOUND,
+ NM_ATT_LIST_REQ_ATTR,
+ NM_ATT_MAIO,
+ NM_ATT_MANUF_STATE,
+ NM_ATT_MANUF_THRESH,
+ NM_ATT_MANUF_ID,
+ NM_ATT_MAX_TA,
+ NM_ATT_MDROP_LINK, /* 0x20 */
+ NM_ATT_MDROP_NEXT,
+ NM_ATT_NACK_CAUSES,
+ NM_ATT_NY1,
+ NM_ATT_OPER_STATE,
+ NM_ATT_OVERL_PERIOD,
+ NM_ATT_PHYS_CONF,
+ NM_ATT_POWER_CLASS,
+ NM_ATT_POWER_THRESH,
+ NM_ATT_PROB_CAUSE,
+ NM_ATT_RACH_B_THRESH,
+ NM_ATT_LDAVG_SLOTS,
+ NM_ATT_RAD_SUBC,
+ NM_ATT_RF_MAXPOWR_R,
+ NM_ATT_SITE_INPUTS,
+ NM_ATT_SITE_OUTPUTS,
+ NM_ATT_SOURCE, /* 0x30 */
+ NM_ATT_SPEC_PROB,
+ NM_ATT_START_TIME,
+ NM_ATT_T200,
+ NM_ATT_TEI,
+ NM_ATT_TEST_DUR,
+ NM_ATT_TEST_NO,
+ NM_ATT_TEST_REPORT,
+ NM_ATT_VSWR_THRESH,
+ NM_ATT_WINDOW_SIZE,
+ /* Res */
+ NM_ATT_TSC = 0x40,
+ NM_ATT_SW_CONFIG,
+ NM_ATT_SW_DESCR,
+ NM_ATT_SEVERITY,
+ NM_ATT_GET_ARI,
+ NM_ATT_HW_CONF_CHG,
+ NM_ATT_OUTST_ALARM,
+ NM_ATT_FILE_DATA,
+ NM_ATT_MEAS_RES,
+ NM_ATT_MEAS_TYPE,
+};
+
+/* Section 9.4.4: Administrative State */
+enum abis_nm_adm_state {
+ NM_STATE_LOCKED = 0x01,
+ NM_STATE_UNLOCKED = 0x02,
+ NM_STATE_SHUTDOWN = 0x03,
+ NM_STATE_NULL = 0xff,
+};
+
+/* Section 9.4.13: Channel Combination */
+enum abis_nm_chan_comb {
+ NM_CHANC_TCHFull = 0x00,
+ NM_CHANC_TCHHalf = 0x01,
+ NM_CHANC_TCHHalf2 = 0x02,
+ NM_CHANC_SDCCH = 0x03,
+ NM_CHANC_mainBCCH = 0x04,
+ NM_CHANC_BCCCHComb = 0x05,
+ NM_CHANC_BCCH = 0x06,
+ NM_CHANC_BCCH_CBCH = 0x07,
+ NM_CHANC_SDCCH_CBCH = 0x08,
+};
+
+/* Section 9.4.1 */
+struct abis_nm_abis_channel {
+ u_int8_t attrib;
+ u_int8_t bts_port;
+ u_int8_t timeslot;
+ u_int8_t subslot;
+} __attribute__ ((packed));
+
+/* PUBLIC */
+
+struct msgb;
+
+struct abis_nm_cfg {
+ /* callback for unidirectional reports */
+ int (*report_cb)(struct msgb *,
+ struct abis_om_fom_hdr *);
+ /* callback for software activate requests from BTS */
+ int (*sw_act_req)(struct msgb *);
+};
+
+extern int abis_nm_rx(struct msgb *msg);
+//extern struct abis_nm_h *abis_nm_init(struct abis_nm_cfg *cfg);
+//extern void abis_nm_fini(struct abis_nm_h *nmh);
+
+int abis_nm_rx(struct msgb *msg);
+int abis_nm_establish_tei(struct gsm_bts *bts, u_int8_t trx_nr,
+ u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot,
+ u_int8_t tei);
+int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
+ u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot);
+int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
+ u_int8_t e1_port, u_int8_t e1_timeslot,
+ u_int8_t e1_subslot);
+int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb);
+int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *msg);
+int abis_nm_event_reports(struct gsm_bts *bts, int on);
+int abis_nm_reset_resource(struct gsm_bts *bts);
+int abis_nm_db_transaction(struct gsm_bts *bts, int begin);
+
+#endif /* _NM_H */
diff --git a/include/openbsc/abis_rsl.h b/include/openbsc/abis_rsl.h
new file mode 100644
index 000000000..9413f6577
--- /dev/null
+++ b/include/openbsc/abis_rsl.h
@@ -0,0 +1,303 @@
+/* GSM Radio Signalling Link messages on the A-bis interface
+ * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
+
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * 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.
+ *
+ */
+
+#ifndef _RSL_H
+#define _RSL_H
+
+struct abis_rsl_common_hdr {
+ u_int8_t msg_discr;
+ u_int8_t msg_type;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* Chapter 8.3 */
+struct abis_rsl_rll_hdr {
+ struct abis_rsl_common_hdr c;
+ u_int8_t ie_chan;
+ u_int8_t chan_nr;
+ u_int8_t ie_link_id;
+ u_int8_t link_id;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* Chapter 8.3 and 8.4 */
+struct abis_rsl_dchan_hdr {
+ struct abis_rsl_common_hdr c;
+ u_int8_t ie_chan;
+ u_int8_t chan_nr;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+
+/* Chapter 9.1 */
+#define ABIS_RSL_MDISC_RLL 0x02
+#define ABIS_RSL_MDISC_DED_CHAN 0x08
+#define ABIS_RSL_MDISC_COM_CHAN 0x0c
+#define ABIS_RSL_MDISC_TRX 0x10
+#define ABIS_RSL_MDISC_LOC 0x20
+
+#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01)
+
+/* Chapter 9.2 */
+enum abis_rsl_msgtype {
+ /* Radio Link Layer Management */
+ RSL_MT_DATA_REQ = 0x01,
+ RSL_MT_DATA_IND,
+ RSL_MT_ERROR_IND,
+ RSL_MT_EST_REQ,
+ RSL_MT_EST_CONF,
+ RSL_MT_EST_IND,
+ RSL_MT_REL_REQ,
+ RSL_MT_REL_CONF,
+ RSL_MT_REL_IND,
+ RSL_MT_UNIT_DATA_REQ,
+ RSL_MT_UNIT_DATA_IND, /* 0x0b */
+
+ /* Common Channel Management / TRX Management */
+ RSL_MT_BCCH_INFO = 0x11,
+ RSL_MT_CCCH_LOAD_IND,
+ RSL_MT_CHAN_RQD,
+ RSL_MT_DELETE_IND,
+ RSL_MT_PAGING_CMD,
+ RSL_MT_IMMEDIATE_ASSIGN_CMD,
+ RSL_MT_SMS_BC_REQ,
+ /* empty */
+ RSL_MT_RF_RES_IND = 0x19,
+ RSL_MT_SACCH_FILL,
+ RSL_MT_OVERLOAD,
+ RSL_MT_ERROR_REPORT,
+ RSL_MT_SMS_BC_CMD,
+ RSL_MT_CBCH_LOAD_IND,
+ RSL_MT_NOT_CMD, /* 0x1f */
+
+ /* Dedicate Channel Management */
+ RSL_MT_CHAN_ACTIV = 0x21,
+ RSL_MT_CHAN_ACTIV_ACK,
+ RSL_MT_CHAN_ACTIV_NACK,
+ RSL_MT_CONN_FAIL,
+ RSL_MT_DEACTIVATE_SACCH,
+ RSL_MT_ENCR_CMD,
+ RSL_MT_HANDO_DET,
+ RSL_MT_MEAS_RES,
+ RSL_MT_MODE_MODIFY_REQ,
+ RSL_MT_MODE_MODIFY_ACK,
+ RSL_MT_MODE_MODIFY_NACK,
+ RSL_MT_PHY_CONTEXT_REQ,
+ RSL_MT_PHY_CONTEXT_CONF,
+ RSL_MT_RF_CHAN_REL,
+ RSL_MT_MS_POWER_CONTROL,
+ RSL_MT_BS_POWER_CONTROL,
+ RSL_MT_PREPROC_CONFIG,
+ RSL_MT_PREPROC_MEAS_RES,
+ RSL_MT_RF_CHAN_REL_ACK,
+ RSL_MT_SACCH_INFO_MODIFY,
+ RSL_MT_TALKER_DET,
+ RSL_MT_LISTENER_DET,
+ RSL_MT_REMOTE_CODEC_CONF_REP,
+ RSL_MT_RTD_REP,
+ RSL_MT_PRE_HANDO_NOTIF,
+ RSL_MT_MR_CODEC_MOD_REQ,
+ RSL_MT_MR_CODEC_MOD_ACK,
+ RSL_MT_MR_CODEC_MOD_NACK,
+ RSL_MT_MR_CODEC_MOD_PER,
+ RSL_MT_TFO_REP,
+ RSL_MT_TFO_MOD_REQ, /* 0x3f */
+};
+
+/* Chapter 9.3 */
+enum abis_rsl_ie {
+ RSL_IE_CHAN_NR = 0x01,
+ RSL_IE_LINK_IDENT,
+ RSL_IE_ACT_TYPE,
+ RSL_IE_BS_POWER,
+ RSL_IE_CHAN_IDENT,
+ RSL_IE_CHAN_MODE,
+ RSL_IE_ENCR_INFO,
+ RSL_IE_FRAME_NUMBER,
+ RSL_IE_HANDO_REF,
+ RSL_IE_L1_INFO,
+ RSL_IE_L3_INFO,
+ RSL_IE_MS_IDENTITY,
+ RSL_IE_MS_POWER,
+ RSL_IE_PAGING_GROUP,
+ RSL_IE_PAGING_LOAD,
+ RSL_IE_PYHS_CONTEXT = 0x10,
+ RSL_IE_ACCESS_DELAY,
+ RSL_IE_RACH_LOAD,
+ RSL_IE_REQ_REFERENCE,
+ RSL_IE_RELEASE_MODE,
+ RSL_IE_RESOURCE_INFO,
+ RSL_IE_RLM_CAUSE,
+ RSL_IE_STARTNG_TIME,
+ RSL_IE_TIMING_ADVANCE,
+ RSL_IE_UPLINK_MEAS,
+ RSL_IE_CAUSE,
+ RSL_IE_MEAS_RES_NR,
+ RSL_IE_MSG_ID,
+ /* reserved */
+ RSL_IE_SYSINFO_TYPE = 0x1e,
+ RSL_IE_MS_POWER_PARAM,
+ RSL_IE_BS_POWER_PARAM,
+ RSL_IE_PREPROC_PARAM,
+ RSL_IE_PREPROC_MEAS,
+ RSL_IE_IMM_ASS_INFO, /* Phase 1 (3.6.0), later Full below */
+ RSL_IE_SMSCB_INFO = 0x24,
+ RSL_IE_MS_TIMING_OFFSET,
+ RSL_IE_ERR_MSG,
+ RSL_IE_FULL_BCCH_INFO,
+ RSL_IE_CHAN_NEEDED,
+ RSL_IE_CB_CMD_TYPE,
+ RSL_IE_SMSCB_MSG,
+ RSL_IE_FULL_IMM_ASS_INFO,
+ RSL_IE_SACCH_INFO,
+ RSL_IE_CBCH_LOAD_INFO,
+ RSL_IE_SMSCB_CHAN_INDICATOR,
+ RSL_IE_GROUP_CALL_REF,
+ RSL_IE_CHAN_DESC,
+ RSL_IE_NCH_DRX_INFO,
+ RSL_IE_CMD_INDICATOR,
+ RSL_IE_EMLPP_PRIO,
+ RSL_IE_UIC,
+ RSL_IE_MAIN_CHAN_REF,
+ RSL_IE_MR_CONFIG,
+ RSL_IE_MR_CONTROL,
+ RSL_IE_SUP_CODEC_TYPES,
+ RSL_IE_CODEC_CONFIG,
+ RSL_IE_RTD,
+ RSL_IE_TFO_STATUS,
+ RSL_IE_LLP_APDU,
+};
+
+/* Chapter 9.3.1 */
+#define RSL_CHAN_NR_MASK 0xf8
+#define RSL_CHAN_Bm_ACCHs 0x08
+#define RSL_CHAN_Lm_ACCHs 0x10 /* .. 0x18 */
+#define RSL_CHAN_SDCCH4_ACCH 0x20 /* .. 0x38 */
+#define RSL_CHAN_SDCCH8_ACCH 0x40 /* ...0x78 */
+#define RSL_CHAN_BCCH 0x80
+#define RSL_CHAN_RACH 0x88
+#define RSL_CHAN_PCH_AGCH 0x90
+
+/* Chapter 9.3.3 */
+#define RSL_ACT_TYPE_INITIAL 0x00
+#define RSL_ACT_TYPE_REACT 0x80
+#define RSL_ACT_INTRA_IMM_ASS 0x00
+#define RSL_ACT_INTRA_NORM_ASS 0x01
+#define RSL_ACT_INTER_ASYNC 0x02
+#define RSL_ACT_INTER_SYNC 0x03
+#define RSL_ACT_SECOND_ADD 0x04
+#define RSL_ACT_SECOND_MULTI 0x05
+
+/* Chapter 9.3.6 */
+struct rsl_ie_chan_mode {
+ u_int8_t dtx_dtu;
+ u_int8_t spd_ind;
+ u_int8_t chan_rt;
+ u_int8_t chan_rate;
+} __attribute__ ((packed));
+#define RSL_CMOD_DTXu 0x01 /* uplink */
+#define RSL_CMOD_DTXd 0x02 /* downlink */
+#define RSL_CMOD_SPD_SPEECH 0x01
+#define RSL_CMOD_SPD_DATA 0x02
+#define RSL_CMOD_SPD_SIGN 0x03
+#define RSL_CMOD_CRT_SDCCH 0x01
+#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */
+#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */
+/* FIXME: More CRT types */
+#define RSL_CMOD_SP_GSM1 0x01
+#define RSL_CMOD_SP_GSM2 0x11
+#define RSL_CMOD_SP_GSM3 0x21
+
+/* Chapter 9.3.5 */
+struct rsl_ie_chan_ident {
+ /* GSM 04.08 10.5.2.5 */
+ struct {
+ u_int8_t iei;
+ u_int8_t chan_nr; /* enc_chan_nr */
+ u_int8_t oct3;
+ u_int8_t oct4;
+ } chan_desc;
+#if 0 /* spec says we need this but Abissim doesn't use it */
+ struct {
+ u_int8_t tag;
+ u_int8_t len;
+ } mobile_alloc;
+#endif
+} __attribute__ ((packed));
+
+/* Chapter 9.3.30 */
+#define RSL_SYSTEM_INFO_8 0x00
+#define RSL_SYSTEM_INFO_1 0x01
+#define RSL_SYSTEM_INFO_2 0x02
+#define RSL_SYSTEM_INFO_3 0x03
+#define RSL_SYSTEM_INFO_4 0x04
+#define RSL_SYSTEM_INFO_5 0x05
+#define RSL_SYSTEM_INFO_6 0x06
+#define RSL_SYSTEM_INFO_7 0x07
+#define RSL_SYSTEM_INFO_16 0x08
+#define RSL_SYSTEM_INFO_17 0x09
+#define RSL_SYSTEM_INFO_2bis 0x0a
+#define RSL_SYSTEM_INFO_2ter 0x0b
+#define RSL_SYSTEM_INFO_5bis 0x0d
+#define RSL_SYSTEM_INFO_5ter 0x0e
+#define RSL_SYSTEM_INFO_10 0x0f
+#define REL_EXT_MEAS_ORDER 0x47
+#define RSL_MEAS_INFO 0x48
+#define RSL_SYSTEM_INFO_13 0x28
+#define RSL_SYSTEM_INFO_2quater 0x29
+#define RSL_SYSTEM_INFO_9 0x2a
+#define RSL_SYSTEM_INFO_18 0x2b
+#define RSL_SYSTEM_INFO_19 0x2c
+#define RSL_SYSTEM_INFO_20 0x2d
+
+/* Chapter 9.3.40 */
+#define RSL_CHANNEED_ANY 0x00
+#define RSL_CHANNEED_SDCCH 0x01
+#define RSL_CHANNEED_TCH_F 0x02
+#define RSL_CHANNEED_TCH_ForH 0x03
+
+
+#include "msgb.h"
+
+int rsl_bcch_info(struct gsm_bts *bts, u_int8_t type,
+ const u_int8_t *data, int len);
+int rsl_sacch_filling(struct gsm_bts *bts, u_int8_t type,
+ const u_int8_t *data, int len);
+int rsl_chan_activate(struct gsm_bts *bts, u_int8_t chan_nr,
+ u_int8_t act_type,
+ struct rsl_ie_chan_mode *chan_mode,
+ struct rsl_ie_chan_ident *chan_ident,
+ u_int8_t bs_power, u_int8_t ms_power,
+ u_int8_t ta);
+int rsl_chan_activate_tch_f(struct gsm_bts_trx_ts *ts);
+int rsl_chan_activate_sdcch(struct gsm_bts_trx_ts *ts);
+int rsl_chan_release(struct gsm_bts_trx_ts *ts, u_int8_t chan_nr);
+int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
+ u_int8_t *ms_ident, u_int8_t chan_needed);
+int rsl_paging_cmd_imsi(struct gsm_bts *bts, u_int8_t chan_needed, const char *imsi_str);
+int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val);
+int rsl_data_request(struct gsm_bts *bts, struct msgb *msg);
+
+int abis_rsl_rx(struct msgb *msg);
+
+#endif /* RSL_MT_H */
+
diff --git a/include/openbsc/debug.h b/include/openbsc/debug.h
new file mode 100644
index 000000000..c1db120a9
--- /dev/null
+++ b/include/openbsc/debug.h
@@ -0,0 +1,15 @@
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#define DRLL 0x0001
+#define DCC 0x0002
+#define DMM 0x0004
+#define DRR 0x0008
+
+#ifdef DEBUG
+#define DEBUGP(ss, args, ...) debugp(ss, args, ...)
+#else
+#define DEBUGP(xss, args, ...)
+#endif
+
+#endif /* _DEBUG_H */
diff --git a/include/openbsc/gsm_04_08.h b/include/openbsc/gsm_04_08.h
new file mode 100644
index 000000000..7c51969dc
--- /dev/null
+++ b/include/openbsc/gsm_04_08.h
@@ -0,0 +1,238 @@
+#ifndef _GSM_04_08_H
+#define _GSM_04_08_H
+
+/* GSM TS 04.08 definitions */
+
+/* Chapter 10.5.2.5 */
+struct gsm48_chan_desc {
+ u_int8_t chan_nr;
+ union {
+ struct {
+ u_int8_t maio_high:4,
+ h:1,
+ tsc:3;
+ u_int8_t hsn:6,
+ maio_low:2;
+ } h1;
+ struct {
+ u_int8_t arfcn_high:2,
+ spare:2,
+ h:1,
+ tsc:3;
+ u_int8_t arfcn_low;
+ } h0;
+ };
+};
+
+/* Chapter 10.5.2.30 */
+struct gsm48_req_ref {
+ u_int8_t ra;
+ u_int8_t t3_high:3,
+ t1_:5;
+ u_int8_t t2:5,
+ t3_low:3;
+};
+
+/* Chapter 9.1.18 */
+struct gsm48_imm_ass {
+ u_int8_t l2_plen;
+ u_int8_t proto_discr;
+ u_int8_t msg_type;
+ u_int8_t page_mode;
+ struct gsm48_chan_desc chan_desc;
+ struct gsm48_req_ref req_ref;
+ u_int8_t timing_advance;
+ u_int8_t mob_alloc_len;
+ u_int8_t mob_alloc[0];
+};
+
+struct gsm48_loc_area_id {
+ u_int8_t digits[3]; /* BCD! */
+ u_int16_t lac;
+} __attribute__ ((packed));
+
+/* Section 9.2.15 */
+struct gsm48_loc_upd_req {
+ u_int8_t type:4,
+ key_seq:4;
+ struct gsm48_loc_area_id lai;
+ u_int8_t classmark1;
+ u_int8_t ie_mi;
+ u_int8_t mi_len;
+ u_int8_t mi[0];
+} __attribute__ ((packed));
+
+/* Section 10.1 */
+struct gsm48_hdr {
+ u_int8_t proto_discr;
+ u_int8_t msg_type;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* Section 10.2 */
+#define GSM48_PDISC_CC 0x02
+#define GSM48_PDISC_MM 0x05
+#define GSM48_PDISC_RR 0x06
+#define GSM48_PDISC_MM_GPRS 0x08
+#define GSM48_PDISC_SM 0x0a
+
+/* Section 10.4 */
+#define GSM48_MT_RR_INIT_REQ 0x3c
+#define GSM48_MT_RR_ADD_ASS 0x3b
+#define GSM48_MT_RR_IMM_ASS 0x3f
+#define GSM48_MT_RR_IMM_ASS_EXT 0x39
+#define GSM48_MT_RR_IMM_ASS_REJ 0x3a
+
+#define GSM48_MT_RR_CIPH_M_CMD 0x35
+#define GSM48_MT_RR_CIPH_M_COMPL 0x32
+
+#define GSM48_MT_RR_CFG_CHG_CMD 0x30
+#define GSM48_MT_RR_CFG_CHG_ACK 0x31
+#define GSM48_MT_RR_CFG_CHG_REJ 0x33
+
+#define GSM48_MT_RR_ASS_CMD 0x2e
+#define GSM48_MT_RR_ASS_COMPL 0x29
+#define GSM48_MT_RR_ASS_FAIL 0x2f
+#define GSM48_MT_RR_HANDO_CMD 0x2b
+#define GSM48_MT_RR_HANDO_COMPL 0x2c
+#define GSM48_MT_RR_HANDO_FAIL 0x28
+#define GSM48_MT_RR_HANDO_INFO 0x2d
+
+#define GSM48_MT_RR_CELL_CHG_ORDER 0x08
+#define GSM48_MT_RR_PDCH_ASS_CMD 0x23
+
+#define GSM48_MT_RR_CHAN_REL 0x0d
+#define GSM48_MT_RR_PART_REL 0x0a
+#define GSM48_MT_RR_PART_REL_COMP 0x0f
+
+#define GSM48_MT_RR_PAG_REQ_1 0x21
+#define GSM48_MT_RR_PAG_REQ_2 0x22
+#define GSM48_MT_RR_PAG_REQ_3 0x24
+#define GSM48_MT_RR_PAG_RESP 0x27
+#define GSM48_MT_RR_NOTIF_NCH 0x20
+#define GSM48_MT_RR_NOTIF_FACCH 0x25
+#define GSM48_MT_RR_NOTIF_RESP 0x26
+
+#define GSM48_MT_RR_SYSINFO_8 0x18
+#define GSM48_MT_RR_SYSINFO_1 0x19
+#define GSM48_MT_RR_SYSINFO_2 0x1a
+#define GSM48_MT_RR_SYSINFO_3 0x1b
+#define GSM48_MT_RR_SYSINFO_4 0x1c
+#define GSM48_MT_RR_SYSINFO_5 0x1d
+#define GSM48_MT_RR_SYSINFO_6 0x1e
+#define GSM48_MT_RR_SYSINFO_7 0x1f
+
+#define GSM48_MT_RR_SYSINFO_2bis 0x02
+#define GSM48_MT_RR_SYSINFO_2ter 0x03
+#define GSM48_MT_RR_SYSINFO_5bis 0x05
+#define GSM48_MT_RR_SYSINFO_5ter 0x06
+#define GSM48_MT_RR_SYSINFO_9 0x04
+#define GSM48_MT_RR_SYSINFO_13 0x00
+
+#define GSM48_MT_RR_SYSINFO_16 0x3d
+#define GSM48_MT_RR_SYSINFO_17 0x3e
+
+#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10
+#define GSM48_MT_RR_STATUS 0x12
+#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17
+#define GSM48_MT_RR_FREQ_REDEF 0x14
+#define GSM48_MT_RR_MEAS_REP 0x15
+#define GSM48_MT_RR_CLSM_CHG 0x16
+#define GSM48_MT_RR_CLSM_ENQ 0x13
+#define GSM48_MT_RR_EXT_MEAS_REP 0x36
+#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37
+#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34
+
+#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08
+#define GSM48_MT_RR_UPLINK_RELEASE 0x0e
+#define GSM48_MT_RR_UPLINK_FREE 0x0c
+#define GSM48_MT_RR_UPLINK_BUSY 0x2a
+#define GSM48_MT_RR_TALKER_IND 0x11
+
+#define GSM48_MT_RR_APP_INFO 0x38
+
+/* Table 10.2/3GPP TS 04.08 */
+#define GSM48_MT_MM_IMSI_DETACH_IND 0x01
+#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02
+#define GSM48_MT_MM_LOC_UPD_REJECT 0x04
+#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08
+
+#define GSM48_MT_MM_AUTH_REJ 0x11
+#define GSM48_MT_MM_AUTH_REQ 0x12
+#define GSM48_MT_MM_AUTH_RESP 0x14
+#define GSM48_MT_MM_ID_REQ 0x18
+#define GSM48_MT_MM_ID_RESP 0x19
+#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a
+#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b
+
+#define GSM48_MT_MM_CM_SERV_ACC 0x21
+#define GSM48_MT_MM_CM_SERV_REJ 0x22
+#define GSM48_MT_MM_CM_SERV_ABORT 0x23
+#define GSM48_MT_MM_CM_SERV_REQ 0x24
+#define GSM48_MT_MM_CM_SERV_PROMPT 0x25
+#define GSM48_MT_MM_CM_REEST_REQ 0x28
+#define GSM48_MT_MM_ABORT 0x29
+
+#define GSM48_MT_MM_NULL 0x30
+#define GSM48_MT_MM_STATUS 0x31
+#define GSM48_MT_MM_INFO 0x32
+
+/* Table 10.3/3GPP TS 04.08 */
+#define GSM48_MT_CC_ALERTING 0x01
+#define GSM48_MT_CC_CALL_CONF 0x08
+#define GSM48_MT_CC_CALL_PROC 0x02
+#define GSM48_MT_CC_CONNECT 0x07
+#define GSM48_MT_CC_CONNECT_ACK 0x0f
+#define GSM48_MT_CC_EMERG_SETUP 0x0e
+#define GSM48_MT_CC_PROGRESS 0x03
+#define GSM48_MT_CC_ESTAB 0x04
+#define GSM48_MT_CC_ESTAB_CONF 0x06
+#define GSM48_MT_CC_RECALL 0x0b
+#define GSM48_MT_CC_START_CC 0x09
+#define GSM48_MT_CC_SETUP 0x05
+
+#define GSM48_MT_CC_MODIFY 0x17
+#define GSM48_MT_CC_MODIFY_COMPL 0x1f
+#define GSM48_MT_CC_MODIFY_REJECT 0x13
+#define GSM48_MT_CC_USER_INFO 0x10
+#define GSM48_MT_CC_HOLD 0x18
+#define GSM48_MT_CC_HOLD_ACK 0x19
+#define GSM48_MT_CC_HOLD_REJ 0x1a
+#define GSM48_MT_CC_RETR 0x1c
+#define GSM48_MT_CC_RETR_ACK 0x1d
+#define GSM48_MT_CC_RETR_REJ 0x1e
+
+#define GSM48_MT_CC_DISCONNECT 0x25
+#define GSM48_MT_CC_RELEASE 0x2d
+#define GSM48_MT_CC_RELEASE_COMPL 0xea
+
+#define GSM48_MT_CC_CONG_CTRL 0x39
+#define GSM48_MT_CC_NOTIFY 0x3e
+#define GSM48_MT_CC_STATUS 0x3d
+#define GSM48_MT_CC_STATUS_ENQ 0x34
+#define GSM48_MT_CC_START_DTMF 0x35
+#define GSM48_MT_CC_STOP_DTMF 0x31
+#define GSM48_MT_CC_STOP_DTMF_ACK 0x32
+#define GSM48_MT_CC_START_DTMF_ACK 0x36
+#define GSM48_MT_CC_START_DTMF_REJ 0x37
+#define GSM48_MT_CC_FACILITY 0x3a
+
+/* FIXME: Table 10.4 / 10.4a (GPRS) */
+
+/* Section 10.5.2.26, Table 10.5.64 */
+#define GSM48_PM_MASK 0x03
+#define GSM48_PM_NORMAL 0x00
+#define GSM48_PM_EXTENDED 0x01
+#define GSM48_PM_REORG 0x02
+#define GSM48_PM_SAME 0x03
+
+/* Table 10.5.4 */
+#define GSM_MI_TYPE_MASK 0x07
+#define GSM_MI_TYPE_NONE 0x00
+#define GSM_MI_TYPE_IMSI 0x01
+#define GSM_MI_TYPE_IMEI 0x02
+#define GSM_MI_TYPE_IMEISV 0x03
+#define GSM_MI_TYPE_TMSI 0x04
+#define GSM_MI_ODD 0x08
+
+#endif
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
new file mode 100644
index 000000000..51e246c2d
--- /dev/null
+++ b/include/openbsc/gsm_data.h
@@ -0,0 +1,74 @@
+#ifndef _GSM_DATA_H
+#define _GSM_DATA_H
+
+#include <sys/types.h>
+
+#define GSM_MAX_BTS 8
+#define BTS_MAX_TRX 8
+
+#define HARDCODED_ARFCN 123
+
+/* communications link with a BTS */
+struct gsm_bts_link {
+ struct gsm_bts *bts;
+};
+
+#define BTS_TRX_F_ACTIVATED 0x0001
+/* One Timeslot in a TRX */
+struct gsm_bts_trx_ts {
+ struct gsm_bts_trx *trx;
+ /* number of this timeslot at the TRX */
+ u_int8_t nr;
+
+ unsigned int flags;
+};
+
+/* One TRX in a BTS */
+struct gsm_bts_trx {
+ struct gsm_bts *bts;
+ /* number of this TRX in the BTS */
+ u_int8_t nr;
+
+ u_int16_t arfcn;
+ struct gsm_bts_trx_ts ts[8];
+};
+
+/* One BTS */
+struct gsm_bts {
+ struct gsm_network *network;
+ /* number of ths BTS in network */
+ u_int8_t nr;
+ /* location area code of this BTS */
+ u_int8_t location_area_code;
+
+ /* Abis network management O&M handle */
+ struct abis_nm_h *nmh;
+ /* number of this BTS on given E1 link */
+ u_int8_t bts_nr;
+
+ /* CCCH is on C0 */
+ struct gsm_bts_trx *c0;
+ /* transceivers */
+ int num_trx;
+ struct gsm_bts_trx trx[BTS_MAX_TRX+1];
+};
+
+struct gsm_ms {
+ unsigned long imei;
+};
+
+struct gsm_network {
+ /* global parameters */
+ u_int8_t country_code;
+ u_int8_t network_code;
+
+ unsigned int num_bts;
+ /* private lists */
+ struct gsm_bts bts[GSM_MAX_BTS+1];
+ struct gsm_ms *ms;
+ struct gsm_subscriber *subscriber;
+};
+
+struct gsm_network *gsm_network_init(unsigned int num_bts, u_int8_t country_code,
+ u_int8_t network_code);
+#endif
diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h
new file mode 100644
index 000000000..d5c6eff7a
--- /dev/null
+++ b/include/openbsc/gsm_subscriber.h
@@ -0,0 +1,16 @@
+#ifndef _GSM_SUBSCR_H
+#define _GSM_SUBSCR_H
+
+#include <sys/types.h>
+#include "gsm_data.h"
+
+struct gsm_subscriber {
+ u_int8_t *name;
+ u_int8_t tmsi[4];
+};
+
+struct gsm_subscriber *subscr_get_by_tmsi(u_int8_t *tmsi);
+struct gsm_subscriber *subscr_get_by_imsi(u_int8_t *imsi);
+int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts);
+
+#endif /* _GSM_SUBSCR_H */
diff --git a/include/openbsc/linuxlist.h b/include/openbsc/linuxlist.h
new file mode 100644
index 000000000..a89375e2d
--- /dev/null
+++ b/include/openbsc/linuxlist.h
@@ -0,0 +1,360 @@
+#ifndef _LINUX_LLIST_H
+#define _LINUX_LLIST_H
+
+#include <stddef.h>
+
+#ifndef inline
+#define inline __inline__
+#endif
+
+static inline void prefetch(const void *x) {;}
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized llist entries.
+ */
+#define LLIST_POISON1 ((void *) 0x00100100)
+#define LLIST_POISON2 ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked llist implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole llists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct llist_head {
+ struct llist_head *next, *prev;
+};
+
+#define LLIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LLIST_HEAD(name) \
+ struct llist_head name = LLIST_HEAD_INIT(name)
+
+#define INIT_LLIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_add(struct llist_head *new,
+ struct llist_head *prev,
+ struct llist_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * llist_add - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void llist_add(struct llist_head *new, struct llist_head *head)
+{
+ __llist_add(new, head, head->next);
+}
+
+/**
+ * llist_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void llist_add_tail(struct llist_head *new, struct llist_head *head)
+{
+ __llist_add(new, head->prev, head);
+}
+
+/*
+ * Delete a llist entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * llist_del - deletes entry from llist.
+ * @entry: the element to delete from the llist.
+ * Note: llist_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void llist_del(struct llist_head *entry)
+{
+ __llist_del(entry->prev, entry->next);
+ entry->next = LLIST_POISON1;
+ entry->prev = LLIST_POISON2;
+}
+
+/**
+ * llist_del_init - deletes entry from llist and reinitialize it.
+ * @entry: the element to delete from the llist.
+ */
+static inline void llist_del_init(struct llist_head *entry)
+{
+ __llist_del(entry->prev, entry->next);
+ INIT_LLIST_HEAD(entry);
+}
+
+/**
+ * llist_move - delete from one llist and add as another's head
+ * @llist: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void llist_move(struct llist_head *llist, struct llist_head *head)
+{
+ __llist_del(llist->prev, llist->next);
+ llist_add(llist, head);
+}
+
+/**
+ * llist_move_tail - delete from one llist and add as another's tail
+ * @llist: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void llist_move_tail(struct llist_head *llist,
+ struct llist_head *head)
+{
+ __llist_del(llist->prev, llist->next);
+ llist_add_tail(llist, head);
+}
+
+/**
+ * llist_empty - tests whether a llist is empty
+ * @head: the llist to test.
+ */
+static inline int llist_empty(const struct llist_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __llist_splice(struct llist_head *llist,
+ struct llist_head *head)
+{
+ struct llist_head *first = llist->next;
+ struct llist_head *last = llist->prev;
+ struct llist_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * llist_splice - join two llists
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ */
+static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
+{
+ if (!llist_empty(llist))
+ __llist_splice(llist, head);
+}
+
+/**
+ * llist_splice_init - join two llists and reinitialise the emptied llist.
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ *
+ * The llist at @llist is reinitialised
+ */
+static inline void llist_splice_init(struct llist_head *llist,
+ struct llist_head *head)
+{
+ if (!llist_empty(llist)) {
+ __llist_splice(llist, head);
+ INIT_LLIST_HEAD(llist);
+ }
+}
+
+/**
+ * llist_entry - get the struct for this entry
+ * @ptr: the &struct llist_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * llist_for_each - iterate over a llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+
+/**
+ * __llist_for_each - iterate over a llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ *
+ * This variant differs from llist_for_each() in that it's the
+ * simplest possible llist iteration code, no prefetching is done.
+ * Use this for code that knows the llist to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __llist_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * llist_for_each_prev - iterate over a llist backwards
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_prev(pos, head) \
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+
+/**
+ * llist_for_each_safe - iterate over a llist safe against removal of llist entry
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @n: another &struct llist_head to use as temporary storage
+ * @head: the head for your llist.
+ */
+#define llist_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * llist_for_each_entry - iterate over llist of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry(pos, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_reverse - iterate backwards over llist of given type.
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_reverse(pos, head, member) \
+ for (pos = llist_entry((head)->prev, typeof(*pos), member), \
+ prefetch(pos->member.prev); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.prev, typeof(*pos), member), \
+ prefetch(pos->member.prev))
+
+/**
+ * llist_for_each_entry_continue - iterate over llist of given type
+ * continuing after existing point
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_continue(pos, head, member) \
+ for (pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ n = llist_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = llist_entry(n->member.next, typeof(*n), member))
+
+/**
+ * llist_for_each_rcu - iterate over an rcu-protected llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_rcu(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
+
+#define __llist_for_each_rcu(pos, head) \
+ for (pos = (head)->next; pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
+
+/**
+ * llist_for_each_safe_rcu - iterate over an rcu-protected llist safe
+ * against removal of llist entry
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @n: another &struct llist_head to use as temporary storage
+ * @head: the head for your llist.
+ */
+#define llist_for_each_safe_rcu(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
+
+/**
+ * llist_for_each_entry_rcu - iterate over rcu llist of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_rcu(pos, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ ({ smp_read_barrier_depends(); 0;}), \
+ prefetch(pos->member.next))
+
+
+/**
+ * llist_for_each_continue_rcu - iterate over an rcu-protected llist
+ * continuing after existing point.
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_continue_rcu(pos, head) \
+ for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
+ (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
+
+
+#endif
diff --git a/include/openbsc/msgb.h b/include/openbsc/msgb.h
new file mode 100644
index 000000000..b0740edab
--- /dev/null
+++ b/include/openbsc/msgb.h
@@ -0,0 +1,74 @@
+#ifndef _MSGB_H
+#define _MSGB_H
+
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * 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.
+ *
+ */
+
+struct bts_link;
+
+struct msgb {
+ /* ptr to the incoming (RX) or outgoing (TX) BTS link */
+ struct gsm_bts_link *bts_link;
+
+ u_int8_t l2_off;
+ u_int8_t l3_off;
+
+ u_int16_t data_len;
+ u_int16_t len;
+
+ unsigned char *head;
+ unsigned char *tail;
+ unsigned char *data;
+ unsigned char _data[0];
+};
+
+extern struct msgb *msgb_alloc(u_int16_t size);
+extern void msgb_free(struct msgb *m);
+
+#define msgb_l2(m) ((void *)(m->data + m->l2_off))
+#define msgb_l3(m) ((void *)(m->data + m->l3_off))
+
+static inline unsigned int msgb_headlen(const struct msgb *msgb)
+{
+ return msgb->len - msgb->data_len;
+}
+static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
+{
+ unsigned char *tmp = msgb->tail;
+ msgb->tail += len;
+ msgb->len += len;
+ return tmp;
+}
+static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
+{
+ msgb->data -= len;
+ msgb->len += len;
+ return msgb->data;
+}
+static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
+{
+ msgb->len -= len;
+ return msgb->data += len;
+}
+static inline int msgb_tailroom(const struct msgb *msgb)
+{
+ return (msgb->data + msgb->data_len) - msgb->tail;
+}
+
+#endif /* _MSGB_H */
diff --git a/include/openbsc/select.h b/include/openbsc/select.h
new file mode 100644
index 000000000..f98f72c61
--- /dev/null
+++ b/include/openbsc/select.h
@@ -0,0 +1,17 @@
+#ifndef _BSC_SELECT_H
+#define _BSC_SELECT_H
+
+#define BSC_FD_READ 0x0001
+#define BSC_FD_WRITE 0x0002
+#define BSC_FD_EXCEPT 0x0004
+
+struct bsc_fd {
+ struct llist_head list;
+ int fd;
+ unsigned int when;
+ int (*cb)(struct bsc_fd *fd, unsigned int what);
+ void *data;
+ unsigned int priv_nr;
+};
+
+#endif /* _BSC_SELECT_H */
diff --git a/include/openbsc/tlv.h b/include/openbsc/tlv.h
new file mode 100644
index 000000000..4c007725d
--- /dev/null
+++ b/include/openbsc/tlv.h
@@ -0,0 +1,66 @@
+#ifndef _TLV_H
+#define _TLV_H
+
+#include <sys/types.h>
+#include <string.h>
+
+#define TLV_GROSS_LEN(x) (x+2)
+#define TLV16_GROSS_LEN(x) ((2*x)+2)
+
+static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
+ const u_int8_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len;
+ memcpy(buf, val, len);
+ return buf + len;
+}
+
+static inline u_int8_t *tlv16_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
+ const u_int16_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len;
+ memcpy(buf, val, len*2);
+ return buf + len*2;
+}
+
+static inline u_int8_t *msgb_tlv16_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int16_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
+ return tlv16_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag,
+ u_int8_t val)
+{
+ *buf++ = tag;
+ *buf++ = val;
+ return buf;
+}
+
+static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
+ return tlv_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tv_put(struct msgb *msg, u_int8_t tag, u_int8_t val)
+{
+ u_int8_t *buf = msgb_put(msg, 2);
+ return tv_put(buf, tag, val);
+}
+
+static inline u_int8_t *msgb_tlv_push(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
+ return tlv_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tv_push(struct msgb *msg, u_int8_t tag, u_int8_t val)
+{
+ u_int8_t *buf = msgb_push(msg, 2);
+ return tv_put(buf, tag, val);
+}
+
+#endif /* _TLV_H */