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