mirror of https://gerrit.osmocom.org/libosmocore
doxygen: Add documentation for LAPDm code
This commit is contained in:
parent
57c7d37059
commit
6bdf0b158c
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
|
|
Loading…
Reference in New Issue