This is one step in the direction of re-using the lapdm code in osmo-bts.
};
struct lapdm_entity;
-struct osmocom_ms;
struct lapdm_msg_ctx {
struct lapdm_datalink *dl;
_NR_DL_SAPI
};
+typedef int (*lapdm_cb_t)(struct msgb *msg, struct lapdm_entity *le, void *ctx);
+
+/* 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 */
void *l1_ctx; /* context for layer1 instance */
void *l3_ctx; /* context for layer3 instance */
+
+ lapdm_cb_t l1_cb; /* callback for sending stuff to L1 */
+ lapdm_cb_t l3_cb; /* callback for sending stuff to L3 */
+
+ struct lapdm_channel *lapdm_ch;
+};
+
+/* the two lapdm_entities that form a GSM logical channel (ACCH + DCCH) */
+struct lapdm_channel {
+ struct llist_head list;
+ char *name;
+ struct lapdm_entity lapdm_acch;
+ struct lapdm_entity lapdm_dcch;
};
const char *get_rsl_name(int value);
extern const char *lapdm_state_names[];
/* initialize a LAPDm entity */
-void lapdm_init(struct lapdm_entity *le);
+void lapdm_entity_init(struct lapdm_entity *le);
+void lapdm_channel_init(struct lapdm_channel *lc);
/* deinitialize a LAPDm entity */
-void lapdm_exit(struct lapdm_entity *le);
+void lapdm_entity_exit(struct lapdm_entity *le);
+void lapdm_channel_exit(struct lapdm_channel *lc);
/* input into layer2 (from layer 1) */
int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1ctl_info_dl *l1i);
struct l1ctl_info_dl *dl);
/* input into layer2 (from layer 3) */
-int rslms_recvmsg(struct msgb *msg, struct osmocom_ms *ms);
-
-/* sending messages up from L2 to L3 */
-int rslms_sendmsg(struct msgb *msg, struct osmocom_ms *ms);
+int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc);
-typedef int (*osmol2_cb_t)(struct msgb *msg, struct osmocom_ms *ms);
-
-/* register message handler for messages that are sent from L2->L3 */
-int osmol2_register_handler(struct osmocom_ms *ms, osmol2_cb_t cb);
+int osmol2_register_handler(struct osmocom_ms *ms, lapdm_cb_t cb);
#endif /* _OSMOCOM_LAPDM_H */
#include <osmocom/bb/mobile/gsm48_cc.h>
#include <osmocom/bb/common/sim.h>
-/* A layer2 entity */
-struct osmol2_entity {
- struct lapdm_entity lapdm_dcch;
- struct lapdm_entity lapdm_acch;
- osmol2_cb_t msg_handler;
-};
-
struct osmosap_entity {
osmosap_cb_t msg_handler;
};
struct gsm_settings settings;
struct gsm_subscriber subscr;
struct gsm_sim sim;
- struct osmol2_entity l2_entity;
+ struct lapdm_channel lapdm_channel;
struct osmosap_entity sap_entity;
struct rx_meas_stat meas;
struct gsm48_rrlayer rrlayer;
/* determine LAPDm entity based on SACCH or not */
if (dl->link_id & 0x40)
- le = &ms->l2_entity.lapdm_acch;
+ le = &ms->lapdm_channel.lapdm_acch;
else
- le = &ms->l2_entity.lapdm_dcch;
+ le = &ms->lapdm_channel.lapdm_dcch;
/* make local stack copy of l1ctl_info_dl, as LAPDm will
* overwrite skb hdr */
memcpy(&dl_cpy, dl, sizeof(dl_cpy));
/* determine LAPDm entity based on SACCH or not */
if (dl->link_id & 0x40)
- le = &ms->l2_entity.lapdm_acch;
+ le = &ms->lapdm_channel.lapdm_acch;
else
- le = &ms->l2_entity.lapdm_dcch;
+ le = &ms->lapdm_channel.lapdm_dcch;
/* send it up into LAPDm */
l2_ph_data_conf(msg, le);
dl->entity = entity;
}
-void lapdm_init(struct lapdm_entity *le)
+void lapdm_entity_init(struct lapdm_entity *le)
{
unsigned int i;
lapdm_dl_init(&le->datalink[i], le);
}
+void lapdm_channel_init(struct lapdm_channel *lc)
+{
+ lapdm_entity_init(&lc->lapdm_acch);
+ lapdm_entity_init(&lc->lapdm_dcch);
+}
+
+
static void lapdm_dl_flush_send(struct lapdm_datalink *dl)
{
struct msgb *msg;
dl->tx_length[i] = 0;
}
-void lapdm_exit(struct lapdm_entity *le)
+void lapdm_entity_exit(struct lapdm_entity *le)
{
unsigned int i;
struct lapdm_datalink *dl;
}
}
+void lapdm_channel_exit(struct lapdm_channel *lc)
+{
+ lapdm_entity_exit(&lc->lapdm_acch);
+ lapdm_entity_exit(&lc->lapdm_dcch);
+}
+
static void lapdm_dl_newstate(struct lapdm_datalink *dl, uint32_t state)
{
LOGP(DLAPDM, LOGL_INFO, "new state %s -> %s\n",
memset(data, 0x2B, pad_len);
}
+/* input function that L2 calls when sending messages up to L3 */
+static int rslms_sendmsg(struct msgb *msg, struct lapdm_entity *le)
+{
+ if (!le->l3_cb) {
+ msgb_free(msg);
+ return -EIO;
+ }
+
+ /* call the layer2 message handler that is registered */
+ return le->l3_cb(msg, le, le->l3_ctx);
+}
+
/* write a frame into the tx queue */
static int tx_ph_data_enqueue(struct lapdm_datalink *dl, struct msgb *msg,
uint8_t chan_nr, uint8_t link_id, uint8_t n201)
rsl_rll_push_l3(msg, msg_type, mctx->chan_nr, mctx->link_id, 1);
/* send off the RSLms message to L3 */
- return rslms_sendmsg(msg, mctx->dl->entity->l3_ctx);
+ return rslms_sendmsg(msg, mctx->dl->entity);
}
/* Take a B4 format message from L1 and create RSLms UNIT DATA IND */
rllh->data[2] = RSL_IE_MS_POWER;
rllh->data[3] = mctx->tx_power_ind;
- return rslms_sendmsg(msg, mctx->dl->entity->l3_ctx);
+ return rslms_sendmsg(msg, mctx->dl->entity);
}
static int send_rll_simple(uint8_t msg_type, struct lapdm_msg_ctx *mctx)
msg = rsl_rll_simple(msg_type, mctx->chan_nr, mctx->link_id, 1);
/* send off the RSLms message to L3 */
- return rslms_sendmsg(msg, mctx->dl->entity->l3_ctx);
+ return rslms_sendmsg(msg, mctx->dl->entity);
}
static int rsl_rll_error(uint8_t cause, struct lapdm_msg_ctx *mctx)
tlv[0] = RSL_IE_RLM_CAUSE;
tlv[1] = 1;
tlv[2] = cause;
- return rslms_sendmsg(msg, mctx->dl->entity->l3_ctx);
+ return rslms_sendmsg(msg, mctx->dl->entity);
}
static int check_length_ind(struct lapdm_msg_ctx *mctx, uint8_t length_ind)
}
/* L3 requests channel in idle state */
-static int rslms_rx_chan_rqd(struct osmocom_ms *ms, struct msgb *msg)
+static int rslms_rx_chan_rqd(struct lapdm_channel *lc, struct msgb *msg)
{
struct abis_rsl_cchan_hdr *cch = msgb_l2(msg);
+ void *l1ctx = lc->lapdm_dcch.l1_ctx;
int rc;
if (msgb_l2len(msg) < sizeof(*cch) + 4 + 2 + 2) {
}
/* TA = 0 - delay */
- rc = l1ctl_tx_param_req(ms, 0 - cch->data[5], cch->data[7]);
+ rc = l1ctl_tx_param_req(l1ctx, 0 - cch->data[5], cch->data[7]);
- rc = l1ctl_tx_rach_req(ms, cch->data[1],
+ rc = l1ctl_tx_rach_req(l1ctx, cch->data[1],
((cch->data[2] & 0x7f) << 8) | cch->data[3], cch->data[2] >> 7);
msgb_free(msg);
ref->t3_low = tm.t3 & 0x7;
ref->t3_high = tm.t3 >> 3;
- return rslms_sendmsg(msg, ms);
+ return rslms_sendmsg(msg, &ms->lapdm_channel.lapdm_dcch);
}
/* Names for Radio Link Layer Management */
(sizeof(l2downstatelist) / sizeof(struct l2downstate))
/* incoming RSLms RLL message from L3 */
-static int rslms_rx_rll(struct msgb *msg, struct osmocom_ms *ms)
+static int rslms_rx_rll(struct msgb *msg, struct lapdm_channel *lc)
{
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
int msg_type = rllh->c.msg_type;
}
if (rllh->link_id & 0x40)
- le = &ms->l2_entity.lapdm_acch;
+ le = &lc->lapdm_acch;
else
- le = &ms->l2_entity.lapdm_dcch;
+ le = &lc->lapdm_dcch;
/* G.2.1 No action schall be taken on frames containing an unallocated
* SAPI.
return -EINVAL;
}
- LOGP(DRSL, LOGL_INFO, "(ms %s) RLL Message '%s' received in state %s\n",
- ms->name, get_rsl_name(msg_type), lapdm_state_names[dl->state]);
+ LOGP(DRSL, LOGL_INFO, "(%p) RLL Message '%s' received in state %s\n",
+ lc->name, get_rsl_name(msg_type), lapdm_state_names[dl->state]);
/* find function for current state and message */
for (i = 0; i < L2DOWNSLLEN; i++) {
}
/* incoming RSLms COMMON CHANNEL message from L3 */
-static int rslms_rx_com_chan(struct msgb *msg, struct osmocom_ms *ms)
+static int rslms_rx_com_chan(struct msgb *msg, struct lapdm_channel *lc)
{
struct abis_rsl_cchan_hdr *cch = msgb_l2(msg);
int msg_type = cch->c.msg_type;
switch (msg_type) {
case RSL_MT_CHAN_RQD:
/* create and send RACH request */
- rc = rslms_rx_chan_rqd(ms, msg);
+ rc = rslms_rx_chan_rqd(lc, msg);
break;
default:
LOGP(DRSL, LOGL_NOTICE, "Unknown COMMON CHANNEL msg %d!\n",
}
/* input into layer2 (from layer 3) */
-int rslms_recvmsg(struct msgb *msg, struct osmocom_ms *ms)
+int lapdm_rslms_recvmsg(struct msgb *msg, struct lapdm_channel *lc)
{
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
int rc = 0;
switch (rslh->msg_discr & 0xfe) {
case ABIS_RSL_MDISC_RLL:
- rc = rslms_rx_rll(msg, ms);
+ rc = rslms_rx_rll(msg, lc);
break;
case ABIS_RSL_MDISC_COM_CHAN:
- rc = rslms_rx_com_chan(msg, ms);
+ rc = rslms_rx_com_chan(msg, lc);
break;
default:
LOGP(DRSL, LOGL_ERROR, "unknown RSLms message "
return rc;
}
-/* input function that L2 calls when sending messages up to L3 */
-int rslms_sendmsg(struct msgb *msg, struct osmocom_ms *ms)
-{
- if (!ms->l2_entity.msg_handler) {
- msgb_free(msg);
- return -EIO;
- }
-
- /* call the layer2 message handler that is registered */
- return ms->l2_entity.msg_handler(msg, ms);
-}
-
-/* register message handler for messages that are sent from L2->L3 */
-int osmol2_register_handler(struct osmocom_ms *ms, osmol2_cb_t cb)
+int osmol2_register_handler(struct osmocom_ms *ms, lapdm_cb_t cb)
{
- ms->l2_entity.msg_handler = cb;
+ ms->lapdm_channel.lapdm_acch.l3_cb = cb;
+ ms->lapdm_channel.lapdm_dcch.l3_cb = cb;
+ ms->lapdm_channel.lapdm_acch.l3_ctx = ms;
+ ms->lapdm_channel.lapdm_dcch.l3_ctx = ms;
return 0;
}
if (rc < 0)
fprintf(stderr, "Failed during sap_open(), no SIM reader\n");
- ms->l2_entity.lapdm_dcch.l1_ctx = ms;
- ms->l2_entity.lapdm_dcch.l3_ctx = ms;
- lapdm_init(&ms->l2_entity.lapdm_dcch);
-
- ms->l2_entity.lapdm_acch.l1_ctx = ms;
- ms->l2_entity.lapdm_acch.l3_ctx = ms;
- lapdm_init(&ms->l2_entity.lapdm_acch);
+ ms->lapdm_channel.lapdm_dcch.l1_ctx = ms;
+ 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);
rc = l23_app_init(ms);
if (rc < 0)
return 0;
}
-static int rcv_rsl(struct msgb *msg, struct osmocom_ms *ms)
+static int rcv_rsl(struct msgb *msg, struct lapdm_entity *le, void *l3ctx)
{
+ struct osmocom_ms *ms = l3ctx;
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
int rc = 0;
start_timer(RACH_WAIT);
- rslms_recvmsg(nmsg, ms);
+ lapdm_rslms_recvmsg(nmsg, &ms->lapdm_channel);
}
static void start_sync(void)
return 0;
}
-static int rcv_rsl(struct msgb *msg, struct osmocom_ms *ms)
+static int rcv_rsl(struct msgb *msg, struct lapdm_entity *le, void *l3ctx)
{
+ struct osmocom_ms *ms = l3ctx;
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
int rc = 0;
msg = rsl_rll_simple(msg_type, chan_nr, link_id, 1);
- return rslms_recvmsg(msg, ms);
+ return lapdm_rslms_recvmsg(msg, ms);
}
/* Send a RLL request (including L3 info) to L2 */
{
rsl_rll_push_l3(msg, msg_type, chan_nr, link_id, 1);
- return rslms_recvmsg(msg, ms);
+ return lapdm_rslms_recvmsg(msg, ms);
}
static int rslms_rx_udata_ind(struct msgb *msg, struct osmocom_ms *ms)
gsm_subscr_exit(ms);
gsm48_cc_exit(ms);
gsm_sim_exit(ms);
- lapdm_exit(&ms->l2_entity.lapdm_acch);
- lapdm_exit(&ms->l2_entity.lapdm_dcch);
+ lapdm_channel_exit(&ms->lapdm_channel);
ms->shutdown = 2; /* being down */
vty_notify(ms, NULL);
int rc;
gsm_settings_arfcn(ms);
- ms->l2_entity.lapdm_dcch.l1_ctx = ms;
- ms->l2_entity.lapdm_dcch.l3_ctx = ms;
- lapdm_init(&ms->l2_entity.lapdm_dcch);
- ms->l2_entity.lapdm_acch.l1_ctx = ms;
- ms->l2_entity.lapdm_acch.l3_ctx = ms;
- lapdm_init(&ms->l2_entity.lapdm_acch);
+ ms->lapdm_channel.lapdm_dcch.l1_ctx = ms;
+ 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);
gsm_sim_init(ms);
gsm48_cc_init(ms);
gsm_subscr_init(ms);
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/l1l2_interface.h>
+#include <osmocom/bb/common/l23_app.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/common/l1ctl.h>
rsl_rll_push_l3(msg, msg_type, rr->cd_now.chan_nr,
rr->cd_now.link_id, 1);
- return rslms_recvmsg(msg, ms);
+ return lapdm_rslms_recvmsg(msg, &ms->lapdm_channel);
}
/* push rsl header + release mode and send (RSL-SAP) */
rsl_rll_push_hdr(msg, msg_type, rr->cd_now.chan_nr,
rr->cd_now.link_id, 1);
- return rslms_recvmsg(msg, ms);
+ return lapdm_rslms_recvmsg(msg, &ms->lapdm_channel);
}
/* enqueue messages (RSL-SAP) */
-static int gsm48_rx_rsl(struct msgb *msg, struct osmocom_ms *ms)
+static int rcv_rsl(struct msgb *msg, struct lapdm_entity *le, void *l3ctx)
{
+ struct osmocom_ms *ms = l3ctx;
struct gsm48_rrlayer *rr = &ms->rrlayer;
msgb_enqueue(&rr->rsl_upqueue, msg);
/* store ra until confirmed, then copy it with time into cr_hist */
rr->cr_ra = chan_req;
- return rslms_recvmsg(nmsg, ms);
+ return lapdm_rslms_recvmsg(nmsg, &ms->lapdm_channel);
}
/*
rsl_rll_push_hdr(nmsg, RSL_MT_UNIT_DATA_REQ, rr->cd_now.chan_nr,
0x40, 1);
- return rslms_recvmsg(nmsg, ms);
+ return lapdm_rslms_recvmsg(nmsg, &ms->lapdm_channel);
}
/*
INIT_LLIST_HEAD(&rr->downqueue);
/* downqueue is handled here, so don't add_work */
- osmol2_register_handler(ms, &gsm48_rx_rsl);
+ osmol2_register_handler(ms, &rcv_rsl);
start_rr_t_meas(rr, 1, 0);