blob: f88fb1127af53ddec8396abf6506fd86bc27ed63 [file] [log] [blame]
rootaf48bed2011-09-26 11:23:06 +02001#ifndef _OSMOCOM_LAPD_H
2#define _OSMOCOM_LAPD_H
3
4#include <stdint.h>
5
6#include <osmocom/core/timer.h>
7#include <osmocom/core/msgb.h>
8#include <osmocom/gsm/prim.h>
9
10/*! \defgroup lapd LAPD implementation common part
11 * @{
12 */
13
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +010014/*! \file lapd_core.h
15 * primitive related stuff
16 */
rootaf48bed2011-09-26 11:23:06 +020017
18/*! \brief LAPD related primitives (L2<->L3 SAP)*/
19enum osmo_dl_prim {
20 PRIM_DL_UNIT_DATA, /*!< \brief DL-UNIT-DATA */
21 PRIM_DL_DATA, /*!< \brief DL-DATA */
22 PRIM_DL_EST, /*!< \brief DL-ESTABLISH */
23 PRIM_DL_REL, /*!< \brief DL-RLEEASE */
24 PRIM_DL_SUSP, /*!< \brief DL-SUSPEND */
25 PRIM_DL_RES, /*!< \brief DL-RESUME */
26 PRIM_DL_RECON, /*!< \brief DL-RECONNECT */
27 PRIM_MDL_ERROR, /*!< \brief MDL-ERROR */
28};
29
30/* Uses the same values as RLL, so no conversion for GSM is required. */
31#define MDL_CAUSE_T200_EXPIRED 0x01
32#define MDL_CAUSE_REEST_REQ 0x02
33#define MDL_CAUSE_UNSOL_UA_RESP 0x03
34#define MDL_CAUSE_UNSOL_DM_RESP 0x04
35#define MDL_CAUSE_UNSOL_DM_RESP_MF 0x05
36#define MDL_CAUSE_UNSOL_SPRV_RESP 0x06
37#define MDL_CAUSE_SEQ_ERR 0x07
38#define MDL_CAUSE_UFRM_INC_PARAM 0x08
39#define MDL_CAUSE_SFRM_INC_PARAM 0x09
40#define MDL_CAUSE_IFRM_INC_MBITS 0x0a
41#define MDL_CAUSE_IFRM_INC_LEN 0x0b
42#define MDL_CAUSE_FRM_UNIMPL 0x0c
43#define MDL_CAUSE_SABM_MF 0x0d
44#define MDL_CAUSE_SABM_INFO_NOTALL 0x0e
45#define MDL_CAUSE_FRMR 0x0f
46
47/*! \brief for MDL-ERROR.ind */
48struct mdl_error_ind_param {
49 uint8_t cause; /*!< \brief generic cause value */
50};
51
52/*! \brief for DL-REL.req */
53struct dl_rel_req_param {
54 uint8_t mode; /*!< \brief release mode */
55};
56
57/*! \brief primitive header for LAPD DL-SAP primitives */
58struct osmo_dlsap_prim {
59 struct osmo_prim_hdr oph; /*!< \brief generic primitive header */
60 union {
61 struct mdl_error_ind_param error_ind;
62 struct dl_rel_req_param rel_req;
63 } u; /*!< \brief request-specific data */
64};
65
66/*! \brief LAPD mode/role */
67enum lapd_mode {
68 LAPD_MODE_USER, /*!< \brief behave like user */
69 LAPD_MODE_NETWORK, /*!< \brief behave like network */
70};
71
72/*! \brief LAPD state (Figure B.2/Q.921)*/
73enum lapd_state {
74 LAPD_STATE_NULL = 0,
75 LAPD_STATE_TEI_UNASS,
76 LAPD_STATE_ASS_TEI_WAIT,
77 LAPD_STATE_EST_TEI_WAIT,
78 LAPD_STATE_IDLE,
79 LAPD_STATE_SABM_SENT,
80 LAPD_STATE_DISC_SENT,
81 LAPD_STATE_MF_EST,
82 LAPD_STATE_TIMER_RECOV,
83};
84
85/*! \brief LAPD message format (I / S / U) */
86enum lapd_format {
87 LAPD_FORM_UKN = 0,
88 LAPD_FORM_I,
89 LAPD_FORM_S,
90 LAPD_FORM_U,
91};
92
93/*! \brief LAPD message context */
94struct lapd_msg_ctx {
95 struct lapd_datalink *dl;
96 int n201;
97 /* address */
98 uint8_t cr;
99 uint8_t sapi;
100 uint8_t tei;
101 uint8_t lpd;
102 /* control */
103 uint8_t format;
104 uint8_t p_f; /* poll / final bit */
105 uint8_t n_send;
106 uint8_t n_recv;
107 uint8_t s_u; /* S or repectivly U function bits */
108 /* length */
109 int length;
110 uint8_t more;
111};
112
113struct lapd_cr_ent {
114 uint8_t cmd;
115 uint8_t resp;
116};
117
118struct lapd_history {
119 struct msgb *msg; /* message to be sent / NULL, if histoy is empty */
120 int more; /* if message is fragmented */
121};
122
123/*! \brief LAPD datalink */
124struct lapd_datalink {
125 int (*send_dlsap)(struct osmo_dlsap_prim *dp,
126 struct lapd_msg_ctx *lctx);
127 int (*send_ph_data_req)(struct lapd_msg_ctx *lctx, struct msgb *msg);
Daniel Willmann3dc4e162014-03-20 19:24:48 +0100128 int (*update_pending_frames)(struct lapd_msg_ctx *lctx);
rootaf48bed2011-09-26 11:23:06 +0200129 struct {
130 /*! \brief filled-in once we set the lapd_mode above */
131 struct lapd_cr_ent loc2rem;
132 struct lapd_cr_ent rem2loc;
133 } cr;
134 enum lapd_mode mode; /*!< \brief current mode of link */
135 int use_sabme; /*!< \brief use SABME instead of SABM */
136 int reestablish; /*!< \brief enable reestablish support */
137 int n200, n200_est_rel; /*!< \brief number of retranmissions */
138 struct lapd_msg_ctx lctx; /*!< \brief LAPD context */
139 int maxf; /*!< \brief maximum frame size (after defragmentation) */
140 uint8_t k; /*!< \brief maximum number of unacknowledged frames */
141 uint8_t v_range; /*!< \brief range of sequence numbers */
142 uint8_t v_send; /*!< \brief seq nr of next I frame to be transmitted */
143 uint8_t v_ack; /*!< \brief last frame ACKed by peer */
144 uint8_t v_recv; /*!< \brief seq nr of next I frame expected to be received */
145 uint32_t state; /*!< \brief LAPD state (\ref lapd_state) */
146 int seq_err_cond; /*!< \brief condition of sequence error */
147 uint8_t own_busy; /*!< \brief receiver busy on our side */
148 uint8_t peer_busy; /*!< \brief receiver busy on remote side */
149 int t200_sec, t200_usec; /*!< \brief retry timer (default 1 sec) */
150 int t203_sec, t203_usec; /*!< \brief retry timer (default 10 secs) */
151 struct osmo_timer_list t200; /*!< \brief T200 timer */
152 struct osmo_timer_list t203; /*!< \brief T203 timer */
153 uint8_t retrans_ctr; /*!< \brief re-transmission counter */
154 struct llist_head tx_queue; /*!< \brief frames to L1 */
155 struct llist_head send_queue; /*!< \brief frames from L3 */
156 struct msgb *send_buffer; /*!< \brief current frame transmitting */
157 int send_out; /*!< \brief how much was sent from send_buffer */
158 struct lapd_history *tx_hist; /*!< \brief tx history structure array */
159 uint8_t range_hist; /*!< \brief range of history buffer 2..2^n */
160 struct msgb *rcv_buffer; /*!< \brief buffer to assemble the received message */
161 struct msgb *cont_res; /*!< \brief buffer to store content resolution data on network side, to detect multiple phones on same channel */
162};
163
164void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range,
165 int maxf);
166void lapd_dl_exit(struct lapd_datalink *dl);
167void lapd_dl_reset(struct lapd_datalink *dl);
168int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode);
169int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx);
170int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx);
171
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100172/*! @} */
173
rootaf48bed2011-09-26 11:23:06 +0200174#endif /* _OSMOCOM_LAPD_H */