summaryrefslogtreecommitdiffstats
path: root/apps/osmocomBB/libosmocore/include/osmocom/core
diff options
context:
space:
mode:
Diffstat (limited to 'apps/osmocomBB/libosmocore/include/osmocom/core')
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/application.h23
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/backtrace.h7
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/bits.h78
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/bitvec.h70
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/conv.h146
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/crc16.h34
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/crcXXgen.h.tpl59
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/crcgen.h41
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap.h166
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap_util.h57
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/linuxlist.h360
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/linuxrbtree.h160
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/logging.h214
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/msgb.h401
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/msgfile.h49
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/panic.h20
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/plugin.h6
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/prim.h58
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/process.h2
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/rate_ctr.h88
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/select.h45
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/serial.h43
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/signal.h46
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/socket.h35
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/statistics.h53
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/talloc.h192
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/timer.h89
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/timer_compat.h79
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/utils.h56
-rw-r--r--apps/osmocomBB/libosmocore/include/osmocom/core/write_queue.h63
30 files changed, 2740 insertions, 0 deletions
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/application.h b/apps/osmocomBB/libosmocore/include/osmocom/core/application.h
new file mode 100644
index 0000000000..34571698af
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/application.h
@@ -0,0 +1,23 @@
+#ifndef OSMO_APPLICATION_H
+#define OSMO_APPLICATION_H
+
+/*!
+ * \file application.h
+ * \brief Routines for helping with the osmocom application setup.
+ */
+
+/*! \brief information containing the available logging subsystems */
+struct log_info;
+
+/*! \brief one instance of a logging target (file, stderr, ...) */
+struct log_target;
+
+/*! \brief the default logging target, logging to stderr */
+extern struct log_target *osmo_stderr_target;
+
+void osmo_init_ignore_signals(void);
+int osmo_init_logging(const struct log_info *);
+
+int osmo_daemonize(void);
+
+#endif
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/backtrace.h b/apps/osmocomBB/libosmocore/include/osmocom/core/backtrace.h
new file mode 100644
index 0000000000..a24290c5ca
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/backtrace.h
@@ -0,0 +1,7 @@
+#ifndef _OSMO_BACKTRACE_H_
+#define _OSMO_BACKTRACE_H_
+
+void osmo_generate_backtrace(void);
+void osmo_log_backtrace(int subsys, int level);
+
+#endif
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/bits.h b/apps/osmocomBB/libosmocore/include/osmocom/core/bits.h
new file mode 100644
index 0000000000..4c685321b5
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/bits.h
@@ -0,0 +1,78 @@
+#ifndef _OSMO_BITS_H
+#define _OSMO_BITS_H
+
+#include <stdint.h>
+
+/*! \defgroup bits soft, unpacked and packed bits
+ * @{
+ */
+
+/*! \file bits.h
+ * \brief Osmocom bit level support code
+ */
+
+typedef int8_t sbit_t; /*!< \brief soft bit (-127...127) */
+typedef uint8_t ubit_t; /*!< \brief unpacked bit (0 or 1) */
+typedef uint8_t pbit_t; /*!< \brief packed bis (8 bits in a byte) */
+
+/*
+ NOTE on the endianess of pbit_t:
+ Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit.
+ Bit i in a pbit_t array is array[i/8] & (1<<(7-i%8))
+*/
+
+/*! \brief determine how many bytes we would need for \a num_bits packed bits
+ * \param[in] num_bits Number of packed bits
+ */
+static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits)
+{
+ unsigned int pbit_bytesize = num_bits / 8;
+
+ if (num_bits % 8)
+ pbit_bytesize++;
+
+ return pbit_bytesize;
+}
+
+int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits);
+
+int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits);
+
+int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
+ const ubit_t *in, unsigned int in_ofs,
+ unsigned int num_bits, int lsb_mode);
+
+int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
+ const pbit_t *in, unsigned int in_ofs,
+ unsigned int num_bits, int lsb_mode);
+
+
+/* BIT REVERSAL */
+
+/*! \brief bit-reversal mode for osmo_bit_reversal() */
+enum osmo_br_mode {
+ /*! \brief reverse all bits in a 32bit dword */
+ OSMO_BR_BITS_IN_DWORD = 31,
+ /*! \brief reverse byte order in a 32bit dword */
+ OSMO_BR_BYTES_IN_DWORD = 24,
+ /*! \brief reverse bits of each byte in a 32bit dword */
+ OSMO_BR_BITS_IN_BYTE = 7,
+ /*! \brief swap the two 16bit words in a 32bit dword */
+ OSMO_BR_WORD_SWAP = 16,
+};
+
+/*! \brief generic bit reversal function */
+uint32_t osmo_bit_reversal(uint32_t x, enum osmo_br_mode k);
+
+/* \brief reverse the bits within each byte of a 32bit word */
+uint32_t osmo_revbytebits_32(uint32_t x);
+
+/* \brief reverse the bits within a byte */
+uint32_t osmo_revbytebits_8(uint8_t x);
+
+/* \brief reverse the bits of each byte in a given buffer */
+void osmo_revbytebits_buf(uint8_t *buf, int len);
+
+/*! @} */
+
+#endif /* _OSMO_BITS_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/bitvec.h b/apps/osmocomBB/libosmocore/include/osmocom/core/bitvec.h
new file mode 100644
index 0000000000..9c000d0219
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/bitvec.h
@@ -0,0 +1,70 @@
+#ifndef _BITVEC_H
+#define _BITVEC_H
+
+/* bit vector utility routines */
+
+/* (C) 2009 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.
+ *
+ */
+
+/*! \defgroup bitvec Bit vectors
+ * @{
+ */
+
+/*! \file bitvec.h
+ * \brief Osmocom bit vector abstraction
+ */
+
+#include <stdint.h>
+
+/*! \brief A single GSM bit
+ *
+ * In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are
+ * defined relative to the 0x2b padding pattern */
+enum bit_value {
+ ZERO = 0, /*!< \brief A zero (0) bit */
+ ONE = 1, /*!< \brief A one (1) bit */
+ L = 2, /*!< \brief A CSN.1 "L" bit */
+ H = 3, /*!< \brief A CSN.1 "H" bit */
+};
+
+/*! \brief structure describing a bit vector */
+struct bitvec {
+ unsigned int cur_bit; /*!< \brief curser to the next unused bit */
+ unsigned int data_len; /*!< \brief length of data array in bytes */
+ uint8_t *data; /*!< \brief pointer to data array */
+};
+
+enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr);
+enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv,
+ unsigned int bitnr);
+unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n);
+int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
+ enum bit_value bit);
+int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
+int bitvec_get_bit_high(struct bitvec *bv);
+int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
+int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
+int bitvec_get_uint(struct bitvec *bv, int num_bits);
+int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val);
+int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
+
+/*! @} */
+
+#endif /* _BITVEC_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/conv.h b/apps/osmocomBB/libosmocore/include/osmocom/core/conv.h
new file mode 100644
index 0000000000..e5b2a97568
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/conv.h
@@ -0,0 +1,146 @@
+/*
+ * conv.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.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.
+ */
+
+/*! \defgroup conv Convolutional encoding and decoding routines
+ * @{
+ */
+
+/*! \file conv.h
+ * \file Osmocom convolutional encoder and decoder
+ */
+
+#ifndef __OSMO_CONV_H__
+#define __OSMO_CONV_H__
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+
+/*! \brief possibe termination types
+ *
+ * The termination type will determine which state the encoder/decoder
+ * can start/end with. This is mostly taken care of in the high level API
+ * call. So if you use the low level API, you must take care of making the
+ * proper calls yourself.
+ */
+enum osmo_conv_term {
+ CONV_TERM_FLUSH = 0, /*!< \brief Flush encoder state */
+ CONV_TERM_TRUNCATION, /*!< \brief Direct truncation */
+ CONV_TERM_TAIL_BITING, /*!< \brief Tail biting */
+};
+
+/*! \brief structure describing a given convolutional code
+ *
+ * The only required fields are N,K and the next_output/next_state arrays. The
+ * other can be left to default value of zero depending on what the code does.
+ * If 'len' is left at 0 then only the low level API can be used.
+ */
+struct osmo_conv_code {
+ int N; /*!< \brief Inverse of code rate */
+ int K; /*!< \brief Constraint length */
+ int len; /*!< \brief # of data bits */
+
+ enum osmo_conv_term term; /*!< \brief Termination type */
+
+ const uint8_t (*next_output)[2];/*!< \brief Next output array */
+ const uint8_t (*next_state)[2]; /*!< \brief Next state array */
+
+ const uint8_t *next_term_output;/*!< \brief Flush termination output */
+ const uint8_t *next_term_state; /*!< \brief Flush termination state */
+
+ const int *puncture; /*!< \brief Punctured bits indexes */
+};
+
+
+/* Common */
+
+int osmo_conv_get_input_length(const struct osmo_conv_code *code, int len);
+int osmo_conv_get_output_length(const struct osmo_conv_code *code, int len);
+
+
+/* Encoding */
+
+ /* Low level API */
+
+/*! \brief convolutional encoder state */
+struct osmo_conv_encoder {
+ const struct osmo_conv_code *code; /*!< \brief for which code? */
+ int i_idx; /*!< \brief Next input bit index */
+ int p_idx; /*!< \brief Current puncture index */
+ uint8_t state; /*!< \brief Current state */
+};
+
+void osmo_conv_encode_init(struct osmo_conv_encoder *encoder,
+ const struct osmo_conv_code *code);
+void osmo_conv_encode_load_state(struct osmo_conv_encoder *encoder,
+ const ubit_t *input);
+int osmo_conv_encode_raw(struct osmo_conv_encoder *encoder,
+ const ubit_t *input, ubit_t *output, int n);
+int osmo_conv_encode_flush(struct osmo_conv_encoder *encoder, ubit_t *output);
+
+ /* All-in-one */
+int osmo_conv_encode(const struct osmo_conv_code *code,
+ const ubit_t *input, ubit_t *output);
+
+
+/* Decoding */
+
+ /* Low level API */
+
+/*! \brief convolutional decoder state */
+struct osmo_conv_decoder {
+ const struct osmo_conv_code *code; /*!< \brief for which code? */
+
+ int n_states; /*!< \brief number of states */
+
+ int len; /*!< \brief Max o_idx (excl. termination) */
+
+ int o_idx; /*!< \brief output index */
+ int p_idx; /*!< \brief puncture index */
+
+ unsigned int *ae; /*!< \brief accumulated error */
+ unsigned int *ae_next; /*!< \brief next accumulated error (tmp in scan) */
+ uint8_t *state_history; /*!< \brief state history [len][n_states] */
+};
+
+void osmo_conv_decode_init(struct osmo_conv_decoder *decoder,
+ const struct osmo_conv_code *code,
+ int len, int start_state);
+void osmo_conv_decode_reset(struct osmo_conv_decoder *decoder, int start_state);
+void osmo_conv_decode_rewind(struct osmo_conv_decoder *decoder);
+void osmo_conv_decode_deinit(struct osmo_conv_decoder *decoder);
+
+int osmo_conv_decode_scan(struct osmo_conv_decoder *decoder,
+ const sbit_t *input, int n);
+int osmo_conv_decode_flush(struct osmo_conv_decoder *decoder,
+ const sbit_t *input);
+int osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
+ ubit_t *output, int has_flush, int end_state);
+
+ /* All-in-one */
+int osmo_conv_decode(const struct osmo_conv_code *code,
+ const sbit_t *input, ubit_t *output);
+
+
+/*! @} */
+
+#endif /* __OSMO_CONV_H__ */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/crc16.h b/apps/osmocomBB/libosmocore/include/osmocom/core/crc16.h
new file mode 100644
index 0000000000..0e5241768d
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/crc16.h
@@ -0,0 +1,34 @@
+/*
+ * This was copied from the linux kernel and adjusted for our types.
+ */
+/*
+ * crc16.h - CRC-16 routine
+ *
+ * Implements the standard CRC-16:
+ * Width 16
+ * Poly 0x8005 (x^16 + x^15 + x^2 + 1)
+ * Init 0
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef __CRC16_H
+#define __CRC16_H
+
+#include <stdint.h>
+
+#include <sys/types.h>
+
+extern uint16_t const osmo_crc16_table[256];
+
+extern uint16_t osmo_crc16(uint16_t crc, const uint8_t *buffer, size_t len);
+
+static inline uint16_t osmo_crc16_byte(uint16_t crc, const uint8_t data)
+{
+ return (crc >> 8) ^ osmo_crc16_table[(crc ^ data) & 0xff];
+}
+
+#endif /* __CRC16_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/crcXXgen.h.tpl b/apps/osmocomBB/libosmocore/include/osmocom/core/crcXXgen.h.tpl
new file mode 100644
index 0000000000..89d083aeab
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/crcXXgen.h.tpl
@@ -0,0 +1,59 @@
+/*
+ * crcXXgen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.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.
+ */
+
+#ifndef __OSMO_CRCXXGEN_H__
+#define __OSMO_CRCXXGEN_H__
+
+/*! \addtogroup crcgen
+ * @{
+ */
+
+/*! \file crcXXgen.h
+ * \file Osmocom generic CRC routines (for max XX bits poly) header
+ */
+
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+
+/*! \brief structure describing a given CRC code of max XX bits */
+struct osmo_crcXXgen_code {
+ int bits; /*!< \brief Actual number of bits of the CRC */
+ uintXX_t poly; /*!< \brief Polynom (normal representation, MSB omitted */
+ uintXX_t init; /*!< \brief Initialization value of the CRC state */
+ uintXX_t remainder; /*!< \brief Remainder of the CRC (final XOR) */
+};
+
+uintXX_t osmo_crcXXgen_compute_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len);
+int osmo_crcXXgen_check_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len, const ubit_t *crc_bits);
+void osmo_crcXXgen_set_bits(const struct osmo_crcXXgen_code *code,
+ const ubit_t *in, int len, ubit_t *crc_bits);
+
+
+/*! @} */
+
+#endif /* __OSMO_CRCXXGEN_H__ */
+
+/* vim: set syntax=c: */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/crcgen.h b/apps/osmocomBB/libosmocore/include/osmocom/core/crcgen.h
new file mode 100644
index 0000000000..8e208a7482
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/crcgen.h
@@ -0,0 +1,41 @@
+/*
+ * crcgen.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.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.
+ */
+
+#ifndef __OSMO_CRCGEN_H__
+#define __OSMO_CRCGEN_H__
+
+/*! \defgroup crcgen Osmocom generic CRC routines
+ * @{
+ */
+
+/*! \file crcgen.h
+ * \file Osmocom generic CRC routines global header
+ */
+
+#include <osmocom/core/crc8gen.h>
+#include <osmocom/core/crc16gen.h>
+#include <osmocom/core/crc32gen.h>
+#include <osmocom/core/crc64gen.h>
+
+/*! @} */
+
+#endif /* __OSMO_CRCGEN_H__ */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap.h b/apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap.h
new file mode 100644
index 0000000000..0b647b28be
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap.h
@@ -0,0 +1,166 @@
+#ifndef _GSMTAP_H
+#define _GSMTAP_H
+
+/* gsmtap header, pseudo-header in front of the actua GSM payload */
+
+/* GSMTAP is a generic header format for GSM protocol captures,
+ * it uses the IANA-assigned UDP port number 4729 and carries
+ * payload in various formats of GSM interfaces such as Um MAC
+ * blocks or Um bursts.
+ *
+ * Example programs generating GSMTAP data are airprobe
+ * (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/)
+ */
+
+#include <stdint.h>
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* The GSMTAP format definition is maintained in libosmocore,
+ * specifically the latest version can always be obtained from
+ * http://cgit.osmocom.org/cgit/libosmocore/tree/include/osmocom/core/gsmtap.h
+ *
+ * If you want to introduce new protocol/burst/channel types or extend
+ * GSMTAP in any way, please contact the GSMTAP maintainer at either the
+ * public openbsc@lists.osmocom.org mailing list, or privately at
+ * Harald Welte <laforge@gnumonks.org>.
+ *
+ * Your cooperation ensures that all projects will use the same GSMTAP
+ * definitions and remain compatible with each other.
+ */
+
+#define GSMTAP_VERSION 0x02
+
+#define GSMTAP_TYPE_UM 0x01
+#define GSMTAP_TYPE_ABIS 0x02
+#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */
+#define GSMTAP_TYPE_SIM 0x04
+#define GSMTAP_TYPE_TETRA_I1 0x05 /* tetra air interface */
+#define GSMTAP_TYPE_TETRA_I1_BURST 0x06 /* tetra air interface */
+#define GSMTAP_TYPE_WMX_BURST 0x07 /* WiMAX burst */
+#define GSMTAP_TYPE_GB_LLC 0x08 /* GPRS Gb interface: LLC */
+#define GSMTAP_TYPE_GB_SNDCP 0x09 /* GPRS Gb interface: SNDCP */
+#define GSMTAP_TYPE_GMR1_UM 0x0a /* GMR-1 L2 packets */
+#define GSMTAP_TYPE_UMTS_RLC_MAC 0x0b
+#define GSMTAP_TYPE_UMTS_RRC 0x0c
+
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_UM_BURST */
+#define GSMTAP_BURST_UNKNOWN 0x00
+#define GSMTAP_BURST_FCCH 0x01
+#define GSMTAP_BURST_PARTIAL_SCH 0x02
+#define GSMTAP_BURST_SCH 0x03
+#define GSMTAP_BURST_CTS_SCH 0x04
+#define GSMTAP_BURST_COMPACT_SCH 0x05
+#define GSMTAP_BURST_NORMAL 0x06
+#define GSMTAP_BURST_DUMMY 0x07
+#define GSMTAP_BURST_ACCESS 0x08
+#define GSMTAP_BURST_NONE 0x09
+/* WiMAX bursts */
+#define GSMTAP_BURST_CDMA_CODE 0x10 /* WiMAX CDMA Code Attribute burst */
+#define GSMTAP_BURST_FCH 0x11 /* WiMAX FCH burst */
+#define GSMTAP_BURST_FFB 0x12 /* WiMAX Fast Feedback burst */
+#define GSMTAP_BURST_PDU 0x13 /* WiMAX PDU burst */
+#define GSMTAP_BURST_HACK 0x14 /* WiMAX HARQ ACK burst */
+#define GSMTAP_BURST_PHY_ATTRIBUTES 0x15 /* WiMAX PHY Attributes burst */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_UM */
+#define GSMTAP_CHANNEL_UNKNOWN 0x00
+#define GSMTAP_CHANNEL_BCCH 0x01
+#define GSMTAP_CHANNEL_CCCH 0x02
+#define GSMTAP_CHANNEL_RACH 0x03
+#define GSMTAP_CHANNEL_AGCH 0x04
+#define GSMTAP_CHANNEL_PCH 0x05
+#define GSMTAP_CHANNEL_SDCCH 0x06
+#define GSMTAP_CHANNEL_SDCCH4 0x07
+#define GSMTAP_CHANNEL_SDCCH8 0x08
+#define GSMTAP_CHANNEL_TCH_F 0x09
+#define GSMTAP_CHANNEL_TCH_H 0x0a
+#define GSMTAP_CHANNEL_PACCH 0x0b
+#define GSMTAP_CHANNEL_CBCH52 0x0c
+#define GSMTAP_CHANNEL_PDCH 0x0d
+#define GSMTAP_CHANNEL_PTCCH 0x0e
+#define GSMTAP_CHANNEL_CBCH51 0x0f
+
+/* GPRS Coding Scheme CS1..4 */
+#define GSMTAP_GPRS_CS_BASE 0x20
+#define GSMTAP_GPRS_CS(N) (GSMTAP_GPRS_CS_BASE + N)
+/* (E) GPRS Coding Scheme MCS0..9 */
+#define GSMTAP_GPRS_MCS_BASE 0x30
+#define GSMTAP_GPRS_MCS(N) (GSMTAP_GPRS_MCS_BASE + N)
+
+#define GSMTAP_CHANNEL_ACCH 0x80
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_TETRA_AIR */
+#define GSMTAP_TETRA_BSCH 0x01
+#define GSMTAP_TETRA_AACH 0x02
+#define GSMTAP_TETRA_SCH_HU 0x03
+#define GSMTAP_TETRA_SCH_HD 0x04
+#define GSMTAP_TETRA_SCH_F 0x05
+#define GSMTAP_TETRA_BNCH 0x06
+#define GSMTAP_TETRA_STCH 0x07
+#define GSMTAP_TETRA_TCH_F 0x08
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_GMR1_UM */
+#define GSMTAP_GMR1_UNKNOWN 0x00
+#define GSMTAP_GMR1_BCCH 0x01
+#define GSMTAP_GMR1_CCCH 0x02 /* either AGCH or PCH */
+#define GSMTAP_GMR1_PCH 0x03
+#define GSMTAP_GMR1_AGCH 0x04
+#define GSMTAP_GMR1_BACH 0x05
+#define GSMTAP_GMR1_RACH 0x06
+#define GSMTAP_GMR1_CBCH 0x07
+#define GSMTAP_GMR1_SDCCH 0x08
+#define GSMTAP_GMR1_TACCH 0x09
+#define GSMTAP_GMR1_GBCH 0x0a
+
+#define GSMTAP_GMR1_SACCH 0x01 /* to be combined with _TCH{6,9} */
+#define GSMTAP_GMR1_FACCH 0x02 /* to be combines with _TCH{3,6,9} */
+#define GSMTAP_GMR1_DKAB 0x03 /* to be combined with _TCH3 */
+#define GSMTAP_GMR1_TCH3 0x10
+#define GSMTAP_GMR1_TCH6 0x14
+#define GSMTAP_GMR1_TCH9 0x18
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+#define GSMTAP_UMTS_CH_PCCH 0x01
+#define GSMTAP_UMTS_CH_CCCH 0x02
+#define GSMTAP_UMTS_CH_DCCH 0x03
+
+/* flags for the ARFCN */
+#define GSMTAP_ARFCN_F_PCS 0x8000
+#define GSMTAP_ARFCN_F_UPLINK 0x4000
+#define GSMTAP_ARFCN_MASK 0x3fff
+
+/* IANA-assigned well-known UDP port for GSMTAP messages */
+#define GSMTAP_UDP_PORT 4729
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+struct gsmtap_hdr {
+ uint8_t version; /* version, set to 0x01 currently */
+ uint8_t hdr_len; /* length in number of 32bit words */
+ uint8_t type; /* see GSMTAP_TYPE_* */
+ uint8_t timeslot; /* timeslot (0..7 on Um) */
+
+ uint16_t arfcn; /* ARFCN (frequency) */
+ int8_t signal_dbm; /* signal level in dBm */
+ int8_t snr_db; /* signal/noise ratio in dB */
+
+ uint32_t frame_number; /* GSM Frame Number (FN) */
+
+ uint8_t sub_type; /* Type of burst/channel, see above */
+ uint8_t antenna_nr; /* Antenna Number */
+ uint8_t sub_slot; /* sub-slot within timeslot */
+ uint8_t res; /* reserved for future use (RFU) */
+
+} __attribute__((packed));
+
+#endif /* _GSMTAP_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap_util.h b/apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap_util.h
new file mode 100644
index 0000000000..5609381f32
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/gsmtap_util.h
@@ -0,0 +1,57 @@
+#ifndef _GSMTAP_UTIL_H
+#define _GSMTAP_UTIL_H
+
+#include <stdint.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/select.h>
+
+/*! \defgroup gsmtap GSMTAP
+ * @{
+ */
+/*! \file gsmtap_util.h */
+
+uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id);
+
+struct msgb *gsmtap_makemsg_ex(uint8_t type, uint16_t arfcn, uint8_t ts, uint8_t chan_type,
+ uint8_t ss, uint32_t fn, int8_t signal_dbm,
+ uint8_t snr, const uint8_t *data, unsigned int len);
+
+struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
+ uint8_t ss, uint32_t fn, int8_t signal_dbm,
+ uint8_t snr, const uint8_t *data, unsigned int len);
+
+/*! \brief one gsmtap instance */
+struct gsmtap_inst {
+ int ofd_wq_mode; /*!< \brief wait queue mode? */
+ struct osmo_wqueue wq; /*!< \brief the wait queue */
+ struct osmo_fd sink_ofd;/*!< \brief file descriptor */
+};
+
+/*! \brief obtain the file descriptor associated with a gsmtap instance */
+static inline int gsmtap_inst_fd(struct gsmtap_inst *gti)
+{
+ return gti->wq.bfd.fd;
+}
+
+int gsmtap_source_init_fd(const char *host, uint16_t port);
+
+int gsmtap_source_add_sink_fd(int gsmtap_fd);
+
+struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port,
+ int ofd_wq_mode);
+
+int gsmtap_source_add_sink(struct gsmtap_inst *gti);
+
+int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg);
+
+int gsmtap_send_ex(struct gsmtap_inst *gti, uint8_t type, uint16_t arfcn, uint8_t ts,
+ uint8_t chan_type, uint8_t ss, uint32_t fn,
+ int8_t signal_dbm, uint8_t snr, const uint8_t *data,
+ unsigned int len);
+
+int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts,
+ uint8_t chan_type, uint8_t ss, uint32_t fn,
+ int8_t signal_dbm, uint8_t snr, const uint8_t *data,
+ unsigned int len);
+
+#endif /* _GSMTAP_UTIL_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/linuxlist.h b/apps/osmocomBB/libosmocore/include/osmocom/core/linuxlist.h
new file mode 100644
index 0000000000..ff2c491566
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/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(__attribute__((unused)) 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 = (typeof( ((type *)0)->member ) *)(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 = (struct llist_head *)LLIST_POISON1;
+ entry->prev = (struct llist_head *)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/apps/osmocomBB/libosmocore/include/osmocom/core/linuxrbtree.h b/apps/osmocomBB/libosmocore/include/osmocom/core/linuxrbtree.h
new file mode 100644
index 0000000000..079f440d0d
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/linuxrbtree.h
@@ -0,0 +1,160 @@
+/*
+ Red Black Trees
+ (C) 1999 Andrea Arcangeli <andrea@suse.de>
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ linux/include/linux/rbtree.h
+
+ To use rbtrees you'll have to implement your own insert and search cores.
+ This will avoid us to use callbacks and to drop drammatically performances.
+ I know it's not the cleaner way, but in C (not in C++) to get
+ performances and genericity...
+
+ Some example of insert and search follows here. The search is a plain
+ normal search over an ordered tree. The insert instead must be implemented
+ int two steps: as first thing the code must insert the element in
+ order as a red leaf in the tree, then the support library function
+ rb_insert_color() must be called. Such function will do the
+ not trivial work to rebalance the rbtree if necessary.
+
+-----------------------------------------------------------------------
+static inline struct page * rb_search_page_cache(struct inode * inode,
+ unsigned long offset)
+{
+ struct rb_node * n = inode->i_rb_page_cache.rb_node;
+ struct page * page;
+
+ while (n)
+ {
+ page = rb_entry(n, struct page, rb_page_cache);
+
+ if (offset < page->offset)
+ n = n->rb_left;
+ else if (offset > page->offset)
+ n = n->rb_right;
+ else
+ return page;
+ }
+ return NULL;
+}
+
+static inline struct page * __rb_insert_page_cache(struct inode * inode,
+ unsigned long offset,
+ struct rb_node * node)
+{
+ struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
+ struct rb_node * parent = NULL;
+ struct page * page;
+
+ while (*p)
+ {
+ parent = *p;
+ page = rb_entry(parent, struct page, rb_page_cache);
+
+ if (offset < page->offset)
+ p = &(*p)->rb_left;
+ else if (offset > page->offset)
+ p = &(*p)->rb_right;
+ else
+ return page;
+ }
+
+ rb_link_node(node, parent, p);
+
+ return NULL;
+}
+
+static inline struct page * rb_insert_page_cache(struct inode * inode,
+ unsigned long offset,
+ struct rb_node * node)
+{
+ struct page * ret;
+ if ((ret = __rb_insert_page_cache(inode, offset, node)))
+ goto out;
+ rb_insert_color(node, &inode->i_rb_page_cache);
+ out:
+ return ret;
+}
+-----------------------------------------------------------------------
+*/
+
+#ifndef _LINUX_RBTREE_H
+#define _LINUX_RBTREE_H
+
+#include <stdlib.h>
+
+struct rb_node
+{
+ unsigned long rb_parent_color;
+#define RB_RED 0
+#define RB_BLACK 1
+ struct rb_node *rb_right;
+ struct rb_node *rb_left;
+} __attribute__((aligned(sizeof(long))));
+ /* The alignment might seem pointless, but allegedly CRIS needs it */
+
+struct rb_root
+{
+ struct rb_node *rb_node;
+};
+
+
+#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
+#define rb_color(r) ((r)->rb_parent_color & 1)
+#define rb_is_red(r) (!rb_color(r))
+#define rb_is_black(r) rb_color(r)
+#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
+#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
+
+static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
+{
+ rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
+}
+static inline void rb_set_color(struct rb_node *rb, int color)
+{
+ rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
+}
+
+#define RB_ROOT { NULL, }
+#define rb_entry(ptr, type, member) container_of(ptr, type, member)
+
+#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
+#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
+#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
+
+extern void rb_insert_color(struct rb_node *, struct rb_root *);
+extern void rb_erase(struct rb_node *, struct rb_root *);
+
+/* Find logical next and previous nodes in a tree */
+extern struct rb_node *rb_next(const struct rb_node *);
+extern struct rb_node *rb_prev(const struct rb_node *);
+extern struct rb_node *rb_first(const struct rb_root *);
+extern struct rb_node *rb_last(const struct rb_root *);
+
+/* Fast replacement of a single node without remove/rebalance/add/rebalance */
+extern void rb_replace_node(struct rb_node *victim, struct rb_node *_new,
+ struct rb_root *root);
+
+static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
+ struct rb_node ** rb_link)
+{
+ node->rb_parent_color = (unsigned long )parent;
+ node->rb_left = node->rb_right = NULL;
+
+ *rb_link = node;
+}
+
+#endif /* _LINUX_RBTREE_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/logging.h b/apps/osmocomBB/libosmocore/include/osmocom/core/logging.h
new file mode 100644
index 0000000000..655f7a4459
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/logging.h
@@ -0,0 +1,214 @@
+#ifndef _OSMOCORE_LOGGING_H
+#define _OSMOCORE_LOGGING_H
+
+/*! \defgroup logging Osmocom logging framework
+ * @{
+ */
+
+/*! \file logging.h */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <osmocom/core/linuxlist.h>
+
+/*! \brief Maximum number of logging contexts */
+#define LOG_MAX_CTX 8
+/*! \brief Maximum number of logging filters */
+#define LOG_MAX_FILTERS 8
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DEBUGP(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 0, fmt, ## args)
+#define DEBUGPC(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 1, fmt, ## args)
+#else
+#define DEBUGP(xss, fmt, args...)
+#define DEBUGPC(ss, fmt, args...)
+#endif
+
+
+void osmo_vlogp(int subsys, int level, const char *file, int line,
+ int cont, const char *format, va_list ap);
+
+void logp(int subsys, const char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
+
+/*! \brief Log a new message through the Osmocom logging framework
+ * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL)
+ * \param[in] level logging level (e.g. \ref LOGL_NOTICE)
+ * \param[in] fmt format string
+ * \param[in] args variable argument list
+ */
+#define LOGP(ss, level, fmt, args...) \
+ logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args)
+
+/*! \brief Continue a log message through the Osmocom logging framework
+ * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL)
+ * \param[in] level logging level (e.g. \ref LOGL_NOTICE)
+ * \param[in] fmt format string
+ * \param[in] args variable argument list
+ */
+#define LOGPC(ss, level, fmt, args...) \
+ logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args)
+
+/*! \brief different log levels */
+#define LOGL_DEBUG 1 /*!< \brief debugging information */
+#define LOGL_INFO 3
+#define LOGL_NOTICE 5 /*!< \brief abnormal/unexpected condition */
+#define LOGL_ERROR 7 /*!< \brief error condition, requires user action */
+#define LOGL_FATAL 8 /*!< \brief fatal, program aborted */
+
+#define LOG_FILTER_ALL 0x0001
+
+/* logging levels defined by the library itself */
+#define DLGLOBAL -1
+#define DLLAPD -2
+#define DLINP -3
+#define DLMUX -4
+#define DLMI -5
+#define DLMIB -6
+#define DLSMS -7
+#define OSMO_NUM_DLIB 7
+
+struct log_category {
+ uint8_t loglevel;
+ uint8_t enabled;
+};
+
+/*! \brief Information regarding one logging category */
+struct log_info_cat {
+ const char *name; /*!< name of category */
+ const char *color; /*!< color string for cateyory */
+ const char *description; /*!< description text */
+ uint8_t loglevel; /*!< currently selected log-level */
+ uint8_t enabled; /*!< is this category enabled or not */
+};
+
+/*! \brief Log context information, passed to filter */
+struct log_context {
+ void *ctx[LOG_MAX_CTX+1];
+};
+
+struct log_target;
+
+/*! \brief Log filter function */
+typedef int log_filter(const struct log_context *ctx,
+ struct log_target *target);
+
+/*! \brief Logging configuration, passed to \ref log_init */
+struct log_info {
+ /* \brief filter callback function */
+ log_filter *filter_fn;
+
+ /*! \brief per-category information */
+ const struct log_info_cat *cat;
+ /*! \brief total number of categories */
+ unsigned int num_cat;
+ /*! \brief total number of user categories (not library) */
+ unsigned int num_cat_user;
+};
+
+/*! \brief Type of logging target */
+enum log_target_type {
+ LOG_TGT_TYPE_VTY, /*!< \brief VTY logging */
+ LOG_TGT_TYPE_SYSLOG, /*!< \brief syslog based logging */
+ LOG_TGT_TYPE_FILE, /*!< \brief text file logging */
+ LOG_TGT_TYPE_STDERR, /*!< \brief stderr logging */
+};
+
+/*! \brief structure representing a logging target */
+struct log_target {
+ struct llist_head entry; /*!< \brief linked list */
+
+ /*! \brief Internal data for filtering */
+ int filter_map;
+ /*! \brief Internal data for filtering */
+ void *filter_data[LOG_MAX_FILTERS+1];
+
+ /*! \brief logging categories */
+ struct log_category *categories;
+
+ /*! \brief global log level */
+ uint8_t loglevel;
+ /*! \brief should color be used when printing log messages? */
+ unsigned int use_color:1;
+ /*! \brief should log messages be prefixed with a timestamp? */
+ unsigned int print_timestamp:1;
+ /*! \brief should log messages be prefixed with a filename? */
+ unsigned int print_filename:1;
+
+ /*! \brief the type of this log taget */
+ enum log_target_type type;
+
+ union {
+ struct {
+ FILE *out;
+ const char *fname;
+ } tgt_file;
+
+ struct {
+ int priority;
+ int facility;
+ } tgt_syslog;
+
+ struct {
+ void *vty;
+ } tgt_vty;
+ };
+
+ /*! \brief call-back function to be called when the logging framework
+ * wants to log somethnig.
+ * \param[[in] target logging target
+ * \param[in] level log level of currnet message
+ * \param[in] string the string that is to be written to the log
+ */
+ void (*output) (struct log_target *target, unsigned int level,
+ const char *string);
+};
+
+/* use the above macros */
+void logp2(int subsys, unsigned int level, const char *file,
+ int line, int cont, const char *format, ...)
+ __attribute__ ((format (printf, 6, 7)));
+int log_init(const struct log_info *inf, void *talloc_ctx);
+
+/* context management */
+void log_reset_context(void);
+int log_set_context(uint8_t ctx, void *value);
+
+/* filter on the targets */
+void log_set_all_filter(struct log_target *target, int);
+
+void log_set_use_color(struct log_target *target, int);
+void log_set_print_timestamp(struct log_target *target, int);
+void log_set_print_filename(struct log_target *target, int);
+void log_set_log_level(struct log_target *target, int log_level);
+void log_parse_category_mask(struct log_target *target, const char* mask);
+int log_parse_level(const char *lvl);
+const char *log_level_str(unsigned int lvl);
+int log_parse_category(const char *category);
+void log_set_category_filter(struct log_target *target, int category,
+ int enable, int level);
+
+/* management of the targets */
+struct log_target *log_target_create(void);
+void log_target_destroy(struct log_target *target);
+struct log_target *log_target_create_stderr(void);
+struct log_target *log_target_create_file(const char *fname);
+struct log_target *log_target_create_syslog(const char *ident, int option,
+ int facility);
+int log_target_file_reopen(struct log_target *tgt);
+
+void log_add_target(struct log_target *target);
+void log_del_target(struct log_target *target);
+
+/* Generate command string for VTY use */
+const char *log_vty_command_string(const struct log_info *info);
+const char *log_vty_command_description(const struct log_info *info);
+
+struct log_target *log_target_find(int type, const char *fname);
+extern struct llist_head osmo_log_target_list;
+
+/*! @} */
+
+#endif /* _OSMOCORE_LOGGING_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/msgb.h b/apps/osmocomBB/libosmocore/include/osmocom/core/msgb.h
new file mode 100644
index 0000000000..a1939ab68f
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/msgb.h
@@ -0,0 +1,401 @@
+#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.
+ *
+ */
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/utils.h>
+
+/*! \defgroup msgb Message buffers
+ * @{
+ */
+
+/*! \file msgb.h
+ * \brief Osmocom message buffers
+ * The Osmocom message buffers are modelled after the 'struct skb'
+ * inside the Linux kernel network stack. As they exist in userspace,
+ * they are much simplified. However, terminology such as headroom,
+ * tailroom, push/pull/put etc. remains the same.
+ */
+
+#define MSGB_DEBUG
+
+/*! \brief Osmocom message buffer */
+struct msgb {
+ struct llist_head list; /*!< \brief linked list header */
+
+
+ /* Part of which TRX logical channel we were received / transmitted */
+ /* FIXME: move them into the control buffer */
+ union {
+ void *dst; /*!< \brief reference of origin/destination */
+ struct gsm_bts_trx *trx;
+ };
+ struct gsm_lchan *lchan; /*!< \brief logical channel */
+
+ unsigned char *l1h; /*!< \brief pointer to Layer1 header (if any) */
+ unsigned char *l2h; /*!< \brief pointer to A-bis layer 2 header: OML, RSL(RLL), NS */
+ unsigned char *l3h; /*!< \brief pointer to Layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */
+ unsigned char *l4h; /*!< \brief pointer to layer 4 header */
+
+ unsigned long cb[5]; /*!< \brief control buffer */
+
+ uint16_t data_len; /*!< \brief length of underlying data array */
+ uint16_t len; /*!< \brief length of bytes used in msgb */
+
+ unsigned char *head; /*!< \brief start of underlying memory buffer */
+ unsigned char *tail; /*!< \brief end of message in buffer */
+ unsigned char *data; /*!< \brief start of message in buffer */
+ unsigned char _data[0]; /*!< \brief optional immediate data array */
+};
+
+extern struct msgb *msgb_alloc(uint16_t size, const char *name);
+extern void msgb_free(struct msgb *m);
+extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
+extern struct msgb *msgb_dequeue(struct llist_head *queue);
+extern void msgb_reset(struct msgb *m);
+uint16_t msgb_length(const struct msgb *msg);
+
+#ifdef MSGB_DEBUG
+#include <osmocom/core/panic.h>
+#define MSGB_ABORT(msg, fmt, args ...) do { \
+ osmo_panic("msgb(%p): " fmt, msg, ## args); \
+ } while(0)
+#else
+#define MSGB_ABORT(msg, fmt, args ...)
+#endif
+
+/*! \brief obtain L1 header of msgb */
+#define msgb_l1(m) ((void *)(m->l1h))
+/*! \brief obtain L2 header of msgb */
+#define msgb_l2(m) ((void *)(m->l2h))
+/*! \brief obtain L3 header of msgb */
+#define msgb_l3(m) ((void *)(m->l3h))
+/*! \brief obtain SMS header of msgb */
+#define msgb_sms(m) ((void *)(m->l4h))
+
+/*! \brief determine length of L1 message
+ * \param[in] msgb message buffer
+ * \returns size of L1 message in bytes
+ *
+ * This function computes the number of bytes between the tail of the
+ * message and the layer 1 header.
+ */
+static inline unsigned int msgb_l1len(const struct msgb *msgb)
+{
+ return msgb->tail - (uint8_t *)msgb_l1(msgb);
+}
+
+/*! \brief determine length of L2 message
+ * \param[in] msgb message buffer
+ * \returns size of L2 message in bytes
+ *
+ * This function computes the number of bytes between the tail of the
+ * message and the layer 2 header.
+ */
+static inline unsigned int msgb_l2len(const struct msgb *msgb)
+{
+ return msgb->tail - (uint8_t *)msgb_l2(msgb);
+}
+
+/*! \brief determine length of L3 message
+ * \param[in] msgb message buffer
+ * \returns size of L3 message in bytes
+ *
+ * This function computes the number of bytes between the tail of the
+ * message and the layer 3 header.
+ */
+static inline unsigned int msgb_l3len(const struct msgb *msgb)
+{
+ return msgb->tail - (uint8_t *)msgb_l3(msgb);
+}
+
+/*! \brief determine the length of the header
+ * \param[in] msgb message buffer
+ * \returns number of bytes between start of buffer and start of msg
+ *
+ * This function computes the length difference between the underlying
+ * data buffer and the used section of the \a msgb.
+ */
+static inline unsigned int msgb_headlen(const struct msgb *msgb)
+{
+ return msgb->len - msgb->data_len;
+}
+
+/*! \brief determine how much tail room is left in msgb
+ * \param[in] msgb message buffer
+ * \returns number of bytes remaining at end of msgb
+ *
+ * This function computes the amount of octets left in the underlying
+ * data buffer after the end of the message.
+ */
+static inline int msgb_tailroom(const struct msgb *msgb)
+{
+ return (msgb->head + msgb->data_len) - msgb->tail;
+}
+
+/*! \brief determine the amount of headroom in msgb
+ * \param[in] msgb message buffer
+ * \returns number of bytes left ahead of message start in msgb
+ *
+ * This function computes the amount of bytes left in the underlying
+ * data buffer before the start of the actual message.
+ */
+static inline int msgb_headroom(const struct msgb *msgb)
+{
+ return (msgb->data - msgb->head);
+}
+
+/*! \brief append data to end of message buffer
+ * \param[in] msgb message buffer
+ * \param[in] len number of bytes to append to message
+ * \returns pointer to start of newly-appended data
+ *
+ * This function will move the \a tail pointer of the message buffer \a
+ * len bytes further, thus enlarging the message by \a len bytes.
+ *
+ * The return value is a pointer to start of the newly added section at
+ * the end of the message and can be used for actually filling/copying
+ * data into it.
+ */
+static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
+{
+ unsigned char *tmp = msgb->tail;
+ if (msgb_tailroom(msgb) < (int) len)
+ MSGB_ABORT(msgb, "Not enough tailroom msgb_push (%u < %u)\n",
+ msgb_tailroom(msgb), len);
+ msgb->tail += len;
+ msgb->len += len;
+ return tmp;
+}
+
+/*! \brief append a uint8 value to the end of the message
+ * \param[in] msgb message buffer
+ * \param[in] word unsigned 8bit byte to be appended
+ */
+static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
+{
+ uint8_t *space = msgb_put(msgb, 1);
+ space[0] = word & 0xFF;
+}
+
+/*! \brief append a uint16 value to the end of the message
+ * \param[in] msgb message buffer
+ * \param[in] word unsigned 16bit byte to be appended
+ */
+static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
+{
+ uint8_t *space = msgb_put(msgb, 2);
+ space[0] = word >> 8 & 0xFF;
+ space[1] = word & 0xFF;
+}
+
+/*! \brief append a uint32 value to the end of the message
+ * \param[in] msgb message buffer
+ * \param[in] word unsigned 32bit byte to be appended
+ */
+static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
+{
+ uint8_t *space = msgb_put(msgb, 4);
+ space[0] = word >> 24 & 0xFF;
+ space[1] = word >> 16 & 0xFF;
+ space[2] = word >> 8 & 0xFF;
+ space[3] = word & 0xFF;
+}
+
+/*! \brief remove data from end of message
+ * \param[in] msgb message buffer
+ * \param[in] len number of bytes to remove from end
+ */
+static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
+{
+ unsigned char *tmp = msgb->data - len;
+ if (msgb_length(msgb) < len)
+ MSGB_ABORT(msgb, "msgb too small to get %u (len %u)\n",
+ len, msgb_length(msgb));
+ msgb->tail -= len;
+ msgb->len -= len;
+ return tmp;
+}
+/*! \brief remove uint8 from end of message
+ * \param[in] msgb message buffer
+ * \returns 8bit value taken from end of msgb
+ */
+static inline uint8_t msgb_get_u8(struct msgb *msgb)
+{
+ uint8_t *space = msgb_get(msgb, 1);
+ return space[0];
+}
+/*! \brief remove uint16 from end of message
+ * \param[in] msgb message buffer
+ * \returns 16bit value taken from end of msgb
+ */
+static inline uint16_t msgb_get_u16(struct msgb *msgb)
+{
+ uint8_t *space = msgb_get(msgb, 2);
+ return space[0] << 8 | space[1];
+}
+/*! \brief remove uint32 from end of message
+ * \param[in] msgb message buffer
+ * \returns 32bit value taken from end of msgb
+ */
+static inline uint32_t msgb_get_u32(struct msgb *msgb)
+{
+ uint8_t *space = msgb_get(msgb, 4);
+ return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
+}
+
+/*! \brief prepend (push) some data to start of message
+ * \param[in] msgb message buffer
+ * \param[in] len number of bytes to pre-pend
+ * \returns pointer to newly added portion at start of \a msgb
+ *
+ * This function moves the \a data pointer of the \ref msgb further
+ * to the front (by \a len bytes), thereby enlarging the message by \a
+ * len bytes.
+ *
+ * The return value is a pointer to the newly added section in the
+ * beginning of the message. It can be used to fill/copy data into it.
+ */
+static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
+{
+ if (msgb_headroom(msgb) < (int) len)
+ MSGB_ABORT(msgb, "Not enough headroom msgb_push (%u < %u)\n",
+ msgb_headroom(msgb), len);
+ msgb->data -= len;
+ msgb->len += len;
+ return msgb->data;
+}
+/*! \brief remove (pull) a header from the front of the message buffer
+ * \param[in] msgb message buffer
+ * \param[in] len number of octets to be pulled
+ * \returns pointer to new start of msgb
+ *
+ * This function moves the \a data pointer of the \ref msgb further back
+ * in the message, thereby shrinking the size of the message by \a len
+ * bytes.
+ */
+static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
+{
+ msgb->len -= len;
+ return msgb->data += len;
+}
+
+/*! \brief remove uint8 from front of message
+ * \param[in] msgb message buffer
+ * \returns 8bit value taken from end of msgb
+ */
+static inline uint8_t msgb_pull_u8(struct msgb *msgb)
+{
+ uint8_t *space = msgb_pull(msgb, 1) - 1;
+ return space[0];
+}
+/*! \brief remove uint16 from front of message
+ * \param[in] msgb message buffer
+ * \returns 16bit value taken from end of msgb
+ */
+static inline uint16_t msgb_pull_u16(struct msgb *msgb)
+{
+ uint8_t *space = msgb_pull(msgb, 2) - 2;
+ return space[0] << 8 | space[1];
+}
+/*! \brief remove uint32 from front of message
+ * \param[in] msgb message buffer
+ * \returns 32bit value taken from end of msgb
+ */
+static inline uint32_t msgb_pull_u32(struct msgb *msgb)
+{
+ uint8_t *space = msgb_pull(msgb, 4) - 4;
+ return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
+}
+
+/*! \brief Increase headroom of empty msgb, reducing the tailroom
+ * \param[in] msg message buffer
+ * \param[in] len amount of extra octets to be reserved as headroom
+ *
+ * This function reserves some memory at the beginning of the underlying
+ * data buffer. The idea is to reserve space in case further headers
+ * have to be pushed to the \ref msgb during further processing.
+ *
+ * Calling this function leads to undefined reusults if it is called on
+ * a non-empty \ref msgb.
+ */
+static inline void msgb_reserve(struct msgb *msg, int len)
+{
+ msg->data += len;
+ msg->tail += len;
+}
+
+/*! \brief Trim the msgb to a given absolute length
+ * \param[in] msg message buffer
+ * \param[in] len new total length of buffer
+ * \returns 0 in case of success, negative in case of error
+ */
+static inline int msgb_trim(struct msgb *msg, int len)
+{
+ if (len > msg->data_len)
+ return -1;
+
+ msg->len = len;
+ msg->tail = msg->data + len;
+
+ return 0;
+}
+
+/*! \brief Trim the msgb to a given layer3 length
+ * \pram[in] msg message buffer
+ * \param[in] l3len new layer3 length
+ * \returns 0 in case of success, negative in case of error
+ */
+static inline int msgb_l3trim(struct msgb *msg, int l3len)
+{
+ return msgb_trim(msg, (msg->l3h - msg->data) + l3len);
+}
+
+/*! \brief Allocate message buffer with specified headroom
+ * \param[in] size size in bytes, including headroom
+ * \param[in] headroom headroom in bytes
+ * \param[in] name human-readable name
+ * \returns allocated message buffer with specified headroom
+ *
+ * This function is a convenience wrapper around \ref msgb_alloc
+ * followed by \ref msgb_reserve in order to create a new \ref msgb with
+ * user-specified amount of headroom.
+ */
+static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
+ const char *name)
+{
+ osmo_static_assert(size > headroom, headroom_bigger);
+
+ struct msgb *msg = msgb_alloc(size, name);
+ if (msg)
+ msgb_reserve(msg, headroom);
+ return msg;
+}
+
+/* non inline functions to ease binding */
+
+uint8_t *msgb_data(const struct msgb *msg);
+void msgb_set_talloc_ctx(void *ctx);
+
+/*! @} */
+
+#endif /* _MSGB_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/msgfile.h b/apps/osmocomBB/libosmocore/include/osmocom/core/msgfile.h
new file mode 100644
index 0000000000..c5e67a45c2
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/msgfile.h
@@ -0,0 +1,49 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by On-Waves
+ * 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 MSG_FILE_H
+#define MSG_FILE_H
+
+#include <osmocom/core/linuxlist.h>
+
+/**
+ * One message in the list.
+ */
+struct osmo_config_entry {
+ struct llist_head list;
+
+ /* number for everyone to use */
+ int nr;
+
+ /* data from the file */
+ char *mcc;
+ char *mnc;
+ char *option;
+ char *text;
+};
+
+struct osmo_config_list {
+ struct llist_head entry;
+};
+
+struct osmo_config_list* osmo_config_list_parse(void *ctx, const char *filename);
+
+#endif
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/panic.h b/apps/osmocomBB/libosmocore/include/osmocom/core/panic.h
new file mode 100644
index 0000000000..fd5cf2082c
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/panic.h
@@ -0,0 +1,20 @@
+#ifndef OSMOCORE_PANIC_H
+#define OSMOCORE_PANIC_H
+
+/*! \addtogroup utils
+ * @{
+ */
+
+/*! \file panic.h */
+
+#include <stdarg.h>
+
+/*! \brief panic handler callback function type */
+typedef void (*osmo_panic_handler_t)(const char *fmt, va_list args);
+
+extern void osmo_panic(const char *fmt, ...);
+extern void osmo_set_panic_handler(osmo_panic_handler_t h);
+
+/*! @} */
+
+#endif /* OSMOCORE_PANIC_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/plugin.h b/apps/osmocomBB/libosmocore/include/osmocom/core/plugin.h
new file mode 100644
index 0000000000..6c0eccc652
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/plugin.h
@@ -0,0 +1,6 @@
+#ifndef _OSMO_PLUGIN_H
+#define _OSMO_PLUGIN_H
+
+int osmo_plugin_load_all(const char *directory);
+
+#endif
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/prim.h b/apps/osmocomBB/libosmocore/include/osmocom/core/prim.h
new file mode 100644
index 0000000000..b1026fe3fd
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/prim.h
@@ -0,0 +1,58 @@
+#ifndef OSMO_PRIMITIVE_H
+#define OSMO_PRIMITIVE_H
+
+/*! \defgroup prim Osmocom primitives
+ * @{
+ */
+
+/*! \file prim.c */
+
+#include <stdint.h>
+#include <osmocom/core/msgb.h>
+
+#define OSMO_PRIM(prim, op) ((prim << 8) | (op & 0xFF))
+#define OSMO_PRIM_HDR(oph) OSMO_PRIM((oph)->primitive, (oph)->operation)
+
+/*! \brief primitive operation */
+enum osmo_prim_operation {
+ PRIM_OP_REQUEST, /*!< \brief request */
+ PRIM_OP_RESPONSE, /*!< \brief response */
+ PRIM_OP_INDICATION, /*!< \brief indication */
+ PRIM_OP_CONFIRM, /*!< \brief cofirm */
+};
+
+#define _SAP_GSM_SHIFT 24
+
+#define _SAP_GSM_BASE (0x01 << _SAP_GSM_SHIFT)
+#define _SAP_TETRA_BASE (0x02 << _SAP_GSM_SHIFT)
+
+/*! \brief primitive header */
+struct osmo_prim_hdr {
+ unsigned int sap; /*!< \brief Service Access Point */
+ unsigned int primitive; /*!< \brief Primitive number */
+ enum osmo_prim_operation operation; /*! \brief Primitive Operation */
+ struct msgb *msg; /*!< \brief \ref msgb containing associated data */
+};
+
+/*! \brief initialize a primitive header
+ * \param[in,out] oph primitive header
+ * \param[in] sap Service Access Point
+ * \param[in] primtive Primitive Number
+ * \param[in] operation Primitive Operation (REQ/RESP/IND/CONF)
+ * \param[in] msg Message
+ */
+static inline void
+osmo_prim_init(struct osmo_prim_hdr *oph, unsigned int sap,
+ unsigned int primitive, enum osmo_prim_operation operation,
+ struct msgb *msg)
+{
+ oph->sap = sap;
+ oph->primitive = primitive;
+ oph->operation = operation;
+ oph->msg = msg;
+}
+
+/*! \brief primitive handler callback type */
+typedef int (*osmo_prim_cb)(struct osmo_prim_hdr *oph, void *ctx);
+
+#endif /* OSMO_PRIMITIVE_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/process.h b/apps/osmocomBB/libosmocore/include/osmocom/core/process.h
new file mode 100644
index 0000000000..1dde02193b
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/process.h
@@ -0,0 +1,2 @@
+#warning "Update from osmocom/core/process.h to osmocom/core/application.h"
+#include <osmocom/core/application.h>
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/rate_ctr.h b/apps/osmocomBB/libosmocore/include/osmocom/core/rate_ctr.h
new file mode 100644
index 0000000000..24577fdfca
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/rate_ctr.h
@@ -0,0 +1,88 @@
+#ifndef _RATE_CTR_H
+#define _RATE_CTR_H
+
+/*! \defgroup rate_ctr Rate counters
+ * @{
+ */
+
+/*! \file rate_ctr.h */
+
+#include <stdint.h>
+
+#include <osmocom/core/linuxlist.h>
+
+/*! \brief Number of rate counter intervals */
+#define RATE_CTR_INTV_NUM 4
+
+/*! \brief Rate counter interval */
+enum rate_ctr_intv {
+ RATE_CTR_INTV_SEC, /*!< \brief last second */
+ RATE_CTR_INTV_MIN, /*!< \brief last minute */
+ RATE_CTR_INTV_HOUR, /*!< \brief last hour */
+ RATE_CTR_INTV_DAY, /*!< \brief last day */
+};
+
+/*! \brief data we keep for each of the intervals */
+struct rate_ctr_per_intv {
+ uint64_t last; /*!< \brief counter value in last interval */
+ uint64_t rate; /*!< \brief counter rate */
+};
+
+/*! \brief data we keep for each actual value */
+struct rate_ctr {
+ uint64_t current; /*!< \brief current value */
+ /*! \brief per-interval data */
+ struct rate_ctr_per_intv intv[RATE_CTR_INTV_NUM];
+};
+
+/*! \brief rate counter description */
+struct rate_ctr_desc {
+ const char *name; /*!< \brief name of the counter */
+ const char *description;/*!< \brief description of the counter */
+};
+
+/*! \brief description of a rate counter group */
+struct rate_ctr_group_desc {
+ /*! \brief The prefix to the name of all counters in this group */
+ const char *group_name_prefix;
+ /*! \brief The human-readable description of the group */
+ const char *group_description;
+ /*! \brief The number of counters in this group */
+ const unsigned int num_ctr;
+ /*! \brief Pointer to array of counter names */
+ const struct rate_ctr_desc *ctr_desc;
+};
+
+/*! \brief One instance of a counter group class */
+struct rate_ctr_group {
+ /*! \brief Linked list of all counter groups in the system */
+ struct llist_head list;
+ /*! \brief Pointer to the counter group class */
+ const struct rate_ctr_group_desc *desc;
+ /*! \brief The index of this ctr_group within its class */
+ unsigned int idx;
+ /*! \brief Actual counter structures below */
+ struct rate_ctr ctr[0];
+};
+
+struct rate_ctr_group *rate_ctr_group_alloc(void *ctx,
+ const struct rate_ctr_group_desc *desc,
+ unsigned int idx);
+
+void rate_ctr_group_free(struct rate_ctr_group *grp);
+
+void rate_ctr_add(struct rate_ctr *ctr, int inc);
+
+/*! \brief Increment the counter by 1 */
+static inline void rate_ctr_inc(struct rate_ctr *ctr)
+{
+ rate_ctr_add(ctr, 1);
+}
+
+int rate_ctr_init(void *tall_ctx);
+
+struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const unsigned int idx);
+const struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name);
+
+/*! @} */
+#endif /* RATE_CTR_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/select.h b/apps/osmocomBB/libosmocore/include/osmocom/core/select.h
new file mode 100644
index 0000000000..efdd716fad
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/select.h
@@ -0,0 +1,45 @@
+#ifndef _BSC_SELECT_H
+#define _BSC_SELECT_H
+
+#include <osmocom/core/linuxlist.h>
+
+/*! \defgroup select Select loop abstraction
+ * @{
+ */
+
+/*! \file select.h
+ * \brief select loop abstraction
+ */
+
+/*! \brief Indicate interest in reading from the file descriptor */
+#define BSC_FD_READ 0x0001
+/*! \brief Indicate interest in writing to the file descriptor */
+#define BSC_FD_WRITE 0x0002
+/*! \brief Indicate interest in exceptions from the file descriptor */
+#define BSC_FD_EXCEPT 0x0004
+
+/*! \brief Structure representing a file dsecriptor */
+struct osmo_fd {
+ /*! linked list for internal management */
+ struct llist_head list;
+ /*! actual operating-system level file decriptor */
+ int fd;
+ /*! bit-mask or of \ref BSC_FD_READ, \ref BSC_FD_WRITE and/or
+ * \ref BSC_FD_EXCEPT */
+ unsigned int when;
+ /*! call-back function to be called once file descriptor becomes
+ * available */
+ int (*cb)(struct osmo_fd *fd, unsigned int what);
+ /*! data pointer passed through to call-back function */
+ void *data;
+ /*! private number, extending \a data */
+ unsigned int priv_nr;
+};
+
+int osmo_fd_register(struct osmo_fd *fd);
+void osmo_fd_unregister(struct osmo_fd *fd);
+int osmo_select_main(int polling);
+
+/*! @} */
+
+#endif /* _BSC_SELECT_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/serial.h b/apps/osmocomBB/libosmocore/include/osmocom/core/serial.h
new file mode 100644
index 0000000000..889bd8a125
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/serial.h
@@ -0,0 +1,43 @@
+/*
+ * serial.h
+ *
+ * Copyright (C) 2011 Sylvain Munaut <tnt@246tNt.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.
+ */
+
+/*! \defgroup serial Utility functions to deal with serial ports
+ * @{
+ */
+
+/*! \file serial.h
+ * \file Osmocom serial port helpers
+ */
+
+#ifndef __OSMO_SERIAL_H__
+#define __OSMO_SERIAL_H__
+
+#include <termios.h>
+
+int osmo_serial_init(const char *dev, speed_t baudrate);
+int osmo_serial_set_baudrate(int fd, speed_t baudrate);
+int osmo_serial_set_custom_baudrate(int fd, int baudrate);
+int osmo_serial_clear_custom_baudrate(int fd);
+
+/*! @} */
+
+#endif /* __OSMO_SERIAL_H__ */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/signal.h b/apps/osmocomBB/libosmocore/include/osmocom/core/signal.h
new file mode 100644
index 0000000000..b3a5aaee82
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/signal.h
@@ -0,0 +1,46 @@
+#ifndef OSMO_SIGNAL_H
+#define OSMO_SIGNAL_H
+
+#include <stdint.h>
+
+/*! \defgroup signal Intra-application signals
+ * @{
+ */
+/*! \file signal.h */
+
+/* subsystem signaling numbers: we split the numberspace for applications and
+ * libraries: from 0 to UINT_MAX/2 for applications, from UINT_MAX/2 to
+ * UINT_MAX for libraries. */
+#define OSMO_SIGNAL_SS_APPS 0
+#define OSMO_SIGNAL_SS_RESERVED 2147483648u
+
+/*! \brief signal subsystems */
+enum {
+ SS_L_GLOBAL = OSMO_SIGNAL_SS_RESERVED,
+ SS_L_INPUT,
+ SS_L_NS,
+};
+
+/* application-defined signal types. */
+#define OSMO_SIGNAL_T_APPS 0
+#define OSMO_SIGNAL_T_RESERVED 2147483648u
+
+/*! \brief signal types. */
+enum {
+ S_L_GLOBAL_SHUTDOWN = OSMO_SIGNAL_T_RESERVED,
+};
+
+/*! signal callback function type */
+typedef int osmo_signal_cbfn(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data);
+
+
+/* Management */
+int osmo_signal_register_handler(unsigned int subsys, osmo_signal_cbfn *cbfn, void *data);
+void osmo_signal_unregister_handler(unsigned int subsys, osmo_signal_cbfn *cbfn, void *data);
+
+/* Dispatch */
+void osmo_signal_dispatch(unsigned int subsys, unsigned int signal, void *signal_data);
+
+/*! @} */
+
+#endif /* OSMO_SIGNAL_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/socket.h b/apps/osmocomBB/libosmocore/include/osmocom/core/socket.h
new file mode 100644
index 0000000000..f15a03a91b
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/socket.h
@@ -0,0 +1,35 @@
+#ifndef _OSMOCORE_SOCKET_H
+#define _OSMOCORE_SOCKET_H
+
+/*! \defgroup socket Socket convenience functions
+ * @{
+ */
+
+/*! \file socket.h
+ * \brief Osmocom socket convenience functions
+ */
+
+#include <stdint.h>
+
+struct sockaddr;
+struct osmo_fd;
+
+/* flags for osmo_sock_init. */
+#define OSMO_SOCK_F_CONNECT (1 << 0)
+#define OSMO_SOCK_F_BIND (1 << 1)
+#define OSMO_SOCK_F_NONBLOCK (1 << 2)
+
+int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
+ const char *host, uint16_t port, unsigned int flags);
+
+int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
+ const char *host, uint16_t port, unsigned int flags);
+
+int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
+ uint8_t proto, unsigned int flags);
+
+int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen);
+
+/*! @} */
+
+#endif /* _OSMOCORE_SOCKET_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/statistics.h b/apps/osmocomBB/libosmocore/include/osmocom/core/statistics.h
new file mode 100644
index 0000000000..04816c166f
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/statistics.h
@@ -0,0 +1,53 @@
+#ifndef _STATISTICS_H
+#define _STATISTICS_H
+
+/*! \file statistics.h
+ * \brief Common routines regarding statistics */
+
+/*! structure representing a single counter */
+struct osmo_counter {
+ struct llist_head list; /*!< \brief internal list head */
+ const char *name; /*!< \brief human-readable name */
+ const char *description; /*!< \brief humn-readable description */
+ unsigned long value; /*!< \brief current value */
+};
+
+/*! \brief Increment counter */
+static inline void osmo_counter_inc(struct osmo_counter *ctr)
+{
+ ctr->value++;
+}
+
+/*! \brief Get current value of counter */
+static inline unsigned long osmo_counter_get(struct osmo_counter *ctr)
+{
+ return ctr->value;
+}
+
+/*! \brief Reset current value of counter to 0 */
+static inline void osmo_counter_reset(struct osmo_counter *ctr)
+{
+ ctr->value = 0;
+}
+
+/*! \brief Allocate a new counter */
+struct osmo_counter *osmo_counter_alloc(const char *name);
+
+/*! \brief Free the specified counter
+ * \param[ctr] Counter
+ */
+void osmo_counter_free(struct osmo_counter *ctr);
+
+/*! \brief Iteate over all counters
+ * \param[in] handle_counter Call-back function
+ * \param[in] data Private dtata handed through to \a handle_counter
+ */
+int osmo_counters_for_each(int (*handle_counter)(struct osmo_counter *, void *), void *data);
+
+/*! \brief Resolve counter by human-readable name
+ * \param[in] name human-readable name of counter
+ * \returns pointer to counter (\ref osmo_counter) or NULL otherwise
+ */
+struct osmo_counter *osmo_counter_get_by_name(const char *name);
+
+#endif /* _STATISTICS_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/talloc.h b/apps/osmocomBB/libosmocore/include/osmocom/core/talloc.h
new file mode 100644
index 0000000000..f7f7643b81
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/talloc.h
@@ -0,0 +1,192 @@
+#ifndef _TALLOC_H_
+#define _TALLOC_H_
+/*
+ Unix SMB/CIFS implementation.
+ Samba temporary memory allocation functions
+
+ Copyright (C) Andrew Tridgell 2004-2005
+ Copyright (C) Stefan Metzmacher 2006
+
+ ** NOTE! The following LGPL license applies to the talloc
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define HAVE_VA_COPY
+
+/* this is only needed for compatibility with the old talloc */
+typedef void TALLOC_CTX;
+
+/*
+ this uses a little trick to allow __LINE__ to be stringified
+*/
+#ifndef __location__
+#define __TALLOC_STRING_LINE1__(s) #s
+#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
+#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
+#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
+#endif
+
+#ifndef TALLOC_DEPRECATED
+#define TALLOC_DEPRECATED 0
+#endif
+
+#ifndef PRINTF_ATTRIBUTE
+#if (__GNUC__ >= 3)
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
+
+/* try to make talloc_set_destructor() and talloc_steal() type safe,
+ if we have a recent gcc */
+#if (__GNUC__ >= 3)
+#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
+#define talloc_set_destructor(ptr, function) \
+ do { \
+ int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
+ _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
+ } while(0)
+/* this extremely strange macro is to avoid some braindamaged warning
+ stupidity in gcc 4.1.x */
+#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
+#else
+#define talloc_set_destructor(ptr, function) \
+ _talloc_set_destructor((ptr), (int (*)(void *))(function))
+#define _TALLOC_TYPEOF(ptr) void *
+#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
+#endif
+
+#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
+#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
+
+/* useful macros for creating type checked pointers */
+#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
+#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
+#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
+
+#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
+
+#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
+#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
+
+#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
+#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
+#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
+#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
+#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
+
+#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
+#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
+
+#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
+
+#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
+#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
+#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
+
+#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
+
+#if TALLOC_DEPRECATED
+#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
+#define talloc_p(ctx, type) talloc(ctx, type)
+#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
+#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
+#define talloc_destroy(ctx) talloc_free(ctx)
+#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
+#endif
+
+#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
+
+/* The following definitions come from talloc.c */
+void *_talloc(const void *context, size_t size);
+void *talloc_pool(const void *context, size_t size);
+void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
+int talloc_increase_ref_count(const void *ptr);
+size_t talloc_reference_count(const void *ptr);
+void *_talloc_reference(const void *context, const void *ptr);
+int talloc_unlink(const void *context, void *ptr);
+const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+void talloc_set_name_const(const void *ptr, const char *name);
+void *talloc_named(const void *context, size_t size,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
+void *talloc_named_const(const void *context, size_t size, const char *name);
+const char *talloc_get_name(const void *ptr);
+void *talloc_check_name(const void *ptr, const char *name);
+void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
+void *talloc_parent(const void *ptr);
+const char *talloc_parent_name(const void *ptr);
+void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
+int talloc_free(void *ptr);
+void talloc_free_children(void *ptr);
+void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
+void *_talloc_steal(const void *new_ctx, const void *ptr);
+void *_talloc_move(const void *new_ctx, const void *pptr);
+size_t talloc_total_size(const void *ptr);
+size_t talloc_total_blocks(const void *ptr);
+void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
+ void (*callback)(const void *ptr,
+ int depth, int max_depth,
+ int is_ref,
+ void *private_data),
+ void *private_data);
+void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
+void talloc_report_full(const void *ptr, FILE *f);
+void talloc_report(const void *ptr, FILE *f);
+void talloc_enable_null_tracking(void);
+void talloc_disable_null_tracking(void);
+void talloc_enable_leak_report(void);
+void talloc_enable_leak_report_full(void);
+void *_talloc_zero(const void *ctx, size_t size, const char *name);
+void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
+void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
+void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
+void *talloc_autofree_context(void);
+size_t talloc_get_size(const void *ctx);
+void *talloc_find_parent_byname(const void *ctx, const char *name);
+void talloc_show_parents(const void *context, FILE *file);
+int talloc_is_parent(const void *context, const void *ptr);
+
+char *talloc_strdup(const void *t, const char *p);
+char *talloc_strdup_append(char *s, const char *a);
+char *talloc_strdup_append_buffer(char *s, const char *a);
+
+char *talloc_strndup(const void *t, const char *p, size_t n);
+char *talloc_strndup_append(char *s, const char *a, size_t n);
+char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
+
+char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
+
+char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+
+void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
+
+#endif
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/timer.h b/apps/osmocomBB/libosmocore/include/osmocom/core/timer.h
new file mode 100644
index 0000000000..d37af8060d
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/timer.h
@@ -0,0 +1,89 @@
+/*
+ * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.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.
+ *
+ */
+
+/*! \defgroup timer Osmocom timers
+ * @{
+ */
+
+/*! \file timer.h
+ * \brief Osmocom timer handling routines
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include <sys/time.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/linuxrbtree.h>
+
+/**
+ * Timer management:
+ * - Create a struct osmo_timer_list
+ * - Fill out timeout and use add_timer or
+ * use schedule_timer to schedule a timer in
+ * x seconds and microseconds from now...
+ * - Use del_timer to remove the timer
+ *
+ * Internally:
+ * - We hook into select.c to give a timeval of the
+ * nearest timer. On already passed timers we give
+ * it a 0 to immediately fire after the select
+ * - update_timers will call the callbacks and remove
+ * the timers.
+ *
+ */
+/*! \brief A structure representing a single instance of a timer */
+struct osmo_timer_list {
+ struct rb_node node; /*!< \brief rb-tree node header */
+ struct llist_head list; /*!< \brief internal list header */
+ struct timeval timeout; /*!< \brief expiration time */
+ unsigned int active : 1; /*!< \brief is it active? */
+
+ void (*cb)(void*); /*!< \brief call-back called at timeout */
+ void *data; /*!< \brief user data for callback */
+};
+
+/**
+ * timer management
+ */
+
+void osmo_timer_add(struct osmo_timer_list *timer);
+
+void osmo_timer_schedule(struct osmo_timer_list *timer, int seconds, int microseconds);
+
+void osmo_timer_del(struct osmo_timer_list *timer);
+
+int osmo_timer_pending(struct osmo_timer_list *timer);
+
+int osmo_timer_remaining(const struct osmo_timer_list *timer,
+ const struct timeval *now,
+ struct timeval *remaining);
+/*
+ * internal timer list management
+ */
+struct timeval *osmo_timers_nearest(void);
+void osmo_timers_prepare(void);
+int osmo_timers_update(void);
+int osmo_timers_check(void);
+
+/*! @} */
+
+#endif
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/timer_compat.h b/apps/osmocomBB/libosmocore/include/osmocom/core/timer_compat.h
new file mode 100644
index 0000000000..d86c109e2d
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/timer_compat.h
@@ -0,0 +1,79 @@
+/*
+ * (C) 2011 Sylvain Munaut <tnt@246tNt.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.
+ *
+ */
+
+/*! \defgroup timer Osmocom timers
+ * @{
+ */
+
+/*! \file timer_compat.h
+ * \brief Compatibility header with some helpers
+ */
+
+#ifndef TIMER_COMPAT_H
+#define TIMER_COMPAT_H
+
+
+/* Convenience macros for operations on timevals.
+ NOTE: `timercmp' does not work for >= or <=. */
+
+#ifndef timerisset
+# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
+#endif
+
+#ifndef timerclear
+# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+#endif
+
+#ifndef timercmp
+# define timercmp(a, b, CMP) \
+ (((a)->tv_sec == (b)->tv_sec) ? \
+ ((a)->tv_usec CMP (b)->tv_usec) : \
+ ((a)->tv_sec CMP (b)->tv_sec))
+#endif
+
+#ifndef timeradd
+# define timeradd(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
+ if ((result)->tv_usec >= 1000000) \
+ { \
+ ++(result)->tv_sec; \
+ (result)->tv_usec -= 1000000; \
+ } \
+ } while (0)
+#endif
+
+#ifndef timersub
+# define timersub(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+
+
+/*! @} */
+
+#endif /* TIMER_COMPAT_H */
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/utils.h b/apps/osmocomBB/libosmocore/include/osmocom/core/utils.h
new file mode 100644
index 0000000000..03861d7899
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/utils.h
@@ -0,0 +1,56 @@
+#ifndef OSMOCORE_UTIL_H
+#define OSMOCORE_UTIL_H
+
+/*! \defgroup utils General-purpose utility functions
+ * @{
+ */
+
+/*! \file utils.h */
+
+/*! \brief Determine number of elements in an array of static size */
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+/*! \brief Return the maximum of two specified values */
+#define OSMO_MAX(a, b) ((a) >= (b) ? (a) : (b))
+/*! \brief Return the minimum of two specified values */
+#define OSMO_MIN(a, b) ((a) >= (b) ? (b) : (a))
+
+#include <stdint.h>
+
+/*! \brief A mapping between human-readable string and numeric value */
+struct value_string {
+ unsigned int value; /*!< \brief numeric value */
+ const char *str; /*!< \brief human-readable string */
+};
+
+const char *get_value_string(const struct value_string *vs, uint32_t val);
+
+int get_string_value(const struct value_string *vs, const char *str);
+
+char osmo_bcd2char(uint8_t bcd);
+/* only works for numbers in ascci */
+uint8_t osmo_char2bcd(char c);
+
+int osmo_hexparse(const char *str, uint8_t *b, int max_len);
+
+char *osmo_ubit_dump(const uint8_t *bits, unsigned int len);
+char *osmo_hexdump(const unsigned char *buf, int len);
+char *osmo_hexdump_nospc(const unsigned char *buf, int len);
+char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len) __attribute__((__deprecated__));
+
+#define osmo_static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
+
+void osmo_str2lower(char *out, const char *in);
+void osmo_str2upper(char *out, const char *in);
+
+#define OSMO_SNPRINTF_RET(ret, rem, offset, len) \
+do { \
+ len += ret; \
+ if (ret > rem) \
+ ret = rem; \
+ offset += ret; \
+ rem -= ret; \
+} while (0)
+
+/*! @} */
+
+#endif
diff --git a/apps/osmocomBB/libosmocore/include/osmocom/core/write_queue.h b/apps/osmocomBB/libosmocore/include/osmocom/core/write_queue.h
new file mode 100644
index 0000000000..816c03649e
--- /dev/null
+++ b/apps/osmocomBB/libosmocore/include/osmocom/core/write_queue.h
@@ -0,0 +1,63 @@
+/* Generic write queue implementation */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by On-Waves
+ *
+ * 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 OSMO_WQUEUE_H
+#define OSMO_WQUEUE_H
+
+/*! \defgroup write_queue Osmocom msgb write queues
+ * @{
+ */
+
+/*! \file write_queue.h
+ */
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
+
+/*! write queue instance */
+struct osmo_wqueue {
+ /*! \brief osmocom file descriptor */
+ struct osmo_fd bfd;
+ /*! \brief maximum length of write queue */
+ unsigned int max_length;
+ /*! \brief current length of write queue */
+ unsigned int current_length;
+
+ /*! \brief actual linked list implementing the queue */
+ struct llist_head msg_queue;
+
+ /*! \brief call-back in case qeueue is readable */
+ int (*read_cb)(struct osmo_fd *fd);
+ /*! \brief call-back in case qeueue is writable */
+ int (*write_cb)(struct osmo_fd *fd, struct msgb *msg);
+ /*! \brief call-back in case qeueue has exceptions */
+ int (*except_cb)(struct osmo_fd *fd);
+};
+
+void osmo_wqueue_init(struct osmo_wqueue *queue, int max_length);
+void osmo_wqueue_clear(struct osmo_wqueue *queue);
+int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data);
+int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what);
+
+/*! @} */
+
+#endif