lapdm: Introduce LAPDM_MODE_{BTS,MS} to run on both sides
We also introduce some related functions like lapdm_{entity,channel}_set_mode() lapdm_{entity,channel}_reset() This is all in preparation for the Osmo-BTS Work.
This commit is contained in:
parent
68d03b86f4
commit
04190eabd3
|
@ -53,6 +53,11 @@ struct osmo_phsap_prim {
|
|||
} u;
|
||||
};
|
||||
|
||||
enum lapdm_mode {
|
||||
LAPDM_MODE_MS,
|
||||
LAPDM_MODE_BTS,
|
||||
};
|
||||
|
||||
enum lapdm_state {
|
||||
LAPDm_STATE_NULL = 0,
|
||||
LAPDm_STATE_IDLE,
|
||||
|
@ -108,11 +113,23 @@ enum lapdm_dl_sapi {
|
|||
|
||||
typedef int (*lapdm_cb_t)(struct msgb *msg, struct lapdm_entity *le, void *ctx);
|
||||
|
||||
struct lapdm_cr_ent {
|
||||
uint8_t cmd;
|
||||
uint8_t resp;
|
||||
};
|
||||
|
||||
/* register message handler for messages that are sent from L2->L3 */
|
||||
struct 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 */
|
||||
|
||||
struct {
|
||||
/* 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 */
|
||||
|
@ -135,8 +152,8 @@ const char *get_rsl_name(int value);
|
|||
extern const char *lapdm_state_names[];
|
||||
|
||||
/* initialize a LAPDm entity */
|
||||
void lapdm_entity_init(struct lapdm_entity *le);
|
||||
void lapdm_channel_init(struct lapdm_channel *lc);
|
||||
void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode);
|
||||
void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode);
|
||||
|
||||
/* deinitialize a LAPDm entity */
|
||||
void lapdm_entity_exit(struct lapdm_entity *le);
|
||||
|
@ -151,4 +168,10 @@ int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc);
|
|||
void lapdm_channel_set_l3(struct lapdm_channel *lc, lapdm_cb_t cb, void *ctx);
|
||||
void lapdm_channel_set_l1(struct lapdm_channel *lc, osmo_prim_cb cb, void *ctx);
|
||||
|
||||
int lapdm_entity_set_mode(struct lapdm_entity *le, enum lapdm_mode mode);
|
||||
int lapdm_channel_set_mode(struct lapdm_channel *lc, enum lapdm_mode mode);
|
||||
|
||||
void lapdm_entity_reset(struct lapdm_entity *le);
|
||||
void lapdm_channel_reset(struct lapdm_channel *lc);
|
||||
|
||||
#endif /* _OSMOCOM_LAPDM_H */
|
||||
|
|
|
@ -184,18 +184,20 @@ static void lapdm_dl_init(struct lapdm_datalink *dl,
|
|||
dl->entity = entity;
|
||||
}
|
||||
|
||||
void lapdm_entity_init(struct lapdm_entity *le)
|
||||
void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(le->datalink); i++)
|
||||
lapdm_dl_init(&le->datalink[i], le);
|
||||
|
||||
lapdm_entity_set_mode(le, mode);
|
||||
}
|
||||
|
||||
void lapdm_channel_init(struct lapdm_channel *lc)
|
||||
void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)
|
||||
{
|
||||
lapdm_entity_init(&lc->lapdm_acch);
|
||||
lapdm_entity_init(&lc->lapdm_dcch);
|
||||
lapdm_entity_init(&lc->lapdm_acch, mode);
|
||||
lapdm_entity_init(&lc->lapdm_dcch, mode);
|
||||
}
|
||||
|
||||
|
||||
|
@ -468,9 +470,10 @@ static int lapdm_send_ua(struct lapdm_msg_ctx *mctx, uint8_t len, uint8_t *data)
|
|||
uint8_t sapi = mctx->link_id & 7;
|
||||
uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl);
|
||||
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm UA");
|
||||
msg->l2h = msgb_put(msg, 3 + len);
|
||||
struct lapdm_entity *le = mctx->dl->entity;
|
||||
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_RESP);
|
||||
msg->l2h = msgb_put(msg, 3 + len);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
|
||||
msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_UA, f_bit);
|
||||
msg->l2h[2] = LAPDm_LEN(len);
|
||||
if (len)
|
||||
|
@ -485,9 +488,10 @@ static int lapdm_send_dm(struct lapdm_msg_ctx *mctx)
|
|||
uint8_t sapi = mctx->link_id & 7;
|
||||
uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl);
|
||||
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm DM");
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
struct lapdm_entity *le = mctx->dl->entity;
|
||||
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_RESP);
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
|
||||
msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_DM, f_bit);
|
||||
msg->l2h[2] = 0;
|
||||
|
||||
|
@ -499,9 +503,10 @@ static int lapdm_send_rr(struct lapdm_msg_ctx *mctx, uint8_t f_bit)
|
|||
{
|
||||
uint8_t sapi = mctx->link_id & 7;
|
||||
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm RR");
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
struct lapdm_entity *le = mctx->dl->entity;
|
||||
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_RESP);
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
|
||||
msg->l2h[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_RR, f_bit);
|
||||
msg->l2h[2] = LAPDm_LEN(0);
|
||||
|
||||
|
@ -513,9 +518,10 @@ static int lapdm_send_rnr(struct lapdm_msg_ctx *mctx, uint8_t f_bit)
|
|||
{
|
||||
uint8_t sapi = mctx->link_id & 7;
|
||||
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm RNR");
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
struct lapdm_entity *le = mctx->dl->entity;
|
||||
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_RESP);
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
|
||||
msg->l2h[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_RNR, f_bit);
|
||||
msg->l2h[2] = LAPDm_LEN(0);
|
||||
|
||||
|
@ -527,9 +533,10 @@ static int lapdm_send_rej(struct lapdm_msg_ctx *mctx, uint8_t f_bit)
|
|||
{
|
||||
uint8_t sapi = mctx->link_id & 7;
|
||||
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm REJ");
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
struct lapdm_entity *le = mctx->dl->entity;
|
||||
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_RESP);
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.resp);
|
||||
msg->l2h[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_REJ, f_bit);
|
||||
msg->l2h[2] = LAPDm_LEN(0);
|
||||
|
||||
|
@ -713,6 +720,7 @@ static void lapdm_acknowledge(struct lapdm_msg_ctx *mctx)
|
|||
static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
||||
{
|
||||
struct lapdm_datalink *dl = mctx->dl;
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
uint8_t length;
|
||||
int rc;
|
||||
int rsl_msg;
|
||||
|
@ -725,7 +733,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
/* 5.7.1 */
|
||||
dl->seq_err_cond = 0;
|
||||
/* G.2.2 Wrong value of the C/R bit */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
|
||||
LOGP(DLAPDM, LOGL_NOTICE, "SABM response error\n");
|
||||
msgb_free(msg);
|
||||
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
|
||||
|
@ -756,6 +764,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
dl->mctx.dl = dl;
|
||||
dl->mctx.chan_nr = mctx->chan_nr;
|
||||
dl->mctx.link_id = mctx->link_id;
|
||||
dl->mctx.n201 = mctx->n201;
|
||||
break;
|
||||
case LAPDm_STATE_MF_EST:
|
||||
if (length == 0) {
|
||||
|
@ -807,7 +816,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
case LAPDm_U_DM:
|
||||
LOGP(DLAPDM, LOGL_INFO, "DM received\n");
|
||||
/* G.2.2 Wrong value of the C/R bit */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_CMD) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd) {
|
||||
LOGP(DLAPDM, LOGL_NOTICE, "DM command error\n");
|
||||
msgb_free(msg);
|
||||
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
|
||||
|
@ -871,7 +880,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
case LAPDm_U_UI:
|
||||
LOGP(DLAPDM, LOGL_INFO, "UI received\n");
|
||||
/* G.2.2 Wrong value of the C/R bit */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
|
||||
LOGP(DLAPDM, LOGL_NOTICE, "UI indicates response "
|
||||
"error\n");
|
||||
msgb_free(msg);
|
||||
|
@ -931,7 +940,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
/* 5.7.1 */
|
||||
dl->seq_err_cond = 0;
|
||||
/* G.2.2 Wrong value of the C/R bit */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
|
||||
LOGP(DLAPDM, LOGL_NOTICE, "DISC response error\n");
|
||||
msgb_free(msg);
|
||||
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
|
||||
|
@ -987,7 +996,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
case LAPDm_U_UA:
|
||||
LOGP(DLAPDM, LOGL_INFO, "UA received\n");
|
||||
/* G.2.2 Wrong value of the C/R bit */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_CMD) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd) {
|
||||
LOGP(DLAPDM, LOGL_NOTICE, "UA indicates command "
|
||||
"error\n");
|
||||
msgb_free(msg);
|
||||
|
@ -1093,6 +1102,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
||||
{
|
||||
struct lapdm_datalink *dl = mctx->dl;
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
uint8_t length;
|
||||
|
||||
length = msg->l2h[2] >> 2;
|
||||
|
@ -1108,7 +1118,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
|
||||
&& LAPDm_CTRL_PF_BIT(mctx->ctrl)
|
||||
&& dl->state != LAPDm_STATE_TIMER_RECOV) {
|
||||
/* 5.4.2.2: Inidcate error on supervisory reponse F=1 */
|
||||
|
@ -1136,7 +1146,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
lapdm_acknowledge(mctx);
|
||||
|
||||
/* 5.5.3.2 */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_CMD
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd
|
||||
&& LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
|
||||
if (!dl->own_busy && !dl->seq_err_cond) {
|
||||
LOGP(DLAPDM, LOGL_NOTICE, "RR frame command "
|
||||
|
@ -1154,7 +1164,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
"so we reply with RR frame\n");
|
||||
lapdm_send_rnr(mctx, 1);
|
||||
}
|
||||
} else if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP
|
||||
} else if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
|
||||
&& LAPDm_CTRL_PF_BIT(mctx->ctrl)
|
||||
&& dl->state == LAPDm_STATE_TIMER_RECOV) {
|
||||
LOGP(DLAPDM, LOGL_INFO, "RR response with F==1, "
|
||||
|
@ -1181,7 +1191,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
dl->peer_busy = 1;
|
||||
|
||||
if (LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_CMD) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd) {
|
||||
if (!dl->own_busy) {
|
||||
LOGP(DLAPDM, LOGL_INFO, "RNR poll "
|
||||
"command and we are not busy, "
|
||||
|
@ -1228,7 +1238,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
/* reset Timer T200 */
|
||||
osmo_timer_del(&dl->t200);
|
||||
/* 5.5.3.2 */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_CMD
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd
|
||||
&& LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
|
||||
if (!dl->own_busy && !dl->seq_err_cond) {
|
||||
LOGP(DLAPDM, LOGL_INFO, "REJ poll "
|
||||
|
@ -1258,12 +1268,12 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
"polling command not in timer recovery "
|
||||
"state received\n");
|
||||
/* send MDL ERROR INIDCATION to L3 */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
|
||||
&& LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
|
||||
rsl_rll_error(RLL_CAUSE_UNSOL_SPRV_RESP, mctx);
|
||||
}
|
||||
|
||||
} else if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP
|
||||
} else if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp
|
||||
&& LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
|
||||
LOGP(DLAPDM, LOGL_INFO, "REJ poll response in timer "
|
||||
"recovery state received\n");
|
||||
|
@ -1281,7 +1291,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
/* V(S) and V(A) to the N(R) in the REJ frame */
|
||||
dl->V_send = dl->V_ack = LAPDm_CTRL_Nr(mctx->ctrl);
|
||||
/* 5.5.3.2 */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_CMD
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.cmd
|
||||
&& LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
|
||||
if (!dl->own_busy && !dl->seq_err_cond) {
|
||||
LOGP(DLAPDM, LOGL_INFO, "REJ poll "
|
||||
|
@ -1333,6 +1343,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
static int lapdm_rx_i(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
||||
{
|
||||
struct lapdm_datalink *dl = mctx->dl;
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
//uint8_t nr = LAPDm_CTRL_Nr(mctx->ctrl);
|
||||
uint8_t ns = LAPDm_CTRL_I_Ns(mctx->ctrl);
|
||||
uint8_t length;
|
||||
|
@ -1341,7 +1352,7 @@ static int lapdm_rx_i(struct msgb *msg, struct lapdm_msg_ctx *mctx)
|
|||
LOGP(DLAPDM, LOGL_NOTICE, "I received\n");
|
||||
|
||||
/* G.2.2 Wrong value of the C/R bit */
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == CR_BS2MS_RESP) {
|
||||
if (LAPDm_ADDR_CR(mctx->addr) == le->cr.rem2loc.resp) {
|
||||
LOGP(DLAPDM, LOGL_NOTICE, "I frame response not allowed\n");
|
||||
msgb_free(msg);
|
||||
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx);
|
||||
|
@ -1684,6 +1695,7 @@ int lapdm_phsap_up(struct osmo_prim_hdr *oph, struct lapdm_entity *le)
|
|||
/* L3 requests establishment of data link */
|
||||
static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
|
||||
{
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
|
||||
uint8_t chan_nr = rllh->chan_nr;
|
||||
uint8_t link_id = rllh->link_id;
|
||||
|
@ -1744,7 +1756,7 @@ static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
|
||||
/* Push LAPDm header on msgb */
|
||||
msg->l2h = msgb_push(msg, 3);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_CMD);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
|
||||
msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_SABM, 1);
|
||||
msg->l2h[2] = LAPDm_LEN(length);
|
||||
/* Transmit-buffer carries exactly one segment */
|
||||
|
@ -1766,6 +1778,7 @@ static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
/* L3 requests transfer of unnumbered information */
|
||||
static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl)
|
||||
{
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
|
||||
uint8_t chan_nr = rllh->chan_nr;
|
||||
uint8_t link_id = rllh->link_id;
|
||||
|
@ -1810,7 +1823,7 @@ static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
msg->l2h = msgb_push(msg, 2 + 3);
|
||||
msg->l2h[0] = tx_power;
|
||||
msg->l2h[1] = ta;
|
||||
msg->l2h[2] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_CMD);
|
||||
msg->l2h[2] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
|
||||
msg->l2h[3] = LAPDm_CTRL_U(LAPDm_U_UI, 0);
|
||||
msg->l2h[4] = LAPDm_LEN(length);
|
||||
// FIXME: short L2 header support
|
||||
|
@ -1850,6 +1863,7 @@ static int rslms_rx_rll_data_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
static int rslms_send_i(struct lapdm_msg_ctx *mctx, int line)
|
||||
{
|
||||
struct lapdm_datalink *dl = mctx->dl;
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
uint8_t chan_nr = mctx->chan_nr;
|
||||
uint8_t link_id = mctx->link_id;
|
||||
uint8_t sapi = link_id & 7;
|
||||
|
@ -1922,7 +1936,7 @@ static int rslms_send_i(struct lapdm_msg_ctx *mctx, int line)
|
|||
/* Create I frame (segment) and transmit-buffer content */
|
||||
msg = msgb_alloc_headroom(23+10, 10, "LAPDm I");
|
||||
msg->l2h = msgb_put(msg, 3 + length);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_CMD);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
|
||||
msg->l2h[1] = LAPDm_CTRL_I(dl->V_recv, dl->V_send, 0);
|
||||
msg->l2h[2] = LAPDm_LEN(length);
|
||||
if (left > length)
|
||||
|
@ -1995,6 +2009,7 @@ static int rslms_rx_rll_susp_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
/* L3 requests resume of data link */
|
||||
static int rslms_rx_rll_res_req(struct msgb *msg, struct lapdm_datalink *dl)
|
||||
{
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
|
||||
uint8_t chan_nr = rllh->chan_nr;
|
||||
uint8_t link_id = rllh->link_id;
|
||||
|
@ -2041,7 +2056,7 @@ static int rslms_rx_rll_res_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
/* Create new msgb (old one is now free) */
|
||||
msg = msgb_alloc_headroom(23+10, 10, "LAPDm SABM");
|
||||
msg->l2h = msgb_put(msg, 3);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_CMD);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
|
||||
msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_SABM, 1);
|
||||
msg->l2h[2] = LAPDm_LEN(0);
|
||||
/* Transmit-buffer carries exactly one segment */
|
||||
|
@ -2063,6 +2078,7 @@ static int rslms_rx_rll_res_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
/* L3 requests release of data link */
|
||||
static int rslms_rx_rll_rel_req(struct msgb *msg, struct lapdm_datalink *dl)
|
||||
{
|
||||
struct lapdm_entity *le = dl->entity;
|
||||
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
|
||||
uint8_t chan_nr = rllh->chan_nr;
|
||||
uint8_t link_id = rllh->link_id;
|
||||
|
@ -2099,7 +2115,7 @@ static int rslms_rx_rll_rel_req(struct msgb *msg, struct lapdm_datalink *dl)
|
|||
|
||||
/* Push LAPDm header on msgb */
|
||||
msg->l2h = msgb_push(msg, 3);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, CR_MS2BS_CMD);
|
||||
msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, le->cr.loc2rem.cmd);
|
||||
msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_DISC, 1);
|
||||
msg->l2h[2] = LAPDm_LEN(0);
|
||||
/* Transmit-buffer carries exactly one segment */
|
||||
|
@ -2360,6 +2376,41 @@ int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int lapdm_entity_set_mode(struct lapdm_entity *le, enum lapdm_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case LAPDM_MODE_MS:
|
||||
le->cr.loc2rem.cmd = CR_MS2BS_CMD;
|
||||
le->cr.loc2rem.resp = CR_MS2BS_RESP;
|
||||
le->cr.rem2loc.cmd = CR_BS2MS_CMD;
|
||||
le->cr.rem2loc.resp = CR_BS2MS_RESP;
|
||||
break;
|
||||
case LAPDM_MODE_BTS:
|
||||
le->cr.loc2rem.cmd = CR_BS2MS_CMD;
|
||||
le->cr.loc2rem.resp = CR_BS2MS_RESP;
|
||||
le->cr.rem2loc.cmd = CR_MS2BS_CMD;
|
||||
le->cr.rem2loc.resp = CR_MS2BS_RESP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
le->mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lapdm_channel_set_mode(struct lapdm_channel *lc, enum lapdm_mode mode)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = lapdm_entity_set_mode(&lc->lapdm_dcch, mode);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return lapdm_entity_set_mode(&lc->lapdm_acch, mode);
|
||||
}
|
||||
|
||||
void lapdm_channel_set_l1(struct lapdm_channel *lc, osmo_prim_cb cb, void *ctx)
|
||||
{
|
||||
lc->lapdm_dcch.l1_prim_cb = cb;
|
||||
|
@ -2375,3 +2426,29 @@ void lapdm_channel_set_l3(struct lapdm_channel *lc, lapdm_cb_t cb, void *ctx)
|
|||
lc->lapdm_dcch.l3_ctx = ctx;
|
||||
lc->lapdm_acch.l3_ctx = ctx;
|
||||
}
|
||||
|
||||
void lapdm_entity_reset(struct lapdm_entity *le)
|
||||
{
|
||||
struct lapdm_datalink *dl;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(le->datalink); i++) {
|
||||
dl = &le->datalink[i];
|
||||
if (dl->state == LAPDm_STATE_IDLE)
|
||||
continue;
|
||||
LOGP(DLAPDM, LOGL_INFO, "Resetting LAPDm instance\n");
|
||||
/* reset Timer T200 */
|
||||
osmo_timer_del(&dl->t200);
|
||||
/* enter idle state */
|
||||
dl->state = LAPDm_STATE_IDLE;
|
||||
/* flush buffer */
|
||||
lapdm_dl_flush_tx(dl);
|
||||
lapdm_dl_flush_send(dl);
|
||||
}
|
||||
}
|
||||
|
||||
void lapdm_channel_reset(struct lapdm_channel *lc)
|
||||
{
|
||||
lapdm_entity_reset(&lc->lapdm_dcch);
|
||||
lapdm_entity_reset(&lc->lapdm_acch);
|
||||
}
|
||||
|
|
|
@ -258,7 +258,7 @@ int main(int argc, char **argv)
|
|||
ms->lapdm_channel.lapdm_dcch.l3_ctx = ms;
|
||||
ms->lapdm_channel.lapdm_acch.l1_ctx = ms;
|
||||
ms->lapdm_channel.lapdm_acch.l3_ctx = ms;
|
||||
lapdm_channel_init(&ms->lapdm_channel);
|
||||
lapdm_channel_init(&ms->lapdm_channel, LAPDM_MODE_MS);
|
||||
|
||||
rc = l23_app_init(ms);
|
||||
if (rc < 0)
|
||||
|
|
|
@ -162,7 +162,7 @@ int mobile_init(struct osmocom_ms *ms)
|
|||
|
||||
gsm_settings_arfcn(ms);
|
||||
|
||||
lapdm_channel_init(&ms->lapdm_channel);
|
||||
lapdm_channel_init(&ms->lapdm_channel, LAPDM_MODE_MS);
|
||||
lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms);
|
||||
|
||||
gsm_sim_init(ms);
|
||||
|
|
Loading…
Reference in New Issue