From bd598e3c5eff85ed3958909584d3d8e1e2235b41 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 16 Aug 2011 23:26:52 +0200 Subject: start to add doxygen documentation to libosmocore headers --- include/osmocom/core/bits.h | 48 ++++++-- include/osmocom/core/logging.h | 25 +++- include/osmocom/core/msgb.h | 234 +++++++++++++++++++++++++++++++++---- include/osmocom/core/select.h | 30 ++++- include/osmocom/core/socket.h | 43 ++++++- include/osmocom/core/statistics.h | 28 ++++- include/osmocom/core/timer.h | 51 ++++++-- include/osmocom/core/utils.h | 65 ++++++++++- include/osmocom/core/write_queue.h | 35 ++++++ 9 files changed, 507 insertions(+), 52 deletions(-) (limited to 'include/osmocom') diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h index eb22d07c..9f8e1fb5 100644 --- a/include/osmocom/core/bits.h +++ b/include/osmocom/core/bits.h @@ -3,9 +3,13 @@ #include -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) */ +/*! \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 +17,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,20 +30,42 @@ static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits) return pbit_bytesize; } -/* convert unpacked bits to packed bits, return length in bytes */ +/*! \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); -/* 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); -/* 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); -/* 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); diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 154ee198..537dc609 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -1,11 +1,17 @@ #ifndef _OSMOCORE_LOGGING_H #define _OSMOCORE_LOGGING_H +/*! \file logging.h + * \brief Osmocom logging framework + */ + #include #include #include +/*! \brief Maximum number of logging contexts */ #define LOG_MAX_CTX 8 +/*! \brief Maximum number of logging filters */ #define LOG_MAX_FILTERS 8 #define DEBUG @@ -21,9 +27,21 @@ 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) @@ -151,7 +169,12 @@ struct log_target *log_target_create_syslog(const char *ident, int option, int facility); int log_target_file_reopen(struct log_target *tgt); +/*! \brief Add a new logging target + */ void log_add_target(struct log_target *target); + +/*! \brief Deelete an existing logging target + */ void log_del_target(struct log_target *target); /* Generate command string for VTY use */ diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h index 915c4a04..c579b8a7 100644 --- a/include/osmocom/core/msgb.h +++ b/include/osmocom/core/msgb.h @@ -24,45 +24,85 @@ #include #include +/*! \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; - - /* 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; - - /* the 'control buffer', large enough to contain 5 pointers */ - unsigned long cb[5]; - - uint16_t data_len; - uint16_t len; - - unsigned char *head; - unsigned char *tail; - unsigned char *data; - unsigned char _data[0]; + struct gsm_lchan *lchan; /*!< \brief logical channel */ + + unsigned char *l1h; /*!< \brief pointer to Layer1 header (if any) */ + unsigned char *l2h; /*!< \brief pointer to A-bis layer 2 header: OML, RSL(RLL), NS */ + unsigned char *l3h; /*!< \brief pointer to Layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */ + unsigned char *l4h; /*!< \brief pointer to layer 4 header */ + + unsigned long cb[5]; /*!< \brief control buffer */ + + uint16_t data_len; /*!< \brief length of underlying data array */ + uint16_t len; /*!< \brief length of bytes used in msgb */ + + unsigned char *head; /*!< \brief start of underlying memory buffer */ + unsigned char *tail; /*!< \brief end of message in buffer */ + unsigned char *data; /*!< \brief start of message in buffer */ + unsigned char _data[0]; /*!< \brief optional immediate data array */ }; +/*! \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 @@ -74,41 +114,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 +217,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 +251,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 +263,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 +312,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 +366,22 @@ static inline struct msgb *msgb_alloc_headroom(int size, int headroom, } /* 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); -/* set the talloc context for msgb_alloc[_headroom] */ +/*! \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 476c564e..b1b82672 100644 --- a/include/osmocom/core/select.h +++ b/include/osmocom/core/select.h @@ -3,20 +3,48 @@ #include +/*! \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; }; +/*! \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 612b12c8..e915f78d 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 +/*! \file socket.h + * \brief Osmocom socket convenience functions + */ + #include struct sockaddr; @@ -10,16 +14,53 @@ struct sockaddr; #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); -/* 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, unsigned int addrlen); #endif /* _OSMOCORE_SOCKET_H */ diff --git a/include/osmocom/core/statistics.h b/include/osmocom/core/statistics.h index 18493277..04816c16 100644 --- a/include/osmocom/core/statistics.h +++ b/include/osmocom/core/statistics.h @@ -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 */ diff --git a/include/osmocom/core/timer.h b/include/osmocom/core/timer.h index 6c2e8c50..326a0c88 100644 --- a/include/osmocom/core/timer.h +++ b/include/osmocom/core/timer.h @@ -18,6 +18,10 @@ * */ +/*! \file timer.h + * \brief Osmocom timer handling routines + */ + #ifndef TIMER_H #define TIMER_H @@ -41,27 +45,58 @@ * 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 */ + +/*! \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); -/** +/* * internal timer list management */ struct timeval *osmo_timers_nearest(void); diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index a1a18e30..1e5fab70 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -1,32 +1,93 @@ #ifndef OSMOCORE_UTIL_H #define OSMOCORE_UTIL_H +/*! \file utils.h + * \brief General-purpose utilities in the Osmocom core library + */ + +/*! \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 +/*! \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 */ }; +/*! \fn get_value_string(const struct value_string *vs, uint32_t val) + * \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); + +/*! \fn get_string_value(const struct value_string *vs, const char *str) + * \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); +/*! \fn osmo_bcd2char(uint8_t bcd) + * \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); /* only works for numbers in ascci */ uint8_t osmo_char2bcd(char c); int osmo_hexparse(const char *str, uint8_t *b, int max_len); + +/*! \fn osmo_hexdump(const unsigned char *buf, int len) + * \brief Convert binary sequence to hexadecimal ASCII string + * This function will print a sequence of bytes as hexadecimal numbers, + * adding one space character between each byte (e.g. "1a ef d9") + * \param[in] buf pointer to sequence of bytes + * \param[in] len length of buf in number of bytes + * \returns pointer to zero-terminated string + */ char *osmo_hexdump(const unsigned char *buf, int len); + +/*! \fn osmo_hexdump_nospc(const unsigned char *buf, int len) + * \brief Convert binary sequence to hexadecimal ASCII string + * This function will print a sequence of bytes as hexadecimal numbers, + * without any space character between each byte (e.g. "1aefd9") + * \param[in] buf pointer to sequence of bytes + * \param[in] len length of buf in number of bytes + * \returns pointer to zero-terminated string + */ char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len); + +/*! \fn osmo_ubit_dump(const uint8_t *bits, unsigned int len) + * \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); #define osmo_static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; +/*! \fn osmo_str2lower(char *out, const char *in) + * \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); + +/*! \fn osmo_str2upper(char *out, const char *in) + * \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); #define OSMO_SNPRINTF_RET(ret, rem, offset, len) \ diff --git a/include/osmocom/core/write_queue.h b/include/osmocom/core/write_queue.h index 41748d72..373b64ff 100644 --- a/include/osmocom/core/write_queue.h +++ b/include/osmocom/core/write_queue.h @@ -23,24 +23,59 @@ #ifndef OSMO_WQUEUE_H #define OSMO_WQUEUE_H +/*! \file write_queue.h + * \brief Osmocom write queues + */ + #include #include +/*! 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); }; +/*! \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); + +/*! \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); + +/*! \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); + +/*! \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); #endif -- cgit v1.2.3