diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2011-08-20 10:16:59 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2011-10-03 13:01:00 +0200 |
commit | 55e7a2e87dc79a936e0993e57f411e33299643cf (patch) | |
tree | 72b74c0a4d023001a4cf0a068cbf7ca17ef11d4b | |
parent | e9871f0d722ce135b00b6afe29aea975f5753df3 (diff) |
[WIP] Split of L1CTL and L1IF
-rw-r--r-- | include/osmo-bts/gsm_data.h | 4 | ||||
-rw-r--r-- | src/osmo-bts-bb/Makefile.am | 2 | ||||
-rw-r--r-- | src/osmo-bts-bb/l1_if.c | 289 | ||||
-rw-r--r-- | src/osmo-bts-bb/l1_if.h | 39 | ||||
-rw-r--r-- | src/osmo-bts-bb/l1ctl.c | 305 | ||||
-rw-r--r-- | src/osmo-bts-bb/l1ctl.h | 109 | ||||
-rw-r--r-- | src/osmo-bts-bb/main.c | 4 | ||||
-rw-r--r-- | src/osmo-bts-bb/oml.c | 1 |
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, |