Inter-Layer intergration work
authorHarald Welte <laforge@gnumonks.org>
Tue, 2 Mar 2010 17:47:01 +0000 (18:47 +0100)
committerHarald Welte <laforge@gnumonks.org>
Tue, 2 Mar 2010 17:47:01 +0000 (18:47 +0100)
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.

15 files changed:
include/l1a_l23_interface.h
src/host/layer2/include/osmocom/Makefile.am
src/host/layer2/include/osmocom/lapdm.h
src/host/layer2/include/osmocom/osmocom_data.h
src/host/layer2/include/osmocom/osmocom_layer2.h
src/host/layer2/src/Makefile.am
src/host/layer2/src/lapdm.c
src/host/layer2/src/layer2_main.c
src/host/layer2/src/osmocom_layer2.c
src/host/layer2/src/osmocom_rslms.c
src/shared/libosmocore/include/osmocore/msgb.h
src/target/firmware/comm/sercomm.c
src/target/firmware/include/comm/msgb.h
src/target/firmware/layer1/l23_api.c
src/target/firmware/layer1/sync.c

index 01fcf9f..7c57cd6 100644 (file)
 #ifndef l1a_l23_interface_h
 #define l1a_l23_interface_h
 
-#define SYNC_NEW_CCCH_REQ      1
-#define SYNC_NEW_CCCH_RESP     2
-#define CCCH_INFO_IND          3
-#define CCCH_RACH_REQ          4
-#define DEDIC_MODE_EST_REQ     5
-#define DEDIC_MODE_DATA_IND    6
-#define DEDIC_MODE_DATA_REQ    7
-#define LAYER1_RESET           8
+#define L1CTL_NEW_CCCH_REQ     1
+#define L1CTL_NEW_CCCH_RESP    2
+#define L1CTL_DATA_IND         3
+#define L1CTL_RACH_REQ         4
+#define L1CTL_DM_EST_REQ       5
+#define L1CTL_DATA_REQ         7
+#define L1CTL_RESET            8
 
 /*
  * NOTE: struct size. We do add manual padding out of the believe
@@ -49,43 +48,51 @@ struct gsm_time {
 /*
  * downlink info ... down from the BTS..
  */
-struct l1_info_dl {
+struct l1ctl_info_dl {
        /* common header, should be its own struct */
        uint8_t msg_type;
        uint8_t padding;
 
-       /* the ARFCN and the band. FIXME: what about MAIO? */
-       uint16_t band_arfcn;
        /* GSM 08.58 channel number (9.3.1) */
        uint8_t chan_nr;
        /* GSM 08.58 link identifier (9.3.2) */
        uint8_t link_id;
 
+       /* the ARFCN and the band. FIXME: what about MAIO? */
+       uint16_t band_arfcn;
+
        struct gsm_time time;
        uint8_t rx_level;
        uint16_t snr[4];
 } __attribute__((packed));
 
 /* new CCCH was found. This is following the header */
-struct l1_sync_new_ccch_resp {
+struct l1ctl_sync_new_ccch_resp {
        uint8_t bsic;
        uint8_t padding[3];
 } __attribute__((packed));
 
 /* data on the CCCH was found. This is following the header */
-struct l1_ccch_info_ind {
+struct l1ctl_data_ind {
        uint8_t data[23];
 } __attribute__((packed));
 
 /*
  * uplink info
  */
-struct l1_info_ul {
+struct l1ctl_info_ul {
+       /* common header, should be its own struct */
        uint8_t msg_type;
        uint8_t padding;
+
+       /* GSM 08.58 channel number (9.3.1) */
+       uint8_t chan_nr;
+       /* GSM 08.58 link identifier (9.3.2) */
+       uint8_t link_id;
+
        uint8_t tx_power;
-       uint8_t channel_number;
-       uint32_t tdma_frame;
+       uint8_t padding2;
+
        uint8_t payload[0];
 } __attribute__((packed));
 
@@ -93,19 +100,18 @@ struct l1_info_ul {
  * msg for SYNC_NEW_CCCH_REQ
  * the l1_info_ul header is in front
  */
-struct l1_sync_new_ccch_req {
+struct l1ctl_sync_new_ccch_req {
        uint16_t band_arfcn;
 } __attribute__((packed));
 
 
 /* the l1_info_ul header is in front */
-struct l1_rach_req {
+struct l1ctl_rach_req {
        uint8_t ra;
        uint8_t padding[3];
 } __attribute__((packed));
 
-struct l1_dedic_mode_est_req {
-       struct l1_info_ul header;
+struct l1ctl_dm_est_req {
        uint16_t band_arfcn;
        union {
                struct {
@@ -125,17 +131,4 @@ struct l1_dedic_mode_est_req {
        };
 } __attribute__((packed));
 
-/* it is like the ccch ind... unite it? */
-
-/* the l1_info_dl header is in front */
-struct l1_dedic_mode_data_ind {
-       uint8_t data[23];
-} __attribute__((packed));
-
-/* the l1_info_ul header is in front */
-struct l1_dedic_mode_data_req {
-       uint8_t data[23];
-} __attribute__((packed));
-
-
 #endif
index e23eb40..37f37bf 100644 (file)
@@ -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
index 14b26e5..0e54b94 100644 (file)
@@ -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);
index d94cdb0..48c5579 100644 (file)
@@ -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
index 41c9bd0..97bd9e1 100644 (file)
@@ -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
index 41b42d4..0f1bf55 100644 (file)
@@ -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)
index d15179a..9ca26ff 100644 (file)
@@ -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)
index 2ccf3d1..e45b654 100644 (file)
@@ -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);
index 877ce4a..6df67fe 100644 (file)
@@ -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
  *
  *
  */
 
-#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);
index a0afa46..f34c64d 100644 (file)
@@ -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);
index 7de242b..4f0c8c3 100644 (file)
@@ -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);
index 1cd0f3b..7baedcd 100644 (file)
@@ -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;
index bf9ac63..6114d4b 100644 (file)
@@ -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 */
index 4784c85..aefec3f 100644 (file)
 
 #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:
index c71caaf..d9958ca 100644 (file)
@@ -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.