some more doxygen work (include the notion of modules)
diff --git a/Doxyfile b/Doxyfile
index 42b06b0..22d3bd6 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -610,7 +610,7 @@
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = include
+INPUT                  = include src
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -1406,7 +1406,7 @@
 # evaluate all C-preprocessor directives found in the sources and include
 # files.
 
-ENABLE_PREPROCESSING   = YES
+ENABLE_PREPROCESSING   = NO
 
 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
 # names in the source code. If set to NO (the default) only conditional
diff --git a/include/osmocom/core/application.h b/include/osmocom/core/application.h
index 5d09896..3457169 100644
--- a/include/osmocom/core/application.h
+++ b/include/osmocom/core/application.h
@@ -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);
diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h
index 9f8e1fb..ab4cf77 100644
--- a/include/osmocom/core/bits.h
+++ b/include/osmocom/core/bits.h
@@ -3,6 +3,10 @@
 
 #include <stdint.h>
 
+/*! \defgroup bits soft, unpacked and packed bits
+ *  @{
+ */
+
 /*! \file bits.h
  *  \brief Osmocom bit level support code
  */
@@ -30,44 +34,18 @@
 	return pbit_bytesize;
 }
 
-/*! \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);
 
-/*! \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);
 
-/*! \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);
 
-/*! \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);
 
-#endif
+/*! }@ */
+
+#endif /* _OSMO_BITS_H */
diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h
index 7cb8a87..c2422e6 100644
--- a/include/osmocom/core/bitvec.h
+++ b/include/osmocom/core/bitvec.h
@@ -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 */
diff --git a/include/osmocom/core/conv.h b/include/osmocom/core/conv.h
index af676ee..db3058c 100644
--- a/include/osmocom/core/conv.h
+++ b/include/osmocom/core/conv.h
@@ -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 @@
 /* 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 @@
 /* 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 @@
                      const sbit_t *input, ubit_t *output);
 
 
+/*! }@ */
+
 #endif /* __OSMO_CONV_H__ */
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h
index c579b8a..9f46e6c 100644
--- a/include/osmocom/core/msgb.h
+++ b/include/osmocom/core/msgb.h
@@ -24,6 +24,10 @@
 #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'
@@ -63,46 +67,10 @@
 	unsigned char _data[0]; /*!< \brief optional immediate data array */
 };
 
-/*! \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
- */
 extern struct msgb *msgb_alloc(uint16_t size, const char *name);
-
-/*! \brief Release given message buffer
- * \param[in] m Message buffer to be free'd
- */
 extern void msgb_free(struct msgb *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
- */
 extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
-
-/*! \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.
- */
 extern struct msgb *msgb_dequeue(struct llist_head *queue);
-
-/*! \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.
- */
 extern void msgb_reset(struct msgb *m);
 
 #ifdef MSGB_DEBUG
@@ -367,21 +335,10 @@
 
 /* non inline functions to ease binding */
 
-/*! \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);
-
-/*! \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);
-
-/*! \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);
 
+/*! }@ */
+
 #endif /* _MSGB_H */
diff --git a/include/osmocom/core/select.h b/include/osmocom/core/select.h
index b1b8267..18aad35 100644
--- a/include/osmocom/core/select.h
+++ b/include/osmocom/core/select.h
@@ -3,6 +3,10 @@
 
 #include <osmocom/core/linuxlist.h>
 
+/*! \defgroup select Select loop abstraction
+ *  @{
+ */
+
 /*! \file select.h
  *  \brief select loop abstraction
  */
@@ -32,19 +36,10 @@
 	unsigned int priv_nr;
 };
 
-/*! \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);
-
-/*! \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);
-
-/*! \brief select main loop integration
- *  \param[in] polling should we pollonly (1) or block on select (0)
- */
 int osmo_select_main(int polling);
 
+/*! }@ */
+
 #endif /* _BSC_SELECT_H */
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index e915f78..c5288df 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -1,6 +1,10 @@
 #ifndef _OSMOCORE_SOCKET_H
 #define _OSMOCORE_SOCKET_H
 
+/*! \defgroup socket Socket convenience functions
+ *  @{
+ */
+
 /*! \file socket.h
  *  \brief Osmocom socket convenience functions
  */
@@ -14,53 +18,17 @@
 #define OSMO_SOCK_F_BIND	(1 << 1)
 #define OSMO_SOCK_F_NONBLOCK	(1 << 2)
 
-/*! \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);
 
-/*! \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);
 
-/*! \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);
 
-/*! \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, unsigned int addrlen);
 
+/*! }@ */
+
 #endif /* _OSMOCORE_SOCKET_H */
diff --git a/include/osmocom/core/timer.h b/include/osmocom/core/timer.h
index 326a0c8..8f8c826 100644
--- a/include/osmocom/core/timer.h
+++ b/include/osmocom/core/timer.h
@@ -18,6 +18,10 @@
  *
  */
 
+/*! \defgroup timer Osmocom timers
+ *  @{
+ */
+
 /*! \file timer.h
  *  \brief Osmocom timer handling routines
  */
@@ -61,38 +65,12 @@
  * timer management
  */
 
-/*! \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);
 
-/*! \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);
 
-/*! \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);
 
-/*! \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);
 
 
@@ -104,4 +82,6 @@
 int osmo_timers_update(void);
 int osmo_timers_check(void);
 
+/*! }@ */
+
 #endif
diff --git a/src/application.c b/src/application.c
index b7e943d..6871df1 100644
--- a/src/application.c
+++ b/src/application.c
@@ -21,6 +21,10 @@
  *
  */
 
+/*! \file application.c
+ *  \brief Routines for helping with the osmocom application setup.
+ */
+
 #include <osmocom/core/application.h>
 #include <osmocom/core/logging.h>
 
@@ -33,6 +37,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 +47,13 @@
 	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 +66,11 @@
 	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;
diff --git a/src/backtrace.c b/src/backtrace.c
index dfe0305..189a3ce 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -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;
diff --git a/src/bits.c b/src/bits.c
index ff5d176..3955e3b 100644
--- a/src/bits.c
+++ b/src/bits.c
@@ -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 @@
 	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 @@
 	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 @@
 	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,5 @@
 	}
 	return out_ofs + num_bits;
 }
+
+/*! }@ */
diff --git a/src/bitvec.c b/src/bitvec.c
index 4fd3834..8a086b8 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -20,6 +20,13 @@
  *
  */
 
+/*! \addtogroup bitvec
+ *  @{
+ */
+
+/*! \file bitvec.c
+ *  \brief Osmocom bit vector abstraction
+ */
 
 #include <errno.h>
 #include <stdint.h>
@@ -59,7 +66,11 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	return -1;
 }
+
+/*! }@ */
diff --git a/src/conv.c b/src/conv.c
index 70bdffb..f47d75c 100644
--- a/src/conv.c
+++ b/src/conv.c
@@ -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 @@
 	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 @@
 	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 @@
 
 	return rv;
 }
+
+/*! }@ */
diff --git a/src/msgb.c b/src/msgb.c
index f9841ed..a403580 100644
--- a/src/msgb.c
+++ b/src/msgb.c
@@ -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 @@
 	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 @@
 	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 @@
 	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;
 }
+
+/*! }@ */
diff --git a/src/select.c b/src/select.c
index 4b002ae..c0705d3 100644
--- a/src/select.c
+++ b/src/select.c
@@ -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 @@
 	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 @@
 	return work;
 }
 
+/*! }@ */
+
 #endif /* _HAVE_SYS_SELECT_H */
diff --git a/src/socket.c b/src/socket.c
index f1fcccd..1a1d71d 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 }
 
 #endif /* HAVE_SYS_SOCKET_H */
+
+/*! }@ */
diff --git a/src/timer.c b/src/timer.c
index bd11a46..ed2b296 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -18,6 +18,13 @@
  *
  */
 
+/*! \addtogroup timer
+ *  @{
+ */
+
+/*! \file timer.c
+ */
+
 #include <assert.h>
 #include <string.h>
 #include <osmocom/core/timer.h>
@@ -31,6 +38,10 @@
 #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 @@
 	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_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 @@
 	}
 }
 
+/*! \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 @@
 	}
 	return i;
 }
+
+/*! }@ */