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:
Harald Welte 2011-06-24 12:23:17 +02:00
parent 68d03b86f4
commit 04190eabd3
4 changed files with 137 additions and 37 deletions

View File

@ -53,6 +53,11 @@ struct osmo_phsap_prim {
} u; } u;
}; };
enum lapdm_mode {
LAPDM_MODE_MS,
LAPDM_MODE_BTS,
};
enum lapdm_state { enum lapdm_state {
LAPDm_STATE_NULL = 0, LAPDm_STATE_NULL = 0,
LAPDm_STATE_IDLE, 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); 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 */ /* register message handler for messages that are sent from L2->L3 */
struct lapdm_entity { struct lapdm_entity {
struct lapdm_datalink datalink[_NR_DL_SAPI]; struct lapdm_datalink datalink[_NR_DL_SAPI];
int last_tx_dequeue; /* last entity that was dequeued */ int last_tx_dequeue; /* last entity that was dequeued */
int tx_pending; /* currently a pending frame not confirmed by L1 */ 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 *l1_ctx; /* context for layer1 instance */
void *l3_ctx; /* context for layer3 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[]; extern const char *lapdm_state_names[];
/* initialize a LAPDm entity */ /* initialize a LAPDm entity */
void lapdm_entity_init(struct lapdm_entity *le); void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode);
void lapdm_channel_init(struct lapdm_channel *lc); void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode);
/* deinitialize a LAPDm entity */ /* deinitialize a LAPDm entity */
void lapdm_entity_exit(struct lapdm_entity *le); 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_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); 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 */ #endif /* _OSMOCOM_LAPDM_H */

View File

@ -184,18 +184,20 @@ static void lapdm_dl_init(struct lapdm_datalink *dl,
dl->entity = entity; 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; unsigned int i;
for (i = 0; i < ARRAY_SIZE(le->datalink); i++) for (i = 0; i < ARRAY_SIZE(le->datalink); i++)
lapdm_dl_init(&le->datalink[i], le); 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_acch, mode);
lapdm_entity_init(&lc->lapdm_dcch); 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 sapi = mctx->link_id & 7;
uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl); uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl);
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm UA"); 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[1] = LAPDm_CTRL_U(LAPDm_U_UA, f_bit);
msg->l2h[2] = LAPDm_LEN(len); msg->l2h[2] = LAPDm_LEN(len);
if (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 sapi = mctx->link_id & 7;
uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl); uint8_t f_bit = LAPDm_CTRL_PF_BIT(mctx->ctrl);
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm DM"); 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[1] = LAPDm_CTRL_U(LAPDm_U_DM, f_bit);
msg->l2h[2] = 0; 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; uint8_t sapi = mctx->link_id & 7;
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm RR"); 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[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_RR, f_bit);
msg->l2h[2] = LAPDm_LEN(0); 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; uint8_t sapi = mctx->link_id & 7;
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm RNR"); 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[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_RNR, f_bit);
msg->l2h[2] = LAPDm_LEN(0); 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; uint8_t sapi = mctx->link_id & 7;
struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm REJ"); 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[1] = LAPDm_CTRL_S(mctx->dl->V_recv, LAPDm_S_REJ, f_bit);
msg->l2h[2] = LAPDm_LEN(0); 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) static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
{ {
struct lapdm_datalink *dl = mctx->dl; struct lapdm_datalink *dl = mctx->dl;
struct lapdm_entity *le = dl->entity;
uint8_t length; uint8_t length;
int rc; int rc;
int rsl_msg; int rsl_msg;
@ -725,7 +733,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
/* 5.7.1 */ /* 5.7.1 */
dl->seq_err_cond = 0; dl->seq_err_cond = 0;
/* G.2.2 Wrong value of the C/R bit */ /* 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"); LOGP(DLAPDM, LOGL_NOTICE, "SABM response error\n");
msgb_free(msg); msgb_free(msg);
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx); 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.dl = dl;
dl->mctx.chan_nr = mctx->chan_nr; dl->mctx.chan_nr = mctx->chan_nr;
dl->mctx.link_id = mctx->link_id; dl->mctx.link_id = mctx->link_id;
dl->mctx.n201 = mctx->n201;
break; break;
case LAPDm_STATE_MF_EST: case LAPDm_STATE_MF_EST:
if (length == 0) { if (length == 0) {
@ -807,7 +816,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
case LAPDm_U_DM: case LAPDm_U_DM:
LOGP(DLAPDM, LOGL_INFO, "DM received\n"); LOGP(DLAPDM, LOGL_INFO, "DM received\n");
/* G.2.2 Wrong value of the C/R bit */ /* 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"); LOGP(DLAPDM, LOGL_NOTICE, "DM command error\n");
msgb_free(msg); msgb_free(msg);
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx); 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: case LAPDm_U_UI:
LOGP(DLAPDM, LOGL_INFO, "UI received\n"); LOGP(DLAPDM, LOGL_INFO, "UI received\n");
/* G.2.2 Wrong value of the C/R bit */ /* 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 " LOGP(DLAPDM, LOGL_NOTICE, "UI indicates response "
"error\n"); "error\n");
msgb_free(msg); msgb_free(msg);
@ -931,7 +940,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
/* 5.7.1 */ /* 5.7.1 */
dl->seq_err_cond = 0; dl->seq_err_cond = 0;
/* G.2.2 Wrong value of the C/R bit */ /* 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"); LOGP(DLAPDM, LOGL_NOTICE, "DISC response error\n");
msgb_free(msg); msgb_free(msg);
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx); 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: case LAPDm_U_UA:
LOGP(DLAPDM, LOGL_INFO, "UA received\n"); LOGP(DLAPDM, LOGL_INFO, "UA received\n");
/* G.2.2 Wrong value of the C/R bit */ /* 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 " LOGP(DLAPDM, LOGL_NOTICE, "UA indicates command "
"error\n"); "error\n");
msgb_free(msg); 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) static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
{ {
struct lapdm_datalink *dl = mctx->dl; struct lapdm_datalink *dl = mctx->dl;
struct lapdm_entity *le = dl->entity;
uint8_t length; uint8_t length;
length = msg->l2h[2] >> 2; length = msg->l2h[2] >> 2;
@ -1108,7 +1118,7 @@ static int lapdm_rx_s(struct msgb *msg, struct lapdm_msg_ctx *mctx)
return -EIO; 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) && LAPDm_CTRL_PF_BIT(mctx->ctrl)
&& dl->state != LAPDm_STATE_TIMER_RECOV) { && dl->state != LAPDm_STATE_TIMER_RECOV) {
/* 5.4.2.2: Inidcate error on supervisory reponse F=1 */ /* 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); lapdm_acknowledge(mctx);
/* 5.5.3.2 */ /* 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)) { && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
if (!dl->own_busy && !dl->seq_err_cond) { if (!dl->own_busy && !dl->seq_err_cond) {
LOGP(DLAPDM, LOGL_NOTICE, "RR frame command " 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"); "so we reply with RR frame\n");
lapdm_send_rnr(mctx, 1); 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) && LAPDm_CTRL_PF_BIT(mctx->ctrl)
&& dl->state == LAPDm_STATE_TIMER_RECOV) { && dl->state == LAPDm_STATE_TIMER_RECOV) {
LOGP(DLAPDM, LOGL_INFO, "RR response with F==1, " 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; dl->peer_busy = 1;
if (LAPDm_CTRL_PF_BIT(mctx->ctrl)) { 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) { if (!dl->own_busy) {
LOGP(DLAPDM, LOGL_INFO, "RNR poll " LOGP(DLAPDM, LOGL_INFO, "RNR poll "
"command and we are not busy, " "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 */ /* reset Timer T200 */
osmo_timer_del(&dl->t200); osmo_timer_del(&dl->t200);
/* 5.5.3.2 */ /* 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)) { && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
if (!dl->own_busy && !dl->seq_err_cond) { if (!dl->own_busy && !dl->seq_err_cond) {
LOGP(DLAPDM, LOGL_INFO, "REJ poll " 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 " "polling command not in timer recovery "
"state received\n"); "state received\n");
/* send MDL ERROR INIDCATION to L3 */ /* 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)) { && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
rsl_rll_error(RLL_CAUSE_UNSOL_SPRV_RESP, mctx); 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)) { && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
LOGP(DLAPDM, LOGL_INFO, "REJ poll response in timer " LOGP(DLAPDM, LOGL_INFO, "REJ poll response in timer "
"recovery state received\n"); "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 */ /* V(S) and V(A) to the N(R) in the REJ frame */
dl->V_send = dl->V_ack = LAPDm_CTRL_Nr(mctx->ctrl); dl->V_send = dl->V_ack = LAPDm_CTRL_Nr(mctx->ctrl);
/* 5.5.3.2 */ /* 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)) { && LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
if (!dl->own_busy && !dl->seq_err_cond) { if (!dl->own_busy && !dl->seq_err_cond) {
LOGP(DLAPDM, LOGL_INFO, "REJ poll " 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) static int lapdm_rx_i(struct msgb *msg, struct lapdm_msg_ctx *mctx)
{ {
struct lapdm_datalink *dl = mctx->dl; struct lapdm_datalink *dl = mctx->dl;
struct lapdm_entity *le = dl->entity;
//uint8_t nr = LAPDm_CTRL_Nr(mctx->ctrl); //uint8_t nr = LAPDm_CTRL_Nr(mctx->ctrl);
uint8_t ns = LAPDm_CTRL_I_Ns(mctx->ctrl); uint8_t ns = LAPDm_CTRL_I_Ns(mctx->ctrl);
uint8_t length; 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"); LOGP(DLAPDM, LOGL_NOTICE, "I received\n");
/* G.2.2 Wrong value of the C/R bit */ /* 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"); LOGP(DLAPDM, LOGL_NOTICE, "I frame response not allowed\n");
msgb_free(msg); msgb_free(msg);
rsl_rll_error(RLL_CAUSE_FRM_UNIMPL, mctx); 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 */ /* L3 requests establishment of data link */
static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl) 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); struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t chan_nr = rllh->chan_nr; uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id; 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 */ /* Push LAPDm header on msgb */
msg->l2h = msgb_push(msg, 3); 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[1] = LAPDm_CTRL_U(LAPDm_U_SABM, 1);
msg->l2h[2] = LAPDm_LEN(length); msg->l2h[2] = LAPDm_LEN(length);
/* Transmit-buffer carries exactly one segment */ /* 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 */ /* L3 requests transfer of unnumbered information */
static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl) 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); struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t chan_nr = rllh->chan_nr; uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id; 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 = msgb_push(msg, 2 + 3);
msg->l2h[0] = tx_power; msg->l2h[0] = tx_power;
msg->l2h[1] = ta; 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[3] = LAPDm_CTRL_U(LAPDm_U_UI, 0);
msg->l2h[4] = LAPDm_LEN(length); msg->l2h[4] = LAPDm_LEN(length);
// FIXME: short L2 header support // 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) static int rslms_send_i(struct lapdm_msg_ctx *mctx, int line)
{ {
struct lapdm_datalink *dl = mctx->dl; struct lapdm_datalink *dl = mctx->dl;
struct lapdm_entity *le = dl->entity;
uint8_t chan_nr = mctx->chan_nr; uint8_t chan_nr = mctx->chan_nr;
uint8_t link_id = mctx->link_id; uint8_t link_id = mctx->link_id;
uint8_t sapi = link_id & 7; 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 */ /* Create I frame (segment) and transmit-buffer content */
msg = msgb_alloc_headroom(23+10, 10, "LAPDm I"); msg = msgb_alloc_headroom(23+10, 10, "LAPDm I");
msg->l2h = msgb_put(msg, 3 + length); 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[1] = LAPDm_CTRL_I(dl->V_recv, dl->V_send, 0);
msg->l2h[2] = LAPDm_LEN(length); msg->l2h[2] = LAPDm_LEN(length);
if (left > 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 */ /* L3 requests resume of data link */
static int rslms_rx_rll_res_req(struct msgb *msg, struct lapdm_datalink *dl) 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); struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t chan_nr = rllh->chan_nr; uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id; 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) */ /* Create new msgb (old one is now free) */
msg = msgb_alloc_headroom(23+10, 10, "LAPDm SABM"); msg = msgb_alloc_headroom(23+10, 10, "LAPDm SABM");
msg->l2h = msgb_put(msg, 3); 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[1] = LAPDm_CTRL_U(LAPDm_U_SABM, 1);
msg->l2h[2] = LAPDm_LEN(0); msg->l2h[2] = LAPDm_LEN(0);
/* Transmit-buffer carries exactly one segment */ /* 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 */ /* L3 requests release of data link */
static int rslms_rx_rll_rel_req(struct msgb *msg, struct lapdm_datalink *dl) 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); struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t chan_nr = rllh->chan_nr; uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id; 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 */ /* Push LAPDm header on msgb */
msg->l2h = msgb_push(msg, 3); 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[1] = LAPDm_CTRL_U(LAPDm_U_DISC, 1);
msg->l2h[2] = LAPDm_LEN(0); msg->l2h[2] = LAPDm_LEN(0);
/* Transmit-buffer carries exactly one segment */ /* Transmit-buffer carries exactly one segment */
@ -2360,6 +2376,41 @@ int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
return rc; 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) void lapdm_channel_set_l1(struct lapdm_channel *lc, osmo_prim_cb cb, void *ctx)
{ {
lc->lapdm_dcch.l1_prim_cb = cb; 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_dcch.l3_ctx = ctx;
lc->lapdm_acch.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);
}

View File

@ -258,7 +258,7 @@ int main(int argc, char **argv)
ms->lapdm_channel.lapdm_dcch.l3_ctx = ms; ms->lapdm_channel.lapdm_dcch.l3_ctx = ms;
ms->lapdm_channel.lapdm_acch.l1_ctx = ms; ms->lapdm_channel.lapdm_acch.l1_ctx = ms;
ms->lapdm_channel.lapdm_acch.l3_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); rc = l23_app_init(ms);
if (rc < 0) if (rc < 0)

View File

@ -162,7 +162,7 @@ int mobile_init(struct osmocom_ms *ms)
gsm_settings_arfcn(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); lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms);
gsm_sim_init(ms); gsm_sim_init(ms);