Merge commit 'fe28dedd4c25b5f0f3df39d5e33ce3639574406c'

This commit is contained in:
Sylvain Munaut 2011-09-02 22:21:13 +02:00
commit 176f72a2ed
71 changed files with 9404 additions and 527 deletions

View File

@ -21,6 +21,12 @@ ltmain.sh
install-sh
stamp-h1
libtool
libosmocore-*.tar.*
Doxyfile.core
Doxyfile.gsm
Doxyfile.vty
Doxyfile.codec
.tarball-version
.version
@ -30,3 +36,11 @@ tests/timer/timer_test
tests/msgfile/msgfile_test
tests/ussd/ussd_test
tests/smscb/smscb_test
utils/osmo-arfcn
doc/codec
doc/core
doc/vty
doc/gsm
doc/html.tar

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
ACLOCAL_AMFLAGS = -I m4
INCLUDES = $(all_includes) -I$(top_srcdir)/include
SUBDIRS = include src tests
SUBDIRS = include src tests utils
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc libosmogsm.pc
@ -14,3 +14,47 @@ dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version
EXTRA_DIST = git-version-gen
if HAVE_DOXYGEN
pkgdocdir=$(docdir)/$(PACKAGE)-$(VERSION)
doc_htmldir=$(pkgdocdir)/html
doc_html_DATA = $(top_builddir)/doc/html.tar
$(doc_html_DATA): $(top_builddir)/doc/core/html/index.html \
$(top_builddir)/doc/gsm/html/index.html \
$(top_builddir)/doc/vty/html/index.html \
$(top_builddir)/doc/codec/html/index.html
cd $(top_builddir)/doc && tar cf html.tar */html
$(top_builddir)/doc/core/html/index.html: $(SOURCES) Doxyfile.core
@rm -rf doc/core
mkdir -p doc/core
$(DOXYGEN) Doxyfile.core
$(top_builddir)/doc/gsm/html/index.html: $(SOURCES) Doxyfile.gsm
@rm -rf doc/gsm
mkdir -p doc/gsm
$(DOXYGEN) Doxyfile.gsm
$(top_builddir)/doc/vty/html/index.html: $(SOURCES) Doxyfile.vty
@rm -rf doc/vty
mkdir -p doc/vty
$(DOXYGEN) Doxyfile.vty
$(top_builddir)/doc/codec/html/index.html: $(SOURCES) Doxyfile.codec
@rm -rf doc/codec
mkdir -p doc/codec
$(DOXYGEN) Doxyfile.codec
install-data-hook:
cd $(DESTDIR)$(doc_htmldir) && tar xf html.tar && rm -f html.tar
uninstall-hook:
cd $(DESTDIR)$(doc_htmldir) && rm -rf {core,gsm,vty,codec}
DX_CLEAN = doc/{core,gsm,vty,codec}/{html,latex}/* doc/html.tar
endif
MOSTLYCLEANFILES = $(DX_CLEAN)

View File

@ -20,6 +20,9 @@ dnl checks for header files
AC_HEADER_STDC
AC_CHECK_HEADERS(execinfo.h sys/select.h sys/socket.h syslog.h ctype.h)
AC_PATH_PROG(DOXYGEN,doxygen,false)
AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
# The following test is taken from WebKit's webkit.m4
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fvisibility=hidden "
@ -39,40 +42,40 @@ AC_ARG_ENABLE(talloc,
[--disable-talloc],
[Disable building talloc memory allocator]
)],
[enable_talloc=0], [enable_talloc=1])
AM_CONDITIONAL(ENABLE_TALLOC, test "x$enable_talloc" = "x1")
[enable_talloc=$enableval], [enable_talloc="yes"])
AM_CONDITIONAL(ENABLE_TALLOC, [test x"$enable_talloc" = x"yes"])
AC_ARG_ENABLE(plugin,
[AS_HELP_STRING(
[--disable-plugin],
[Disable support for dlopen plugins],
)],
[enable_plugin=0], [enable_plugin=1])
AM_CONDITIONAL(ENABLE_PLUGIN, test "x$enable_plugin" = "x1")
[enable_plugin=$enableval], [enable_plugin="yes"])
AM_CONDITIONAL(ENABLE_PLUGIN, test x"$enable_plugin" = x"yes")
AC_ARG_ENABLE(tests,
[AS_HELP_STRING(
[--disable-tests],
[Disable building test programs]
)],
[enable_tests=0], [enable_tests=1])
AM_CONDITIONAL(ENABLE_TESTS, test "x$enable_tests" = "x1")
[enable_tests=$enableval], [enable_tests="yes"])
AM_CONDITIONAL(ENABLE_TESTS, test x"$enable_tests" = x"yes")
AC_ARG_ENABLE(vty,
[AS_HELP_STRING(
[--disable-vty],
[Disable building VTY telnet interface]
)],
[enable_vty=0], [enable_vty=1])
AM_CONDITIONAL(ENABLE_VTY, test "x$enable_vty" = "x1")
[enable_vty=$enableval], [enable_vty="yes"])
AM_CONDITIONAL(ENABLE_VTY, test x"$enable_vty" = x"yes")
AC_ARG_ENABLE(panic_infloop,
[AS_HELP_STRING(
[--enable-panic-infloop],
[Trigger infinite loop on panic rather than fprintf/abort]
)],
[panic_infloop=1], [panic_infloop=0])
if test "x$panic_infloop" = "x1"
[panic_infloop=$enableval], [panic_infloop="no"])
if test x"$panic_infloop" = x"yes"
then
AC_DEFINE([PANIC_INFLOOP],[1],[Use infinite loop on panic rather than fprintf/abort])
fi
@ -82,8 +85,8 @@ AC_ARG_ENABLE(bsc_fd_check,
[--enable-bsc-fd-check],
[Instrument bsc_register_fd to check that the fd is registered]
)],
[fd_check=1], [fd_check=0])
if test "x$fd_check" = "x1"
[fd_check=$enableval], [fd_check="no"])
if test x"$fd_check" = x"no"
then
AC_DEFINE([BSC_FD_CHECK],[1],[Instrument the bsc_register_fd])
fi
@ -93,9 +96,43 @@ AC_ARG_ENABLE(msgfile,
[--disable-msgfile],
[Disable support for the msgfile],
)],
[enable_msgfile=0], [enable_msgfile=1])
AM_CONDITIONAL(ENABLE_MSGFILE, test "x$enable_msgfile" = "x1")
[enable_msgfile=$enableval], [enable_msgfile="yes"])
AM_CONDITIONAL(ENABLE_MSGFILE, test x"$enable_msgfile" = x"yes")
AC_ARG_ENABLE(serial,
[AS_HELP_STRING(
[--disable-serial],
[Disable support for the serial helpers],
)],
[enable_serial=$enableval], [enable_serial="yes"])
AM_CONDITIONAL(ENABLE_SERIAL, test x"$enable_serial" = x"yes")
AC_ARG_ENABLE(utilities,
[AS_HELP_STRING(
[--disable-utilities],
[Disable building utility programs],
)],
[enable_utilities=$enableval], [enable_utilities="yes"])
AM_CONDITIONAL(ENABLE_UTILITIES, test x"$enable_utilities" = x"yes")
AC_ARG_ENABLE(embedded,
[AS_HELP_STRING(
[--enable-embedded],
[Enable building for embedded use and disable unsupported features]
)],
[embedded=$enableval], [embedded="no"])
if test x"$embedded" = x"yes"
then
AC_DEFINE([EMBEDDED],[1],[Select building for embedded use])
AM_CONDITIONAL(ENABLE_TESTS, false)
AM_CONDITIONAL(ENABLE_PLUGIN, false)
AM_CONDITIONAL(ENABLE_MSGFILE, false)
AM_CONDITIONAL(ENABLE_SERIAL, false)
AM_CONDITIONAL(ENABLE_VTY, false)
AM_CONDITIONAL(ENABLE_TALLOC, false)
AM_CONDITIONAL(ENABLE_UTILITIES, false)
AC_DEFINE([PANIC_INFLOOP],[1],[Use infinite loop on panic rather than fprintf/abort])
fi
AC_OUTPUT(
libosmocore.pc
@ -120,4 +157,10 @@ AC_OUTPUT(
tests/msgfile/Makefile
tests/ussd/Makefile
tests/smscb/Makefile
tests/bits/Makefile
utils/Makefile
Doxyfile.core
Doxyfile.gsm
Doxyfile.vty
Doxyfile.codec
Makefile)

View File

View File

@ -2,11 +2,23 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \
bitvec.h statistics.h utils.h socket.h \
gsmtap.h write_queue.h prim.h \
logging.h rate_ctr.h gsmtap_util.h \
plugin.h crc16.h panic.h process.h msgfile.h \
crc16.h panic.h process.h \
backtrace.h conv.h application.h
if ENABLE_PLUGIN
osmocore_HEADERS += plugin.h
endif
if ENABLE_TALLOC
osmocore_HEADERS += talloc.h
endif
if ENABLE_MSGFILE
osmocore_HEADERS += msgfile.h
endif
if ENABLE_SERIAL
osmocore_HEADERS += serial.h
endif
osmocoredir = $(includedir)/osmocom/core

View File

@ -1,13 +1,18 @@
#ifndef OSMO_APPLICATION_H
#define OSMO_APPLICATION_H
/**
* Routines for helping with the application setup.
/*!
* \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);

View File

@ -3,9 +3,17 @@
#include <stdint.h>
typedef int8_t sbit_t; /* soft bit (-127...127) */
typedef uint8_t ubit_t; /* unpacked bit (0 or 1) */
typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */
/*! \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:
@ -13,7 +21,9 @@ typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */
Bit i in a pbit_t array is array[i/8] & (1<<(7-i%8))
*/
/* determine how many bytes we would need for 'num_bits' packed bits */
/*! \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;
@ -24,22 +34,45 @@ static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits)
return pbit_bytesize;
}
/* convert unpacked bits to packed bits, return length in bytes */
int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits);
/* convert packed bits to unpacked bits, return length in bytes */
int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits);
/* convert unpacked bits to packed bits (extended options but slower),
* return length in bytes (max written ofs of output buffer + 1) */
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);
/* convert packed bits to unpacked bits (extended options but slower),
* return length in bytes (max written ofs of output buffer + 1) */
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);
#endif
/* 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 */

View File

@ -23,56 +23,48 @@
*
*/
/*! \defgroup bitvec Bit vectors
* @{
*/
/*! \file bitvec.h
* \brief Osmocom bit vector abstraction
*/
#include <stdint.h>
/* In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are
/*! \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,
ONE = 1,
L = 2,
H = 3,
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; /* curser to the next unused bit */
unsigned int data_len; /* length of data array in bytes */
uint8_t *data; /* pointer to data array */
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 */
};
/* check if the bit is 0 or 1 for a given position inside a bitvec */
enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr);
/* check if the bit is L or H for a given position inside a bitvec */
enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv,
unsigned int bitnr);
/* get the Nth set bit inside the bit vector */
unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n);
/* Set a bit at given position */
int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
enum bit_value bit);
/* Set the next bit in the vector */
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
/* get the next bit (low/high) inside a bitvec */
int bitvec_get_bit_high(struct bitvec *bv);
/* Set multiple bits at the current position */
int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
/* Add an unsigned integer (of length count bits) to current position */
int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
/* get multiple bits (based on numeric value) from current pos */
int bitvec_get_uint(struct bitvec *bv, int num_bits);
/* find the first bit set in bit vector */
int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val);
/* Pad the bit vector up to a certain bit position */
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
/*! }@ */
#endif /* _BITVEC_H */

View File

@ -20,6 +20,14 @@
* 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__
@ -27,6 +35,7 @@
#include <osmocom/core/bits.h>
/*! \brief structure describing a given convolutional code */
struct osmo_conv_code {
int N;
int K;
@ -45,11 +54,12 @@ struct osmo_conv_code {
/* Encoding */
/* Low level API */
/*! \brief convolutional encoder state */
struct osmo_conv_encoder {
const struct osmo_conv_code *code;
int i_idx; /* Next input bit index */
int p_idx; /* Current puncture index */
uint8_t state; /* Current state */
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,
@ -66,19 +76,21 @@ int osmo_conv_encode(const struct osmo_conv_code *code,
/* Decoding */
/* Low level API */
/*! \brief convolutional decoder state */
struct osmo_conv_decoder {
/*! \brief description of convolutional code */
const struct osmo_conv_code *code;
int n_states;
int n_states; /*!< \brief number of states */
int len; /* Max o_idx (excl. termination) */
int len; /*!< \brief Max o_idx (excl. termination) */
int o_idx; /* output index */
int p_idx; /* puncture index */
int o_idx; /*!< \brief output index */
int p_idx; /*!< \brief puncture index */
unsigned int *ae; /* accumulater error */
unsigned int *ae_next; /* next accumulated error (tmp in scan) */
uint8_t *state_history; /* state history [len][n_states] */
unsigned int *ae; /*!< \brief accumulater 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,
@ -98,4 +110,6 @@ int osmo_conv_decode(const struct osmo_conv_code *code,
const sbit_t *input, ubit_t *output);
/*! }@ */
#endif /* __OSMO_CONV_H__ */

View File

@ -5,46 +5,41 @@
#include <osmocom/core/write_queue.h>
#include <osmocom/core/select.h>
/* convert RSL channel number to GSMTAP channel type */
/*! \defgroup gsmtap GSMTAP
* @{
*/
/*! \file gsmtap_util.h */
uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id);
/* generate msgb from data + metadata */
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);
/* one gsmtap instance */
/*! \brief one gsmtap instance */
struct gsmtap_inst {
int ofd_wq_mode;
struct osmo_wqueue wq;
struct osmo_fd sink_ofd;
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;
}
/* Open a GSMTAP source (sending) socket, conncet it to host/port and
* return resulting fd */
int gsmtap_source_init_fd(const char *host, uint16_t port);
/* Add a local sink to an existing GSMTAP source and return fd */
int gsmtap_source_add_sink_fd(int gsmtap_fd);
/* Open GSMTAP source (sending) socket, connect it to host/port,
* allocate 'struct gsmtap_inst' and optionally osmo_fd/osmo_wqueue
* registration */
struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port,
int ofd_wq_mode);
/* Add a local sink to an existing GSMTAP source instance */
int gsmtap_source_add_sink(struct gsmtap_inst *gti);
/* Send a msgb through a GSMTAP source */
int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg);
/* generate a message and send it via GSMTAP */
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,

View File

@ -1,11 +1,20 @@
#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
@ -19,20 +28,35 @@
#endif
void osmo_vlogp(int subsys, int level, char *file, int line,
int cont, const char *format, va_list ap);
void logp(int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
/* new logging interface */
/*! \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)
/* different levels */
#define LOGL_DEBUG 1 /* debugging information */
/*! \brief different log levels */
#define LOGL_DEBUG 1 /*!< \brief debugging information */
#define LOGL_INFO 3
#define LOGL_NOTICE 5 /* abnormal/unexpected condition */
#define LOGL_ERROR 7 /* error condition, requires user action */
#define LOGL_FATAL 8 /* fatal, program aborted */
#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
@ -50,53 +74,67 @@ struct log_category {
uint8_t enabled;
};
/*! \brief Information regarding one logging category */
struct log_info_cat {
const char *name;
const char *color;
const char *description;
uint8_t loglevel;
uint8_t enabled;
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 */
};
/* log context information, passed to filter */
/*! \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 {
/* filter callback function */
/* \brief filter callback function */
log_filter *filter_fn;
/* per-category information */
/*! \brief per-category information */
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,
LOG_TGT_TYPE_SYSLOG,
LOG_TGT_TYPE_FILE,
LOG_TGT_TYPE_STDERR,
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;
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 the type of this log taget */
enum log_target_type type;
union {
@ -115,6 +153,12 @@ struct log_target {
} 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);
};
@ -161,4 +205,6 @@ 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 */

View File

@ -24,39 +24,47 @@
#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;
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;
void *dst; /*!< \brief reference of origin/destination */
struct gsm_bts_trx *trx;
};
struct gsm_lchan *lchan;
struct gsm_lchan *lchan; /*!< \brief logical channel */
/* the Layer1 header (if any) */
unsigned char *l1h;
/* the A-bis layer 2 header: OML, RSL(RLL), NS */
unsigned char *l2h;
/* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */
unsigned char *l3h;
/* the layer 4 header */
unsigned char *l4h;
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 */
/* the 'control buffer', large enough to contain 5 pointers */
unsigned long cb[5];
unsigned long cb[5]; /*!< \brief control buffer */
uint16_t data_len;
uint16_t len;
uint16_t data_len; /*!< \brief length of underlying data array */
uint16_t len; /*!< \brief length of bytes used in msgb */
unsigned char *head;
unsigned char *tail;
unsigned char *data;
unsigned char _data[0];
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);
@ -74,41 +82,99 @@ extern void msgb_reset(struct msgb *m);
#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;
@ -119,17 +185,32 @@ static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int 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);
@ -138,6 +219,11 @@ static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
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;
@ -145,21 +231,46 @@ static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int 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)
@ -169,19 +280,48 @@ static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int 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;
}
/* increase the headroom of an empty msgb, reducing the tailroom */
/*! \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 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)
{
@ -194,10 +334,11 @@ static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
}
/* non inline functions to ease binding */
uint8_t *msgb_data(const struct msgb *msg);
uint16_t msgb_length(const struct msgb *msg);
/* set the talloc context for msgb_alloc[_headroom] */
void msgb_set_talloc_ctx(void *ctx);
/*! }@ */
#endif /* _MSGB_H */

View File

@ -1,11 +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
/*! @} */
#endif /* OSMOCORE_PANIC_H */

View File

@ -1,14 +1,21 @@
#ifndef OSMO_PRIMITIVE_H
#define OSMO_PRIMITIVE_H
/*! \defgroup prim Osmocom primitives
* @{
*/
/*! \file prim.c */
#include <stdint.h>
#include <osmocom/core/msgb.h>
/*! \brief primitive operation */
enum osmo_prim_operation {
PRIM_OP_REQUEST,
PRIM_OP_RESPONSE,
PRIM_OP_INDICATION,
PRIM_OP_CONFIRM,
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
@ -16,13 +23,21 @@ enum osmo_prim_operation {
#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;
unsigned int primitive;
enum osmo_prim_operation operation;
struct msgb *msg; /* message containing associated data */
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,
@ -34,5 +49,7 @@ osmo_prim_init(struct osmo_prim_hdr *oph, unsigned int sap,
oph->msg = msg;
}
/*! \brief primitive handler callback type */
typedef int (*osmo_prim_cb)(struct osmo_prim_hdr *oph, void *ctx);
#endif
#endif /* OSMO_PRIMITIVE_H */

View File

@ -1,80 +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,
RATE_CTR_INTV_MIN,
RATE_CTR_INTV_HOUR,
RATE_CTR_INTV_DAY,
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 */
};
/* for each of the intervals, we keep the following values */
/*! \brief data we keep for each of the intervals */
struct rate_ctr_per_intv {
uint64_t last;
uint64_t rate;
uint64_t last; /*!< \brief counter value in last interval */
uint64_t rate; /*!< \brief counter rate */
};
/* for each actual value, we keep the following data */
/*! \brief data we keep for each actual value */
struct rate_ctr {
uint64_t current;
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;
const char *description;
const char *name; /*!< \brief name of the counter */
const char *description;/*!< \brief description of the counter */
};
/* Describe a counter group class */
/*! \brief description of a rate counter group */
struct rate_ctr_group_desc {
/* The prefix to the name of all counters in this group */
/*! \brief The prefix to the name of all counters in this group */
const char *group_name_prefix;
/* The human-readable description of the group */
/*! \brief The human-readable description of the group */
const char *group_description;
/* The number of counters in this group */
/*! \brief The number of counters in this group */
const unsigned int num_ctr;
/* Pointer to array of counter names */
/*! \brief Pointer to array of counter names */
const struct rate_ctr_desc *ctr_desc;
};
/* One instance of a counter group class */
/*! \brief One instance of a counter group class */
struct rate_ctr_group {
/* Linked list of all counter groups in the system */
/*! \brief Linked list of all counter groups in the system */
struct llist_head list;
/* Pointer to the counter group class */
/*! \brief Pointer to the counter group class */
const struct rate_ctr_group_desc *desc;
/* The index of this ctr_group within its class */
/*! \brief The index of this ctr_group within its class */
unsigned int idx;
/* Actual counter structures below */
/*! \brief Actual counter structures below */
struct rate_ctr ctr[0];
};
/* Allocate a new group of counters according to description */
struct rate_ctr_group *rate_ctr_group_alloc(void *ctx,
const struct rate_ctr_group_desc *desc,
unsigned int idx);
/* Free the memory for the specified group of counters */
void rate_ctr_group_free(struct rate_ctr_group *grp);
/* Add a number to the counter */
void rate_ctr_add(struct rate_ctr *ctr, int inc);
/* Increment the counter by 1 */
/*! \brief Increment the counter by 1 */
static inline void rate_ctr_inc(struct rate_ctr *ctr)
{
rate_ctr_add(ctr, 1);
}
/* Initialize the counter module */
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 */

View File

@ -3,20 +3,43 @@
#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 {
struct llist_head list;
/*! 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 */

View File

@ -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__ */

View File

@ -3,13 +3,18 @@
#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 2147483648
#define OSMO_SIGNAL_SS_RESERVED 2147483648u
/* signal subsystems. */
/*! \brief signal subsystems */
enum {
SS_L_GLOBAL = OSMO_SIGNAL_SS_RESERVED,
SS_L_INPUT,
@ -17,13 +22,14 @@ enum {
/* application-defined signal types. */
#define OSMO_SIGNAL_T_APPS 0
#define OSMO_SIGNAL_T_RESERVED 2147483648
#define OSMO_SIGNAL_T_RESERVED 2147483648u
/* signal types. */
/*! \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);
@ -34,4 +40,6 @@ void osmo_signal_unregister_handler(unsigned int subsys, osmo_signal_cbfn *cbfn,
/* Dispatch */
void osmo_signal_dispatch(unsigned int subsys, unsigned int signal, void *signal_data);
/*! }@ */
#endif /* OSMO_SIGNAL_H */

View File

@ -1,6 +1,14 @@
#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;
@ -19,7 +27,8 @@ int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
uint8_t proto, unsigned int flags);
/* determine if the given address is a local address */
int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen);
/*! }@ */
#endif /* _OSMOCORE_SOCKET_H */

View File

@ -1,33 +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;
const char *name;
const char *description;
unsigned long value;
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 */

View File

@ -18,6 +18,14 @@
*
*/
/*! \defgroup timer Osmocom timers
* @{
*/
/*! \file timer.h
* \brief Osmocom timer handling routines
*/
#ifndef TIMER_H
#define TIMER_H
@ -41,27 +49,32 @@
* the timers.
*
*/
/*! \brief A structure representing a single instance of a timer */
struct osmo_timer_list {
struct llist_head entry;
struct timeval timeout;
unsigned int active : 1;
unsigned int handled : 1;
unsigned int in_list : 1;
struct llist_head entry; /*!< \brief linked list header */
struct timeval timeout; /*!< \brief expiration time */
unsigned int active : 1; /*!< \brief is it active? */
unsigned int handled : 1; /*!< \brief did we already handle it */
unsigned int in_list : 1; /*!< \brief is it in the global list? */
void (*cb)(void*);
void *data;
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);
/**
/*
* internal timer list management
*/
struct timeval *osmo_timers_nearest(void);
@ -69,4 +82,6 @@ void osmo_timers_prepare(void);
int osmo_timers_update(void);
int osmo_timers_check(void);
/*! }@ */
#endif

View File

@ -1,18 +1,29 @@
#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;
const char *str;
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);
@ -20,9 +31,10 @@ char osmo_bcd2char(uint8_t bcd);
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_osmo_hexdump_nospc(const unsigned char *buf, int len);
char *osmo_ubit_dump(const uint8_t *bits, unsigned int len);
#define osmo_static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
@ -38,4 +50,6 @@ do { \
rem -= ret; \
} while (0)
/*! }@ */
#endif

View File

@ -23,18 +23,33 @@
#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);
};
@ -43,4 +58,6 @@ 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

View File

@ -1,10 +1,16 @@
#ifndef _OSMO_GSM_ABIS_NM_H
#define _OSMO_GSM_ABIS_NM_H
/*! \defgroup oml A-bis OML
* @{
*/
#include <osmocom/gsm/tlv.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/protocol/gsm_12_21.h>
/*! \file abis_nm.h */
enum abis_nm_msgtype;
enum gsm_phys_chan_config;
@ -28,4 +34,7 @@ void abis_nm_debugp_foh(int ss, struct abis_om_fom_hdr *foh);
int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan);
enum abis_nm_chan_comb abis_nm_pchan4chcomb(uint8_t chcomb);
/*! }@ */
#endif /* _OSMO_GSM_ABIS_NM_H */

View File

@ -7,57 +7,68 @@
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/prim.h>
/*! \defgroup lapdm LAPDm implementation according to GSM TS 04.06
* @{
*/
/*! \file lapdm.h */
/* primitive related sutff */
/*! \brief LAPDm related primitives */
enum osmo_ph_prim {
PRIM_PH_DATA, /* PH-DATA */
PRIM_PH_RACH, /* PH-RANDOM_ACCESS */
PRIM_PH_CONN, /* PH-CONNECT */
PRIM_PH_EMPTY_FRAME, /* PH-EMPTY_FRAME */
PRIM_PH_RTS, /* PH-RTS */
PRIM_PH_DATA, /*!< \brief PH-DATA */
PRIM_PH_RACH, /*!< \brief PH-RANDOM_ACCESS */
PRIM_PH_CONN, /*!< \brief PH-CONNECT */
PRIM_PH_EMPTY_FRAME, /*!< \brief PH-EMPTY_FRAME */
PRIM_PH_RTS, /*!< \brief PH-RTS */
};
/* for PH-RANDOM_ACCESS.req */
/*! \brief for PH-RANDOM_ACCESS.req */
struct ph_rach_req_param {
uint8_t ra;
uint8_t ta;
uint8_t tx_power;
uint8_t is_combined_ccch;
uint16_t offset;
uint8_t ra; /*!< \brief Random Access */
uint8_t ta; /*!< \brief Timing Advance */
uint8_t tx_power; /*!< \brief Transmit Power */
uint8_t is_combined_ccch;/*!< \brief Are we using a combined CCCH? */
uint16_t offset; /*!< \brief Timing Offset */
};
/* for PH-RANDOM_ACCESS.ind */
/*! \brief for PH-RANDOM_ACCESS.ind */
struct ph_rach_ind_param {
uint8_t ra;
uint8_t acc_delay;
uint32_t fn;
uint8_t ra; /*!< \brief Random Access */
uint8_t acc_delay; /*!< \brief Delay in bit periods */
uint32_t fn; /*!< \brief GSM Frame Number at time of RA */
};
/* for PH-[UNIT]DATA.{req,ind} */
/*! \brief for PH-[UNIT]DATA.{req,ind} */
struct ph_data_param {
uint8_t link_id;
uint8_t chan_nr;
uint8_t link_id; /*!< \brief Link Identifier (Like RSL) */
uint8_t chan_nr; /*!< \brief Channel Number (Like RSL) */
};
/*! \brief for PH-CONN.ind */
struct ph_conn_ind_param {
uint32_t fn;
uint32_t fn; /*!< \brief GSM Frame Number */
};
/*! \brief primitive header for LAPDm PH-SAP primitives */
struct osmo_phsap_prim {
struct osmo_prim_hdr oph;
struct osmo_prim_hdr oph; /*!< \brief generic primitive header */
union {
struct ph_data_param data;
struct ph_rach_req_param rach_req;
struct ph_rach_ind_param rach_ind;
struct ph_conn_ind_param conn_ind;
} u;
} u; /*!< \brief request-specific data */
};
/*! \brief LAPDm mode/role */
enum lapdm_mode {
LAPDM_MODE_MS,
LAPDM_MODE_BTS,
LAPDM_MODE_MS, /*!< \brief behave like a MS (mobile phone) */
LAPDM_MODE_BTS, /*!< \brief behave like a BTS (network) */
};
/*! \brief LAPDm state */
enum lapdm_state {
LAPDm_STATE_NULL = 0,
LAPDm_STATE_IDLE,
@ -69,6 +80,7 @@ enum lapdm_state {
struct lapdm_entity;
/*! \brief LAPDm message context */
struct lapdm_msg_ctx {
struct lapdm_datalink *dl;
int lapdm_fmt;
@ -81,33 +93,35 @@ struct lapdm_msg_ctx {
uint8_t tx_power_ind;
};
/* TS 04.06 / Section 3.5.2 */
/*! \brief LAPDm datalink like TS 04.06 / Section 3.5.2 */
struct lapdm_datalink {
uint8_t V_send; /* seq nr of next I frame to be transmitted */
uint8_t V_ack; /* last frame ACKed by peer */
uint8_t N_send; /* ? set to V_send at Tx time*/
uint8_t V_recv; /* seq nr of next I frame expected to be received */
uint8_t N_recv; /* expected send seq nr of the next received I frame */
uint32_t state;
int seq_err_cond; /* condition of sequence error */
uint8_t own_busy, peer_busy;
struct osmo_timer_list t200;
uint8_t retrans_ctr;
struct llist_head send_queue; /* frames from L3 */
struct msgb *send_buffer; /* current frame transmitting */
int send_out; /* how much was sent from send_buffer */
uint8_t tx_hist[8][200]; /* tx history buffer */
int tx_length[8]; /* length in history buffer */
struct llist_head tx_queue; /* frames to L1 */
struct lapdm_msg_ctx mctx; /* context of established connection */
struct msgb *rcv_buffer; /* buffer to assemble the received message */
uint8_t V_send; /*!< \brief seq nr of next I frame to be transmitted */
uint8_t V_ack; /*!< \brief last frame ACKed by peer */
uint8_t N_send; /*!< \brief ? set to V_send at Tx time*/
uint8_t V_recv; /*!< \brief seq nr of next I frame expected to be received */
uint8_t N_recv; /*!< \brief expected send seq nr of the next received I frame */
uint32_t state; /*!< \brief LAPDm state (\ref lapdm_state) */
int seq_err_cond; /*!< \brief condition of sequence error */
uint8_t own_busy; /*!< \brief receiver busy on our side */
uint8_t peer_busy; /*!< \brief receiver busy on remote side */
struct osmo_timer_list t200; /*!< \brief T200 timer */
uint8_t retrans_ctr; /*!< \brief re-transmission counter */
struct llist_head send_queue; /*!< \brief frames from L3 */
struct msgb *send_buffer; /*!< \brief current frame transmitting */
int send_out; /*!< \brief how much was sent from send_buffer */
uint8_t tx_hist[8][200]; /*!< \brief tx history buffer */
int tx_length[8]; /*!< \brief length in history buffer */
struct llist_head tx_queue; /*!< \brief frames to L1 */
struct lapdm_msg_ctx mctx; /*!< \brief context of established connection */
struct msgb *rcv_buffer; /*!< \brief buffer to assemble the received message */
struct lapdm_entity *entity;
struct lapdm_entity *entity; /*!< \brief LAPDm entity we are part of */
};
/*! \brief LAPDm datalink SAPIs */
enum lapdm_dl_sapi {
DL_SAPI0 = 0,
DL_SAPI3 = 1,
DL_SAPI0 = 0, /*!< \brief SAPI 0 */
DL_SAPI3 = 1, /*!< \brief SAPI 1 */
_NR_DL_SAPI
};
@ -121,35 +135,37 @@ struct lapdm_cr_ent {
#define LAPDM_ENT_F_EMPTY_FRAME 0x0001
#define LAPDM_ENT_F_POLLING_ONLY 0x0002
/* register message handler for messages that are sent from L2->L3 */
/*! \brief a LAPDm Entity */
struct lapdm_entity {
/*! \brief the SAPIs of the LAPDm entity */
struct lapdm_datalink datalink[_NR_DL_SAPI];
int last_tx_dequeue; /* last entity that was dequeued */
int tx_pending; /* currently a pending frame not confirmed by L1 */
enum lapdm_mode mode; /* are we in BTS mode or MS mode */
int last_tx_dequeue; /*!< \brief last entity that was dequeued */
int tx_pending; /*!< \brief currently a pending frame not confirmed by L1 */
enum lapdm_mode mode; /*!< \brief are we in BTS mode or MS mode */
unsigned int flags;
struct {
/* filled-in once we set the lapdm_mode above */
/*! \brief filled-in once we set the lapdm_mode above */
struct lapdm_cr_ent loc2rem;
struct lapdm_cr_ent rem2loc;
} cr;
void *l1_ctx; /* context for layer1 instance */
void *l3_ctx; /* context for layer3 instance */
void *l1_ctx; /*!< \brief context for layer1 instance */
void *l3_ctx; /*!< \brief context for layer3 instance */
osmo_prim_cb l1_prim_cb;
lapdm_cb_t l3_cb; /* callback for sending stuff to L3 */
osmo_prim_cb l1_prim_cb;/*!< \brief callback for sending prims to L1 */
lapdm_cb_t l3_cb; /*!< \brief callback for sending stuff to L3 */
/*! \brief pointer to \ref lapdm_channel of which we're part */
struct lapdm_channel *lapdm_ch;
};
/* the two lapdm_entities that form a GSM logical channel (ACCH + DCCH) */
/*! \brief the two lapdm_entities that form a GSM logical channel (ACCH + DCCH) */
struct lapdm_channel {
struct llist_head list;
char *name;
struct lapdm_entity lapdm_acch;
struct lapdm_entity lapdm_dcch;
struct llist_head list; /*!< \brief internal linked list */
char *name; /*!< \brief human-readable name */
struct lapdm_entity lapdm_acch; /*!< \brief Associated Control Channel */
struct lapdm_entity lapdm_dcch; /*!< \brief Dedicated Control Channel */
};
const char *get_rsl_name(int value);
@ -183,4 +199,6 @@ void lapdm_channel_set_flags(struct lapdm_channel *lc, unsigned int flags);
int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp);
/*! }@ */
#endif /* _OSMOCOM_LAPDM_H */

View File

@ -25,51 +25,65 @@
#include <stdint.h>
/*! \addtogroup rsl
* @{
*/
/*! \file gsm_08_58.h */
/*! \brief RSL common header */
struct abis_rsl_common_hdr {
uint8_t msg_discr;
uint8_t msg_type;
uint8_t data[0];
uint8_t msg_discr; /*!< \brief message discriminator (ABIS_RSL_MDISC_*) */
uint8_t msg_type; /*!< \brief message type (\ref abis_rsl_msgtype) */
uint8_t data[0]; /*!< \brief actual payload data */
} __attribute__ ((packed));
/* Chapter 8.3 */
/* \brief RSL RLL header (Chapter 8.3) */
struct abis_rsl_rll_hdr {
struct abis_rsl_common_hdr c;
uint8_t ie_chan;
uint8_t chan_nr;
uint8_t ie_link_id;
uint8_t link_id;
uint8_t data[0];
uint8_t ie_chan; /*!< \brief \ref RSL_IE_CHAN_NR (tag) */
uint8_t chan_nr; /*!< \brief RSL channel number (value) */
uint8_t ie_link_id; /*!< \brief \ref RSL_IE_LINK_IDENT (tag) */
uint8_t link_id; /*!< \brief RSL link identifier (value) */
uint8_t data[0]; /*!< \brief message payload data */
} __attribute__ ((packed));
/* Chapter 8.3 and 8.4 */
/* \brief RSL Dedicated Channel header (Chapter 8.3 and 8.4) */
struct abis_rsl_dchan_hdr {
struct abis_rsl_common_hdr c;
uint8_t ie_chan;
uint8_t chan_nr;
uint8_t data[0];
uint8_t ie_chan; /*!< \brief \ref RSL_IE_CHAN_NR (tag) */
uint8_t chan_nr; /*!< \brief RSL channel number (value) */
uint8_t data[0]; /*!< \brief message payload data */
} __attribute__ ((packed));
/* Chapter 8.5 */
/* \brief RSL Common Channel header (Chapter 8.5) */
struct abis_rsl_cchan_hdr {
struct abis_rsl_common_hdr c;
uint8_t ie_chan;
uint8_t chan_nr;
uint8_t data[0];
uint8_t ie_chan; /*!< \brief \ref RSL_IE_CHAN_NR (tag) */
uint8_t chan_nr; /*!< \brief RSL channel number (value) */
uint8_t data[0]; /*!< \brief message payload data */
} __attribute__ ((packed));
/* Chapter 9.1 */
/* \brief RSL Message Discriminator: RLL */
#define ABIS_RSL_MDISC_RLL 0x02
/* \brief RSL Message Discriminator: Dedicated Channel */
#define ABIS_RSL_MDISC_DED_CHAN 0x08
/* \brief RSL Message Discriminator: Common Channel */
#define ABIS_RSL_MDISC_COM_CHAN 0x0c
/* \brief RSL Message Discriminator: TRX Management */
#define ABIS_RSL_MDISC_TRX 0x10
/* \brief RSL Message Discriminator: Location Service */
#define ABIS_RSL_MDISC_LOC 0x20
/* \brief RSL Message Discriminator: ip.access */
#define ABIS_RSL_MDISC_IPACCESS 0x7e
#define ABIS_RSL_MDISC_TRANSP 0x01
/* \brief Check if given RSL message discriminator is transparent */
#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01)
/* Chapter 9.1 */
/* \brief RSL Message Tyoe (Chapter 9.1) */
enum abis_rsl_msgtype {
/* Radio Link Layer Management */
RSL_MT_DATA_REQ = 0x01,
@ -169,7 +183,7 @@ enum abis_rsl_msgtype {
RSL_MT_IPAC_DLCX_NACK,
};
/* Siemens vendor-specific */
/*! \brief Siemens vendor-specific RSL message types */
enum abis_rsl_msgtype_siemens {
RSL_MT_SIEMENS_MRPCI = 0x41,
RSL_MT_SIEMENS_INTRAC_HO_COND_IND = 0x42,
@ -189,7 +203,7 @@ enum abis_rsl_msgtype_siemens {
RSL_MT_SIEMENS_MODIF_COND_IND = 0x50,
};
/* Chapter 9.3 */
/*! \brief RSL Information Element Identifiers (Chapter 9.3) */
enum abis_rsl_ie {
RSL_IE_CHAN_NR = 0x01,
RSL_IE_LINK_IDENT,
@ -302,7 +316,7 @@ enum abis_rsl_ie {
#define RSL_ACT_SECOND_ADD 0x04
#define RSL_ACT_SECOND_MULTI 0x05
/* Chapter 9.3.6 */
/*! \brief RSL Channel Mode IF (Chapter 9.3.6) */
struct rsl_ie_chan_mode {
uint8_t dtx_dtu;
uint8_t spd_ind;
@ -329,7 +343,7 @@ enum rsl_cmod_spd {
#define RSL_CMOD_SP_NT_12k0 0x50
#define RSL_CMOD_SP_NT_6k0 0x51
/* Chapter 9.3.5 */
/*! \brief RSL Channel Identification IE (Chapter 9.3.5) */
struct rsl_ie_chan_ident {
/* GSM 04.08 10.5.2.5 */
struct {
@ -441,7 +455,7 @@ struct rsl_ie_chan_ident {
#define RSL_CHANNEED_TCH_F 0x02
#define RSL_CHANNEED_TCH_ForH 0x03
/* Chapter 9.3.45 */
/*! \brief RSL Cell Broadcast Command (Chapter 9.3.45) */
struct rsl_ie_cb_cmd_type {
uint8_t last_block:2;
uint8_t spare:1;
@ -542,5 +556,6 @@ enum rsl_mrpci_phase {
RSL_MRPCI_PHASE_2PLUS = 3,
};
/*! }@ */
#endif /* PROTO_GSM_08_58_H */

View File

@ -23,43 +23,66 @@
*
*/
/*! \addtogroup oml
* @{
*/
/*! \file gsm_12_21.h */
#include <stdint.h>
#include <osmocom/gsm/tlv.h>
/* generic header in front of every OML message according to TS 08.59 */
/*! \brief generic header in front of every OML message according to TS 08.59 */
struct abis_om_hdr {
/*! \brief Message Discriminator \ref abis_oml_mdisc */
uint8_t mdisc;
/*! \brief Placement (like \ref ABIS_OM_PLACEMENT_ONLY) */
uint8_t placement;
/*! \brief Sequence Number (if \ref ABIS_OM_PLACEMENT_MIDDLE) */
uint8_t sequence;
/*! \brief Length in octets */
uint8_t length;
/*! \brief actual payload data */
uint8_t data[0];
} __attribute__ ((packed));
/*! \brief Message Discriminator for Formatted Object Messages */
#define ABIS_OM_MDISC_FOM 0x80
/*! \brief Message Discriminator for Man Machine Interface */
#define ABIS_OM_MDISC_MMI 0x40
/*! \brief Message Discriminator for TRAU management */
#define ABIS_OM_MDISC_TRAU 0x20
/*! \brief Message Discriminator for Manufacturer Specific Messages */
#define ABIS_OM_MDISC_MANUF 0x10
/*! \brief Entire OML message is in the L2 frame */
#define ABIS_OM_PLACEMENT_ONLY 0x80
/*! \brief First fragment of OML message is in this L2 frame */
#define ABIS_OM_PLACEMENT_FIRST 0x40
/*! \brief Middle fragment of OML message is in this L2 frame */
#define ABIS_OM_PLACEMENT_MIDDLE 0x20
/*! \brief Last fragment of OML message is in this L2 frame */
#define ABIS_OM_PLACEMENT_LAST 0x10
/*! \brief OML Object Instance */
struct abis_om_obj_inst {
uint8_t bts_nr;
uint8_t trx_nr;
uint8_t ts_nr;
uint8_t bts_nr; /*!< \brief BTS Number */
uint8_t trx_nr; /*!< \brief TRX Number */
uint8_t ts_nr; /*!< \brief Timeslot Number */
} __attribute__ ((packed));
/*! \brief OML Object Instance */
struct abis_om_fom_hdr {
uint8_t msg_type;
uint8_t obj_class;
struct abis_om_obj_inst obj_inst;
uint8_t data[0];
uint8_t msg_type; /*!< \brief Message Type (\ref abis_nm_msgtype) */
uint8_t obj_class; /*!< \brief Object Class (\ref abis_nm_obj_class) */
struct abis_om_obj_inst obj_inst; /*!< \brief Object Instance */
uint8_t data[0]; /*!< \brief Data */
} __attribute__ ((packed));
/*! \brief Size of the OML FOM header in octets */
#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr))
/* Section 9.1: Message Types */
/*! \brief OML Message Type (Section 9.1) */
enum abis_nm_msgtype {
/* SW Download Management Messages */
NM_MT_LOAD_INIT = 0x01,
@ -170,6 +193,7 @@ enum abis_nm_msgtype {
NM_MT_SET_ALARM_THRES_NACK,
};
/*! \brief Siemens specific OML Message Types */
enum abis_nm_msgtype_bs11 {
NM_MT_BS11_RESET_RESOURCE = 0x74,
@ -205,6 +229,7 @@ enum abis_nm_msgtype_bs11 {
NM_MT_BS11_RECONNECT_ACK,
};
/*! \brief ip.access specific OML Message Types */
enum abis_nm_msgtype_ipacc {
NM_MT_IPACC_RESTART = 0x87,
NM_MT_IPACC_RESTART_ACK,
@ -237,7 +262,7 @@ enum abis_nm_bs11_cell_alloc {
NM_BS11_CANR_DCS1800 = 0x01,
};
/* Section 9.2: Object Class */
/*! \brief OML Object Class (Section 9.2) */
enum abis_nm_obj_class {
NM_OC_SITE_MANAGER = 0x00,
NM_OC_BTS,
@ -268,7 +293,7 @@ enum abis_nm_obj_class {
NM_OC_NULL = 0xff,
};
/* Section 9.4: Attributes */
/*! \brief OML Attributes / IEs (Section 9.4) */
enum abis_nm_attr {
NM_ATT_ABIS_CHANNEL = 0x01,
NM_ATT_ADD_INFO,
@ -464,7 +489,7 @@ enum abis_nm_attr {
};
#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE
/* Section 9.4.4: Administrative State */
/*! \brief OML Administrative State (Section 9.4.4) */
enum abis_nm_adm_state {
NM_STATE_LOCKED = 0x01,
NM_STATE_UNLOCKED = 0x02,
@ -472,7 +497,7 @@ enum abis_nm_adm_state {
NM_STATE_NULL = 0xff,
};
/* Section 9.4.7: Administrative State */
/*! \brief OML Availability State (Section 9.4.7) */
enum abis_nm_avail_state {
NM_AVSTATE_IN_TEST = 1,
NM_AVSTATE_POWER_OFF = 2,
@ -483,13 +508,14 @@ enum abis_nm_avail_state {
NM_AVSTATE_OK = 0xff,
};
/*! \brief OML Operational State */
enum abis_nm_op_state {
NM_OPSTATE_DISABLED = 1,
NM_OPSTATE_ENABLED = 2,
NM_OPSTATE_NULL = 0xff,
};
/* Section 9.4.13: Channel Combination */
/* \brief Channel Combination (Section 9.4.13) */
enum abis_nm_chan_comb {
NM_CHANC_TCHFull = 0x00, /* TCH/F + TCH/H + SACCH/TF */
NM_CHANC_TCHHalf = 0x01, /* TCH/H(0,1) + FACCH/H(0,1) +
@ -512,7 +538,7 @@ enum abis_nm_chan_comb {
NM_CHANC_IPAC_TCHFull_TCHHalf = 0x81,
};
/* Section 9.4.16: Event Type */
/*! \brief Event Type (Section 9.4.16) */
enum abis_nm_event_type {
NM_EVT_COMM_FAIL = 0x00,
NM_EVT_QOS_FAIL = 0x01,
@ -521,7 +547,7 @@ enum abis_nm_event_type {
NM_EVT_ENV_FAIL = 0x04,
};
/* Section: 9.4.63: Perceived Severity */
/*! \brief Perceived Severity (Section: 9.4.63) */
enum abis_nm_severity {
NM_SEVER_CEASED = 0x00,
NM_SEVER_CRITICAL = 0x01,
@ -531,14 +557,14 @@ enum abis_nm_severity {
NM_SEVER_INDETERMINATE = 0x05,
};
/* Section 9.4.43: Probable Cause Type */
/*! \brief Probable Cause Type (Section 9.4.43) */
enum abis_nm_pcause_type {
NM_PCAUSE_T_X721 = 0x01,
NM_PCAUSE_T_GSM = 0x02,
NM_PCAUSE_T_MANUF = 0x03,
};
/* Section 9.4.36: NACK Causes */
/*! \brief NACK causes (Section 9.4.36) */
enum abis_nm_nack_cause {
/* General Nack Causes */
NM_NACK_INCORR_STRUCT = 0x01,
@ -576,15 +602,15 @@ enum abis_nm_nack_cause {
NM_NACK_MEAS_NOTSTART = 0x2c,
};
/* Section 9.4.1 */
/*! \brief Abis OML Channel (Section 9.4.1) */
struct abis_nm_channel {
uint8_t attrib;
uint8_t bts_port;
uint8_t timeslot;
uint8_t subslot;
uint8_t bts_port; /*!< \brief BTS port number */
uint8_t timeslot; /*!< \brief E1 timeslot */
uint8_t subslot; /*!< \brief E1 sub-slot */
} __attribute__ ((packed));
/* Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */
/*! \brief Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */
enum abis_bs11_objtype {
BS11_OBJ_ALCO = 0x01,
BS11_OBJ_BBSIG = 0x02, /* obj_class: 0,1 */
@ -595,6 +621,7 @@ enum abis_bs11_objtype {
BS11_OBJ_PA = 0x09, /* obj_class: 0, 1*/
};
/*! \brief Siemens BS11 TRX power */
enum abis_bs11_trx_power {
BS11_TRX_POWER_GSM_2W = 0x06,
BS11_TRX_POWER_GSM_250mW= 0x07,
@ -606,17 +633,20 @@ enum abis_bs11_trx_power {
BS11_TRX_POWER_DCS_160mW= 0x0d,
};
/*! \brief Siemens BS11 PLL mode */
enum abis_bs11_li_pll_mode {
BS11_LI_PLL_LOCKED = 2,
BS11_LI_PLL_STANDALONE = 3,
};
/*! \brief Siemens BS11 E1 line configuration */
enum abis_bs11_line_cfg {
BS11_LINE_CFG_STAR = 0x00,
BS11_LINE_CFG_MULTIDROP = 0x01,
BS11_LINE_CFG_LOOP = 0x02,
};
/*! \brief Siemens BS11 boot phase */
enum abis_bs11_phase {
BS11_STATE_SOFTWARE_RQD = 0x01,
BS11_STATE_LOAD_SMU_INTENDED = 0x11,
@ -633,6 +663,7 @@ enum abis_bs11_phase {
BS11_STATE_ABIS_LOAD = 0x13,
};
/*! \brief ip.access test number */
enum abis_nm_ipacc_test_no {
NM_IPACC_TESTNO_RLOOP_ANT = 0x01,
NM_IPACC_TESTNO_RLOOP_XCVR = 0x02,
@ -646,7 +677,7 @@ enum abis_nm_ipacc_test_no {
NM_IPACC_TESTNO_BCCCH_MONITOR = 0x46,
};
/* first byte after length inside NM_ATT_TEST_REPORT */
/*! \brief first byte after length inside NM_ATT_TEST_REPORT */
enum abis_nm_ipacc_test_res {
NM_IPACC_TESTRES_SUCCESS = 0,
NM_IPACC_TESTRES_TIMEOUT = 1,
@ -655,7 +686,7 @@ enum abis_nm_ipacc_test_res {
NM_IPACC_TESTRES_STOPPED = 4,
};
/* internal IE inside NM_ATT_TEST_REPORT */
/*! \brief internal IE inside NM_ATT_TEST_REPORT */
enum abis_nm_ipacc_testres_ie {
NM_IPACC_TR_IE_FREQ_ERR_LIST = 3,
NM_IPACC_TR_IE_CHAN_USAGE = 4,
@ -664,6 +695,7 @@ enum abis_nm_ipacc_testres_ie {
NM_IPACC_TR_IE_FREQ_ERR = 18,
};
/*! \brief ip.access IEI */
enum ipac_eie {
NM_IPAC_EIE_ARFCN_WHITE = 0x01,
NM_IPAC_EIE_ARFCH_BLACK = 0x02,
@ -696,6 +728,7 @@ enum ipac_eie {
NM_IPAC_EIE_BTS_ID = 0x25,
};
/*! \brief ip.access NWL BCCH information type */
enum ipac_bcch_info_type {
IPAC_BINF_RXLEV = (1 << 8),
IPAC_BINF_RXQUAL = (1 << 9),
@ -710,4 +743,6 @@ enum ipac_bcch_info_type {
IPAC_BINF_CELL_ALLOC = (1 << 2),
};
/*! }@ */
#endif /* PROTO_GSM_12_21_H */

View File

@ -6,11 +6,19 @@
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
/*! \defgroup rsl RSL
* @{
*/
/*! \file rsl.h */
void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type);
void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type);
extern const struct tlv_definition rsl_att_tlvdef;
/*! \brief Parse RSL TLV structure using \ref tlv_parse */
#define rsl_tlv_parse(dec, buf, len) \
tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
@ -25,6 +33,7 @@ const char *rsl_chan_nr_str(uint8_t chan_nr);
const char *rsl_err_name(uint8_t err);
const char *rsl_rlm_cause_name(uint8_t err);
const char *rsl_msg_name(uint8_t err);
const char *rsl_ipac_msg_name(uint8_t msg_type);
/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
@ -40,4 +49,7 @@ void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
/* Allocate msgb and fill with simple RSL RLL header */
struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
uint8_t link_id, int transparent);
/*! }@ */
#endif /* _OSMOCORE_RSL_H */

View File

@ -6,6 +6,11 @@
#include <osmocom/core/msgb.h>
/*! \defgroup tlv GSM L3 compatible TLV parser
* @{
*/
/*! \file tlv.h */
/* Terminology / wording
tag length value (in bits)
@ -18,14 +23,21 @@
*/
/*! \brief gross length of a LV type field */
#define LV_GROSS_LEN(x) (x+1)
/*! \brief gross length of a TLV type field */
#define TLV_GROSS_LEN(x) (x+2)
/*! \brief gross length of a TLV16 type field */
#define TLV16_GROSS_LEN(x) ((2*x)+2)
/*! \brief gross length of a TL16V type field */
#define TL16V_GROSS_LEN(x) (x+3)
/*! \brief gross length of a L16TV type field */
#define L16TV_GROSS_LEN(x) (x+3)
/*! \brief maximum length of TLV of one byte length */
#define TVLV_MAX_ONEBYTE 0x7f
/*! \brief gross length of a TVLV type field */
static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
{
if (len <= TVLV_MAX_ONEBYTE)
@ -36,6 +48,7 @@ static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
/* TLV generation */
/*! \brief put (append) a LV field */
static inline uint8_t *lv_put(uint8_t *buf, uint8_t len,
const uint8_t *val)
{
@ -44,6 +57,7 @@ static inline uint8_t *lv_put(uint8_t *buf, uint8_t len,
return buf + len;
}
/*! \brief put (append) a TLV field */
static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len,
const uint8_t *val)
{
@ -53,6 +67,7 @@ static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len,
return buf + len;
}
/*! \brief put (append) a TLV16 field */
static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len,
const uint16_t *val)
{
@ -62,6 +77,7 @@ static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len,
return buf + len*2;
}
/*! \brief put (append) a TL16V field */
static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
const uint8_t *val)
{
@ -72,6 +88,7 @@ static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
return buf + len*2;
}
/*! \brief put (append) a TvLV field */
static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
const uint8_t *val)
{
@ -86,12 +103,14 @@ static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
return ret;
}
/*! \brief put (append) a TLV16 field to \ref msgb */
static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val)
{
uint8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
return tlv16_put(buf, tag, len, val);
}
/*! \brief put (append) a TL16V field to \ref msgb */
static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len,
const uint8_t *val)
{
@ -99,6 +118,7 @@ static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t le
return tl16v_put(buf, tag, len, val);
}
/*! \brief put (append) a TvLV field to \ref msgb */
static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len,
const uint8_t *val)
{
@ -106,6 +126,7 @@ static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len
return tvlv_put(buf, tag, len, val);
}
/*! \brief put (append) a L16TV field to \ref msgb */
static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag,
const uint8_t *val)
{
@ -118,12 +139,14 @@ static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t ta
return buf + len;
}
/*! \brief put (append) a V field */
static inline uint8_t *v_put(uint8_t *buf, uint8_t val)
{
*buf++ = val;
return buf;
}
/*! \brief put (append) a TV field */
static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
uint8_t val)
{
@ -132,6 +155,7 @@ static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
return buf;
}
/*! \brief put (append) a TVfixed field */
static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag,
unsigned int len, const uint8_t *val)
{
@ -140,7 +164,11 @@ static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag,
return buf + len;
}
/* 'val' is still in host byte order! */
/*! \brief put (append) a TV16 field
* \param[in,out] buf data buffer
* \param[in] tag Tag value
* \param[in] val Value (in host byte order!)
*/
static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
uint16_t val)
{
@ -150,24 +178,28 @@ static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
return buf;
}
/*! \brief put (append) a LV field to a \ref msgb */
static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
return lv_put(buf, len, val);
}
/*! \brief put (append) a TLV field to a \ref msgb */
static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
return tlv_put(buf, tag, len, val);
}
/*! \brief put (append) a TV field to a \ref msgb */
static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
{
uint8_t *buf = msgb_put(msg, 2);
return tv_put(buf, tag, val);
}
/*! \brief put (append) a TVfixed field to a \ref msgb */
static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
unsigned int len, const uint8_t *val)
{
@ -175,36 +207,42 @@ static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
return tv_fixed_put(buf, tag, len, val);
}
/*! \brief put (append) a V field to a \ref msgb */
static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val)
{
uint8_t *buf = msgb_put(msg, 1);
return v_put(buf, val);
}
/*! \brief put (append) a TV16 field to a \ref msgb */
static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
{
uint8_t *buf = msgb_put(msg, 3);
return tv16_put(buf, tag, val);
}
/*! \brief push (prepend) a TLV field to a \ref msgb */
static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
return tlv_put(buf, tag, len, val);
}
/*! \brief push (prepend) a TV field to a \ref msgb */
static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
{
uint8_t *buf = msgb_push(msg, 2);
return tv_put(buf, tag, val);
}
/*! \brief push (prepend) a TV16 field to a \ref msgb */
static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
{
uint8_t *buf = msgb_push(msg, 3);
return tv16_put(buf, tag, val);
}
/*! \brief push (prepend) a TvLV field to a \ref msgb */
static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len,
const uint8_t *val)
{
@ -214,31 +252,36 @@ static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t le
/* TLV parsing */
/*! \brief Entry in a TLV parser array */
struct tlv_p_entry {
uint16_t len;
const uint8_t *val;
uint16_t len; /*!< \brief length */
const uint8_t *val; /*!< \brief pointer to value */
};
/*! \brief TLV type */
enum tlv_type {
TLV_TYPE_NONE,
TLV_TYPE_FIXED,
TLV_TYPE_T,
TLV_TYPE_TV,
TLV_TYPE_TLV,
TLV_TYPE_TL16V,
TLV_TYPE_TvLV,
TLV_TYPE_SINGLE_TV
TLV_TYPE_NONE, /*!< \brief no type */
TLV_TYPE_FIXED, /*!< \brief fixed-length value-only */
TLV_TYPE_T, /*!< \brief tag-only */
TLV_TYPE_TV, /*!< \brief tag-value (8bit) */
TLV_TYPE_TLV, /*!< \brief tag-length-value */
TLV_TYPE_TL16V, /*!< \brief tag, 16 bit length, value */
TLV_TYPE_TvLV, /*!< \brief tag, variable length, value */
TLV_TYPE_SINGLE_TV /*!< \brief tag and value (both 4 bit) in 1 byte */
};
/*! \brief Definition of a single IE (Information Element) */
struct tlv_def {
enum tlv_type type;
uint8_t fixed_len;
enum tlv_type type; /*!< \brief TLV type */
uint8_t fixed_len; /*!< \brief length in case of \ref TLV_TYPE_FIXED */
};
/*! \brief Definition of All 256 IE / TLV */
struct tlv_definition {
struct tlv_def def[256];
};
/*! \brief result of the TLV parser */
struct tlv_parsed {
struct tlv_p_entry lv[256];
};
@ -257,4 +300,6 @@ void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src)
#define TLVP_LEN(x, y) (x)->lv[y].len
#define TLVP_VAL(x, y) (x)->lv[y].val
/*! }@ */
#endif /* _TLV_H */

View File

@ -28,74 +28,80 @@
#include "vector.h"
#include "vty.h"
/* Host configuration variable */
/*! \defgroup command VTY Command
* @{
*/
/*! \file command.h */
/*! \brief Host configuration variable */
struct host {
/* Host name of this router. */
/*! \brief Host name of this router. */
char *name;
/* Password for vty interface. */
/*! \brief Password for vty interface. */
char *password;
char *password_encrypt;
/* Enable password */
/*! \brief Enable password */
char *enable;
char *enable_encrypt;
/* System wide terminal lines. */
/*! \brief System wide terminal lines. */
int lines;
/* Log filename. */
/*! \brief Log filename. */
char *logfile;
/* config file name of this host */
/*! \brief config file name of this host */
char *config;
/* Flags for services */
/*! \brief Flags for services */
int advanced;
int encrypt;
/* Banner configuration. */
/*! \brief Banner configuration. */
const char *motd;
char *motdfile;
/*! \brief VTY application information */
const struct vty_app_info *app_info;
};
/* There are some command levels which called from command node. */
/*! \brief There are some command levels which called from command node. */
enum node_type {
AUTH_NODE, /* Authentication mode of vty interface. */
VIEW_NODE, /* View node. Default mode of vty interface. */
AUTH_ENABLE_NODE, /* Authentication mode for change enable. */
ENABLE_NODE, /* Enable node. */
CONFIG_NODE, /* Config node. Default mode of config file. */
SERVICE_NODE, /* Service node. */
DEBUG_NODE, /* Debug node. */
CFG_LOG_NODE, /* Configure the logging */
AUTH_NODE, /*!< \brief Authentication mode of vty interface. */
VIEW_NODE, /*!< \brief View node. Default mode of vty interface. */
AUTH_ENABLE_NODE, /*!< \brief Authentication mode for change enable. */
ENABLE_NODE, /*!< \brief Enable node. */
CONFIG_NODE, /*!< \brief Config node. Default mode of config file. */
SERVICE_NODE, /*!< \brief Service node. */
DEBUG_NODE, /*!< \brief Debug node. */
CFG_LOG_NODE, /*!< \brief Configure the logging */
VTY_NODE, /* Vty node. */
VTY_NODE, /*!< \brief Vty node. */
L_E1INP_NODE, /* E1 line in libosmo-abis. */
L_IPA_NODE, /* IPA proxying commands in libosmo-abis. */
L_E1INP_NODE, /*!< \brief E1 line in libosmo-abis. */
L_IPA_NODE, /*!< \brief IPA proxying commands in libosmo-abis. */
_LAST_OSMOVTY_NODE
};
/* Node which has some commands and prompt string and configuration
function pointer . */
/*! \brief Node which has some commands and prompt string and
* configuration function pointer . */
struct cmd_node {
/* Node index. */
/*! \brief Node index */
enum node_type node;
/* Prompt character at vty interface. */
/*! \brief Prompt character at vty interface. */
const char *prompt;
/* Is this node's configuration goes to vtysh ? */
/*! \brief Is this node's configuration goes to vtysh ? */
int vtysh;
/* Node's configuration write function */
/*! \brief Node's configuration write function */
int (*func) (struct vty *);
/* Vector of this node's command list. */
/*! \brief Vector of this node's command list. */
vector cmd_vector;
};
@ -104,26 +110,26 @@ enum {
CMD_ATTR_HIDDEN,
};
/* Structure of command element. */
/*! \brief Structure of a command element */
struct cmd_element {
const char *string; /* Command specification by string. */
const char *string; /*!< \brief Command specification by string. */
int (*func) (struct cmd_element *, struct vty *, int, const char *[]);
const char *doc; /* Documentation of this command. */
int daemon; /* Daemon to which this command belong. */
vector strvec; /* Pointing out each description vector. */
unsigned int cmdsize; /* Command index count. */
char *config; /* Configuration string */
vector subconfig; /* Sub configuration string */
u_char attr; /* Command attributes */
const char *doc; /*!< \brief Documentation of this command. */
int daemon; /*!< \brief Daemon to which this command belong. */
vector strvec; /*!< \brief Pointing out each description vector. */
unsigned int cmdsize; /*!< \brief Command index count. */
char *config; /*!< \brief Configuration string */
vector subconfig; /*!< \brief Sub configuration string */
u_char attr; /*!< \brief Command attributes */
};
/* Command description structure. */
/*! \brief Command description structure. */
struct desc {
const char *cmd; /* Command string. */
const char *str; /* Command's description. */
const char *cmd; /*!< \brief Command string. */
const char *str; /*!< \brief Command's description. */
};
/* Return value of the commands. */
/*! \brief Return value of the commands. */
#define CMD_SUCCESS 0
#define CMD_WARNING 1
#define CMD_ERR_NO_MATCH 2
@ -171,13 +177,23 @@ struct desc {
static int funcname \
(struct cmd_element *self, struct vty *vty, int argc, const char *argv[])
/* DEFUN for vty command interafce. Little bit hacky ;-). */
/*! \brief Macro for defining a VTY node and function
* \param[in] funcname Name of the function implementing the node
* \param[in] cmdname Name of the command node
* \param[in] cmdstr String with syntax of node
* \param[in] helpstr String with help message of node
*/
#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_FUNC_DECL(funcname) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
DEFUN_CMD_FUNC_TEXT(funcname)
/* global (non static) cmd_element */
/*! \brief Macro for defining a non-static (global) VTY node and function
* \param[in] funcname Name of the function implementing the node
* \param[in] cmdname Name of the command node
* \param[in] cmdstr String with syntax of node
* \param[in] helpstr String with help message of node
*/
#define gDEFUN(funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_FUNC_DECL(funcname) \
gDEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
@ -350,4 +366,5 @@ void print_version(int print_copyright);
extern void *tall_vty_cmd_ctx;
/*! }@ */
#endif /* _ZEBRA_COMMAND_H */

View File

@ -26,15 +26,28 @@
#include <osmocom/vty/vty.h>
/*! \defgroup telnet_interface Telnet Interface
* @{
*/
/*! \file telnet_interface.h */
/*! \brief A telnet connection */
struct telnet_connection {
/*! \brief linked list header for internal management */
struct llist_head entry;
/*! \brief private data pointer passed through */
void *priv;
/*! \brief filedsecriptor (socket ) */
struct osmo_fd fd;
/*! \brief VTY instance associated with telnet connection */
struct vty *vty;
/*! \brief logging target associated with this telnet connection */
struct log_target *dbg;
};
int telnet_init(void *tall_ctx, void *priv, int port);
#endif
/*! }@ */
#endif /* TELNET_INTERFACE_H */

View File

@ -4,6 +4,11 @@
#include <stdio.h>
#include <stdarg.h>
/*! \defgroup vty VTY (Virtual TTY) interface
* @{
*/
/*! \file vty.h */
/* GCC have printf type attribute check. */
#ifdef __GNUC__
#define VTY_PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
@ -21,7 +26,7 @@
#define VTY_BUFSIZ 512
#define VTY_MAXHIST 20
/* Vty events */
/*! \brief VTY events */
enum event {
VTY_SERV,
VTY_READ,
@ -35,87 +40,94 @@ enum event {
#endif /* VTYSH */
};
/*! Internal representation of a single VTY */
struct vty {
/*! \brief underlying file (if any) */
FILE *file;
/* private data, specified by creator */
/*! \brief private data, specified by creator */
void *priv;
/* File descripter of this vty. */
/*! \brief File descripter of this vty. */
int fd;
/* Is this vty connect to file or not */
/*! \brief Is this vty connect to file or not */
enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
/* Node status of this vty */
/*! \brief Node status of this vty */
int node;
/* Failure count */
/*! \brief Failure count */
int fail;
/* Output buffer. */
/*! \brief Output buffer. */
struct buffer *obuf;
/* Command input buffer */
/*! \brief Command input buffer */
char *buf;
/* Command cursor point */
/*! \brief Command cursor point */
int cp;
/* Command length */
/*! \brief Command length */
int length;
/* Command max length. */
/*! \brief Command max length. */
int max;
/* Histry of command */
/*! \brief Histry of command */
char *hist[VTY_MAXHIST];
/* History lookup current point */
/*! \brief History lookup current point */
int hp;
/* History insert end point */
/*! \brief History insert end point */
int hindex;
/* For current referencing point of interface, route-map,
/*! \brief For current referencing point of interface, route-map,
access-list etc... */
void *index;
/* For multiple level index treatment such as key chain and key. */
/*! \brief For multiple level index treatment such as key chain and key. */
void *index_sub;
/* For escape character. */
/*! \brief For escape character. */
unsigned char escape;
/* Current vty status. */
/*! \brief Current vty status. */
enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status;
/* IAC handling: was the last character received the IAC
/*! \brief IAC handling
*
* IAC handling: was the last character received the IAC
* (interpret-as-command) escape character (and therefore the next
* character will be the command code)? Refer to Telnet RFC 854. */
unsigned char iac;
/* IAC SB (option subnegotiation) handling */
/*! \brief IAC SB (option subnegotiation) handling */
unsigned char iac_sb_in_progress;
/* At the moment, we care only about the NAWS (window size) negotiation,
* and that requires just a 5-character buffer (RFC 1073):
* <NAWS char> <16-bit width> <16-bit height> */
#define TELNET_NAWS_SB_LEN 5
/*! \brief sub-negotiation buffer */
unsigned char sb_buf[TELNET_NAWS_SB_LEN];
/* How many subnegotiation characters have we received? We just drop
* those that do not fit in the buffer. */
/*! \brief How many subnegotiation characters have we received?
*
* We just drop those that do not fit in the buffer. */
size_t sb_len;
/* Window width/height. */
/*! \brief Window width */
int width;
/*! \brief Widnow height */
int height;
/* Configure lines. */
/*! \brief Configure lines. */
int lines;
int monitor;
/* In configure mode. */
/*! \brief In configure mode. */
int config;
};
@ -127,12 +139,19 @@ static inline char *vty_newline(struct vty *vty)
return VTY_NEWLINE;
}
/*! Information an application registers with the VTY */
struct vty_app_info {
/*! \brief name of the application */
const char *name;
/*! \brief version string of the application */
const char *version;
/*! \brief copyright string of the application */
const char *copyright;
/*! \brief \ref talloc context */
void *tall_ctx;
/*! \brief call-back for returning to parent n ode */
enum node_type (*go_parent_cb)(struct vty *vty);
/*! \brief call-back to determine if node is config node */
int (*is_config_node)(struct vty *vty, int node);
};
@ -159,4 +178,7 @@ void *vty_current_index(struct vty *);
int vty_current_node(struct vty *vty);
extern void *tall_vty_ctx;
/*! }@ */
#endif

View File

@ -30,3 +30,7 @@ endif
if ENABLE_MSGFILE
libosmocore_la_SOURCES += msgfile.c
endif
if ENABLE_SERIAL
libosmocore_la_SOURCES += serial.c
endif

View File

@ -21,6 +21,45 @@
*
*/
/*! \file application.c
* \brief Routines for helping with the osmocom application setup.
*/
/*! \mainpage libosmocore Documentation
* \section sec_intro Introduction
* This library is a collection of common code used in various
* sub-projects inside the Osmocom family of projects. It includes a
* logging framework, select() loop abstraction, timers with callbacks,
* bit vectors, bit packing/unpacking, convolutional decoding, GSMTAP, a
* generic plugin interface, statistics counters, memory allocator,
* socket abstraction, message buffers, etc.
* \n\n
* Please note that C language projects inside Osmocom are typically
* single-threaded event-loop state machine designs. As such,
* routines in libosmocore are not thread-safe. If you must use them in
* a multi-threaded context, you have to add your own locking.
*
* \section sec_copyright Copyright and License
* Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
* All rights reserved. \n\n
* The source code of libosmocore is licensed 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.\n
* See <http://www.gnu.org/licenses/> or COPYING included in the source
* code package istelf.\n
* The information detailed here is provided AS IS with NO WARRANTY OF
* ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE.
* \n\n
*
* \section sec_contact Contact and Support
* Community-based support is available at the OpenBSC mailing list
* <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
* Commercial support options available upon request from
* <http://sysmocom.de/>
*/
#include <osmocom/core/application.h>
#include <osmocom/core/logging.h>
@ -33,6 +72,7 @@
struct log_target *osmo_stderr_target;
/*! \brief Ignore \ref SIGPIPE, \ref SIGALRM, \ref SIGHUP and \ref SIGIO */
void osmo_init_ignore_signals(void)
{
/* Signals that by default would terminate */
@ -42,6 +82,13 @@ void osmo_init_ignore_signals(void)
signal(SIGIO, SIG_IGN);
}
/*! \brief Initialize the osmocom logging framework
* \param[in] log_info Array of available logging sub-systems
* \returns 0 on success, -1 in case of error
*
* This function initializes the osmocom logging systems. It also
* creates the default (stderr) logging target.
*/
int osmo_init_logging(const struct log_info *log_info)
{
log_init(log_info, NULL);
@ -54,6 +101,11 @@ int osmo_init_logging(const struct log_info *log_info)
return 0;
}
/*! \brief Turn the current process into a background daemon
*
* This function will fork the process, exit the parent and set umask,
* create a new session, close stdin/stdout/stderr and chdir to /tmp
*/
int osmo_daemonize(void)
{
int rc;

View File

@ -22,6 +22,10 @@
*
*/
/*! \file backtrace.c
* \brief Routines realted to generating call back traces
*/
#include <stdio.h>
#include <stdlib.h>
#include <osmocom/core/utils.h>
@ -29,6 +33,12 @@
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
/*! \brief Generate and print a call back-trace
*
* This function will generate a function call back-trace of the
* current process and print it to stdout
*/
void osmo_generate_backtrace(void)
{
int i, nptrs;

View File

@ -3,7 +3,20 @@
#include <osmocom/core/bits.h>
/* convert unpacked bits to packed bits, return length in bytes */
/*! \addtogroup bits
* @{
*/
/*! \file bits.c
* \brief Osmocom bit level support code
*/
/*! \brief convert unpacked bits to packed bits, return length in bytes
* \param[out] out output buffer of packed bits
* \param[in] in input buffer of unpacked bits
* \param[in] num_bits number of bits
*/
int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits)
{
unsigned int i;
@ -27,7 +40,11 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits)
return outptr - out;
}
/* convert packed bits to unpacked bits, return length in bytes */
/*! \brief convert packed bits to unpacked bits, return length in bytes
* \param[out] out output buffer of unpacked bits
* \param[in] in input buffer of packed bits
* \param[in] num_bits number of bits
*/
int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits)
{
unsigned int i;
@ -64,8 +81,15 @@ int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits)
return cur - out;
}
/* convert unpacked bits to packed bits (extended options but slower),
* return length in bytes (max written ofs of output buffer + 1) */
/*! \brief convert unpacked bits to packed bits (extended options)
* \param[out] out output buffer of packed bits
* \param[in] out_ofs offset into output buffer
* \param[in] in input buffer of unpacked bits
* \param[in] in_ofs offset into input buffer
* \param[in] num_bits number of bits
* \param[in] lsb_mode Encode bits in LSB orde instead of MSB
* \returns length in bytes (max written offset of output buffer + 1)
*/
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)
@ -82,8 +106,15 @@ int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs,
return ((out_ofs + num_bits - 1) >> 3) + 1;
}
/* convert packed bits to unpacked bits (extended options but slower),
* return length in bytes (max written ofs of output buffer + 1) */
/*! \brief convert packed bits to unpacked bits (extended options)
* \param[out] out output buffer of unpacked bits
* \param[in] out_ofs offset into output buffer
* \param[in] in input buffer of packed bits
* \param[in] in_ofs offset into input buffer
* \param[in] num_bits number of bits
* \param[in] lsb_mode Encode bits in LSB orde instead of MSB
* \returns length in bytes (max written offset of output buffer + 1)
*/
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)
@ -96,3 +127,62 @@ int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs,
}
return out_ofs + num_bits;
}
/* generalized bit reversal function, Chapter 7 "Hackers Delight" */
uint32_t osmo_bit_reversal(uint32_t x, enum osmo_br_mode k)
{
if (k & 1) x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
if (k & 2) x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
if (k & 4) x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
if (k & 8) x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
if (k & 16) x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
return x;
}
/* generalized bit reversal function, Chapter 7 "Hackers Delight" */
uint32_t osmo_revbytebits_32(uint32_t x)
{
x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
return x;
}
uint32_t osmo_revbytebits_8(uint8_t x)
{
x = (x & 0x55) << 1 | (x & 0xAA) >> 1;
x = (x & 0x33) << 2 | (x & 0xCC) >> 2;
x = (x & 0x0F) << 4 | (x & 0xF0) >> 4;
return x;
}
void osmo_revbytebits_buf(uint8_t *buf, int len)
{
unsigned int i;
unsigned int unaligned_cnt;
int len_remain = len;
unaligned_cnt = ((unsigned long)buf & 3);
for (i = 0; i < unaligned_cnt; i++) {
buf[i] = osmo_revbytebits_8(buf[i]);
len_remain--;
if (len_remain <= 0)
return;
}
for (i = unaligned_cnt; i < len; i += 4) {
uint32_t *cur = (uint32_t *) (buf + i);
*cur = osmo_revbytebits_32(*cur);
len_remain -= 4;
}
for (i = len - len_remain; i < len; i++) {
buf[i] = osmo_revbytebits_8(buf[i]);
len_remain--;
}
}
/*! }@ */

View File

@ -20,6 +20,13 @@
*
*/
/*! \addtogroup bitvec
* @{
*/
/*! \file bitvec.c
* \brief Osmocom bit vector abstraction
*/
#include <errno.h>
#include <stdint.h>
@ -59,7 +66,11 @@ static uint8_t bitval2mask(enum bit_value bit, uint8_t bitnum)
return bitval;
}
/* check if the bit is 0 or 1 for a given position inside a bitvec */
/*! \brief check if the bit is 0 or 1 for a given position inside a bitvec
* \param[in] bv the bit vector on which to check
* \param[in] bitnr the bit number inside the bit vector to check
* \returns
*/
enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr)
{
unsigned int bytenum = bytenum_from_bitnum(bitnr);
@ -77,7 +88,10 @@ enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr)
return ZERO;
}
/* check if the bit is L or H for a given position inside a bitvec */
/*! \brief check if the bit is L or H for a given position inside a bitvec
* \param[in] bv the bit vector on which to check
* \param[in] bitnr the bit number inside the bit vector to check
*/
enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv,
unsigned int bitnr)
{
@ -96,7 +110,11 @@ enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv,
return L;
}
/* get the Nth set bit inside the bit vector */
/*! \brief get the Nth set bit inside the bit vector
* \param[in] bv the bit vector to use
* \param[in] n the bit number to get
* \returns the bit number (offset) of the Nth set bit in \a bv
*/
unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n)
{
unsigned int i, k = 0;
@ -112,7 +130,11 @@ unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n)
return 0;
}
/* set the bit at a given position inside a bitvec */
/*! \brief set a bit at given position in a bit vector
* \param[in] bv bit vector on which to operate
* \param[in] bitnum number of bit to be set
* \param[in] bit value to which the bit is to be set
*/
int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
enum bit_value bit)
{
@ -134,7 +156,10 @@ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
return 0;
}
/* set the next bit inside a bitvec */
/*! \brief set the next bit inside a bitvec
* \param[in] bv bit vector to be used
* \param[in] bit value of the bit to be set
*/
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit)
{
int rc;
@ -146,7 +171,7 @@ int bitvec_set_bit(struct bitvec *bv, enum bit_value bit)
return rc;
}
/* get the next bit (low/high) inside a bitvec */
/*! \brief get the next bit (low/high) inside a bitvec */
int bitvec_get_bit_high(struct bitvec *bv)
{
int rc;
@ -158,7 +183,11 @@ int bitvec_get_bit_high(struct bitvec *bv)
return rc;
}
/* set multiple bits (based on array of bitvals) at current pos */
/*! \brief set multiple bits (based on array of bitvals) at current pos
* \param[in] bv bit vector
* \param[in] bits array of \ref bit_value
* \param[in] count number of bits to set
*/
int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count)
{
int i, rc;
@ -172,7 +201,7 @@ int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count)
return 0;
}
/* set multiple bits (based on numeric value) at current pos */
/*! \brief set multiple bits (based on numeric value) at current pos */
int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits)
{
int i, rc;
@ -189,7 +218,7 @@ int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits)
return 0;
}
/* get multiple bits (based on numeric value) from current pos */
/*! \brief get multiple bits (based on numeric value) from current pos */
int bitvec_get_uint(struct bitvec *bv, int num_bits)
{
int i;
@ -207,7 +236,7 @@ int bitvec_get_uint(struct bitvec *bv, int num_bits)
return ui;
}
/* pad all remaining bits up to num_bits */
/*! \brief pad all remaining bits up to num_bits */
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
{
unsigned int i;
@ -218,7 +247,7 @@ int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
return 0;
}
/* find first bit set in bit vector */
/*! \brief find first bit set in bit vector */
int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n,
enum bit_value val)
{
@ -231,3 +260,5 @@ int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n,
return -1;
}
/*! }@ */

View File

@ -22,6 +22,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*! \addtogroup conv
* @{
*/
/*! \file conv.c
* \file Osmocom convolutional encoder and decoder
*/
#include <alloca.h>
#include <stdint.h>
#include <stdlib.h>
@ -35,6 +43,10 @@
/* Encoding */
/* ------------------------------------------------------------------------ */
/*! \brief Initialize a convolutional encoder
* \param[in,out] encoder Encoder state to initialize
* \param[in] code Description of convolutional code
*/
void
osmo_conv_encode_init(struct osmo_conv_encoder *encoder,
const struct osmo_conv_code *code)
@ -138,6 +150,15 @@ osmo_conv_encode_finish(struct osmo_conv_encoder *encoder,
return o_idx;
}
/*! \brief All-in-one convolutional encoding function
* \param[in] code description of convolutional code to be used
* \param[in] input array of unpacked bits (uncoded)
* \param[out] output array of unpacked bits (encoded)
*
* This is an all-in-one function, taking care of
* \ref osmo_conv_init, \ref osmo_conv_encode_raw and
* \ref osmo_conv_encode_finish.
*/
int
osmo_conv_encode(const struct osmo_conv_code *code,
const ubit_t *input, ubit_t *output)
@ -476,6 +497,16 @@ osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
return min_ae;
}
/*! \brief All-in-one convolutional decoding function
* \param[in] code description of convolutional code to be used
* \param[in] input array of soft bits (coded)
* \param[out] output array of unpacked bits (decoded)
*
* This is an all-in-one function, taking care of
* \ref osmo_conv_decode_init, \ref osmo_conv_decode_scan,
* \ref osmo_conv_decode_finish, \ref osmo_conv_decode_get_output and
* \ref osmo_conv_decode_deinit.
*/
int
osmo_conv_decode(const struct osmo_conv_code *code,
const sbit_t *input, ubit_t *output)
@ -494,3 +525,5 @@ osmo_conv_decode(const struct osmo_conv_code *code,
return rv;
}
/*! }@ */

View File

@ -20,6 +20,12 @@
*
*/
/*! \addtogroup oml
* @{
*/
/*! \file abis_nm.c */
#include <stdint.h>
#include <errno.h>
@ -30,7 +36,7 @@
#include <osmocom/gsm/protocol/gsm_12_21.h>
#include <osmocom/gsm/abis_nm.h>
/* unidirectional messages from BTS to BSC */
/*! \brief unidirectional messages from BTS to BSC */
const enum abis_nm_msgtype abis_nm_reports[4] = {
NM_MT_SW_ACTIVATED_REP,
NM_MT_TEST_REP,
@ -38,14 +44,14 @@ const enum abis_nm_msgtype abis_nm_reports[4] = {
NM_MT_FAILURE_EVENT_REP,
};
/* messages without ACK/NACK */
/*! \brief messages without ACK/NACK */
const enum abis_nm_msgtype abis_nm_no_ack_nack[3] = {
NM_MT_MEAS_RES_REQ,
NM_MT_STOP_MEAS,
NM_MT_START_MEAS,
};
/* Messages related to software load */
/*! \brief messages related to software load */
const enum abis_nm_msgtype abis_nm_sw_load_msgs[9] = {
NM_MT_LOAD_INIT_ACK,
NM_MT_LOAD_INIT_NACK,
@ -59,6 +65,7 @@ const enum abis_nm_msgtype abis_nm_sw_load_msgs[9] = {
NM_MT_SW_ACTIVATED_REP,
};
/*! \brief All NACKs (negative acknowledgements */
const enum abis_nm_msgtype abis_nm_nacks[33] = {
NM_MT_LOAD_INIT_NACK,
NM_MT_LOAD_END_NACK,
@ -133,6 +140,7 @@ static const struct value_string nack_names[] = {
{ 0, NULL }
};
/*! \brief Get human-readable string for OML NACK message type */
const char *abis_nm_nack_name(uint8_t nack)
{
return get_value_string(nack_names, nack);
@ -177,6 +185,7 @@ static const struct value_string nack_cause_names[] = {
{ 0, NULL }
};
/*! \brief Get human-readable string for NACK cause */
const char *abis_nm_nack_cause_name(uint8_t cause)
{
return get_value_string(nack_cause_names, cause);
@ -192,6 +201,7 @@ static const struct value_string event_type_names[] = {
{ 0, NULL }
};
/*! \brief Get human-readable string for OML event type */
const char *abis_nm_event_type_name(uint8_t cause)
{
return get_value_string(event_type_names, cause);
@ -208,12 +218,13 @@ static const struct value_string severity_names[] = {
{ 0, NULL }
};
/*! \brief Get human-readable string for perceived OML severity */
const char *abis_nm_severity_name(uint8_t cause)
{
return get_value_string(severity_names, cause);
}
/* Attributes that the BSC can set, not only get, according to Section 9.4 */
/*! \brief Attributes that the BSC can set, not only get, according to Section 9.4 */
const enum abis_nm_attr abis_nm_att_settable[] = {
NM_ATT_ADD_INFO,
NM_ATT_ADD_TEXT,
@ -242,6 +253,7 @@ const enum abis_nm_attr abis_nm_att_settable[] = {
NM_ATT_MEAS_TYPE,
};
/*! \brief GSM A-bis OML TLV parser definition */
const struct tlv_definition abis_nm_att_tlvdef = {
.def = {
[NM_ATT_ABIS_CHANNEL] = { TLV_TYPE_FIXED, 3 },
@ -311,6 +323,7 @@ const struct tlv_definition abis_nm_att_tlvdef = {
},
};
/*! \brief Human-readable strings for A-bis OML Object Class */
const struct value_string abis_nm_obj_class_names[] = {
{ NM_OC_SITE_MANAGER, "SITE-MANAGER" },
{ NM_OC_BTS, "BTS" },
@ -332,6 +345,7 @@ const struct value_string abis_nm_obj_class_names[] = {
{ 0, NULL }
};
/*! \brief Get human-readable string for OML Operational State */
const char *abis_nm_opstate_name(uint8_t os)
{
switch (os) {
@ -360,6 +374,7 @@ static const struct value_string avail_names[] = {
{ 0, NULL }
};
/*! \brief Get human-readable string for OML Availability State */
const char *abis_nm_avail_name(uint8_t avail)
{
return get_value_string(avail_names, avail);
@ -377,11 +392,13 @@ static struct value_string test_names[] = {
{ 0, NULL }
};
/*! \brief Get human-readable string for OML test */
const char *abis_nm_test_name(uint8_t test)
{
return get_value_string(test_names, test);
}
/*! \brief Human-readable names for OML administrative state */
const struct value_string abis_nm_adm_state_names[] = {
{ NM_STATE_LOCKED, "Locked" },
{ NM_STATE_UNLOCKED, "Unlocked" },
@ -390,6 +407,10 @@ const struct value_string abis_nm_adm_state_names[] = {
{ 0, NULL }
};
/*! \brief write a human-readable OML header to the debug log
* \param[in] ss Logging sub-system
* \param[in] foh A-bis OML FOM header
*/
void abis_nm_debugp_foh(int ss, struct abis_om_fom_hdr *foh)
{
DEBUGP(ss, "OC=%s(%02x) INST=(%02x,%02x,%02x) ",
@ -411,6 +432,7 @@ static const enum abis_nm_chan_comb chcomb4pchan[] = {
/* FIXME: bounds check */
};
/*! \brief Obtain OML Channel Combination for phnsical channel config */
int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan)
{
if (pchan < ARRAY_SIZE(chcomb4pchan))
@ -419,6 +441,7 @@ int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan)
return -EINVAL;
}
/*! \brief Obtain physical channel config for OML Channel Combination */
enum abis_nm_chan_comb abis_nm_pchan4chcomb(uint8_t chcomb)
{
int i;
@ -428,3 +451,5 @@ enum abis_nm_chan_comb abis_nm_pchan4chcomb(uint8_t chcomb)
}
return GSM_PCHAN_NONE;
}
/*! }@ */

View File

@ -659,6 +659,18 @@ int gsm48_encode_more(struct msgb *msg)
return 0;
}
static int32_t smod(int32_t n, int32_t m)
{
int32_t res;
res = n % m;
if (res <= 0)
res += m;
return res;
}
/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */
int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
uint8_t len, uint8_t mask, uint8_t frqt)
@ -739,35 +751,35 @@ int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
if (w[1])
f[w[1]].mask |= frqt;
if (w[2])
f[((w[1] - 512 + w[2] - 1) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + w[2], 1023)].mask |= frqt;
if (w[3])
f[((w[1] + w[3] - 1) % 1023) + 1].mask |= frqt;
f[smod(w[1] + w[3], 1023)].mask |= frqt;
if (w[4])
f[((w[1] - 512 + ((w[2] - 256 + w[4] - 1) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + smod(w[2] - 256 + w[4], 511), 1023)].mask |= frqt;
if (w[5])
f[((w[1] + ((w[3] - 256 + w[5] - 1) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] + smod(w[3] - 256 + w[5], 511), 1023)].mask |= frqt;
if (w[6])
f[((w[1] - 512 + ((w[2] + w[6] - 1) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + smod(w[2] + w[6], 511), 1023)].mask |= frqt;
if (w[7])
f[((w[1] + ((w[3] + w[7] - 1) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] + smod(w[3] + w[7], 511), 1023)].mask |= frqt;
if (w[8])
f[((w[1] - 512 + ((w[2] - 256 + ((w[4] - 128 + w[8] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + smod(w[2] - 256 + smod(w[4] - 128 + w[8] , 255), 511), 1023)].mask |= frqt;
if (w[9])
f[((w[1] + ((w[3] - 256 + ((w[5] - 128 + w[9] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] + smod(w[3] - 256 + smod(w[5] - 128 + w[9] , 255), 511), 1023)].mask |= frqt;
if (w[10])
f[((w[1] - 512 + ((w[2] + ((w[6] - 128 + w[10] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + smod(w[2] + smod(w[6] - 128 + w[10], 255), 511), 1023)].mask |= frqt;
if (w[11])
f[((w[1] + ((w[3] + ((w[7] - 128 + w[11] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] + smod(w[3] + smod(w[7] - 128 + w[11], 255), 511), 1023)].mask |= frqt;
if (w[12])
f[((w[1] - 512 + ((w[2] - 256 + ((w[4] + w[12] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + smod(w[2] - 256 + smod(w[4] + w[12], 255), 511), 1023)].mask |= frqt;
if (w[13])
f[((w[1] + ((w[3] - 256 + ((w[5] + w[13] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] + smod(w[3] - 256 + smod(w[5] + w[13], 255), 511), 1023)].mask |= frqt;
if (w[14])
f[((w[1] - 512 + ((w[2] + ((w[6] + w[14] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + smod(w[2] + smod(w[6] + w[14], 255), 511), 1023)].mask |= frqt;
if (w[15])
f[((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] + smod(w[3] + smod(w[7] + w[15], 255), 511), 1023)].mask |= frqt;
if (w[16])
f[((w[1] - 512 + ((w[2] - 256 + ((w[4] - 128 + ((w[8] - 64 + w[16] - 1) % 127)) % 255)) % 511)) % 1023) + 1].mask |= frqt;
f[smod(w[1] - 512 + smod(w[2] - 256 + smod(w[4] - 128 + smod(w[8] - 64 + w[16], 127), 255), 511), 1023)].mask |= frqt;
return 0;
}
@ -818,37 +830,37 @@ int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
if (w[1])
f[(w[0] + w[1]) % 1024].mask |= frqt;
if (w[2])
f[(w[0] + ((w[1] - 256 + w[2] - 1) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + w[2], 511)) % 1024].mask |= frqt;
if (w[3])
f[(w[0] + ((w[1] + w[3] - 1) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + w[3], 511)) % 1024].mask |= frqt;
if (w[4])
f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + w[4] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + smod(w[2] - 128 + w[4], 255), 511)) % 1024].mask |= frqt;
if (w[5])
f[(w[0] + ((w[1] + ((w[3] - 128 + w[5] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 128 + w[5], 255), 511)) % 1024].mask |= frqt;
if (w[6])
f[(w[0] + ((w[1] - 256 + ((w[2] + w[6] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + smod(w[2] + w[6], 255), 511)) % 1024].mask |= frqt;
if (w[7])
f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + w[7], 255), 511)) % 1024].mask |= frqt;
if (w[8])
f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] - 64 + w[8] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + smod(w[2] - 128 + smod(w[4] - 64 + w[8] , 127), 255), 511)) % 1024].mask |= frqt;
if (w[9])
f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] - 64 + w[9] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 128 + smod(w[5] - 64 + w[9] , 127), 255), 511)) % 1024].mask |= frqt;
if (w[10])
f[(w[0] + ((w[1] - 256 + ((w[2] + ((w[6] - 64 + w[10] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + smod(w[2] + smod(w[6] - 64 + w[10], 127), 255), 511)) % 1024].mask |= frqt;
if (w[11])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 64 + w[11] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] - 64 + w[11], 127), 255), 511)) % 1024].mask |= frqt;
if (w[12])
f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] + w[12] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + smod(w[2] - 128 + smod(w[4] + w[12], 127), 255), 511)) % 1024].mask |= frqt;
if (w[13])
f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] + w[13] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 128 + smod(w[5] + w[13], 127), 255), 511)) % 1024].mask |= frqt;
if (w[14])
f[(w[0] + ((w[1] - 256 + ((w[2] + ((w[6] + w[14] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + smod(w[2] + smod(w[6] + w[14], 127), 255), 511)) % 1024].mask |= frqt;
if (w[15])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] + w[15], 127), 255), 511)) % 1024].mask |= frqt;
if (w[16])
f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] - 64 + ((w[8] - 32 + w[16] - 1) % 63)) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 256 + smod(w[2] - 128 + smod(w[4] - 64 + smod(w[8] - 32 + w[16], 63), 127), 255), 511)) % 1024].mask |= frqt;
if (w[17])
f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] - 64 + ((w[9] - 32 + w[17] - 1) % 63)) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 128 + smod(w[5] - 64 + smod(w[9] - 32 + w[17], 63), 127), 255), 511)) % 1024].mask |= frqt;
return 0;
}
@ -907,45 +919,45 @@ int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
if (w[1])
f[(w[0] + w[1]) % 1024].mask |= frqt;
if (w[2])
f[(w[0] + ((w[1] - 128 + w[2] - 1) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + w[2], 255)) % 1024].mask |= frqt;
if (w[3])
f[(w[0] + ((w[1] + w[3] - 1) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + w[3], 255)) % 1024].mask |= frqt;
if (w[4])
f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + w[4] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] - 64 + w[4], 127), 255)) % 1024].mask |= frqt;
if (w[5])
f[(w[0] + ((w[1] + ((w[3] - 64 + w[5] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 64 + w[5], 127), 255)) % 1024].mask |= frqt;
if (w[6])
f[(w[0] + ((w[1] - 128 + ((w[2] + w[6] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] + w[6], 127), 255)) % 1024].mask |= frqt;
if (w[7])
f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + w[7], 127), 255)) % 1024].mask |= frqt;
if (w[8])
f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] - 32 + w[8] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] - 64 + smod(w[4] - 32 + w[8] , 63), 127), 255)) % 1024].mask |= frqt;
if (w[9])
f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] - 32 + w[9] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 64 + smod(w[5] - 32 + w[9] , 63), 127), 255)) % 1024].mask |= frqt;
if (w[10])
f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] - 32 + w[10] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] + smod(w[6] - 32 + w[10], 63), 127), 255)) % 1024].mask |= frqt;
if (w[11])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 32 + w[11] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] - 32 + w[11], 63), 127), 255)) % 1024].mask |= frqt;
if (w[12])
f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] + w[12] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] - 64 + smod(w[4] + w[12], 63), 127), 255)) % 1024].mask |= frqt;
if (w[13])
f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] + w[13] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 64 + smod(w[5] + w[13], 63), 127), 255)) % 1024].mask |= frqt;
if (w[14])
f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] + w[14] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] + smod(w[6] + w[14], 63), 127), 255)) % 1024].mask |= frqt;
if (w[15])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] + w[15], 63), 127), 255)) % 1024].mask |= frqt;
if (w[16])
f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] - 32 + ((w[8] - 16 + w[16] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] - 64 + smod(w[4] - 32 + smod(w[8] - 16 + w[16], 31), 63), 127), 255)) % 1024].mask |= frqt;
if (w[17])
f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] - 32 + ((w[9] - 16 + w[17] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 64 + smod(w[5] - 32 + smod(w[9] - 16 + w[17], 31), 63), 127), 255)) % 1024].mask |= frqt;
if (w[18])
f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] - 32 + ((w[10] - 16 + w[18] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] + smod(w[6] - 32 + smod(w[10] - 16 + w[18], 31), 63), 127), 255)) % 1024].mask |= frqt;
if (w[19])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 32 + ((w[11] - 16 + w[19] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] - 32 + smod(w[11] - 16 + w[19], 31), 63), 127), 255)) % 1024].mask |= frqt;
if (w[20])
f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] + ((w[12] - 16 + w[20] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 128 + smod(w[2] - 64 + smod(w[4] + smod(w[12] - 16 + w[20], 31), 63), 127), 255)) % 1024].mask |= frqt;
if (w[21])
f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] + ((w[13] - 16 + w[21] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 64 + smod(w[5] + smod(w[13] - 16 + w[21], 31), 63), 127), 255)) % 1024].mask |= frqt;
return 0;
}
@ -1018,59 +1030,59 @@ int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
if (w[1])
f[(w[0] + w[1]) % 1024].mask |= frqt;
if (w[2])
f[(w[0] + ((w[1] - 64 + w[2] - 1) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + w[2], 127)) % 1024].mask |= frqt;
if (w[3])
f[(w[0] + ((w[1] + w[3] - 1) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + w[3], 127)) % 1024].mask |= frqt;
if (w[4])
f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + w[4] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] - 32 + w[4], 63), 127)) % 1024].mask |= frqt;
if (w[5])
f[(w[0] + ((w[1] + ((w[3] - 32 + w[5] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 32 + w[5], 63), 127)) % 1024].mask |= frqt;
if (w[6])
f[(w[0] + ((w[1] - 64 + ((w[2] + w[6] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] + w[6], 63), 127)) % 1024].mask |= frqt;
if (w[7])
f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + w[7], 63), 127)) % 1024].mask |= frqt;
if (w[8])
f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + w[8] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] - 32 + smod(w[4] - 16 + w[8] , 31), 63), 127)) % 1024].mask |= frqt;
if (w[9])
f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + w[9] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 32 + smod(w[5] - 16 + w[9] , 31), 63), 127)) % 1024].mask |= frqt;
if (w[10])
f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + w[10] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] + smod(w[6] - 16 + w[10], 31), 63), 127)) % 1024].mask |= frqt;
if (w[11])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + w[11] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] - 16 + w[11], 31), 63), 127)) % 1024].mask |= frqt;
if (w[12])
f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + w[12] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] - 32 + smod(w[4] + w[12], 31), 63), 127)) % 1024].mask |= frqt;
if (w[13])
f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] + w[13] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 32 + smod(w[5] + w[13], 31), 63), 127)) % 1024].mask |= frqt;
if (w[14])
f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] + w[14] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] + smod(w[6] + w[14], 31), 63), 127)) % 1024].mask |= frqt;
if (w[15])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] + w[15], 31), 63), 127)) % 1024].mask |= frqt;
if (w[16])
f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + ((w[8] - 8 + w[16] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] - 32 + smod(w[4] - 16 + smod(w[8] - 8 + w[16], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[17])
f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + ((w[9] - 8 + w[17] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 32 + smod(w[5] - 16 + smod(w[9] - 8 + w[17], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[18])
f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + ((w[10] - 8 + w[18] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] + smod(w[6] - 16 + smod(w[10] - 8 + w[18], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[19])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + ((w[11] - 8 + w[19] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] - 16 + smod(w[11] - 8 + w[19], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[20])
f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + ((w[12] - 8 + w[20] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] - 32 + smod(w[4] + smod(w[12] - 8 + w[20], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[21])
f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] + ((w[13] - 8 + w[21] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 32 + smod(w[5] + smod(w[13] - 8 + w[21], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[22])
f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] + ((w[14] - 8 + w[22] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] + smod(w[6] + smod(w[14] - 8 + w[22], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[23])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] + ((w[15] - 8 + w[23] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] + smod(w[15] - 8 + w[23], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[24])
f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + ((w[8] + w[24] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] - 32 + smod(w[4] - 16 + smod(w[8] + w[24], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[25])
f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + ((w[9] + w[25] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] - 32 + smod(w[5] - 16 + smod(w[9] + w[25], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[26])
f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + ((w[10] + w[26] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] + smod(w[6] - 16 + smod(w[10] + w[26], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[27])
f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + ((w[11] + w[27] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] + smod(w[3] + smod(w[7] - 16 + smod(w[11] + w[27], 15), 31), 63), 127)) % 1024].mask |= frqt;
if (w[28])
f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + ((w[12] + w[28] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt;
f[(w[0] + smod(w[1] - 64 + smod(w[2] - 32 + smod(w[4] + smod(w[12] + w[28], 15), 31), 63), 127)) % 1024].mask |= frqt;
return 0;
}

View File

@ -22,6 +22,46 @@
*
*/
/*! \mainpage libosmogsm Documentation
*
* \section sec_intro Introduction
* This library is a collection of common code used in various
* GSM related sub-projects inside the Osmocom family of projects. It
* includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
* a GSM TLV parser, SMS utility routines as well as
* protocol definitions for a series of protocols:
* * Um L2 (04.06)
* * Um L3 (04.08)
* * A-bis RSL (08.58)
* * A-bis OML (08.59, 12.21)
* * A (08.08)
* \n\n
* Please note that C language projects inside Osmocom are typically
* single-threaded event-loop state machine designs. As such,
* routines in libosmogsm are not thread-safe. If you must use them in
* a multi-threaded context, you have to add your own locking.
*
* \section sec_copyright Copyright and License
* Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
* All rights reserved. \n\n
* The source code of libosmogsm is licensed 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.\n
* See <http://www.gnu.org/licenses/> or COPYING included in the source
* code package istelf.\n
* The information detailed here is provided AS IS with NO WARRANTY OF
* ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE.
* \n\n
*
* \section sec_contact Contact and Support
* Community-based support is available at the OpenBSC mailing list
* <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
* Commercial support options available upon request from
* <http://sysmocom.de/>
*/
//#include <openbsc/gsm_data.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/gsm_utils.h>

View File

@ -21,7 +21,14 @@
*
*/
/* Notes on Buffering: rcv_buffer, tx_queue, tx_hist, send_buffer, send_queue
/*! \addtogroup lapdm
* @{
*/
/*! \file lapdm.c */
/*!
* Notes on Buffering: rcv_buffer, tx_queue, tx_hist, send_buffer, send_queue
*
* RX data is stored in the rcv_buffer (pointer). If the message is complete, it
* is removed from rcv_buffer pointer and forwarded to L3. If the RX data is
@ -184,6 +191,10 @@ static void lapdm_dl_init(struct lapdm_datalink *dl,
dl->entity = entity;
}
/*! \brief initialize a LAPDm entity and all datalinks inside
* \param[in] le LAPDm entity
* \param[in] mode \ref lapdm_mode (BTS/MS)
*/
void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode)
{
unsigned int i;
@ -194,13 +205,19 @@ void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode)
lapdm_entity_set_mode(le, mode);
}
/*! \brief initialize a LAPDm channel and all its channels
* \param[in] lc \ref lapdm_channel to be initialized
* \param[in] mode \ref lapdm_mode (BTS/MS)
*
* This really is a convenience wrapper around calling \ref
* lapdm_entity_init twice.
*/
void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)
{
lapdm_entity_init(&lc->lapdm_acch, mode);
lapdm_entity_init(&lc->lapdm_dcch, mode);
}
static void lapdm_dl_flush_send(struct lapdm_datalink *dl)
{
struct msgb *msg;
@ -227,6 +244,7 @@ static void lapdm_dl_flush_tx(struct lapdm_datalink *dl)
dl->tx_length[i] = 0;
}
/*! \brief flush and release all resoures in LAPDm entity */
void lapdm_entity_exit(struct lapdm_entity *le)
{
unsigned int i;
@ -241,6 +259,11 @@ void lapdm_entity_exit(struct lapdm_entity *le)
}
}
/* \brief lfush and release all resources in LAPDm channel
*
* A convenience wrapper calling \ref lapdm_entity_exit on both
* entities inside the \ref lapdm_channel
*/
void lapdm_channel_exit(struct lapdm_channel *lc)
{
lapdm_entity_exit(&lc->lapdm_acch);
@ -355,7 +378,7 @@ static struct msgb *tx_dequeue_msgb(struct lapdm_entity *le)
return msg;
}
/* dequeue a msg that's pending transmission via L1 and wrap it into
/*! \brief dequeue a msg that's pending transmission via L1 and wrap it into
* a osmo_phsap_prim */
int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp)
{
@ -1702,6 +1725,7 @@ static int l2_ph_rach_ind(struct lapdm_entity *le, uint8_t ra, uint32_t fn, uint
static int l2_ph_chan_conf(struct msgb *msg, struct lapdm_entity *le, uint32_t frame_nr);
/*! \brief Receive a PH-SAP primitive from L1 */
int lapdm_phsap_up(struct osmo_prim_hdr *oph, struct lapdm_entity *le)
{
struct osmo_phsap_prim *pp = (struct osmo_phsap_prim *) oph;
@ -2411,7 +2435,7 @@ static int rslms_rx_com_chan(struct msgb *msg, struct lapdm_channel *lc)
return rc;
}
/* input into layer2 (from layer 3) */
/*! \brief Receive a RSLms \ref msgb from Layer 3 */
int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
{
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
@ -2439,6 +2463,7 @@ int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
return rc;
}
/*! \brief Set the \ref lapdm_mode of a LAPDm entity */
int lapdm_entity_set_mode(struct lapdm_entity *le, enum lapdm_mode mode)
{
switch (mode) {
@ -2463,6 +2488,7 @@ int lapdm_entity_set_mode(struct lapdm_entity *le, enum lapdm_mode mode)
return 0;
}
/*! \brief Set the \ref lapdm_mode of a LAPDm channel*/
int lapdm_channel_set_mode(struct lapdm_channel *lc, enum lapdm_mode mode)
{
int rc;
@ -2474,6 +2500,7 @@ int lapdm_channel_set_mode(struct lapdm_channel *lc, enum lapdm_mode mode)
return lapdm_entity_set_mode(&lc->lapdm_acch, mode);
}
/*! \brief Set the L1 callback and context of a LAPDm channel */
void lapdm_channel_set_l1(struct lapdm_channel *lc, osmo_prim_cb cb, void *ctx)
{
lc->lapdm_dcch.l1_prim_cb = cb;
@ -2482,6 +2509,7 @@ void lapdm_channel_set_l1(struct lapdm_channel *lc, osmo_prim_cb cb, void *ctx)
lc->lapdm_acch.l1_ctx = ctx;
}
/*! \brief Set the L3 callback and context of a LAPDm channel */
void lapdm_channel_set_l3(struct lapdm_channel *lc, lapdm_cb_t cb, void *ctx)
{
lc->lapdm_dcch.l3_cb = cb;
@ -2490,6 +2518,7 @@ void lapdm_channel_set_l3(struct lapdm_channel *lc, lapdm_cb_t cb, void *ctx)
lc->lapdm_acch.l3_ctx = ctx;
}
/*! \brief Reset an entire LAPDm entity and all its datalinks */
void lapdm_entity_reset(struct lapdm_entity *le)
{
struct lapdm_datalink *dl;
@ -2510,19 +2539,24 @@ void lapdm_entity_reset(struct lapdm_entity *le)
}
}
/*! \brief Reset a LAPDm channel with all its entities */
void lapdm_channel_reset(struct lapdm_channel *lc)
{
lapdm_entity_reset(&lc->lapdm_dcch);
lapdm_entity_reset(&lc->lapdm_acch);
}
/*! \brief Set the flags of a LAPDm entity */
void lapdm_entity_set_flags(struct lapdm_entity *le, unsigned int flags)
{
le->flags = flags;
}
/*! \brief Set the flags of all LAPDm entities in a LAPDm channel */
void lapdm_channel_set_flags(struct lapdm_channel *lc, unsigned int flags)
{
lapdm_entity_set_flags(&lc->lapdm_dcch, flags);
lapdm_entity_set_flags(&lc->lapdm_acch, flags);
}
/*! }@ */

View File

@ -28,9 +28,18 @@
#include <osmocom/gsm/tlv.h>
#include <osmocom/gsm/rsl.h>
/*! \addtogroup rsl
* @{
*/
/*! \file rsl.c */
/*! \brief Size for RSL \ref msgb_alloc */
#define RSL_ALLOC_SIZE 200
/*! \brief Headroom size for RSL \ref msgb_alloc */
#define RSL_ALLOC_HEADROOM 56
/*! \brief Initialize a RSL RLL header */
void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type)
{
dh->c.msg_discr = ABIS_RSL_MDISC_RLL;
@ -39,6 +48,7 @@ void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type)
dh->ie_link_id = RSL_IE_LINK_IDENT;
}
/*! \brief Initialize a RSL Common Channel header */
void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type)
{
ch->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN;
@ -46,6 +56,7 @@ void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type)
ch->ie_chan = RSL_IE_CHAN_NR;
}
/* \brief TLV parser definition for RSL */
const struct tlv_definition rsl_att_tlvdef = {
.def = {
[RSL_IE_CHAN_NR] = { TLV_TYPE_TV },
@ -126,7 +137,7 @@ const struct tlv_definition rsl_att_tlvdef = {
},
};
/* encode channel number as per Section 9.3.1 */
/*! \brief Encode channel number as per Section 9.3.1 */
uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot)
{
uint8_t ret;
@ -153,6 +164,12 @@ uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot)
return ret;
}
/*! \brief Decode RSL channel number
* \param[in] chan_nr Channel Number
* \param[out] type Channel Type
* \param[out] subch Sub-channel Number
* \param[out] timeslot Timeslot
*/
int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot)
{
*timeslot = chan_nr & 0x7;
@ -184,6 +201,7 @@ int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *tim
return 0;
}
/*! \brief Get human-readable string for RSL channel number */
const char *rsl_chan_nr_str(uint8_t chan_nr)
{
static char str[20];
@ -245,6 +263,7 @@ static const struct value_string rsl_err_vals[] = {
{ 0, NULL }
};
/*! \brief Get human-readable name for RSL Error */
const char *rsl_err_name(uint8_t err)
{
return get_value_string(rsl_err_vals, err);
@ -321,11 +340,48 @@ static const struct value_string rsl_msgt_names[] = {
};
/*! \brief Get human-readable string for RSL Message Type */
const char *rsl_msg_name(uint8_t msg_type)
{
return get_value_string(rsl_msgt_names, msg_type);
}
/*! \brief ip.access specific */
static const struct value_string rsl_ipac_msgt_names[] = {
{ RSL_MT_IPAC_PDCH_ACT, "IPAC_PDCH_ACT" },
{ RSL_MT_IPAC_PDCH_ACT_ACK, "IPAC_PDCH_ACT_ACK" },
{ RSL_MT_IPAC_PDCH_ACT_NACK, "IPAC_PDCH_ACT_NACK" },
{ RSL_MT_IPAC_PDCH_DEACT, "IPAC_PDCH_DEACT" },
{ RSL_MT_IPAC_PDCH_DEACT_ACK, "IPAC_PDCH_DEACT_ACK" },
{ RSL_MT_IPAC_PDCH_DEACT_NACK, "IPAC_PDCH_DEACT_NACK" },
{ RSL_MT_IPAC_CONNECT_MUX, "IPAC_CONNECT_MUX" },
{ RSL_MT_IPAC_CONNECT_MUX_ACK, "IPAC_CONNECT_MUX_ACK" },
{ RSL_MT_IPAC_CONNECT_MUX_NACK, "IPAC_CONNECT_MUX_NACK" },
{ RSL_MT_IPAC_BIND_MUX, "IPAC_BIND_MUX" },
{ RSL_MT_IPAC_BIND_MUX_ACK, "IPAC_BIND_MUX_ACK" },
{ RSL_MT_IPAC_BIND_MUX_NACK, "IPAC_BIND_MUX_NACK" },
{ RSL_MT_IPAC_DISC_MUX, "IPAC_DISC_MUX" },
{ RSL_MT_IPAC_DISC_MUX_ACK, "IPAC_DISC_MUX_ACK" },
{ RSL_MT_IPAC_DISC_MUX_NACK, "IPAC_DISC_MUX_NACK" },
{ RSL_MT_IPAC_CRCX, "IPAC_CRCX" },
{ RSL_MT_IPAC_CRCX_ACK, "IPAC_CRCX_ACK" },
{ RSL_MT_IPAC_CRCX_NACK, "IPAC_CRCX_NACK" },
{ RSL_MT_IPAC_MDCX, "IPAC_MDCX" },
{ RSL_MT_IPAC_MDCX_ACK, "IPAC_MDCX_ACK" },
{ RSL_MT_IPAC_MDCX_NACK, "IPAC_MDCX_NACK" },
{ RSL_MT_IPAC_DLCX_IND, "IPAC_DLCX_IND" },
{ RSL_MT_IPAC_DLCX, "IPAC_DLCX" },
{ RSL_MT_IPAC_DLCX_ACK, "IPAC_DLCX_ACK" },
{ RSL_MT_IPAC_DLCX_NACK, "IPAC_DLCX_NACK" },
{ 0, NULL }
};
/*! \brief Get human-readable name of ip.access RSL msg type */
const char *rsl_ipac_msg_name(uint8_t msg_type)
{
return get_value_string(rsl_ipac_msgt_names, msg_type);
}
static const struct value_string rsl_rlm_cause_strs[] = {
{ RLL_CAUSE_T200_EXPIRED, "Timer T200 expired (N200+1) times" },
{ RLL_CAUSE_REEST_REQ, "Re-establishment request" },
@ -344,6 +400,7 @@ static const struct value_string rsl_rlm_cause_strs[] = {
{ 0, NULL },
};
/*! \brief Get human-readable string for RLM cause */
const char *rsl_rlm_cause_name(uint8_t err)
{
return get_value_string(rsl_rlm_cause_strs, err);
@ -387,7 +444,7 @@ int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf)
}
}
/* Push a RSL RLL header */
/*! \brief Push a RSL RLL header onto an existing msgb */
void rsl_rll_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
uint8_t link_id, int transparent)
{
@ -404,7 +461,7 @@ void rsl_rll_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
msg->l2h = (uint8_t *)rh;
}
/* Push a RSL RLL header with L3_INFO IE */
/*! \brief Push a RSL RLL header with L3_INFO IE */
void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
uint8_t link_id, int transparent)
{
@ -420,6 +477,7 @@ void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
rsl_rll_push_hdr(msg, msg_type, chan_nr, link_id, transparent);
}
/*! \brief Create msgb with RSL RLL header */
struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
uint8_t link_id, int transparent)
{
@ -445,3 +503,5 @@ struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
return msg;
}
/*! }@ */

View File

@ -3,8 +3,14 @@
#include <osmocom/core/utils.h>
#include <osmocom/gsm/tlv.h>
/*! \addtogroup tlv
* @{
*/
/*! \file tlv.c */
struct tlv_definition tvlv_att_def;
/*! \brief Dump pasred TLV structure to stdout */
int tlv_dump(struct tlv_parsed *dec)
{
int i;
@ -17,14 +23,14 @@ int tlv_dump(struct tlv_parsed *dec)
return 0;
}
/* o_tag: output: tag found
* o_len: output: length of the data
* o_val: output: pointer to the data
* def: input: a structure defining the valid TLV tags / configurations
* buf: input: the input data buffer to be parsed
* buf_len: input: the length of the input data buffer
*
* Also, returns the number of bytes consumed by the TLV entry
/*! \brief Parse a single TLV encoded IE
* \param[out] o_tag the tag of the IE that was found
* \param[out] o_len length of the IE that was found
* \param[out] o_val pointer to the data of the IE that was found
* \param[in] def structure defining the valid TLV tags / configurations
* \param[in] buf the input data buffer to be parsed
* \param[in] buf_len length of the input data buffer
* \returns number of bytes consumed by the TLV entry / IE parsed
*/
int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
const struct tlv_definition *def,
@ -101,12 +107,14 @@ int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
return len;
}
/* dec: output: a caller-allocated pointer to a struct tlv_parsed,
* def: input: a structure defining the valid TLV tags / configurations
* buf: input: the input data buffer to be parsed
* buf_len: input: the length of the input data buffer
* lv_tag: input: an initial LV tag at the start of the buffer
* lv_tag2: input: a second initial LV tag following lv_tag
/*! \brief Parse an entire buffer of TLV encoded Information Eleemnts
* \param[out] dec caller-allocated pointer to \ref tlv_parsed
* \param[in] def structure defining the valid TLV tags / configurations
* \param[in] buf the input data buffer to be parsed
* \param[in] buf_len length of the input data buffer
* \param[in] lv_tag an initial LV tag at the start of the buffer
* \param[in] lv_tag2 a second initial LV tag following the \a lv_tag
* \returns number of bytes consumed by the TLV entry / IE parsed
*/
int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
const uint8_t *buf, int buf_len, uint8_t lv_tag,
@ -158,7 +166,7 @@ int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
return num_parsed;
}
/* take a master (src) tlvdev and fill up all empty slots in 'dst' */
/*! \brief take a master (src) tlvdev and fill up all empty slots in 'dst' */
void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src)
{
int i;
@ -177,3 +185,5 @@ static __attribute__((constructor)) void on_dso_load_tlv(void)
for (i = 0; i < ARRAY_SIZE(tvlv_att_def.def); i++)
tvlv_att_def.def[i].type = TLV_TYPE_TvLV;
}
/*! }@ */

View File

@ -42,6 +42,17 @@
#include <string.h>
#include <errno.h>
/*! \addtogroup gsmtap
* @{
*/
/*! \file gsmtap_util.c */
/*! \brief convert RSL channel number to GSMTAP channel type
* \param[in] rsl_cantype RSL channel type
* \param[in] link_id RSL link identifier
* \returns GSMTAP channel type
*/
uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id)
{
uint8_t ret = GSMTAP_CHANNEL_UNKNOWN;
@ -77,7 +88,20 @@ uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id)
return ret;
}
/* receive a message from L1/L2 and put it in GSMTAP */
/*! \brief create L1/L2 data and put it into GSMTAP
* \param[in] arfcn GSM ARFCN (Channel Number)
* \param[in] ts GSM time slot
* \param[in] chan_type Channel Type
* \param[in] ss Sub-slot
* \param[in] fn GSM Frame Number
* \param[in] signal_dbm Signal Strength (dBm)
* \param[in] snr Signal/Noise Ratio (SNR)
* \param[in] data Pointer to data buffer
* \param[in] len Length of \ref data
*
* This function will allocate a new msgb and fill it with a GSMTAP
* header containing the information
*/
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)
@ -115,8 +139,15 @@ struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
#include <sys/socket.h>
#include <netinet/in.h>
/* Open a GSMTAP source (sending) socket, conncet it to host/port and
* return resulting fd */
/*! \brief Create a new (sending) GSMTAP source socket
* \param[in] host host name or IP address in string format
* \param[in] port UDP port number in host byte order
*
* Opens a GSMTAP source (sending) socket, conncet it to host/port and
* return resulting fd. If \a host is NULL, the destination address
* will be localhost. If \a port is 0, the default \ref
* GSMTAP_UDP_PORT will be used.
* */
int gsmtap_source_init_fd(const char *host, uint16_t port)
{
if (port == 0)
@ -128,6 +159,7 @@ int gsmtap_source_init_fd(const char *host, uint16_t port)
OSMO_SOCK_F_CONNECT);
}
/*! \brief Add a local sink to an existing GSMTAP source and return fd */
int gsmtap_source_add_sink_fd(int gsmtap_fd)
{
struct sockaddr_storage ss;
@ -148,6 +180,10 @@ int gsmtap_source_add_sink_fd(int gsmtap_fd)
return -ENODEV;
}
/*! \brief Send a \ref msgb through a GSMTAP source
* \param[in] gti GSMTAP instance
* \param[in] msgb message buffer
*/
int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg)
{
if (!gti)
@ -172,7 +208,7 @@ int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg)
}
}
/* receive a message from L1/L2 and put it in GSMTAP */
/*! \brief receive a message from L1/L2 and put it in GSMTAP */
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,
@ -228,7 +264,7 @@ static int gsmtap_sink_fd_cb(struct osmo_fd *fd, unsigned int flags)
return 0;
}
/* Add a local sink to an existing GSMTAP source instance */
/*! \brief Add a local sink to an existing GSMTAP source instance */
int gsmtap_source_add_sink(struct gsmtap_inst *gti)
{
int fd;
@ -251,7 +287,16 @@ int gsmtap_source_add_sink(struct gsmtap_inst *gti)
return fd;
}
/* like gsmtap_init2() but integrated with libosmocore select.c */
/*! \brief Open GSMTAP source socket, connect and register osmo_fd
* \param[in] host host name or IP address in string format
* \param[in] port UDP port number in host byte order
* \param[in] osmo_wq_mode Register \ref osmo_wqueue (1) or not (0)
*
* Open GSMTAP source (sending) socket, connect it to host/port,
* allocate 'struct gsmtap_inst' and optionally osmo_fd/osmo_wqueue
* registration. This means it is like \ref gsmtap_init2 but integrated
* with libosmocore \ref select */
struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port,
int ofd_wq_mode)
{

View File

@ -20,6 +20,12 @@
*
*/
/* \addtogroup logging
* @{
*/
/* \file logging.c */
#include "../config.h"
#include <stdarg.h>
@ -113,16 +119,22 @@ static int subsys_lib2index(int subsys)
return (subsys * -1) + (osmo_log_info->num_cat_user-1);
}
/*! \brief Parse a human-readable log level into a numeric value */
int log_parse_level(const char *lvl)
{
return get_string_value(loglevel_strs, lvl);
}
/*! \brief convert a numeric log level into human-readable string */
const char *log_level_str(unsigned int lvl)
{
return get_value_string(loglevel_strs, lvl);
}
/*! \brief parse a human-readable log category into numeric form
* \param[in] category human-readable log category name
* \returns numeric category value, or -EINVAL otherwise
*/
int log_parse_category(const char *category)
{
int i;
@ -137,8 +149,10 @@ int log_parse_category(const char *category)
return -EINVAL;
}
/*
* Parse the category mask.
/*! \brief parse the log category mask
* \param[in] target log target to be configured
* \param[in] _mask log category mask string
*
* The format can be this: category1:category2:category3
* or category1,2:category2,3:...
*/
@ -157,6 +171,11 @@ void log_parse_category_mask(struct log_target* target, const char *_mask)
for (i = 0; i < osmo_log_info->num_cat; ++i) {
char* colon = strstr(category_token, ",");
int length = strlen(category_token);
int cat_length = strlen(osmo_log_info->cat[i].name);
/* Use longest length not to match subocurrences. */
if (cat_length > length)
length = cat_length;
if (!osmo_log_info->cat[i].name)
continue;
@ -238,8 +257,9 @@ err:
target->output(target, level, buf);
}
static void _logp(int subsys, int level, char *file, int line,
int cont, const char *format, va_list ap)
/*! \brief vararg version of logging function */
void osmo_vlogp(int subsys, int level, char *file, int line,
int cont, const char *format, va_list ap)
{
struct log_target *tar;
@ -294,7 +314,7 @@ void logp(int subsys, char *file, int line, int cont,
va_list ap;
va_start(ap, format);
_logp(subsys, LOGL_DEBUG, file, line, cont, format, ap);
osmo_vlogp(subsys, LOGL_DEBUG, file, line, cont, format, ap);
va_end(ap);
}
@ -303,25 +323,42 @@ void logp2(int subsys, unsigned int level, char *file, int line, int cont, const
va_list ap;
va_start(ap, format);
_logp(subsys, level, file, line, cont, format, ap);
osmo_vlogp(subsys, level, file, line, cont, format, ap);
va_end(ap);
}
/*! \brief Register a new log target with the logging core
* \param[in] target Log target to be registered
*/
void log_add_target(struct log_target *target)
{
llist_add_tail(&target->entry, &osmo_log_target_list);
}
/*! \brief Unregister a log target from the logging core
* \param[in] target Log target to be unregistered
*/
void log_del_target(struct log_target *target)
{
llist_del(&target->entry);
}
/*! \brief Reset (clear) the logging context */
void log_reset_context(void)
{
memset(&log_context, 0, sizeof(log_context));
}
/*! \brief Set the logging context
* \param[in] ctx_nr logging context number
* \param[in] value value to which the context is to be set
*
* A logging context is something like the subscriber identity to which
* the currently processed message relates, or the BTS through which it
* was received. As soon as this data is known, it can be set using
* this function. The main use of context information is for logging
* filters.
*/
int log_set_context(uint8_t ctx_nr, void *value)
{
if (ctx_nr > LOG_MAX_CTX)
@ -332,6 +369,14 @@ int log_set_context(uint8_t ctx_nr, void *value)
return 0;
}
/*! \brief Enable the \ref LOG_FILTER_ALL log filter
* \param[in] target Log target to be affected
* \param[in] all enable (1) or disable (0) the ALL filter
*
* When the \ref LOG_FILTER_ALL filter is enabled, all log messages will
* be printed. It acts as a wildcard. Setting it to \a 1 means there
* is no filtering.
*/
void log_set_all_filter(struct log_target *target, int all)
{
if (all)
@ -340,16 +385,28 @@ void log_set_all_filter(struct log_target *target, int all)
target->filter_map &= ~LOG_FILTER_ALL;
}
/*! \brief Enable or disable the use of colored output
* \param[in] target Log target to be affected
* \param[in] use_color Use color (1) or don't use color (0)
*/
void log_set_use_color(struct log_target *target, int use_color)
{
target->use_color = use_color;
}
/*! \brief Enable or disable printing of timestamps while logging
* \param[in] target Log target to be affected
* \param[in] print_timestamp Enable (1) or disable (0) timestamps
*/
void log_set_print_timestamp(struct log_target *target, int print_timestamp)
{
target->print_timestamp = print_timestamp;
}
/*! \brief Set the global log level for a given log target
* \param[in] target Log target to be affected
* \param[in] log_level New global log level
*/
void log_set_log_level(struct log_target *target, int log_level)
{
target->loglevel = log_level;
@ -371,6 +428,7 @@ static void _file_output(struct log_target *target, unsigned int level,
fflush(target->tgt_file.out);
}
/*! \brief Create a new log target skeleton */
struct log_target *log_target_create(void)
{
struct log_target *target;
@ -406,6 +464,7 @@ struct log_target *log_target_create(void)
return target;
}
/*! \brief Create the STDERR log target */
struct log_target *log_target_create_stderr(void)
{
/* since C89/C99 says stderr is a macro, we can safely do this! */
@ -425,6 +484,10 @@ struct log_target *log_target_create_stderr(void)
#endif /* stderr */
}
/*! \brief Create a new file-based log target
* \param[in] fname File name of the new log file
* \returns Log target in case of success, NULL otherwise
*/
struct log_target *log_target_create_file(const char *fname)
{
struct log_target *target;
@ -445,6 +508,11 @@ struct log_target *log_target_create_file(const char *fname)
return target;
}
/*! \brief Find a registered log target
* \param[in] type Log target type
* \param[in] fname File name
* \returns Log target (if found), NULL otherwise
*/
struct log_target *log_target_find(int type, const char *fname)
{
struct log_target *tgt;
@ -461,6 +529,7 @@ struct log_target *log_target_find(int type, const char *fname)
return NULL;
}
/*! \brief Unregister, close and delete a log target */
void log_target_destroy(struct log_target *target)
{
@ -482,7 +551,7 @@ void log_target_destroy(struct log_target *target)
talloc_free(target);
}
/* close and re-open a log file (for log file rotation) */
/*! \brief close and re-open a log file (for log file rotation) */
int log_target_file_reopen(struct log_target *target)
{
fclose(target->tgt_file.out);
@ -496,7 +565,9 @@ int log_target_file_reopen(struct log_target *target)
return 0;
}
/* This generates the logging command string for VTY. */
/*! \brief Generates the logging command string for VTY
* \param[in] unused_info Deprecated parameter, no longer used!
*/
const char *log_vty_command_string(const struct log_info *unused_info)
{
struct log_info *info = osmo_log_info;
@ -571,7 +642,9 @@ err:
return str;
}
/* This generates the logging command description for VTY. */
/*! \brief Generates the logging command description for VTY
* \param[in] unused_info Deprecated parameter, no longer used!
*/
const char *log_vty_command_description(const struct log_info *unused_info)
{
struct log_info *info = osmo_log_info;
@ -629,6 +702,11 @@ err:
return str;
}
/*! \brief Initialize the Osmocom logging core
* \param[in] inf Information regarding logging categories
* \param[in] ctx \ref talloc context for logging allocations
* \returns 0 in case of success, negative in case of error
*/
int log_init(const struct log_info *inf, void *ctx)
{
int i;
@ -669,3 +747,5 @@ int log_init(const struct log_info *inf, void *ctx)
return 0;
}
/*! }@ */

View File

@ -19,6 +19,12 @@
*
*/
/*! \addtogroup logging
* @{
*/
/*! \file logging_syslog.c */
#include "../config.h"
#ifdef HAVE_SYSLOG_H
@ -57,6 +63,12 @@ static void _syslog_output(struct log_target *target,
syslog(logp2syslog_level(level), "%s", log);
}
/*! \brief Create a new logging target for syslog logging
* \param[in] ident syslog string identifier
* \param[in] option syslog options
* \param[in] facility syslog facility
* \returns Log target in case of success, NULL in case of error
*/
struct log_target *log_target_create_syslog(const char *ident, int option,
int facility)
{
@ -76,3 +88,5 @@ struct log_target *log_target_create_syslog(const char *ident, int option,
}
#endif /* HAVE_SYSLOG_H */
/* }@ */

View File

@ -18,6 +18,12 @@
*
*/
/*! \addtogroup msgb
* @{
*/
/*! \file msgb.c
*/
#include <unistd.h>
#include <string.h>
@ -30,6 +36,14 @@
void *tall_msgb_ctx;
/*! \brief Allocate a new message buffer
* \param[in] size Length in octets, including headroom
* \param[in] name Human-readable name to be associated with msgb
*
* This function allocates a 'struct msgb' as well as the underlying
* memory buffer for the actual message data (size specified by \a size)
* using the talloc memory context previously set by \ref msgb_set_talloc_ctx
*/
struct msgb *msgb_alloc(uint16_t size, const char *name)
{
struct msgb *msg;
@ -50,16 +64,33 @@ struct msgb *msgb_alloc(uint16_t size, const char *name)
return msg;
}
/*! \brief Release given message buffer
* \param[in] m Message buffer to be free'd
*/
void msgb_free(struct msgb *m)
{
talloc_free(m);
}
/*! \brief Enqueue message buffer to tail of a queue
* \param[in] queue linked list header of queue
* \param[in] msgb message buffer to be added to the queue
*
* The function will append the specified message buffer \a msg to the
* queue implemented by \ref llist_head \a queue
*/
void msgb_enqueue(struct llist_head *queue, struct msgb *msg)
{
llist_add_tail(&msg->list, queue);
}
/*! \brief Dequeue message buffer from head of queue
* \param[in] queue linked list header of queue
* \returns message buffer (if any) or NULL if queue empty
*
* The function will remove the first message buffer from the queue
* implemented by 'ref llist_head \a queue.
*/
struct msgb *msgb_dequeue(struct llist_head *queue)
{
struct llist_head *lh;
@ -73,6 +104,13 @@ struct msgb *msgb_dequeue(struct llist_head *queue)
return llist_entry(lh, struct msgb, list);
}
/*! \brief Re-set all message buffer pointers
* \param[in] m message buffer that is to be resetted
*
* This will re-set the various internal pointers into the underlying
* message buffer, i.e. remvoe all headroom and treat the msgb as
* completely empty. It also initializes the control buffer to zero.
*/
void msgb_reset(struct msgb *msg)
{
msg->len = 0;
@ -89,17 +127,30 @@ void msgb_reset(struct msgb *msg)
memset(&msg->cb, 0, sizeof(msg->cb));
}
/*! \brief get pointer to data section of message buffer
* \param[in] msg message buffer
* \returns pointer to data section of message buffer
*/
uint8_t *msgb_data(const struct msgb *msg)
{
return msg->data;
}
/*! \brief get length of message buffer
* \param[in] msg message buffer
* \returns length of data section in message buffer
*/
uint16_t msgb_length(const struct msgb *msg)
{
return msg->len;
}
/*! \brief Set the talloc context for \ref msgb_alloc
* \param[in] ctx talloc context to be used as root for msgb allocations
*/
void msgb_set_talloc_ctx(void *ctx)
{
tall_msgb_ctx = ctx;
}
/*! }@ */

View File

@ -20,6 +20,12 @@
*
*/
/*! \addtogroup utils
* @{
*/
/*! \file panic.c */
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/core/panic.h>
#include <osmocom/core/backtrace.h>
@ -52,6 +58,7 @@ static void osmo_panic_default(const char *fmt, va_list args)
#endif
/*! \brief Terminate the current program with a panic */
void osmo_panic(const char *fmt, ...)
{
va_list args;
@ -67,6 +74,7 @@ void osmo_panic(const char *fmt, ...)
}
/*! \brief Set the panic handler */
void osmo_set_panic_handler(osmo_panic_handler_t h)
{
osmo_panic_handler = h;

View File

@ -20,6 +20,13 @@
*
*/
/*! \addtogroup rate_ctr
* @{
*/
/*! \file rate_ctr.c */
#include <stdint.h>
#include <string.h>
@ -33,6 +40,11 @@ static LLIST_HEAD(rate_ctr_groups);
static void *tall_rate_ctr_ctx;
/*! \brief Allocate a new group of counters according to description
* \param[in] ctx \ref talloc context
* \param[in] desc Rate counter group description
* \param[in] idx Index of new counter group
*/
struct rate_ctr_group *rate_ctr_group_alloc(void *ctx,
const struct rate_ctr_group_desc *desc,
unsigned int idx)
@ -58,12 +70,14 @@ struct rate_ctr_group *rate_ctr_group_alloc(void *ctx,
return group;
}
/*! \brief Free the memory for the specified group of counters */
void rate_ctr_group_free(struct rate_ctr_group *grp)
{
llist_del(&grp->list);
talloc_free(grp);
}
/*! \brief Add a number to the counter */
void rate_ctr_add(struct rate_ctr *ctr, int inc)
{
ctr->current += inc;
@ -117,6 +131,7 @@ static void rate_ctr_timer_cb(void *data)
osmo_timer_schedule(&rate_ctr_timer, 1, 0);
}
/*! \brief Initialize the counter module */
int rate_ctr_init(void *tall_ctx)
{
tall_rate_ctr_ctx = tall_ctx;
@ -126,6 +141,7 @@ int rate_ctr_init(void *tall_ctx)
return 0;
}
/*! \brief Search for counter group based on group name and index */
struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const unsigned int idx)
{
struct rate_ctr_group *ctrg;
@ -142,6 +158,7 @@ struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const un
return NULL;
}
/*! \brief Search for counter group based on group name */
const struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name)
{
int i;
@ -159,3 +176,5 @@ const struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, c
}
return NULL;
}
/*! }@ */

View File

@ -30,10 +30,21 @@
#ifdef HAVE_SYS_SELECT_H
/*! \addtogroup select
* @{
*/
/*! \file select.c
* \brief select loop abstraction
*/
static int maxfd = 0;
static LLIST_HEAD(osmo_fds);
static int unregistered_count;
/*! \brief Register a new file descriptor with select loop abstraction
* \param[in] fd osmocom file descriptor to be registered
*/
int osmo_fd_register(struct osmo_fd *fd)
{
int flags;
@ -75,12 +86,18 @@ int osmo_fd_register(struct osmo_fd *fd)
return 0;
}
/*! \brief Unregister a file descriptor from select loop abstraction
* \param[in] fd osmocom file descriptor to be unregistered
*/
void osmo_fd_unregister(struct osmo_fd *fd)
{
unregistered_count++;
llist_del(&fd->list);
}
/*! \brief select main loop integration
* \param[in] polling should we pollonly (1) or block on select (0)
*/
int osmo_select_main(int polling)
{
struct osmo_fd *ufd, *tmp;
@ -150,4 +167,6 @@ restart:
return work;
}
/*! }@ */
#endif /* _HAVE_SYS_SELECT_H */

View File

@ -0,0 +1,209 @@
/*
* serial.c
*
* Utility functions to deal with serial ports
*
* 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.
*/
/*! \addtogroup serial
* @{
*/
/*! \file serial.c
* \file Osmocom serial port helpers
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/serial.h>
#include <osmocom/core/serial.h>
#if 0
# define dbg_perror(x) perror(x)
#else
# define dbg_perror(x) do { } while (0)
#endif
/*! \brief Open serial device and does base init
* \param[in] dev Path to the device node to open
* \param[in] baudrate Baudrate constant (speed_t: B9600, B...)
* \returns >=0 file descriptor in case of success or negative errno.
*/
int
osmo_serial_init(const char *dev, speed_t baudrate)
{
int rc, fd=0, v24;
struct termios tio;
/* Open device */
fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
dbg_perror("open");
return -errno;
}
/* Configure serial interface */
rc = tcgetattr(fd, &tio);
if (rc < 0) {
dbg_perror("tcgetattr()");
rc = -errno;
goto error;
}
cfsetispeed(&tio, baudrate);
cfsetospeed(&tio, baudrate);
tio.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
tio.c_cflag |= (CREAD | CLOCAL | CS8);
tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tio.c_iflag |= (INPCK | ISTRIP);
tio.c_iflag &= ~(ISTRIP | IXON | IXOFF | IGNBRK | INLCR | ICRNL | IGNCR);
tio.c_oflag &= ~(OPOST | ONLCR);
rc = tcsetattr(fd, TCSANOW, &tio);
if (rc < 0) {
dbg_perror("tcsetattr()");
rc = -errno;
goto error;
}
/* Set ready to read/write */
v24 = TIOCM_DTR | TIOCM_RTS;
rc = ioctl(fd, TIOCMBIS, &v24);
if (rc < 0) {
dbg_perror("ioctl(TIOCMBIS)");
rc = -errno;
goto error;
}
return fd;
error:
if (fd)
close(fd);
return rc;
}
static int
_osmo_serial_set_baudrate(int fd, speed_t baudrate)
{
int rc;
struct termios tio;
rc = tcgetattr(fd, &tio);
if (rc < 0) {
dbg_perror("tcgetattr()");
return -errno;
}
cfsetispeed(&tio, baudrate);
cfsetospeed(&tio, baudrate);
rc = tcsetattr(fd, TCSANOW, &tio);
if (rc < 0) {
dbg_perror("tcgetattr()");
return -errno;
}
return 0;
}
/*! \brief Change current baudrate
* \param[in] fd File descriptor of the open device
* \param[in] baudrate Baudrate constant (speed_t: B9600, B...)
* \returns 0 for success or negative errno.
*/
int
osmo_serial_set_baudrate(int fd, speed_t baudrate)
{
osmo_serial_clear_custom_baudrate(fd);
return _osmo_serial_set_baudrate(fd, baudrate);
}
/*! \brief Change current baudrate to a custom one using OS specific method
* \param[in] fd File descriptor of the open device
* \param[in] baudrate Baudrate as integer
* \returns 0 for success or negative errno.
*
* This function might not work on all OS or with all type of serial adapters
*/
int
osmo_serial_set_custom_baudrate(int fd, int baudrate)
{
int rc;
struct serial_struct ser_info;
rc = ioctl(fd, TIOCGSERIAL, &ser_info);
if (rc < 0) {
dbg_perror("ioctl(TIOCGSERIAL)");
return -errno;
}
ser_info.flags = ASYNC_SPD_CUST | ASYNC_LOW_LATENCY;
ser_info.custom_divisor = ser_info.baud_base / baudrate;
rc = ioctl(fd, TIOCSSERIAL, &ser_info);
if (rc < 0) {
dbg_perror("ioctl(TIOCSSERIAL)");
return -errno;
}
return _osmo_serial_set_baudrate(fd, B38400); /* 38400 is a kind of magic ... */
}
/*! \brief Clear any custom baudrate
* \param[in] fd File descriptor of the open device
* \returns 0 for success or negative errno.
*
* This function might not work on all OS or with all type of serial adapters
*/
int
osmo_serial_clear_custom_baudrate(int fd)
{
int rc;
struct serial_struct ser_info;
rc = ioctl(fd, TIOCGSERIAL, &ser_info);
if (rc < 0) {
dbg_perror("ioctl(TIOCGSERIAL)");
return -errno;
}
ser_info.flags = ASYNC_LOW_LATENCY;
ser_info.custom_divisor = 0;
rc = ioctl(fd, TIOCSSERIAL, &ser_info);
if (rc < 0) {
dbg_perror("ioctl(TIOCSSERIAL)");
return -errno;
}
return 0;
}
/*! }@ */

View File

@ -25,6 +25,12 @@
#include <string.h>
#include <errno.h>
/*! \addtogroup signal
* @{
*/
/*! \file signal.c */
void *tall_sigh_ctx;
static LLIST_HEAD(signal_handler_list);
@ -36,6 +42,11 @@ struct signal_handler {
};
/*! \brief Register a new signal handler
* \param[in] subsys Subsystem number
* \param[in] cbfn Callback function
* \param[in] data Data passed through to callback
*/
int osmo_signal_register_handler(unsigned int subsys,
osmo_signal_cbfn *cbfn, void *data)
{
@ -58,6 +69,11 @@ int osmo_signal_register_handler(unsigned int subsys,
return 0;
}
/*! \brief Unregister signal handler
* \param[in] subsys Subsystem number
* \param[in] cbfn Callback function
* \param[in] data Data passed through to callback
*/
void osmo_signal_unregister_handler(unsigned int subsys,
osmo_signal_cbfn *cbfn, void *data)
{
@ -73,7 +89,11 @@ void osmo_signal_unregister_handler(unsigned int subsys,
}
}
/*! \brief dispatch (deliver) a new signal to all registered handlers
* \param[in] subsys Subsystem number
* \param[in] signal Signal number,
* \param[in] signal_data Data to be passed along to handlers
*/
void osmo_signal_dispatch(unsigned int subsys, unsigned int signal,
void *signal_data)
{
@ -85,3 +105,5 @@ void osmo_signal_dispatch(unsigned int subsys, unsigned int signal,
(*handler->cbfn)(subsys, signal, handler->data, signal_data);
}
}
/*! }@ */

View File

@ -1,5 +1,13 @@
#include "../config.h"
/*! \addtogroup socket
* @{
*/
/*! \file socket.c
* \brief Osmocom socket convenience functions
*/
#ifdef HAVE_SYS_SOCKET_H
#include <osmocom/core/logging.h>
@ -18,6 +26,18 @@
#include <netdb.h>
#include <ifaddrs.h>
/*! \brief Initialize a socket (including bind/connect)
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
* \param[in] host remote host name or IP address in string form
* \param[in] port remote port number in host byte order
* \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT
*
* This function creates a new socket of the designated \a family, \a
* type and \a proto and optionally binds or connects it, depending on
* the value of \a flags parameter.
*/
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
const char *host, uint16_t port, unsigned int flags)
{
@ -93,6 +113,18 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
return sfd;
}
/*! \brief Initialize a socket and fill \ref osmo_fd
* \param[out] osmocom file descriptor (will be filled in)
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
* \param[in] host remote host name or IP address in string form
* \param[in] port remote port number in host byte order
* \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT
*
* This function creates (and optionall binds/connects) a socket using
* \ref osmo_sock_init, but also fills the \a ofd structure.
*/
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
const char *host, uint16_t port, unsigned int flags)
{
@ -114,6 +146,15 @@ int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
return sfd;
}
/*! \brief Initialize a socket and fill \ref sockaddr
* \param[out] ss socket address (will be filled in)
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
* \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT
*
* This function creates (and optionall binds/connects) a socket using
* \ref osmo_sock_init, but also fills the \a ss structure.
*/
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
uint8_t proto, unsigned int flags)
{
@ -177,7 +218,11 @@ static int sockaddr_equal(const struct sockaddr *a,
return 0;
}
/* determine if the given address is a local address */
/*! \brief Determine if the given address is a local address
* \param[in] addr Socket Address
* \param[in] addrlen Length of socket address in bytes
* \returns 1 if address is local, 0 otherwise.
*/
int osmo_sockaddr_is_local(struct sockaddr *addr, socklen_t addrlen)
{
struct ifaddrs *ifaddr, *ifa;
@ -198,3 +243,5 @@ int osmo_sockaddr_is_local(struct sockaddr *addr, socklen_t addrlen)
}
#endif /* HAVE_SYS_SOCKET_H */
/*! }@ */

View File

@ -18,6 +18,13 @@
*
*/
/*! \addtogroup timer
* @{
*/
/*! \file timer.c
*/
#include <assert.h>
#include <string.h>
#include <osmocom/core/timer.h>
@ -31,6 +38,10 @@ static struct timeval s_select_time;
#define TIME_SMALLER(left, right) \
(left.tv_sec*MICRO_SECONDS+left.tv_usec) <= (right.tv_sec*MICRO_SECONDS+right.tv_usec)
/*! \brief add a new timer to the timer management
* \param[in] timer the timer that should be added
*/
void osmo_timer_add(struct osmo_timer_list *timer)
{
struct osmo_timer_list *list_timer;
@ -47,6 +58,16 @@ void osmo_timer_add(struct osmo_timer_list *timer)
llist_add(&timer->entry, &timer_list);
}
/*! \brief schedule a timer at a given future relative time
* \param[in] timer the to-be-added timer
* \param[in] seconds number of seconds from now
* \param[in] microseconds number of microseconds from now
*
* This function can be used to (re-)schedule a given timer at a
* specified number of seconds+microseconds in the future. It will
* internally add it to the timer management data structures, thus
* osmo_timer_add() is automatically called.
*/
void
osmo_timer_schedule(struct osmo_timer_list *timer, int seconds, int microseconds)
{
@ -60,6 +81,12 @@ osmo_timer_schedule(struct osmo_timer_list *timer, int seconds, int microseconds
osmo_timer_add(timer);
}
/*! \brief delete a timer from timer management
* \param[in] timer the to-be-deleted timer
*
* This function can be used to delete a previously added/scheduled
* timer from the timer management code.
*/
void osmo_timer_del(struct osmo_timer_list *timer)
{
if (timer->in_list) {
@ -69,6 +96,13 @@ void osmo_timer_del(struct osmo_timer_list *timer)
}
}
/*! \brief check if given timer is still pending
* \param[in] timer the to-be-checked timer
* \return 1 if pending, 0 otherwise
*
* This function can be used to determine whether a given timer
* has alredy expired (returns 0) or is still pending (returns 1)
*/
int osmo_timer_pending(struct osmo_timer_list *timer)
{
return timer->active;
@ -184,3 +218,5 @@ int osmo_timers_check(void)
}
return i;
}
/*! }@ */

View File

@ -6,7 +6,19 @@
#include <osmocom/core/utils.h>
/*! \addtogroup utils
* @{
*/
/*! \file utils.c */
static char namebuf[255];
/*! \brief get human-readable string for given value
* \param[in] vs Array of value_string tuples
* \param[in] val Value to be converted
* \returns pointer to human-readable string
*/
const char *get_value_string(const struct value_string *vs, uint32_t val)
{
int i;
@ -22,6 +34,11 @@ const char *get_value_string(const struct value_string *vs, uint32_t val)
return namebuf;
}
/*! \brief get numeric value for given human-readable string
* \param[in] vs Array of value_string tuples
* \param[in] str human-readable string
* \returns numeric value (>0) or negative numer in case of error
*/
int get_string_value(const struct value_string *vs, const char *str)
{
int i;
@ -35,6 +52,10 @@ int get_string_value(const struct value_string *vs, const char *str)
return -EINVAL;
}
/*! \brief Convert BCD-encoded digit into printable character
* \param[in] bcd A single BCD-encoded digit
* \returns single printable character
*/
char osmo_bcd2char(uint8_t bcd)
{
if (bcd < 0xa)
@ -97,6 +118,10 @@ static char *_osmo_hexdump(const unsigned char *buf, int len, char *delim)
return hexd_buff;
}
/*! \brief Convert a sequence of unpacked bits to ASCII string
* \param[in] bits A sequence of unpacked bits
* \param[in] len Length of bits
*/
char *osmo_ubit_dump(const uint8_t *bits, unsigned int len)
{
int i;
@ -127,11 +152,27 @@ char *osmo_ubit_dump(const uint8_t *bits, unsigned int len)
return hexd_buff;
}
/*! \brief Convert binary sequence to hexadecimal ASCII string
* \param[in] buf pointer to sequence of bytes
* \param[in] len length of buf in number of bytes
* \returns pointer to zero-terminated string
*
* This function will print a sequence of bytes as hexadecimal numbers,
* adding one space character between each byte (e.g. "1a ef d9")
*/
char *osmo_hexdump(const unsigned char *buf, int len)
{
return _osmo_hexdump(buf, len, " ");
}
/*! \brief Convert binary sequence to hexadecimal ASCII string
* \param[in] buf pointer to sequence of bytes
* \param[in] len length of buf in number of bytes
* \returns pointer to zero-terminated string
*
* This function will print a sequence of bytes as hexadecimal numbers,
* without any space character between each byte (e.g. "1aefd9")
*/
char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
{
return _osmo_hexdump(buf, len, "");
@ -140,6 +181,10 @@ char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
#include "../config.h"
#ifdef HAVE_CTYPE_H
#include <ctype.h>
/*! \brief Convert an entire string to lower case
* \param[out] out output string, caller-allocated
* \param[in] in input string
*/
void osmo_str2lower(char *out, const char *in)
{
unsigned int i;
@ -149,6 +194,10 @@ void osmo_str2lower(char *out, const char *in)
out[strlen(in)] = '\0';
}
/*! \brief Convert an entire string to upper case
* \param[out] out output string, caller-allocated
* \param[in] in input string
*/
void osmo_str2upper(char *out, const char *in)
{
unsigned int i;
@ -158,3 +207,5 @@ void osmo_str2upper(char *out, const char *in)
out[strlen(in)] = '\0';
}
#endif /* HAVE_CTYPE_H */
/*! }@ */

View File

@ -40,6 +40,11 @@ Boston, MA 02111-1307, USA. */
#include <osmocom/core/talloc.h>
/*! \addtogroup command
* @{
*/
/*! \file command.c */
#define CONFIGFILE_MASK 022
void *tall_vty_cmd_ctx;
@ -81,7 +86,9 @@ struct cmd_node config_node = {
/* Default motd string. */
const char *default_motd = "";
/* This is called from main when a daemon is invoked with -v or --version. */
/*! \brief print the version (and optionally copyright) information
*
* This is called from main when a daemon is invoked with -v or --version. */
void print_version(int print_copyright)
{
printf("%s version %s\n", host.app_info->name, host.app_info->version);
@ -114,7 +121,7 @@ char *argv_concat(const char **argv, int argc, int shift)
return str;
}
/* Install top node of command vector. */
/*! \brief Install top node of command vector. */
void install_node(struct cmd_node *node, int (*func) (struct vty *))
{
vector_set_index(cmdvec, node->node, node);
@ -151,7 +158,7 @@ static int is_config(struct vty *vty)
return vty->node > CONFIG_NODE;
}
/* Sort each node's command element according to command string. */
/*! \brief Sort each node's command element according to command string. */
void sort_node(void)
{
unsigned int i, j;
@ -181,7 +188,7 @@ void sort_node(void)
}
}
/* Breaking up string into each command piece. I assume given
/*! Breaking up string into each command piece. I assume given
character is separated by a space character. Return value is a
vector which includes char ** data element. */
vector cmd_make_strvec(const char *string)
@ -231,7 +238,7 @@ vector cmd_make_strvec(const char *string)
}
}
/* Free allocated string vector. */
/*! \brief Free allocated string vector. */
void cmd_free_strvec(vector v)
{
unsigned int i;
@ -247,7 +254,7 @@ void cmd_free_strvec(vector v)
vector_free(v);
}
/* Fetch next description. Used in cmd_make_descvec(). */
/*! \brief Fetch next description. Used in \ref cmd_make_descvec(). */
static char *cmd_desc_str(const char **string)
{
const char *cp, *start;
@ -282,7 +289,7 @@ static char *cmd_desc_str(const char **string)
return token;
}
/* New string vector. */
/*! \brief New string vector. */
static vector cmd_make_descvec(const char *string, const char *descstr)
{
int multiple = 0;
@ -389,7 +396,7 @@ static int cmd_cmdsize(vector strvec)
return size;
}
/* Return prompt character of specified node. */
/*! \brief Return prompt character of specified node. */
const char *cmd_prompt(enum node_type node)
{
struct cmd_node *cnode;
@ -398,7 +405,10 @@ const char *cmd_prompt(enum node_type node)
return cnode->prompt;
}
/* Install a command into a node. */
/*! \brief Install a command into a node
* \param[in] ntype Node Type
* \param[cmd] element to be installed
*/
void install_element(enum node_type ntype, struct cmd_element *cmd)
{
struct cmd_node *cnode;
@ -3227,3 +3237,5 @@ void cmd_init(int terminal)
}
srand(time(NULL));
}
/*! }@ */

View File

@ -33,6 +33,11 @@
#include <osmocom/vty/buffer.h>
#include <osmocom/vty/command.h>
/*! \addtogroup telnet_interface
* @{
*/
/*! \file telnet_interface.c */
/* per connection data */
LLIST_HEAD(active_connections);
@ -47,6 +52,11 @@ static struct osmo_fd server_socket = {
.priv_nr = 0,
};
/*! \brief Initialize telnet based VTY interface
* \param[in] tall_ctx \ref talloc context
* \param[in] priv private data to be passed to callback
* \param[in] port UDP port number
*/
int telnet_init(void *tall_ctx, void *priv, int port)
{
struct sockaddr_in sock_addr;
@ -55,6 +65,7 @@ int telnet_init(void *tall_ctx, void *priv, int port)
tall_telnet_ctx = talloc_named_const(tall_ctx, 1,
"telnet_connection");
/* FIXME: use new socket.c code of libosmocore */
fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
@ -109,6 +120,7 @@ static void print_welcome(int fd)
write(fd, host.app_info->copyright, strlen(host.app_info->copyright));
}
/*! \brief close a telnet connection */
int telnet_close_client(struct osmo_fd *fd)
{
struct telnet_connection *conn = (struct telnet_connection*)fd->data;
@ -183,7 +195,7 @@ static int telnet_new_connection(struct osmo_fd *fd, unsigned int what)
return 0;
}
/* callback from VTY code */
/*! \brief callback from core VTY code about VTY related events */
void vty_event(enum event event, int sock, struct vty *vty)
{
struct telnet_connection *connection = vty->priv;
@ -209,3 +221,4 @@ void vty_event(enum event event, int sock, struct vty *vty)
}
}
/*! }@ */

View File

@ -30,6 +30,17 @@
#include <osmocom/vty/vty.h>
/* \file utils.c */
/*! \addtogroup rate_ctr
* @{
*/
/*! \brief print a rate counter group to given VTY
* \param[in] vty The VTY to which it should be printed
* \param[in] prefix Any additional log prefix ahead of each line
* \param[in] ctrg Rate counter group to be printed
*/
void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
struct rate_ctr_group *ctrg)
{
@ -48,3 +59,5 @@ void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
VTY_NEWLINE);
};
}
/*! }@ */

View File

@ -1,4 +1,42 @@
/*! \mainpage libosmovty Documentation
*
* \section sec_intro Introduction
* This library is a collection of common code used in various
* GSM related sub-projects inside the Osmocom family of projects. It
* has been imported/derived from the GNU Zebra project.
* \n\n
* libosmovty implements the interactive command-line on the VTY
* (Virtual TTY) as well as configuration file parsing.
* \n\n
* Please note that C language projects inside Osmocom are typically
* single-threaded event-loop state machine designs. As such,
* routines in libosmovty are not thread-safe. If you must use them in
* a multi-threaded context, you have to add your own locking.
*
* \section sec_copyright Copyright and License
* Copyright © 1997-2007 - Kuninhiro Ishiguro\n
* Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
* All rights reserved. \n\n
* The source code of libosmovty is licensed 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.\n
* See <http://www.gnu.org/licenses/> or COPYING included in the source
* code package istelf.\n
* The information detailed here is provided AS IS with NO WARRANTY OF
* ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE.
* \n\n
*
* \section sec_contact Contact and Support
* Community-based support is available at the OpenBSC mailing list
* <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
* Commercial support options available upon request from
* <http://sysmocom.de/>
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@ -18,6 +56,11 @@
#include <osmocom/vty/buffer.h>
#include <osmocom/core/talloc.h>
/* \addtogroup vty
* @{
*/
/*! \file vty.c */
#define SYSCONFDIR "/usr/local/etc"
/* our callback, located in telnet_interface.c */
@ -44,7 +87,7 @@ static void vty_clear_buf(struct vty *vty)
memset(vty->buf, 0, vty->max);
}
/* Allocate new vty struct. */
/*! \brief Allocate a new vty interface structure */
struct vty *vty_new(void)
{
struct vty *new = talloc_zero(tall_vty_ctx, struct vty);
@ -137,7 +180,7 @@ static void vty_auth(struct vty *vty, char *buf)
}
}
/* Close vty interface. */
/*! \brief Close a given vty interface. */
void vty_close(struct vty *vty)
{
int i;
@ -178,13 +221,17 @@ void vty_close(struct vty *vty)
talloc_free(vty);
}
/*! \brief Return if this VTY is a shell or not */
int vty_shell(struct vty *vty)
{
return vty->type == VTY_SHELL ? 1 : 0;
}
/* VTY standard output function. */
/*! \brief VTY standard output function
* \param[in] vty VTY to which we should print
* \param[in] format variable-length format string
*/
int vty_out(struct vty *vty, const char *format, ...)
{
va_list args;
@ -241,6 +288,7 @@ int vty_out(struct vty *vty, const char *format, ...)
return len;
}
/*! \brief print a newline on the given VTY */
int vty_out_newline(struct vty *vty)
{
char *p = vty_newline(vty);
@ -248,15 +296,24 @@ int vty_out_newline(struct vty *vty)
return 0;
}
/*! \brief return the current index of a given VTY */
void *vty_current_index(struct vty *vty)
{
return vty->index;
}
/*! \brief return the current node of a given VTY */
int vty_current_node(struct vty *vty)
{
return vty->node;
}
/*! \brief Lock the configuration to a given VTY
* \param[in] vty VTY to which the config shall be locked
* \returns 1 on success, 0 on error
*
* This shall be used to make sure only one VTY at a given time has
* access to modify the configuration */
int vty_config_lock(struct vty *vty)
{
if (vty_config == 0) {
@ -266,6 +323,10 @@ int vty_config_lock(struct vty *vty)
return vty->config;
}
/*! \brief Unlock the configuration from a given VTY
* \param[in] vty VTY from which the configuration shall be unlocked
* \returns 0 in case of success
*/
int vty_config_unlock(struct vty *vty)
{
if (vty_config == 1 && vty->config == 1) {
@ -1182,7 +1243,7 @@ static void vty_buffer_reset(struct vty *vty)
vty_redraw_line(vty);
}
/* Read data via vty socket. */
/*! \brief Read data via vty socket. */
int vty_read(struct vty *vty)
{
int i;
@ -1401,7 +1462,7 @@ vty_read_file(FILE *confp, void *priv)
return 0;
}
/* Create new vty structure. */
/*! \brief Create new vty structure. */
struct vty *
vty_create (int vty_sock, void *priv)
{
@ -1590,7 +1651,7 @@ struct cmd_node vty_node = {
1,
};
/* Reset all VTY status. */
/*! \brief Reset all VTY status. */
void vty_reset(void)
{
unsigned int i;
@ -1647,6 +1708,10 @@ void vty_init_vtysh(void)
}
extern void *tall_bsc_ctx;
/*! \brief Initialize VTY layer
* \param[in] app_info application information
*/
/* Install vty's own commands like `who' command. */
void vty_init(struct vty_app_info *app_info)
{
@ -1680,6 +1745,10 @@ void vty_init(struct vty_app_info *app_info)
install_element(VTY_NODE, &no_vty_login_cmd);
}
/*! \brief Read the configuration file using the VTY code
* \param[in] file_name file name of the configuration file
* \param[in] priv private data to be passed to \ref vty_read_file
*/
int vty_read_config_file(const char *file_name, void *priv)
{
FILE *cfile;
@ -1696,3 +1765,5 @@ int vty_read_config_file(const char *file_name, void *priv)
return rc;
}
/*! }@ */

View File

@ -23,6 +23,19 @@
#include <osmocom/core/write_queue.h>
/*! \addtogroup write_queue
* @{
*/
/*! \file write_queue.c */
/*! \brief Select loop function for write queue handling
* \param[in] fd osmocom file descriptor
* \param[in] what bit-mask of events that have happened
*
* This function is provided so that it can be registered with the
* select loop abstraction code (\ref osmo_fd::cb).
*/
int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what)
{
struct osmo_wqueue *queue;
@ -56,6 +69,10 @@ int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what)
return 0;
}
/*! \brief Initialize a \ref osmo_wqueue structure
* \param[in] queue Write queue to operate on
* \param[in] max_length Maximum length of write queue
*/
void osmo_wqueue_init(struct osmo_wqueue *queue, int max_length)
{
queue->max_length = max_length;
@ -66,6 +83,10 @@ void osmo_wqueue_init(struct osmo_wqueue *queue, int max_length)
INIT_LLIST_HEAD(&queue->msg_queue);
}
/*! \brief Enqueue a new \ref msgb into a write queue
* \param[in] queue Write queue to be used
* \param[in] data to-be-enqueued message buffer
*/
int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data)
{
// if (queue->current_length + 1 >= queue->max_length)
@ -78,6 +99,11 @@ int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data)
return 0;
}
/*! \brief Clear a \ref osmo_wqueue
* \param[in] queue Write queue to be cleared
*
* This function will clear (remove/release) all messages in it.
*/
void osmo_wqueue_clear(struct osmo_wqueue *queue)
{
while (!llist_empty(&queue->msg_queue)) {
@ -88,3 +114,5 @@ void osmo_wqueue_clear(struct osmo_wqueue *queue)
queue->current_length = 0;
queue->bfd.when &= ~BSC_FD_WRITE;
}
/*! }@ */

View File

@ -1,5 +1,5 @@
if ENABLE_TESTS
SUBDIRS = timer sms ussd smscb
SUBDIRS = timer sms ussd smscb bits
if ENABLE_MSGFILE
SUBDIRS += msgfile
endif

View File

@ -0,0 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = bitrev_test
bitrev_test_SOURCES = bitrev_test.c
bitrev_test_LDADD = $(top_builddir)/src/libosmocore.la

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/bits.h>
static const uint8_t input[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
static const uint8_t exp_out[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
int main(int argc, char **argv)
{
uint8_t out[ARRAY_SIZE(input)];
unsigned int offs;
for (offs = 0; offs < sizeof(out); offs++) {
uint8_t *start = out + offs;
uint8_t len = sizeof(out) - offs;
memcpy(out, input, sizeof(out));
printf("INORDER: %s\n", osmo_hexdump(start, len));
osmo_revbytebits_buf(start, len);
printf("REVERSED: %s\n", osmo_hexdump(start, len));
if (memcmp(start, exp_out + offs, len)) {
printf("EXPECTED: %s\n", osmo_hexdump(exp_out+offs, len));
fprintf(stderr, "REVERSED != EXPECTED!\n");
exit(1);
}
printf("\n");
}
return 0;
}

View File

@ -0,0 +1,7 @@
if ENABLE_UTILITIES
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = osmo-arfcn
osmo_arfcn_SOURCES = osmo-arfcn.c
osmo_arfcn_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
endif

View File

@ -0,0 +1,14 @@
#!/bin/bash
TOPDIR=`pwd`
INDIR="$TOPDIR/doc"
OUTDIR=/tmp/doxywww
GITREV=`./git-version-gen .tarball-version`
[ -f "$OUTDIR" ] || mkdir "$OUTDIR"
for MOD in core gsm vty codec; do
TGTDIR="$OUTDIR/libosmo$MOD/$GITREV"
mkdir -p "$TGTDIR"
cp -R "$INDIR/$MOD/"* "$TGTDIR/"
done

View File

@ -0,0 +1,103 @@
/* Utility program for ARFCN / frequency calculations */
/*
* (C) 2011 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 <stdio.h>
#include <getopt.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <osmocom/gsm/gsm_utils.h>
enum program_mode {
MODE_NONE,
MODE_A2F,
MODE_F2A,
};
static int arfcn2freq(char *arfcn_str)
{
int arfcn = atoi(arfcn_str);
uint16_t freq10u, freq10d;
if (arfcn < 0 || arfcn > 0xffff) {
fprintf(stderr, "Invalid ARFCN %d\n", arfcn);
return -EINVAL;
}
freq10u = gsm_arfcn2freq10(arfcn, 1);
freq10d = gsm_arfcn2freq10(arfcn, 0);
if (freq10u == 0xffff || freq10d == 0xffff) {
fprintf(stderr, "Error during conversion of ARFCN %d\n",
arfcn);
return -EINVAL;
}
printf("ARFCN %4d: Uplink %4u.%1u MHz / Downlink %4u.%1u MHz\n",
arfcn, freq10u/10, freq10u%10, freq10d/10, freq10d%10);
return 0;
}
static void help(const char *progname)
{
printf("Usage: %s [-h] [-a arfcn] [-f freq] [-u|-d]\n",
progname);
}
int main(int argc, char **argv)
{
int opt;
char *param;
enum program_mode mode = MODE_NONE;
while ((opt = getopt(argc, argv, "a:f:ud")) != -1) {
switch (opt) {
case 'a':
mode = MODE_A2F;
param = optarg;
break;
case 'f':
mode = MODE_F2A;
param = optarg;
break;
case 'h':
help(argv[0]);
exit(0);
break;
default:
break;
}
}
switch (mode) {
case MODE_NONE:
help(argv[0]);
exit(2);
break;
case MODE_A2F:
arfcn2freq(param);
break;
}
exit(0);
}