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;
};
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 */

View File

@ -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);
}

View File

@ -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)

View File

@ -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);