summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-03-02 18:47:01 +0100
committerHarald Welte <laforge@gnumonks.org>2010-03-02 18:47:01 +0100
commit092d57bef9bd560438993a85e8d04060386d0f4e (patch)
tree39cea97ebf772416cf1cfbab383f8a66b2d3fa5e /src
parent11c97f5effbb409cdd1c9be21b00de529158401e (diff)
Inter-Layer intergration work
L1 and L2 now pass UI frames like BCCH and CCCH downlink up into L3, which detects an IMMediate ASSignment command and instructs the L1 to switch to SDCCH/4. From this point on, SDCCH/4 and SACCH4/C messages end up in our L2 LAPDm implementation and are forwarded to L3.
Diffstat (limited to 'src')
-rw-r--r--src/host/layer2/include/osmocom/Makefile.am2
-rw-r--r--src/host/layer2/include/osmocom/lapdm.h2
-rw-r--r--src/host/layer2/include/osmocom/osmocom_data.h5
-rw-r--r--src/host/layer2/include/osmocom/osmocom_layer2.h4
-rw-r--r--src/host/layer2/src/Makefile.am2
-rw-r--r--src/host/layer2/src/lapdm.c53
-rw-r--r--src/host/layer2/src/layer2_main.c20
-rw-r--r--src/host/layer2/src/osmocom_layer2.c145
-rw-r--r--src/host/layer2/src/osmocom_rslms.c9
-rw-r--r--src/shared/libosmocore/include/osmocore/msgb.h6
-rw-r--r--src/target/firmware/comm/sercomm.c2
-rw-r--r--src/target/firmware/include/comm/msgb.h2
-rw-r--r--src/target/firmware/layer1/l23_api.c46
-rw-r--r--src/target/firmware/layer1/sync.c17
14 files changed, 219 insertions, 96 deletions
diff --git a/src/host/layer2/include/osmocom/Makefile.am b/src/host/layer2/include/osmocom/Makefile.am
index e23eb403..37f37bfb 100644
--- a/src/host/layer2/include/osmocom/Makefile.am
+++ b/src/host/layer2/include/osmocom/Makefile.am
@@ -1,3 +1,3 @@
# headers from OpenBSC
noinst_HEADERS = debug.h
-noinst_HEADERS += osmocom_layer2.h osmocom_data.h
+noinst_HEADERS += osmocom_layer2.h osmocom_data.h lapdm.h
diff --git a/src/host/layer2/include/osmocom/lapdm.h b/src/host/layer2/include/osmocom/lapdm.h
index 14b26e51..0e54b945 100644
--- a/src/host/layer2/include/osmocom/lapdm.h
+++ b/src/host/layer2/include/osmocom/lapdm.h
@@ -49,7 +49,7 @@ struct lapdm_entity {
void lapdm_init(struct lapdm_entity *le, struct osmocom_ms *ms);
/* input into layer2 (from layer 1) */
-int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1_info_dl *l1i);
+int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1ctl_info_dl *l1i);
/* input into layer2 (from layer 3) */
int rslms_recvmsg(struct msgb *msg, struct osmocom_ms *ms);
diff --git a/src/host/layer2/include/osmocom/osmocom_data.h b/src/host/layer2/include/osmocom/osmocom_data.h
index d94cdb09..48c55798 100644
--- a/src/host/layer2/include/osmocom/osmocom_data.h
+++ b/src/host/layer2/include/osmocom/osmocom_data.h
@@ -4,11 +4,16 @@
#include <osmocore/select.h>
#include <osmocore/gsm_utils.h>
+#include <osmocom/lapdm.h>
+
/* One Mobilestation for osmocom */
struct osmocom_ms {
struct bsc_fd bfd;
enum gsm_band band;
int arfcn;
+
+ struct lapdm_entity lapdm_dcch;
+ struct lapdm_entity lapdm_acch;
};
#endif
diff --git a/src/host/layer2/include/osmocom/osmocom_layer2.h b/src/host/layer2/include/osmocom/osmocom_layer2.h
index 41c9bd0b..97bd9e15 100644
--- a/src/host/layer2/include/osmocom/osmocom_layer2.h
+++ b/src/host/layer2/include/osmocom/osmocom_layer2.h
@@ -7,6 +7,10 @@ struct osmocom_ms;
int osmo_recv(struct osmocom_ms *ms, struct msgb *msg);
+int tx_ph_rach_req(struct osmocom_ms *ms);
+int tx_ph_dm_est_req(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr);
+
extern int osmo_send_l1(struct osmocom_ms *ms, struct msgb *msg);
+
#endif
diff --git a/src/host/layer2/src/Makefile.am b/src/host/layer2/src/Makefile.am
index 41b42d40..0f1bf551 100644
--- a/src/host/layer2/src/Makefile.am
+++ b/src/host/layer2/src/Makefile.am
@@ -5,5 +5,5 @@ noinst_LIBRARIES = libosmocom.a
libosmocom_a_SOURCES = libosmocom/debug.c
sbin_PROGRAMS = layer2
-layer2_SOURCES = layer2_main.c osmocom_layer2.c gsmtap_util.c
+layer2_SOURCES = layer2_main.c osmocom_layer2.c gsmtap_util.c lapdm.c osmocom_rslms.c
layer2_LDADD = libosmocom.a $(LIBOSMOCORE_LIBS)
diff --git a/src/host/layer2/src/lapdm.c b/src/host/layer2/src/lapdm.c
index d15179aa..9ca26ffa 100644
--- a/src/host/layer2/src/lapdm.c
+++ b/src/host/layer2/src/lapdm.c
@@ -298,6 +298,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
switch (LAPDm_CTRL_U_BITS(mctx->ctrl)) {
case LAPDm_U_SABM:
+ printf("SABM ");
/* Must be Format B */
rc = check_length_ind(msg->l2h[2]);
if (rc < 0)
@@ -310,14 +311,12 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
} else {
/* FIXME: check for contention resoultion */
printf("SABM command, multiple frame established state\n");
- msgb_free(msg);
return 0;
}
}
if (length == 0) {
/* 5.4.1.2 Normal establishment procedures */
rc = send_rslms_rll_simple(RSL_MT_EST_IND, mctx);
- msgb_free(msg);
} else {
/* 5.4.1.4 Contention resolution establishment */
msg->l3h = msg->l2h + 3;
@@ -328,28 +327,26 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
dl->state = LAPDm_STATE_SABM_SENT;
break;
case LAPDm_U_DM:
+ printf("DM ");
if (!LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
/* 5.4.1.2 DM responses with the F bit set to "0" shall be ignored. */
- msgb_free(msg);
return 0;
}
switch (dl->state) {
case LAPDm_STATE_IDLE:
/* 5.4.5 all other frame types shall be discarded */
- msgb_free(msg);
+ printf("state=IDLE (discarding) ");
return 0;
case LAPDm_STATE_MF_EST:
if (LAPDm_CTRL_PF_BIT(mctx->ctrl) == 1)
- printf("unsolicited DM resposne\n");
+ printf("unsolicited DM resposne ");
else
- printf("unsolicited DM resposne, multiple frame established state\n");
- msgb_free(msg);
+ printf("unsolicited DM resposne, multiple frame established state ");
return 0;
case LAPDm_STATE_TIMER_RECOV:
/* DM is normal in case PF = 1 */
if (LAPDm_CTRL_PF_BIT(mctx->ctrl) == 0) {
- printf("unsolicited DM resposne, multiple frame established state\n");
- msgb_free(msg);
+ printf("unsolicited DM resposne, multiple frame established state ");
return 0;
}
break;
@@ -357,9 +354,9 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
/* reset T200 */
bsc_del_timer(&dl->t200);
rc = send_rslms_rll_simple(RSL_MT_REL_IND, mctx);
- msgb_free(msg);
break;
case LAPDm_U_UI:
+ printf("UI ");
if (mctx->lapdm_fmt == LAPDm_FMT_B4) {
length = N201_B4;
msg->l3h = msg->l2h + 2;
@@ -373,7 +370,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
/* do some length checks */
if (length == 0) {
/* 5.3.3 UI frames received with the length indicator set to "0" shall be ignored */
- msgb_free(msg);
+ printf("length=0 (discarding) ");
return 0;
}
/* FIXME: G.4.5 check */
@@ -383,19 +380,21 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
break;
default:
/* 5.3.3 UI frames with invalid SAPI values shall be discarded */
- msgb_free(msg);
+ printf("sapi=%u (discarding) ", LAPDm_ADDR_SAPI(mctx->ctrl));
return 0;
}
msgb_pull_l2h(msg);
rc = send_rslms_rll_l3(RSL_MT_UNIT_DATA_IND, mctx, msg);
break;
case LAPDm_U_DISC:
+ printf("DISC ");
length = msg->l2h[2] >> 2;
if (length > 0 || msg->l2h[2] & 0x02) {
/* G.4.4 If a DISC or DM frame is received with L>0 or
* with the M bit set to "1", an MDL-ERROR-INDICATION
* primitive with cause "U frame with incorrect
* parameters" is sent to the mobile management entity. */
+ printf("U frame iwth incorrect parameters ");
return -EIO;
}
switch (dl->state) {
@@ -408,10 +407,11 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
}
break;
case LAPDm_U_UA:
+ printf("UA ");
/* FIXME: G.4.5 check */
if (!LAPDm_CTRL_PF_BIT(mctx->ctrl)) {
/* 5.4.1.2 A UA response with the F bit set to "0" shall be ignored. */
- msgb_free(msg);
+ printf("F=0 (discarding) ");
return 0;
}
switch (dl->state) {
@@ -420,8 +420,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
case LAPDm_STATE_IDLE:
/* 5.4.5 all other frame types shall be discarded */
default:
- printf("unsolicited UA response!\n");
- msgb_free(msg);
+ printf("unsolicited UA response! (discarding) ");
return 0;
}
/* reset Timer T200 */
@@ -432,7 +431,6 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
dl->state = LAPDm_STATE_MF_EST;
/* send notification to L3 */
rc = send_rslms_rll_simple(RSL_MT_EST_CONF, mctx);
- msgb_free(msg);
break;
}
return rc;
@@ -511,7 +509,7 @@ static int lapdm_rx_i(struct msgb *msg, struct lapdm_msg_ctx *mctx)
msgb_pull_l2h(msg);
rc = send_rslms_rll_l3(RSL_MT_DATA_IND, mctx, msg);
} else {
- printf("N(s) sequence error: Ns=%u, V_recv=%u\n", ns, dl->V_recv);
+ printf("N(s) sequence error: Ns=%u, V_recv=%u ", ns, dl->V_recv);
/* FIXME: 5.7.1: N(s) sequence error */
/* discard data */
return -EIO;
@@ -569,20 +567,21 @@ static int lapdm_ph_data_ind(struct msgb *msg, struct lapdm_msg_ctx *mctx)
else if (LAPDm_CTRL_is_I(mctx->ctrl))
rc = lapdm_rx_i(msg, mctx);
else {
- printf("unknown LAPDm format\n");
+ printf("unknown LAPDm format ");
rc = -EINVAL;
}
return rc;
}
/* input into layer2 (from layer 1) */
-int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1_info_dl *l1i)
+int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1ctl_info_dl *l1i)
{
uint8_t cbits = l1i->chan_nr >> 3;
uint8_t sapi = l1i->link_id & 7;
struct lapdm_msg_ctx mctx;
int rc;
+ printf("l2_ph_data_ind() ");
/* when we reach here, we have a msgb with l2h pointing to the raw
* 23byte mac block. The l1h has already been purged. */
@@ -595,13 +594,20 @@ int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1_info_dl
if (cbits == 0x10 || cbits == 0x12) {
/* Format Bbis is used on BCCH and CCCH(PCH, NCH and AGCH) */
mctx.lapdm_fmt = LAPDm_FMT_Bbis;
+ printf("fmt=Bbis ");
} else {
if (mctx.link_id & 0x40) {
/* It was received from network on SACCH, thus
* lapdm_fmt must be B4 */
mctx.lapdm_fmt = LAPDm_FMT_B4;
- } else
+ printf("fmt=B4 ");
+ /* SACCH frames have a two-byte L1 header that OsmocomBB L1 doesn't
+ * strip */
+ msg->l2h += 2;
+ } else {
mctx.lapdm_fmt = LAPDm_FMT_B;
+ printf("fmt=B ");
+ }
}
switch (mctx.lapdm_fmt) {
@@ -610,7 +616,7 @@ int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1_info_dl
case LAPDm_FMT_B4:
mctx.addr = msg->l2h[0];
if (!(mctx.addr & 0x01)) {
- printf("we don't support multibyte addresses\n");
+ printf("we don't support multibyte addresses (discarding)\n");
return -EINVAL;
}
mctx.ctrl = msg->l2h[1];
@@ -622,16 +628,19 @@ int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1_info_dl
/* FIXME */
break;
case LAPDm_FMT_Bbis:
+ /* directly pass up to layer3 */
+ printf("UI ");
msg->l3h = msg->l2h;
msgb_pull_l2h(msg);
rc = send_rslms_rll_l3(RSL_MT_UNIT_DATA_IND, &mctx, msg);
break;
}
+ printf("\n");
return rc;
}
-/* L3 -> L2 */
+/* L3 -> L2 / RSLMS -> LAPDm */
/* L3 requests establishment of data link */
static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
diff --git a/src/host/layer2/src/layer2_main.c b/src/host/layer2/src/layer2_main.c
index 2ccf3d18..e45b6544 100644
--- a/src/host/layer2/src/layer2_main.c
+++ b/src/host/layer2/src/layer2_main.c
@@ -1,5 +1,6 @@
/* Main method of the layer2 stack */
/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -19,8 +20,9 @@
*
*/
-#include <osmocom/osmocom_layer2.h>
#include <osmocom/osmocom_data.h>
+#include <osmocom/osmocom_layer2.h>
+#include <osmocom/lapdm.h>
#include <osmocom/debug.h>
#include <osmocore/msgb.h>
@@ -65,18 +67,19 @@ static int layer2_read(struct bsc_fd *fd, unsigned int flags)
exit(2);
}
- if (ntohs(len) > GSM_L2_LENGTH) {
- fprintf(stderr, "Length is too big: %u\n", ntohs(len));
+ len = ntohs(len);
+ if (len > GSM_L2_LENGTH) {
+ fprintf(stderr, "Length is too big: %u\n", len);
msgb_free(msg);
return -1;
}
/* blocking read for the poor... we can starve in here... */
- msg->l2h = msgb_put(msg, ntohs(len));
- rc = read(fd->fd, msg->l2h, msgb_l2len(msg));
- if (rc != msgb_l2len(msg)) {
- fprintf(stderr, "Can not read data: rc: %d errno: %d\n", rc, errno);
+ msg->l1h = msgb_put(msg, len);
+ rc = read(fd->fd, msg->l1h, msgb_l1len(msg));
+ if (rc != msgb_l1len(msg)) {
+ fprintf(stderr, "Can not read data: len=%d rc=%d errno=%d\n", len, rc, errno);
msgb_free(msg);
return -1;
}
@@ -195,6 +198,9 @@ int main(int argc, char **argv)
ms->bfd.cb = layer2_read;
ms->bfd.data = ms;
+ lapdm_init(&ms->lapdm_dcch, ms);
+ lapdm_init(&ms->lapdm_acch, ms);
+
if (bsc_register_fd(&ms->bfd) != 0) {
fprintf(stderr, "Failed to register fd.\n");
exit(1);
diff --git a/src/host/layer2/src/osmocom_layer2.c b/src/host/layer2/src/osmocom_layer2.c
index 877ce4a6..6df67fe5 100644
--- a/src/host/layer2/src/osmocom_layer2.c
+++ b/src/host/layer2/src/osmocom_layer2.c
@@ -1,6 +1,7 @@
/* Layer2 handling code... LAPD and stuff
*
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -20,20 +21,28 @@
*
*/
-#include <osmocom/osmocom_layer2.h>
-#include <osmocom/osmocom_data.h>
-#include <osmocom/debug.h>
-#include <osmocore/protocol/gsm_04_08.h>
-
#include <stdio.h>
#include <stdint.h>
+#include <string.h>
+#include <errno.h>
#include <l1a_l23_interface.h>
+#include <osmocore/timer.h>
+#include <osmocore/msgb.h>
+#include <osmocore/tlv.h>
+#include <osmocore/protocol/gsm_04_08.h>
+#include <osmocore/protocol/gsm_08_58.h>
+
+#include <osmocom/osmocom_layer2.h>
+#include <osmocom/osmocom_data.h>
+#include <osmocom/lapdm.h>
+#include <osmocom/debug.h>
+
#include "gsmtap_util.h"
static struct msgb *osmo_l1_alloc(uint8_t msg_type)
{
- struct l1_info_ul *ul;
+ struct l1ctl_info_ul *ul;
struct msgb *msg = msgb_alloc_headroom(256, 4, "osmo_l1");
if (!msg) {
@@ -41,33 +50,34 @@ static struct msgb *osmo_l1_alloc(uint8_t msg_type)
return NULL;
}
- ul = (struct l1_info_ul *) msgb_put(msg, sizeof(*ul));
+ msg->l1h = msgb_put(msg, sizeof(*ul));
+ ul = (struct l1ctl_info_ul *) msg->l1h;
ul->msg_type = msg_type;
return msg;
}
+
static int osmo_make_band_arfcn(struct osmocom_ms *ms)
{
/* TODO: Include the band */
return ms->arfcn;
}
-static int l1_rach_req(struct osmocom_ms *ms);
-static int osmo_l2_ccch_resp(struct osmocom_ms *ms, struct msgb *msg)
+static int rx_l1_ccch_resp(struct osmocom_ms *ms, struct msgb *msg)
{
- struct l1_info_dl *dl;
- struct l1_sync_new_ccch_resp *sb;
+ struct l1ctl_info_dl *dl;
+ struct l1ctl_sync_new_ccch_resp *sb;
if (msgb_l3len(msg) < sizeof(*sb)) {
fprintf(stderr, "MSG too short for CCCH RESP: %u\n", msgb_l3len(msg));
return -1;
}
- dl = (struct l1_info_dl *) msg->l2h;
- sb = (struct l1_sync_new_ccch_resp *) msg->l3h;
+ dl = (struct l1ctl_info_dl *) msg->l1h;
+ sb = (struct l1ctl_sync_new_ccch_resp *) msg->l2h;
- printf("Found sync burst: SNR: %u TDMA: (%.4u/%.2u/%.2u) bsic: %d\n",
+ printf("SCH: SNR: %u TDMA: (%.4u/%.2u/%.2u) bsic: %d\n",
dl->snr[0], dl->time.t1, dl->time.t2, dl->time.t3, sb->bsic);
return 0;
@@ -187,18 +197,20 @@ char *chan_nr2string(uint8_t chan_nr)
return str;
}
-static int osmo_l2_ccch_data(struct osmocom_ms *ms, struct msgb *msg)
+/* Data Indication from L1 */
+static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
- struct l1_info_dl *dl;
- struct l1_ccch_info_ind *ccch;
+ struct l1ctl_info_dl *dl, dl_cpy;
+ struct l1ctl_data_ind *ccch;
+ struct lapdm_entity *le;
if (msgb_l3len(msg) < sizeof(*ccch)) {
- fprintf(stderr, "MSG too short DCCH Data Ind: %u\n", msgb_l3len(msg));
+ fprintf(stderr, "MSG too short Data Ind: %u\n", msgb_l3len(msg));
return -1;
}
- dl = (struct l1_info_dl *) msg->l2h;
- ccch = (struct l1_ccch_info_ind *) msg->l3h;
+ dl = (struct l1ctl_info_dl *) msg->l1h;
+ ccch = (struct l1ctl_data_ind *) msg->l2h;
printf("Found %s burst(s): TDMA: (%.4u/%.2u/%.2u) tc:%d %s si: 0x%x\n",
chan_nr2string(dl->chan_nr), dl->time.t1, dl->time.t2,
dl->time.t3, dl->time.tc, hexdump(ccch->data, sizeof(ccch->data)),
@@ -208,66 +220,123 @@ static int osmo_l2_ccch_data(struct osmocom_ms *ms, struct msgb *msg)
/* send CCCH data via GSMTAP */
gsmtap_sendmsg(dl->chan_nr & 0x07, dl->band_arfcn, dl->time.fn, ccch->data,
sizeof(ccch->data));
- //l1_rach_req(ms);
+
+ /* determine LAPDm entity based on SACCH or not */
+ if (dl->link_id & 0x40)
+ le = &ms->lapdm_acch;
+ else
+ le = &ms->lapdm_dcch;
+ /* make local stack copy of l1ctl_info_dl, as LAPDm will overwrite skb hdr */
+ memcpy(&dl_cpy, dl, sizeof(dl_cpy));
+
+ /* pull the L1 header from the msgb */
+ msgb_pull(msg, msg->l2h - msg->l1h);
+ msg->l1h = NULL;
+
+ /* send it up into LAPDm */
+ l2_ph_data_ind(msg, le, &dl_cpy);
+
return 0;
}
-static int osmo_l1_reset(struct osmocom_ms *ms)
+int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg,
+ uint8_t chan_nr, uint8_t link_id)
+{
+ struct l1ctl_info_ul *l1i_ul;
+
+ /* prepend uplink info header */
+ l1i_ul = (struct l1ctl_info_ul *) msgb_push(msg, sizeof(*l1i_ul));
+
+ l1i_ul->msg_type = L1CTL_DATA_REQ;
+
+ l1i_ul->chan_nr = chan_nr;
+ l1i_ul->link_id = link_id;
+
+ /* FIXME: where to get this from? */
+ l1i_ul->tx_power = 0;
+
+ return osmo_send_l1(ms, msg);
+}
+
+static int rx_l1_reset(struct osmocom_ms *ms)
{
struct msgb *msg;
- struct l1_sync_new_ccch_req *req;
+ struct l1ctl_sync_new_ccch_req *req;
- msg = osmo_l1_alloc(SYNC_NEW_CCCH_REQ);
+ msg = osmo_l1_alloc(L1CTL_NEW_CCCH_REQ);
if (!msg)
return -1;
printf("Layer1 Reset.\n");
- req = (struct l1_sync_new_ccch_req *) msgb_put(msg, sizeof(*req));
+ req = (struct l1ctl_sync_new_ccch_req *) msgb_put(msg, sizeof(*req));
req->band_arfcn = osmo_make_band_arfcn(ms);
return osmo_send_l1(ms, msg);
}
-static int l1_rach_req(struct osmocom_ms *ms)
+int tx_ph_rach_req(struct osmocom_ms *ms)
{
struct msgb *msg;
- struct l1_rach_req *req;
+ struct l1ctl_rach_req *req;
static uint8_t i = 0;
- msg = osmo_l1_alloc(CCCH_RACH_REQ);
+ msg = osmo_l1_alloc(L1CTL_RACH_REQ);
if (!msg)
return -1;
printf("RACH Req.\n");
- req = (struct l1_rach_req *) msgb_put(msg, sizeof(*req));
+ req = (struct l1ctl_rach_req *) msgb_put(msg, sizeof(*req));
req->ra = i++;
return osmo_send_l1(ms, msg);
}
+int tx_ph_dm_est_req(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr)
+{
+ struct msgb *msg;
+ struct l1ctl_info_ul *ul;
+ struct l1ctl_dm_est_req *req;
+ static uint8_t i = 0;
+
+ msg = osmo_l1_alloc(L1CTL_DM_EST_REQ);
+ if (!msg)
+ return -1;
+
+ printf("Tx Dedic.Mode Est Req (arfcn=%u, chan_nr=0x%02x)\n",
+ band_arfcn, chan_nr);
+ ul = (struct l1ct_info_ul *) msg->l1h;
+ ul->chan_nr = chan_nr;
+ ul->link_id = 0;
+ ul->tx_power = 0; /* FIXME: initial TX power */
+ req = (struct l1ctl_dm_est_req *) msgb_put(msg, sizeof(*req));
+ req->band_arfcn = band_arfcn;
+
+ return osmo_send_l1(ms, msg);
+
+}
int osmo_recv(struct osmocom_ms *ms, struct msgb *msg)
{
int rc = 0;
- struct l1_info_dl *dl;
+ struct l1ctl_info_dl *dl;
if (msgb_l2len(msg) < sizeof(*dl)) {
fprintf(stderr, "Short Layer2 message: %u\n", msgb_l2len(msg));
return -1;
}
- dl = (struct l1_info_dl *) msg->l2h;
- msg->l3h = &msg->l2h[0] + sizeof(*dl);
+ dl = (struct l1ctl_info_dl *) msg->l1h;
+ msg->l2h = &msg->l1h[0] + sizeof(*dl);
switch (dl->msg_type) {
- case SYNC_NEW_CCCH_RESP:
- rc = osmo_l2_ccch_resp(ms, msg);
+ case L1CTL_NEW_CCCH_RESP:
+ rc = rx_l1_ccch_resp(ms, msg);
break;
- case CCCH_INFO_IND:
- rc = osmo_l2_ccch_data(ms, msg);
+ case L1CTL_DATA_IND:
+ rc = rx_ph_data_ind(ms, msg);
break;
- case LAYER1_RESET:
- rc = osmo_l1_reset(ms);
+ case L1CTL_RESET:
+ rc = rx_l1_reset(ms);
break;
default:
fprintf(stderr, "Unknown MSG: %u\n", dl->msg_type);
diff --git a/src/host/layer2/src/osmocom_rslms.c b/src/host/layer2/src/osmocom_rslms.c
index a0afa46c..f34c64da 100644
--- a/src/host/layer2/src/osmocom_rslms.c
+++ b/src/host/layer2/src/osmocom_rslms.c
@@ -40,11 +40,13 @@ static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms)
{
struct gsm48_imm_ass *ia = msgb_l3(msg);
uint8_t ch_type, ch_subch, ch_ts;
+ uint16_t arfcn;
rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
+ arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
- printf("GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, TS=%u, SS=%u, TSC=%u) ",
- ia->req_ref.ra, ia->chan_desc.chan_nr, ch_ts, ch_subch,
+ printf("GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, ARFCN=%u, TS=%u, SS=%u, TSC=%u) ",
+ ia->req_ref.ra, ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch,
ia->chan_desc.h0.tsc);
/* FIXME: compare RA and GSM time with when we sent RACH req */
@@ -57,6 +59,7 @@ static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms)
}
/* FIXME: request L1 to go to dedicated mode on assigned channel */
+ return tx_ph_dm_est_req(ms, arfcn, ia->chan_desc.chan_nr);
return 0;
}
@@ -151,7 +154,7 @@ static int rslms_rx_rll(struct msgb *msg, struct osmocom_ms *ms)
return rc;
}
-/* sending messages up from L2 to L3 */
+/* input function that L2 calls when sending messages up to L3 */
int rslms_sendmsg(struct msgb *msg, struct osmocom_ms *ms)
{
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
diff --git a/src/shared/libosmocore/include/osmocore/msgb.h b/src/shared/libosmocore/include/osmocore/msgb.h
index 7de242b2..4f0c8c38 100644
--- a/src/shared/libosmocore/include/osmocore/msgb.h
+++ b/src/shared/libosmocore/include/osmocore/msgb.h
@@ -67,10 +67,16 @@ extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
extern struct msgb *msgb_dequeue(struct llist_head *queue);
extern void msgb_reset(struct msgb *m);
+#define msgb_l1(m) ((void *)(m->l1h))
#define msgb_l2(m) ((void *)(m->l2h))
#define msgb_l3(m) ((void *)(m->l3h))
#define msgb_sms(m) ((void *)(m->smsh))
+static inline unsigned int msgb_l1len(const struct msgb *msgb)
+{
+ return msgb->tail - (uint8_t *)msgb_l1(msgb);
+}
+
static inline unsigned int msgb_l2len(const struct msgb *msgb)
{
return msgb->tail - (uint8_t *)msgb_l2(msgb);
diff --git a/src/target/firmware/comm/sercomm.c b/src/target/firmware/comm/sercomm.c
index 1cd0f3b1..7baedcd3 100644
--- a/src/target/firmware/comm/sercomm.c
+++ b/src/target/firmware/comm/sercomm.c
@@ -208,7 +208,7 @@ int sercomm_drv_rx_char(uint8_t ch)
sercomm.rx.msg = sercomm_alloc_msgb(SERCOMM_RX_MSG_SIZE);
if (msgb_tailroom(sercomm.rx.msg) == 0) {
- cons_puts("sercomm_drv_rx_char() overflow!\n");
+ //cons_puts("sercomm_drv_rx_char() overflow!\n");
msgb_free(sercomm.rx.msg);
sercomm.rx.msg = sercomm_alloc_msgb(SERCOMM_RX_MSG_SIZE);
sercomm.rx.state = RX_ST_WAIT_START;
diff --git a/src/target/firmware/include/comm/msgb.h b/src/target/firmware/include/comm/msgb.h
index bf9ac63d..6114d4b2 100644
--- a/src/target/firmware/include/comm/msgb.h
+++ b/src/target/firmware/include/comm/msgb.h
@@ -25,6 +25,8 @@
struct msgb {
struct llist_head list;
+ /* the layer 1 header, if any */
+ unsigned char *l1h;
/* the A-bis layer 2 header: OML, RSL(RLL), NS */
unsigned char *l2h;
/* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */
diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c
index 4784c857..aefec3f4 100644
--- a/src/target/firmware/layer1/l23_api.c
+++ b/src/target/firmware/layer1/l23_api.c
@@ -28,11 +28,12 @@
#include <layer1/sync.h>
#include <layer1/async.h>
+#include <layer1/mframe_sched.h>
#include <l1a_l23_interface.h>
/* the size we will allocate struct msgb* for HDLC */
-#define L3_MSG_SIZE (sizeof(struct l1_ccch_info_ind) + 4)
+#define L3_MSG_SIZE (sizeof(struct l1ctl_data_ind) + 4)
#define L3_MSG_HEAD 4
void l1_queue_for_l2(struct msgb *msg)
@@ -43,7 +44,7 @@ void l1_queue_for_l2(struct msgb *msg)
struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr)
{
- struct l1_info_dl *dl;
+ struct l1ctl_info_dl *dl;
struct msgb *msg;
msg = msgb_alloc_headroom(L3_MSG_SIZE, L3_MSG_HEAD, "l1_burst");
@@ -55,7 +56,7 @@ struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr)
return NULL;
}
- dl = (struct l1_info_dl *) msgb_put(msg, sizeof(*dl));
+ dl = (struct l1ctl_info_dl *) msgb_put(msg, sizeof(*dl));
dl->msg_type = msg_type;
/* FIXME: we may want to compute T1/T2/T3 in L23 */
gsm_fn2gsmtime(&dl->time, fn);
@@ -67,24 +68,26 @@ struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr)
/* callbakc from SERCOMM when L2 sends a message to L1 */
static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
{
- struct l1_info_ul *ul = msg->data;
- struct l1_sync_new_ccch_req *sync_req;
- struct l1_rach_req *rach_req;
- struct l1_dedic_mode_est_req *est_req;
+ struct l1ctl_info_ul *ul = msg->data;
+ struct l1ctl_sync_new_ccch_req *sync_req;
+ struct l1ctl_rach_req *rach_req;
+ struct l1ctl_dedic_mode_est_req *est_req;
+ struct l1ctl_data_ind *data_ind;
+ struct llist_head *tx_queue;
if (sizeof(*ul) > msg->len) {
- printf("la1_l23_cb: Short message. %u\n", msg->len);
+ printf("l1a_l23_cb: Short message. %u\n", msg->len);
goto exit;
}
switch (ul->msg_type) {
- case SYNC_NEW_CCCH_REQ:
+ case L1CTL_NEW_CCCH_REQ:
if (sizeof(*ul) + sizeof(*sync_req) > msg->len) {
printf("Short sync msg. %u\n", msg->len);
break;
}
- sync_req = (struct l1_sync_new_ccch_req *) (&msg->data[0] + sizeof(*ul));
+ sync_req = (struct l1ctl_sync_new_ccch_req *) (&msg->data[0] + sizeof(*ul));
printf("Asked to tune to frequency: %u\n", sync_req->band_arfcn);
/* reset scheduler and hardware */
@@ -98,15 +101,28 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
puts("Starting FCCH Recognition\n");
l1s_fb_test(1, 0);
break;
- case DEDIC_MODE_EST_REQ:
- est_req = (struct l1_dedic_mode_est_req *) ul->payload;
- /* FIXME: ARFCN! */
+ case L1CTL_DM_EST_REQ:
+ est_req = (struct l1ctl_dm_est_req *) ul->payload;
+ /* FIXME: ARFCN */
+ /* FIXME: Timeslot */
/* figure out which MF tasks to enable, depending on channel number */
+ l1s.mf_tasks = (1 << MF_TASK_SDCCH4_0);
break;
- case CCCH_RACH_REQ:
- rach_req = (struct l1_rach_req *) ul->payload;
+ case L1CTL_RACH_REQ:
+ puts("CCCH_RACH_REQ\n");
+ rach_req = (struct l1ctl_rach_req *) ul->payload;
l1a_rach_req(27, rach_req->ra);
break;
+ case L1CTL_DATA_REQ:
+ puts("DEDIC_MODE_DATA_REQ\n");
+ data_ind = (struct l1ctl_data_ind *) ul->payload;
+ if (ul->link_id & 0x40)
+ tx_queue = &l1s.tx_queue[L1S_CHAN_SACCH];
+ else
+ tx_queue = &l1s.tx_queue[L1S_CHAN_MAIN];
+ msg->l3h = data_ind->data;
+ l1a_txq_msgb_enq(tx_queue, msg);
+ break;
}
exit:
diff --git a/src/target/firmware/layer1/sync.c b/src/target/firmware/layer1/sync.c
index c71caaf4..d9958caa 100644
--- a/src/target/firmware/layer1/sync.c
+++ b/src/target/firmware/layer1/sync.c
@@ -675,7 +675,7 @@ static int l1s_sbdet_resp(uint8_t p1, uint8_t attempt, uint16_t p3)
l1s_time_inc(&l1s.next_time, 1);
/* place it in the queue for the layer2 */
- msg = l1_create_l2_msg(SYNC_NEW_CCCH_RESP, sb_time.fn, last_fb->snr);
+ msg = l1_create_l2_msg(L1CTL_NEW_CCCH_RESP, sb_time.fn, last_fb->snr);
l1 = (struct l1_sync_new_ccch_resp *) msgb_put(msg, sizeof(*l1));
l1->bsic = bsic;
l1_queue_for_l2(msg);
@@ -834,7 +834,7 @@ static int l1s_nb_resp(uint8_t p1, uint8_t burst_id, uint16_t p3)
/* 4th burst, get frame data */
if (dsp_api.db_r->d_burst_d == 3) {
struct l1_info_dl *dl;
- struct l1_ccch_info_ind *l1;
+ struct l1_data_ind *l1;
uint8_t i, j;
sig->signum = L1_SIG_NB;
@@ -853,9 +853,9 @@ static int l1s_nb_resp(uint8_t p1, uint8_t burst_id, uint16_t p3)
l1s_cb(sig);
/* place it in the queue for the layer2 */
- msg = l1_create_l2_msg(CCCH_INFO_IND, l1s.current_time.fn-4, last_fb->snr);
+ msg = l1_create_l2_msg(L1CTL_DATA_IND, l1s.current_time.fn-4, last_fb->snr);
dl = (struct l1_info_dl *) msg->data;
- l1 = (struct l1_ccch_info_ind *) msgb_put(msg, sizeof(*l1));
+ l1 = (struct l1_data_ind *) msgb_put(msg, sizeof(*l1));
/* Set Channel Number depending on MFrame Task ID */
dl->chan_nr = mframe_task2chan_nr(mf_task_id, 0); /* FIXME: TS */
@@ -995,10 +995,13 @@ static int l1s_tx_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3)
msg = msgb_dequeue(tx_queue);
/* If the TX queue is empty, send idle pattern */
- if (!msg)
+ if (!msg) {
+ puts("TX idle pattern\n");
data = ubUui;
- else
- data = msg->data;
+ } else {
+ puts("TX uplink msg\n");
+ data = msg->l3h;
+ }
/* Fill data block Header */
info_ptr[0] = (1 << B_BLUD); // 1st word: Set B_BLU bit.