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