aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2011-08-20 10:16:59 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2011-10-03 13:01:00 +0200
commit55e7a2e87dc79a936e0993e57f411e33299643cf (patch)
tree72b74c0a4d023001a4cf0a068cbf7ca17ef11d4b
parente9871f0d722ce135b00b6afe29aea975f5753df3 (diff)
[WIP] Split of L1CTL and L1IF
-rw-r--r--include/osmo-bts/gsm_data.h4
-rw-r--r--src/osmo-bts-bb/Makefile.am2
-rw-r--r--src/osmo-bts-bb/l1_if.c289
-rw-r--r--src/osmo-bts-bb/l1_if.h39
-rw-r--r--src/osmo-bts-bb/l1ctl.c305
-rw-r--r--src/osmo-bts-bb/l1ctl.h109
-rw-r--r--src/osmo-bts-bb/main.c4
-rw-r--r--src/osmo-bts-bb/oml.c1
8 files changed, 485 insertions, 268 deletions
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index c75d726d..a3ae30f4 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -58,9 +58,9 @@ static inline struct femtol1_hdl *trx_femtol1_hdl(struct gsm_bts_trx *trx)
return trx->role_bts.l1h;
}
-struct bbl1_hdl;
+struct osmo_l1_if;
-static inline struct bbl1_hdl *trx_bbl1_hdl(struct gsm_bts_trx *trx)
+static inline struct osmo_l1_if *trx_l1_if(struct gsm_bts_trx *trx)
{
return trx->role_bts.l1h;
}
diff --git a/src/osmo-bts-bb/Makefile.am b/src/osmo-bts-bb/Makefile.am
index c922fd22..f8791365 100644
--- a/src/osmo-bts-bb/Makefile.am
+++ b/src/osmo-bts-bb/Makefile.am
@@ -4,5 +4,5 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS)
bin_PROGRAMS = osmobts
-osmobts_SOURCES = main.c oml.c bts_model.c l1_if.c
+osmobts_SOURCES = main.c oml.c bts_model.c l1_if.c l1ctl.c
osmobts_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD)
diff --git a/src/osmo-bts-bb/l1_if.c b/src/osmo-bts-bb/l1_if.c
index d3f6a69f..77cccac3 100644
--- a/src/osmo-bts-bb/l1_if.c
+++ b/src/osmo-bts-bb/l1_if.c
@@ -1,8 +1,6 @@
/* Interface to layer 1 of baseband */
-/* (C) 2010 by Holger Hans Peter Freyther
- * (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
+/* (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
*
* All Rights Reserved
*
@@ -47,167 +45,16 @@
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/signal.h>
+#include "l1ctl.h"
#include "l1_if.h"
#include "oml.h"
-uint16_t ref_arfcn;
extern int tx_only;
-/*
- * socket communication with baseband
- */
-
-#include "../../osmocom-bb/include/l1ctl_proto.h"
-
-#define GSM_L2_LENGTH 256
-#define GSM_L2_HEADROOM 32
-
-static int l1if_recv(struct osmo_l1l2_if *l1l2if, struct msgb *msg);
-static int layer2_close(struct osmo_l1l2_if *l1l2if);
-
-static int layer2_read(struct osmo_fd *fd)
-{
- struct msgb *msg;
- u_int16_t len;
- int rc;
-
- msg = msgb_alloc_headroom(GSM_L2_LENGTH+GSM_L2_HEADROOM, GSM_L2_HEADROOM, "Layer2");
- if (!msg) {
- LOGP(DL1C, LOGL_ERROR, "Failed to allocate msg.\n");
- return -ENOMEM;
- }
-
- rc = read(fd->fd, &len, sizeof(len));
- if (rc < sizeof(len)) {
- fprintf(stderr, "Layer2 socket failed\n");
- msgb_free(msg);
- if (rc >= 0)
- rc = -EIO;
- layer2_close((struct osmo_l1l2_if *) fd->data);
- return rc;
- }
-
- len = ntohs(len);
- if (len > GSM_L2_LENGTH) {
- LOGP(DL1C, LOGL_ERROR, "Length is too big: %u\n", len);
- msgb_free(msg);
- return -EINVAL;
- }
-
-
- msg->l1h = msgb_put(msg, len);
- rc = read(fd->fd, msg->l1h, msgb_l1len(msg));
- if (rc != msgb_l1len(msg)) {
- LOGP(DL1C, LOGL_ERROR, "Can not read data: len=%d rc=%d "
- "errno=%d\n", len, rc, errno);
- msgb_free(msg);
- return rc;
- }
-
- l1if_recv((struct osmo_l1l2_if *) fd->data, msg);
-
- return 0;
-}
-
-static int layer2_write(struct osmo_fd *fd, struct msgb *msg)
-{
- int rc;
-
- if (fd->fd <= 0)
- return -EINVAL;
-
- rc = write(fd->fd, msg->data, msg->len);
- if (rc != msg->len) {
- LOGP(DL1C, LOGL_ERROR, "Failed to write data: rc: %d\n", rc);
- return rc;
- }
-
- return 0;
-}
-
-static int layer2_open(struct osmo_l1l2_if *l1l2if, const char *socket_path)
-{
- int rc;
- struct sockaddr_un local;
-
- l1l2if->l2_wq.bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (l1l2if->l2_wq.bfd.fd < 0) {
- fprintf(stderr, "Failed to create unix domain socket.\n");
- return l1l2if->l2_wq.bfd.fd;
- }
-
- local.sun_family = AF_UNIX;
- strncpy(local.sun_path, socket_path, sizeof(local.sun_path));
- local.sun_path[sizeof(local.sun_path) - 1] = '\0';
-
- rc = connect(l1l2if->l2_wq.bfd.fd, (struct sockaddr *) &local,
- sizeof(local));
- if (rc < 0) {
- fprintf(stderr, "Failed to connect to '%s': %s\n", local.sun_path,
- strerror(errno));
- fprintf(stderr, "Please run osmocon for this socket.\n");
- close(l1l2if->l2_wq.bfd.fd);
- return rc;
- }
-
- osmo_wqueue_init(&l1l2if->l2_wq, 100);
- l1l2if->l2_wq.bfd.data = l1l2if;
- l1l2if->l2_wq.bfd.when = BSC_FD_READ;
- l1l2if->l2_wq.read_cb = layer2_read;
- l1l2if->l2_wq.write_cb = layer2_write;
-
- rc = osmo_fd_register(&l1l2if->l2_wq.bfd);
- if (rc != 0) {
- fprintf(stderr, "Failed to register fd.\n");
- close(l1l2if->l2_wq.bfd.fd);
- return rc;
- }
-
- return 0;
-}
-
-static int layer2_close(struct osmo_l1l2_if *l1l2if)
-{
- if (l1l2if->l2_wq.bfd.fd <= 0)
- return -EINVAL;
-
- close(l1l2if->l2_wq.bfd.fd);
- l1l2if->l2_wq.bfd.fd = -1;
- osmo_fd_unregister(&l1l2if->l2_wq.bfd);
-
- return 0;
-}
-
-static int osmo_send_l1(struct osmo_l1l2_if *l1l2if, struct msgb *msg)
+static struct msgb *osmo_l1if_alloc(uint8_t msg_type)
{
- uint16_t *len;
-
- DEBUGP(DL1C, "Sending: '%s'\n", osmo_hexdump(msg->data, msg->len));
-
- if (msg->l1h != msg->data)
- LOGP(DL1C, LOGL_ERROR, "Message L1 header != Message Data\n");
-
- /* prepend 16bit length before sending */
- len = (uint16_t *) msgb_push(msg, sizeof(*len));
- *len = htons(msg->len - sizeof(*len));
-
- if (osmo_wqueue_enqueue(&l1l2if->l2_wq, msg) != 0) {
- LOGP(DL1C, LOGL_ERROR, "Failed to enqueue msg.\n");
- msgb_free(msg);
- return -1;
- }
-
- return 0;
-}
-
-/*
- * messages to and from layer 1
- */
-
-static struct msgb *osmo_l1_alloc(uint8_t msg_type)
-{
- struct l1ctl_hdr *l1h;
- struct msgb *msg = msgb_alloc_headroom(256, 4, "osmo_l1");
+ struct l1if_hdr *l1h;
+ struct msgb *msg = msgb_alloc_headroom(256, 16, "osmo_l1if");
if (!msg) {
LOGP(DL1C, LOGL_ERROR, "Failed to allocate memory.\n");
@@ -215,12 +62,11 @@ static struct msgb *osmo_l1_alloc(uint8_t msg_type)
}
msg->l1h = msgb_put(msg, sizeof(*l1h));
- l1h = (struct l1ctl_hdr *) msg->l1h;
+ l1h = (struct l1if_hdr *) msg->l1h;
l1h->msg_type = msg_type;
return msg;
}
-
/* l1 confirms setup */
static int l1if_setup_conf(struct gsm_bts_trx *trx)
{
@@ -246,7 +92,6 @@ int l1if_setup(struct gsm_bts_trx *trx)
LOGP(DL1C, LOGL_INFO, "Setup TRX: arfcn=%d bsic=%d/%d\n",
arfcn, bsic / 8, bsic & 7);
-// Sylvain: put your code here: init trx, then call on a confirm:
l1if_setup_conf(trx);
return 0;
@@ -259,7 +104,6 @@ static int l1if_new_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type osmo_si)
switch (osmo_si) {
case SYSINFO_TYPE_1:
name = "1";
-// Sylvain: put your code here
break;
case SYSINFO_TYPE_2:
name = "2";
@@ -309,8 +153,6 @@ static int l1if_new_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type osmo_si)
LOGP(DL1C, LOGL_INFO, "Providing Sysinfo %s to L1\n",
name);
-// FIXME: prepare bursts and send
-// Sylvain: put your code here
return 0;
}
@@ -327,20 +169,22 @@ static int l1if_signal_cbfn(unsigned int subsys, unsigned int signal, void *hdlr
return 0;
}
-static int l1if_reset_cnf(struct bbl1_hdl *bbl1h, struct msgb *msg, enum baseband_role bb_role)
+static int l1if_reset_cnf(struct osmo_l1ctl *l1ctl, struct msgb *msg)
{
- struct gsm_bts_trx *trx = bbl1h->trx;
+ enum baseband_role bb_role = l1ctl->bb_role;
+ struct osmo_l1_if *l1if = l1ctl->l1_if;
+ struct gsm_bts_trx *trx = l1if->trx;
int on = 1; // FIXME: handle failure (wrong firmware)
if (bb_role == BASEBAND_TX) {
LOGP(DL1C, LOGL_INFO, "Reset of TX baseband complete\n");
- bbl1h->reset_cnf_tx = 1;
+ l1if->reset_cnf_tx = 1;
}
if (bb_role == BASEBAND_RX) {
LOGP(DL1C, LOGL_INFO, "Reset of RX baseband complete\n");
- bbl1h->reset_cnf_rx = 1;
+ l1if->reset_cnf_rx = 1;
}
- if (!bbl1h->reset_cnf_tx || (!bbl1h->reset_cnf_rx && !tx_only)) {
+ if (!l1if->reset_cnf_tx || (!l1if->reset_cnf_rx && !tx_only)) {
LOGP(DL1C, LOGL_INFO, "Waiting for other baseband\n");
return 0;
}
@@ -365,12 +209,12 @@ static int l1if_reset_cnf(struct bbl1_hdl *bbl1h, struct msgb *msg, enum baseban
int l1if_reset(struct gsm_bts_trx *trx)
{
- struct bbl1_hdl *bbl1h = trx_bbl1_hdl(trx);
+ struct osmo_l1_if *l1if = trx_l1_if(trx);
struct msgb *msg;
struct l1ctl_reset *res;
uint8_t type = L1CTL_RES_T_FULL;
- msg = osmo_l1_alloc(L1CTL_RESET_REQ);
+ msg = osmo_l1if_alloc(L1IF_RESET_REQ);
if (!msg)
return -1;
@@ -378,12 +222,12 @@ int l1if_reset(struct gsm_bts_trx *trx)
res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res));
res->type = type;
- osmo_send_l1(&bbl1h->l1l2if_tx, msg);
+ l1ctl_send(&l1if->l1ctl_tx, msg);
if (tx_only)
return 0;
- msg = osmo_l1_alloc(L1CTL_RESET_REQ);
+ msg = osmo_l1if_alloc(L1IF_RESET_REQ);
if (!msg)
return -1;
@@ -391,17 +235,16 @@ int l1if_reset(struct gsm_bts_trx *trx)
res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res));
res->type = type;
- osmo_send_l1(&bbl1h->l1l2if_rx, msg);
+ l1ctl_send(&l1if->l1ctl_rx, msg);
return 0;
}
/* Receive incoming data from L1 using L1CTL format */
-static int l1if_recv(struct osmo_l1l2_if *l1l2if, struct msgb *msg)
+int l1if_recv(struct osmo_l1ctl *l1ctl, struct msgb *msg)
{
- struct bbl1_hdl *bbl1h = l1l2if->bbl1h;
- int rc = 0;
- struct l1ctl_hdr *l1h;
+ int rc = -EINVAL;
+ struct l1if_hdr *l1h;
struct l1ctl_info_dl *dl;
if (msgb_l2len(msg) < sizeof(*dl)) {
@@ -411,60 +254,15 @@ static int l1if_recv(struct osmo_l1l2_if *l1l2if, struct msgb *msg)
return -1;
}
- l1h = (struct l1ctl_hdr *) msg->l1h;
-
- /* move the l1 header pointer to point _BEHIND_ l1ctl_hdr,
- as the l1ctl header is of no interest to subsequent code */
+ l1h = (struct l1if_hdr *) msg->l1h;
msg->l1h = l1h->data;
switch (l1h->msg_type) {
- case L1CTL_RESET_IND:
- case L1CTL_RESET_CONF:
- rc = l1if_reset_cnf(bbl1h, msg, l1l2if->bb_role);
- msgb_free(msg);
- break;
-#if 0
- case L1CTL_FBSB_CONF:
- rc = rx_l1_fbsb_conf(ms, msg);
- msgb_free(msg);
- break;
- case L1CTL_DATA_IND:
- rc = rx_ph_data_ind(ms, msg);
- break;
- case L1CTL_DATA_CONF:
- rc = rx_ph_data_conf(ms, msg);
- break;
- case L1CTL_PM_CONF:
- rc = rx_l1_pm_conf(ms, msg);
- if (l1h->flags & L1CTL_F_DONE)
- osmo_signal_dispatch(SS_L1CTL, S_L1CTL_PM_DONE, ms);
+ case L1IF_RESET_IND:
+ case L1IF_RESET_CNF:
+ rc = l1if_reset_cnf(l1ctl, msg);
msgb_free(msg);
break;
- case L1CTL_RACH_CONF:
- rc = rx_l1_rach_conf(ms, msg);
- break;
- case L1CTL_CCCH_MODE_CONF:
- rc = rx_l1_ccch_mode_conf(ms, msg);
- msgb_free(msg);
- break;
- case L1CTL_TCH_MODE_CONF:
- rc = rx_l1_tch_mode_conf(ms, msg);
- msgb_free(msg);
- break;
- case L1CTL_SIM_CONF:
- rc = rx_l1_sim_conf(ms, msg);
- break;
- case L1CTL_NEIGH_PM_IND:
- rc = rx_l1_neigh_pm_ind(ms, msg);
- msgb_free(msg);
- break;
- case L1CTL_TRAFFIC_IND:
- rc = rx_l1_traffic_ind(ms, msg);
- break;
- case L1CTL_TRAFFIC_CONF:
- msgb_free(msg);
- break;
-#endif
default:
LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type);
msgb_free(msg);
@@ -476,38 +274,38 @@ static int l1if_recv(struct osmo_l1l2_if *l1l2if, struct msgb *msg)
int l1if_open(struct gsm_bts_trx *trx, const char *socket_path)
{
- struct bbl1_hdl *bbl1h;
+ struct osmo_l1_if *l1if;
char pathname[128];
int rc;
osmo_signal_register_handler(SS_GLOBAL, l1if_signal_cbfn, NULL);
- bbl1h = talloc_zero(tall_bts_ctx, struct bbl1_hdl);
- if (!bbl1h)
+ l1if = talloc_zero(tall_bts_ctx, struct osmo_l1_if);
+ if (!l1if)
return -ENOMEM;
- bbl1h->trx = trx;
- bbl1h->l1l2if_tx.bb_role = BASEBAND_TX;
- bbl1h->l1l2if_tx.bbl1h = bbl1h;
+ l1if->trx = trx;
+ l1if->l1ctl_tx.bb_role = BASEBAND_TX;
+ l1if->l1ctl_tx.l1_if = l1if;
sprintf(pathname, "%s.tx", socket_path);
LOGP(DL1C, LOGL_INFO, "Open connection to TX baseband.\n");
- rc = layer2_open(&bbl1h->l1l2if_tx, pathname);
+ rc = l1socket_open(&l1if->l1ctl_tx, pathname);
if (rc) {
- talloc_free(bbl1h);
+ talloc_free(l1if);
return rc;
}
if (!tx_only) {
- bbl1h->l1l2if_rx.bb_role = BASEBAND_RX;
- bbl1h->l1l2if_rx.bbl1h = bbl1h;
+ l1if->l1ctl_rx.bb_role = BASEBAND_RX;
+ l1if->l1ctl_rx.l1_if = l1if;
sprintf(pathname, "%s.rx", socket_path);
LOGP(DL1C, LOGL_INFO, "Open connection to RX baseband.\n");
- rc = layer2_open(&bbl1h->l1l2if_rx, pathname);
+ rc = l1socket_open(&l1if->l1ctl_rx, pathname);
if (rc) {
- layer2_close(&bbl1h->l1l2if_tx);
- talloc_free(bbl1h);
+ l1socket_close(&l1if->l1ctl_tx);
+ talloc_free(l1if);
return rc;
}
}
- trx->role_bts.l1h = bbl1h;
+ trx->role_bts.l1h = l1if;
trx->nominal_power = 23;
return 0;
@@ -515,11 +313,12 @@ int l1if_open(struct gsm_bts_trx *trx, const char *socket_path)
int l1if_close(struct gsm_bts_trx *trx)
{
- struct bbl1_hdl *bbl1h = trx_bbl1_hdl(trx);
+ struct osmo_l1_if *l1if = trx_l1_if(trx);
- layer2_close(&bbl1h->l1l2if_tx);
- layer2_close(&bbl1h->l1l2if_rx);
- talloc_free(bbl1h);
+ l1socket_close(&l1if->l1ctl_tx);
+ l1socket_close(&l1if->l1ctl_rx);
+ talloc_free(l1if);
osmo_signal_unregister_handler(SS_GLOBAL, l1if_signal_cbfn, NULL);
return 0;
}
+
diff --git a/src/osmo-bts-bb/l1_if.h b/src/osmo-bts-bb/l1_if.h
index ce97ba42..bdd33bcc 100644
--- a/src/osmo-bts-bb/l1_if.h
+++ b/src/osmo-bts-bb/l1_if.h
@@ -1,30 +1,31 @@
-#ifndef _BB_L1_H
-#define _BB_L1_H
-
-extern uint16_t ref_arfcn;
-
-#include <osmocom/core/write_queue.h>
-
-enum baseband_role {
- BASEBAND_TX,
- BASEBAND_RX,
+#ifndef _BB_L1_IF_H
+#define _BB_L1_IF_H
+
+enum l1if_prim {
+ L1IF_RESET_REQ,
+ L1IF_RESET_IND,
+ L1IF_RESET_CNF,
+ L1IF_SETUP_REQ,
+ L1IF_SETUP_CNF,
+ L1IF_BCCH_REQ,
+ L1IF_RACH_IND,
};
-struct osmo_l1l2_if {
-
- enum baseband_role bb_role;
- struct bbl1_hdl *bbl1h;
- struct osmo_wqueue l2_wq;
-};
+struct l1if_hdr {
+ uint8_t msg_type;
+ uint8_t data[0];
+} __attribute__((packed));
-struct bbl1_hdl {
+struct osmo_l1_if {
struct gsm_bts_trx *trx;
- struct osmo_l1l2_if l1l2if_tx, l1l2if_rx;
+ struct osmo_l1ctl l1ctl_tx, l1ctl_rx;
int reset_cnf_tx, reset_cnf_rx;
};
int l1if_setup(struct gsm_bts_trx *trx);
+int l1if_reset(struct gsm_bts_trx *trx);
+int l1if_recv(struct osmo_l1ctl *l1ctl, struct msgb *msg);
int l1if_open(struct gsm_bts_trx *trx, const char *socket_path);
int l1if_close(struct gsm_bts_trx *trx);
-#endif /* _BB_L1_H */
+#endif /* _BB_L1_IF_H */
diff --git a/src/osmo-bts-bb/l1ctl.c b/src/osmo-bts-bb/l1ctl.c
new file mode 100644
index 00000000..e180fdd8
--- /dev/null
+++ b/src/osmo-bts-bb/l1ctl.c
@@ -0,0 +1,305 @@
+/* Interface to layer 1 of baseband */
+
+/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <arpa/inet.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+//#include <osmocom/core/select.h>
+//#include <osmocom/core/timer.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/lapdm.h>
+
+#include <osmo-bts/logging.h>
+//#include <osmo-bts/bts.h>
+//#include <osmo-bts/oml.h>
+//#include <osmo-bts/gsm_data.h>
+//#include <osmo-bts/signal.h>
+
+#include "l1ctl.h"
+#include "l1_if.h"
+
+/*
+ * socket communication with baseband
+ */
+
+#define GSM_L2_LENGTH 256
+#define GSM_L2_HEADROOM 32
+
+static int l1ctl_recv(struct osmo_l1ctl *l1ctl, struct msgb *msg);
+
+static int l1socket_read(struct osmo_fd *fd)
+{
+ struct msgb *msg;
+ u_int16_t len;
+ int rc;
+
+ msg = msgb_alloc_headroom(GSM_L2_LENGTH+GSM_L2_HEADROOM, GSM_L2_HEADROOM, "Layer2");
+ if (!msg) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to allocate msg.\n");
+ return -ENOMEM;
+ }
+
+ rc = read(fd->fd, &len, sizeof(len));
+ if (rc < sizeof(len)) {
+ fprintf(stderr, "Layer2 socket failed\n");
+ msgb_free(msg);
+ if (rc >= 0)
+ rc = -EIO;
+ l1socket_close((struct osmo_l1ctl *) fd->data);
+ return rc;
+ }
+
+ len = ntohs(len);
+ if (len > GSM_L2_LENGTH) {
+ LOGP(DL1C, LOGL_ERROR, "Length is too big: %u\n", len);
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+
+ msg->l1h = msgb_put(msg, len);
+ rc = read(fd->fd, msg->l1h, msgb_l1len(msg));
+ if (rc != msgb_l1len(msg)) {
+ LOGP(DL1C, LOGL_ERROR, "Can not read data: len=%d rc=%d "
+ "errno=%d\n", len, rc, errno);
+ msgb_free(msg);
+ return rc;
+ }
+
+ l1ctl_recv((struct osmo_l1ctl *) fd->data, msg);
+
+ return 0;
+}
+
+static int l1socket_write(struct osmo_fd *fd, struct msgb *msg)
+{
+ int rc;
+
+ if (fd->fd <= 0)
+ return -EINVAL;
+
+ rc = write(fd->fd, msg->data, msg->len);
+ if (rc != msg->len) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to write data: rc: %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+int l1socket_open(struct osmo_l1ctl *l1ctl, const char *socket_path)
+{
+ int rc;
+ struct sockaddr_un local;
+
+ l1ctl->l2_wq.bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (l1ctl->l2_wq.bfd.fd < 0) {
+ fprintf(stderr, "Failed to create unix domain socket.\n");
+ return l1ctl->l2_wq.bfd.fd;
+ }
+
+ local.sun_family = AF_UNIX;
+ strncpy(local.sun_path, socket_path, sizeof(local.sun_path));
+ local.sun_path[sizeof(local.sun_path) - 1] = '\0';
+
+ rc = connect(l1ctl->l2_wq.bfd.fd, (struct sockaddr *) &local,
+ sizeof(local));
+ if (rc < 0) {
+ fprintf(stderr, "Failed to connect to '%s': %s\n", local.sun_path,
+ strerror(errno));
+ fprintf(stderr, "Please run osmocon for this socket.\n");
+ close(l1ctl->l2_wq.bfd.fd);
+ return rc;
+ }
+
+ osmo_wqueue_init(&l1ctl->l2_wq, 100);
+ l1ctl->l2_wq.bfd.data = l1ctl;
+ l1ctl->l2_wq.bfd.when = BSC_FD_READ;
+ l1ctl->l2_wq.read_cb = l1socket_read;
+ l1ctl->l2_wq.write_cb = l1socket_write;
+
+ rc = osmo_fd_register(&l1ctl->l2_wq.bfd);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to register fd.\n");
+ close(l1ctl->l2_wq.bfd.fd);
+ return rc;
+ }
+
+ return 0;
+}
+
+int l1socket_close(struct osmo_l1ctl *l1ctl)
+{
+ if (l1ctl->l2_wq.bfd.fd <= 0)
+ return -EINVAL;
+
+ close(l1ctl->l2_wq.bfd.fd);
+ l1ctl->l2_wq.bfd.fd = -1;
+ osmo_fd_unregister(&l1ctl->l2_wq.bfd);
+
+ return 0;
+}
+
+static int osmo_send_l1(struct osmo_l1ctl *l1ctl, struct msgb *msg)
+{
+ uint16_t *len;
+
+ DEBUGP(DL1C, "Sending: '%s'\n", osmo_hexdump(msg->data, msg->len));
+
+ if (msg->l1h != msg->data)
+ LOGP(DL1C, LOGL_ERROR, "Message L1 header != Message Data\n");
+
+ /* prepend 16bit length before sending */
+ len = (uint16_t *) msgb_push(msg, sizeof(*len));
+ *len = htons(msg->len - sizeof(*len));
+
+ if (osmo_wqueue_enqueue(&l1ctl->l2_wq, msg) != 0) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to enqueue msg.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * messages to and from layer 1
+ */
+
+static struct msgb *osmo_l1ctl_alloc(uint8_t msg_type)
+{
+ struct l1ctl_hdr *l1h;
+ struct msgb *msg = msgb_alloc_headroom(256, 4, "osmo_l1ctl");
+
+ if (!msg) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to allocate memory.\n");
+ return NULL;
+ }
+
+ msg->l1h = msgb_put(msg, sizeof(*l1h));
+ l1h = (struct l1ctl_hdr *) msg->l1h;
+ l1h->msg_type = msg_type;
+
+ return msg;
+}
+
+static int l1ctl_reset_req(struct osmo_l1ctl *l1ctl, struct msgb *msg, uint8_t msg_type)
+{
+ struct l1ctl_hdr *l1h;
+
+ l1h = (struct l1ctl_hdr *) msgb_push(msg, sizeof(*l1h));
+ msg->l1h = (uint8_t *) l1h;
+ l1h->msg_type = L1CTL_RESET_REQ;
+
+ osmo_send_l1(l1ctl, msg);
+
+ return 0;
+}
+
+/* got data from upper L1 interface */
+int l1ctl_send(struct osmo_l1ctl *l1ctl, struct msgb *msg)
+{
+ int rc = 0;
+ struct l1if_hdr *l1h;
+ uint8_t msg_type;
+
+ l1h = (struct l1if_hdr *) msg->l1h;
+
+ msg_type = l1h->msg_type;
+ msg->l1h = NULL;
+ msgb_pull(msg, sizeof(*l1h));
+
+ switch (msg_type) {
+ case L1IF_RESET_REQ:
+ rc = l1ctl_reset_req(l1ctl, msg, msg_type);
+ break;
+ default:
+ LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type);
+ msgb_free(msg);
+ break;
+ }
+
+ return rc;
+}
+static int l1ctl_reset_ind(struct osmo_l1ctl *l1ctl, struct msgb *msg, uint8_t msg_type)
+{
+ struct l1if_hdr *l1h;
+
+ if (msg_type == L1CTL_RESET_IND)
+ msg_type = L1IF_RESET_IND;
+ else
+ msg_type = L1IF_RESET_CNF;
+
+ l1h = (struct l1if_hdr *) msgb_push(msg, sizeof(*l1h));
+ msg->l1h = (uint8_t *) l1h;
+ l1h->msg_type = msg_type;
+
+ return l1if_recv(l1ctl, msg);
+}
+
+
+/* Receive incoming data from L1 using L1CTL format */
+static int l1ctl_recv(struct osmo_l1ctl *l1ctl, struct msgb *msg)
+{
+ int rc = 0;
+ struct l1ctl_hdr *l1h;
+ struct l1ctl_info_dl *dl;
+ uint8_t msg_type;
+
+ if (msgb_l2len(msg) < sizeof(*dl)) {
+ LOGP(DL1C, LOGL_ERROR, "Short Layer2 message: %u\n",
+ msgb_l2len(msg));
+ msgb_free(msg);
+ return -1;
+ }
+
+ l1h = (struct l1ctl_hdr *) msg->l1h;
+ msg_type = l1h->msg_type;
+ msg->l1h = NULL;
+ msgb_pull(msg, sizeof(*l1h));
+
+ switch (msg_type) {
+ case L1CTL_RESET_IND:
+ case L1CTL_RESET_CONF:
+ rc = l1ctl_reset_ind(l1ctl, msg, msg_type);
+ break;
+ default:
+ LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type);
+ msgb_free(msg);
+ break;
+ }
+
+ return rc;
+}
diff --git a/src/osmo-bts-bb/l1ctl.h b/src/osmo-bts-bb/l1ctl.h
new file mode 100644
index 00000000..b1402fb0
--- /dev/null
+++ b/src/osmo-bts-bb/l1ctl.h
@@ -0,0 +1,109 @@
+#ifndef _BB_L1CTL_H
+#define _BB_L1CTL_H
+
+#include <osmocom/core/write_queue.h>
+
+enum baseband_role {
+ BASEBAND_TX,
+ BASEBAND_RX,
+};
+
+struct osmo_l1ctl {
+
+ enum baseband_role bb_role;
+ struct osmo_l1_if *l1_if;
+ struct osmo_wqueue l2_wq;
+};
+
+int l1ctl_send(struct osmo_l1ctl *l1ctl, struct msgb *msg);
+int l1socket_open(struct osmo_l1ctl *l1ctl, const char *socket_path);
+int l1socket_close(struct osmo_l1ctl *l1ctl);
+
+/*
+ * L1CTL interface
+ */
+
+enum {
+ _L1CTL_NONE = 0,
+ L1CTL_FBSB_REQ,
+ L1CTL_FBSB_CONF,
+ L1CTL_DATA_IND,
+ L1CTL_RACH_REQ,
+ L1CTL_DM_EST_REQ,
+ L1CTL_DATA_REQ,
+ L1CTL_RESET_IND,
+ L1CTL_PM_REQ, /* power measurement */
+ L1CTL_PM_CONF, /* power measurement */
+ L1CTL_ECHO_REQ,
+ L1CTL_ECHO_CONF,
+ L1CTL_RACH_CONF,
+ L1CTL_RESET_REQ,
+ L1CTL_RESET_CONF,
+ L1CTL_DATA_CONF,
+ L1CTL_CCCH_MODE_REQ,
+ L1CTL_CCCH_MODE_CONF,
+ L1CTL_DM_REL_REQ,
+ L1CTL_PARAM_REQ,
+ L1CTL_DM_FREQ_REQ,
+ L1CTL_CRYPTO_REQ,
+ L1CTL_SIM_REQ,
+ L1CTL_SIM_CONF,
+ L1CTL_TCH_MODE_REQ,
+ L1CTL_TCH_MODE_CONF,
+ L1CTL_NEIGH_PM_REQ,
+ L1CTL_NEIGH_PM_IND,
+ L1CTL_TRAFFIC_REQ,
+ L1CTL_TRAFFIC_CONF,
+ L1CTL_TRAFFIC_IND,
+};
+/* there are no more messages in a sequence */
+#define L1CTL_F_DONE 0x01
+
+struct l1ctl_hdr {
+ uint8_t msg_type;
+ uint8_t flags;
+ uint8_t padding[2];
+ uint8_t data[0];
+} __attribute__((packed));
+
+struct l1ctl_info_dl {
+ /* 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;
+
+ uint32_t frame_nr;
+
+ uint8_t rx_level; /* 0 .. 63 in typical GSM notation (dBm+110) */
+ uint8_t snr; /* Signal/Noise Ration (dB) */
+ uint8_t num_biterr;
+ uint8_t fire_crc;
+
+ uint8_t payload[0];
+} __attribute__((packed));
+
+struct l1ctl_info_ul {
+ /* 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 padding[2];
+
+ uint8_t payload[0];
+} __attribute__((packed));
+
+enum l1ctl_reset_type {
+ L1CTL_RES_T_BOOT, /* only _IND */
+ L1CTL_RES_T_FULL,
+ L1CTL_RES_T_SCHED,
+};
+
+/* argument to L1CTL_RESET_REQ and L1CTL_RESET_IND */
+struct l1ctl_reset {
+ uint8_t type;
+ uint8_t pad[3];
+} __attribute__((packed));
+
+#endif /* _BB_L1CTL_H */
diff --git a/src/osmo-bts-bb/main.c b/src/osmo-bts-bb/main.c
index 1ae46255..2b755837 100644
--- a/src/osmo-bts-bb/main.c
+++ b/src/osmo-bts-bb/main.c
@@ -32,6 +32,7 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/vty.h>
+#include "l1ctl.h"
#include "l1_if.h"
#include <net/if.h>
@@ -49,6 +50,7 @@
char *debugs = "DL1C:DLLAPDM:DABIS:DOML:DRSL:DSUM";
int debug_set = 0;
int level_set = 0;
+uint16_t ref_arfcn = 0;
int ref_set = 0;
static char *layer2_socket_path = "/tmp/osmocom_l2";
int tx_only = 0;
@@ -99,7 +101,7 @@ struct ipabis_link *link_init(struct gsm_bts *bts, uint32_t bsc_ip)
int rc;
link->bts = bts;
- bts->oml_link = link;
+ bts->oml_link = (void *)link;
rc = abis_open(link, bsc_ip);
if (rc < 0)
diff --git a/src/osmo-bts-bb/oml.c b/src/osmo-bts-bb/oml.c
index 32f7e1c9..c812a3a7 100644
--- a/src/osmo-bts-bb/oml.c
+++ b/src/osmo-bts-bb/oml.c
@@ -27,6 +27,7 @@
#include <osmo-bts/logging.h>
#include <osmo-bts/oml.h>
+#include "l1ctl.h"
#include "l1_if.h"
int gsm_abis_mo_check_attr(const struct gsm_abis_mo *mo, uint8_t *attr_ids,