diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2020-10-29 06:40:58 +0700 |
---|---|---|
committer | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2020-11-05 03:39:50 +0700 |
commit | ef1671c6ed3362958b95a7074c8d2242b756c6cf (patch) | |
tree | 1c80d546d39abcee29b0924e251a58b451c20369 /src/osmo-bts-litecell15 | |
parent | 44d25af9cd1288feda867ce60c636d9334521c4f (diff) |
osmo-bts-lc15: use consistent name for containing directory
The binary is called 'osmo-bts-lc15', while the containing folder
is named 'osmo-bts-litecell15'. This inconsistency complicates
automatic generation of the XML VTY reference - fix it.
Change-Id: I55c073fbd01aee42871101401d76d87e7c91832e
Related: SYS#4937, OS#3036
Diffstat (limited to 'src/osmo-bts-litecell15')
43 files changed, 0 insertions, 12145 deletions
diff --git a/src/osmo-bts-litecell15/Makefile.am b/src/osmo-bts-litecell15/Makefile.am deleted file mode 100644 index bb68efaf..00000000 --- a/src/osmo-bts-litecell15/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -AUTOMAKE_OPTIONS = subdir-objects - -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include $(LITECELL15_INCDIR) -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBGPS_CFLAGS) $(LIBSYSTEMD_CFLAGS) -COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) - -AM_CFLAGS += -DENABLE_LC15BTS - -EXTRA_DIST = misc/lc15bts_mgr.h misc/lc15bts_misc.h misc/lc15bts_par.h misc/lc15bts_led.h \ - misc/lc15bts_temp.h misc/lc15bts_power.h misc/lc15bts_clock.h \ - misc/lc15bts_bid.h misc/lc15bts_nl.h misc/lc15bts_bts.h misc/lc15bts_swd.h \ - hw_misc.h l1_if.h l1_transp.h lc15bts.h utils.h - -bin_PROGRAMS = osmo-bts-lc15 lc15bts-mgr lc15bts-util - -COMMON_SOURCES = main.c lc15bts.c l1_if.c oml.c lc15bts_vty.c tch.c hw_misc.c calib_file.c \ - utils.c misc/lc15bts_par.c misc/lc15bts_bid.c - -osmo_bts_lc15_SOURCES = $(COMMON_SOURCES) l1_transp_hw.c -osmo_bts_lc15_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) - -lc15bts_mgr_SOURCES = \ - misc/lc15bts_mgr.c misc/lc15bts_misc.c \ - misc/lc15bts_par.c misc/lc15bts_nl.c \ - misc/lc15bts_temp.c misc/lc15bts_power.c \ - misc/lc15bts_clock.c misc/lc15bts_bid.c \ - misc/lc15bts_mgr_vty.c \ - misc/lc15bts_mgr_nl.c \ - misc/lc15bts_mgr_temp.c \ - misc/lc15bts_mgr_calib.c \ - misc/lc15bts_led.c \ - misc/lc15bts_bts.c \ - misc/lc15bts_swd.c - -lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBSYSTEMD_LIBS) $(COMMON_LDADD) - -lc15bts_util_SOURCES = misc/lc15bts_util.c misc/lc15bts_par.c -lc15bts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-litecell15/calib_file.c b/src/osmo-bts-litecell15/calib_file.c deleted file mode 100644 index 2641552f..00000000 --- a/src/osmo-bts-litecell15/calib_file.c +++ /dev/null @@ -1,456 +0,0 @@ -/* NuRAN Wireless Litecell 1.5 BTS L1 calibration file routines*/ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org> - * - * Based on sysmoBTS: - * (C) 2012 by Harald Welte <laforge@gnumonks.org> - * - * 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 <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <fcntl.h> -#include <limits.h> -#include <errno.h> - -#include <osmocom/core/utils.h> - -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/logging.h> - -#include <nrw/litecell15/litecell15.h> -#include <nrw/litecell15/gsml1const.h> - -#include "l1_if.h" -#include "lc15bts.h" -#include "utils.h" - -/* Maximum calibration data chunk size */ -#define MAX_CALIB_TBL_SIZE 65536 -/* Calibration header version */ -#define CALIB_HDR_V1 0x01 - -struct calib_file_desc { - const char *fname; - int rx; - int trx; - int rxpath; -}; - -static const struct calib_file_desc calib_files[] = { - { - .fname = "calib_rx0a.conf", - .rx = 1, - .trx = 0, - .rxpath = 0, - }, { - .fname = "calib_rx0b.conf", - .rx = 1, - .trx = 0, - .rxpath = 1, - }, { - .fname = "calib_rx1a.conf", - .rx = 1, - .trx = 1, - .rxpath = 0, - }, { - .fname = "calib_rx1b.conf", - .rx = 1, - .trx = 1, - .rxpath = 1, - }, { - .fname = "calib_tx0.conf", - .rx = 0, - .trx = 0, - }, { - .fname = "calib_tx1.conf", - .rx = 0, - .trx = 1, - }, -}; - -struct calTbl_t -{ - union - { - struct - { - uint8_t u8Version; /* Header version (1) */ - uint8_t u8Parity; /* Parity byte (xor) */ - uint8_t u8Type; /* Table type (0:TX Downlink, 1:RX-A Uplink, 2:RX-B Uplink) */ - uint8_t u8Band; /* GSM Band (0:GSM-850, 1:EGSM-900, 2:DCS-1800, 3:PCS-1900) */ - uint32_t u32Len; /* Table length in bytes including the header */ - struct - { - uint32_t u32DescOfst; /* Description section offset */ - uint32_t u32DateOfst; /* Date section offset */ - uint32_t u32StationOfst; /* Calibration test station section offset */ - uint32_t u32FpgaFwVerOfst; /* Calibration FPGA firmware version section offset */ - uint32_t u32DspFwVerOfst; /* Calibration DSP firmware section offset */ - uint32_t u32DataOfst; /* Calibration data section offset */ - } toc; - } v1; - } hdr; - - uint8_t u8RawData[MAX_CALIB_TBL_SIZE - 32]; -}; - - -static int calib_file_send(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc); -static int calib_verify(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc); - -/* determine next calibration file index based on supported bands */ -static int get_next_calib_file_idx(struct lc15l1_hdl *fl1h, int last_idx) -{ - struct phy_link *plink = fl1h->phy_inst->phy_link; - int i; - - for (i = last_idx+1; i < ARRAY_SIZE(calib_files); i++) { - if (calib_files[i].trx == plink->num) - return i; - } - return -1; -} - -static int calib_file_open(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc) -{ - struct calib_send_state *st = &fl1h->st; - char *calib_path = fl1h->phy_inst->u.lc15.calib_path; - char fname[PATH_MAX]; - - if (st->fp) { - LOGP(DL1C, LOGL_NOTICE, "L1 calibration file was left opened !!\n"); - fclose(st->fp); - st->fp = NULL; - } - - fname[0] = '\0'; - snprintf(fname, sizeof(fname)-1, "%s/%s", calib_path, desc->fname); - fname[sizeof(fname)-1] = '\0'; - - st->fp = fopen(fname, "rb"); - if (!st->fp) { - LOGP(DL1C, LOGL_ERROR, - "Failed to open '%s' for calibration data.\n", fname); - return -1; - } - return 0; -} - -static int calib_file_close(struct lc15l1_hdl *fl1h) -{ - struct calib_send_state *st = &fl1h->st; - - if (st->fp) { - fclose(st->fp); - st->fp = NULL; - } - return 0; -} - -/* iteratively download the calibration data into the L1 */ - -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data); - -/* send a chunk of calibration tabledata for a single specified file */ -static int calib_file_send_next_chunk(struct lc15l1_hdl *fl1h) -{ - struct calib_send_state *st = &fl1h->st; - Litecell15_Prim_t *prim; - struct msgb *msg; - size_t n; - - msg = sysp_msgb_alloc(); - prim = msgb_sysprim(msg); - - prim->id = Litecell15_PrimId_SetCalibTblReq; - prim->u.setCalibTblReq.offset = (uint32_t)ftell(st->fp); - n = fread(prim->u.setCalibTblReq.u8Data, 1, - sizeof(prim->u.setCalibTblReq.u8Data), st->fp); - prim->u.setCalibTblReq.length = n; - - - if (n == 0) { - /* The table data has been completely sent and acknowledged */ - LOGP(DL1C, LOGL_NOTICE, "L1 calibration table %s loaded\n", - calib_files[st->last_file_idx].fname); - - calib_file_close(fl1h); - - msgb_free(msg); - - /* Send the next one if any */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) { - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - return l1if_req_compl(fl1h, msg, calib_send_compl_cb, NULL); -} - -/* send the calibration table for a single specified file */ -static int calib_file_send(struct lc15l1_hdl *fl1h, - const struct calib_file_desc *desc) -{ - struct calib_send_state *st = &fl1h->st; - int rc; - - rc = calib_file_open(fl1h, desc); - if (rc < 0) { - /* still, we'd like to continue trying to load - * calibration for all other bands */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - rc = calib_verify(fl1h, desc); - if ( rc < 0 ) { - LOGP(DL1C, LOGL_ERROR, "Verify L1 calibration table %s -> failed (%d)\n", desc->fname, rc); - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - - if (st->last_file_idx >= 0) - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - return 0; - - } - - LOGP(DL1C, LOGL_INFO, "Verify L1 calibration table %s -> done\n", desc->fname); - - return calib_file_send_next_chunk(fl1h); -} - -/* completion callback after every SetCalibTbl is confirmed */ -static int calib_send_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct calib_send_state *st = &fl1h->st; - Litecell15_Prim_t *prim = msgb_sysprim(l1_msg); - - if (prim->u.setCalibTblCnf.status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "L1 rejected calibration table\n"); - - msgb_free(l1_msg); - - calib_file_close(fl1h); - - /* Skip this one and try the next one */ - st->last_file_idx = get_next_calib_file_idx(fl1h, st->last_file_idx); - if (st->last_file_idx >= 0) { - return calib_file_send(fl1h, - &calib_files[st->last_file_idx]); - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table loading complete!\n"); - return 0; - } - - msgb_free(l1_msg); - - /* Keep sending the calibration file data */ - return calib_file_send_next_chunk(fl1h); -} - -int calib_load(struct lc15l1_hdl *fl1h) -{ - int rc; - struct calib_send_state *st = &fl1h->st; - char *calib_path = fl1h->phy_inst->u.lc15.calib_path; - - if (!calib_path) { - LOGP(DL1C, LOGL_ERROR, "Calibration file path not specified\n"); - return -1; - } - - rc = get_next_calib_file_idx(fl1h, -1); - if (rc < 0) { - return -1; - } - st->last_file_idx = rc; - - return calib_file_send(fl1h, &calib_files[st->last_file_idx]); -} - - -static int calib_verify(struct lc15l1_hdl *fl1h, const struct calib_file_desc *desc) -{ - int rc, sz; - struct calib_send_state *st = &fl1h->st; - struct phy_link *plink = fl1h->phy_inst->phy_link; - char *rbuf; - struct calTbl_t *calTbl; - char calChkSum ; - - /* calculate file size in bytes */ - fseek(st->fp, 0L, SEEK_END); - sz = ftell(st->fp); - - /* rewind read pointer */ - fseek(st->fp, 0L, SEEK_SET); - - /* read file */ - rbuf = (char *) malloc( sizeof(char) * sz ); - - rc = fread(rbuf, 1, sizeof(char) * sz, st->fp); - if ( rc != sz) { - - LOGP(DL1C, LOGL_ERROR, "%s reading error\n", desc->fname); - free(rbuf); - - /* close file */ - rc = calib_file_close(fl1h); - if (rc < 0 ) { - LOGP(DL1C, LOGL_ERROR, "%s can not close\n", desc->fname); - return rc; - } - - return -2; - } - - calTbl = (struct calTbl_t*) rbuf; - /* calculate file checksum */ - calChkSum = 0; - while ( sz-- ) { - calChkSum ^= rbuf[sz]; - } - - /* validate Tx calibration parity */ - if ( calChkSum ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid checksum %x.\n", desc->fname, calChkSum); - return -4; - } - - /* validate Tx calibration header */ - if ( calTbl->hdr.v1.u8Version != CALIB_HDR_V1 ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid header version %u.\n", desc->fname, calTbl->hdr.v1.u8Version); - return -5; - } - - /* validate calibration description */ - if ( calTbl->hdr.v1.toc.u32DescOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration description offset.\n", desc->fname); - return -6; - } - - /* validate calibration date */ - if ( calTbl->hdr.v1.toc.u32DateOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration date offset.\n", desc->fname); - return -7; - } - - LOGP(DL1C, LOGL_INFO, "L1 calibration table %s created on %s\n", - desc->fname, - calTbl->u8RawData + calTbl->hdr.v1.toc.u32DateOfst); - - /* validate calibration station */ - if ( calTbl->hdr.v1.toc.u32StationOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration station ID offset.\n", desc->fname); - return -8; - } - - /* validate FPGA FW version */ - if ( calTbl->hdr.v1.toc.u32FpgaFwVerOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid FPGA FW version offset.\n", desc->fname); - return -9; - } - - /* validate DSP FW version */ - if ( calTbl->hdr.v1.toc.u32DspFwVerOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid DSP FW version offset.\n", desc->fname); - return -10; - } - - /* validate Tx calibration data offset */ - if ( calTbl->hdr.v1.toc.u32DataOfst == 0xFFFFFFFF ) { - LOGP(DL1C, LOGL_ERROR, "%s has invalid calibration data offset.\n", desc->fname); - return -11; - } - - if ( !desc->rx ) { - - /* parse min/max Tx power */ - fl1h->phy_inst->u.lc15.minTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (5 << 2)]; - fl1h->phy_inst->u.lc15.maxTxPower = calTbl->u8RawData[calTbl->hdr.v1.toc.u32DataOfst + (6 << 2)]; - - /* override nominal Tx power of given TRX if needed */ - if ( fl1h->phy_inst->trx->nominal_power > fl1h->phy_inst->u.lc15.maxTxPower) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n", - plink->num, - fl1h->phy_inst->u.lc15.maxTxPower, - fl1h->phy_inst->trx->nominal_power); - - fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.lc15.maxTxPower; - } - - if ( fl1h->phy_inst->trx->nominal_power < fl1h->phy_inst->u.lc15.minTxPower) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u nominal Tx power to %d dBm (%d)\n", - plink->num, - fl1h->phy_inst->u.lc15.minTxPower, - fl1h->phy_inst->trx->nominal_power); - - fl1h->phy_inst->trx->nominal_power = fl1h->phy_inst->u.lc15.minTxPower; - } - - if ( fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm > to_mdB(fl1h->phy_inst->u.lc15.maxTxPower) ) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n", - plink->num, - to_mdB(fl1h->phy_inst->u.lc15.maxTxPower), - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm); - - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.lc15.maxTxPower); - } - - if ( fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm < to_mdB(fl1h->phy_inst->u.lc15.minTxPower) ) { - LOGP(DL1C, LOGL_INFO, "Set TRX %u Tx power parameter to %d dBm (%d)\n", - plink->num, - to_mdB(fl1h->phy_inst->u.lc15.minTxPower), - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm); - - fl1h->phy_inst->trx->power_params.trx_p_max_out_mdBm = to_mdB(fl1h->phy_inst->u.lc15.minTxPower); - } - - LOGP(DL1C, LOGL_DEBUG, "%s: minTxPower=%d, maxTxPower=%d\n", - desc->fname, - fl1h->phy_inst->u.lc15.minTxPower, - fl1h->phy_inst->u.lc15.maxTxPower ); - } - - /* rewind read pointer for subsequence tasks */ - fseek(st->fp, 0L, SEEK_SET); - free(rbuf); - - return 0; -} - diff --git a/src/osmo-bts-litecell15/hw_misc.c b/src/osmo-bts-litecell15/hw_misc.c deleted file mode 100644 index 9f070bba..00000000 --- a/src/osmo-bts-litecell15/hw_misc.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Misc HW routines for NuRAN Wireless Litecell 1.5 BTS */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * (C) 2012 by Harald Welte <laforge@gnumonks.org> - * - * 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 <limits.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> - -#include <sys/types.h> -#include <sys/stat.h> - -#include <osmocom/core/utils.h> - -#include "hw_misc.h" - -int lc15bts_led_set(enum lc15bts_led_color c) -{ - int fd, rc; - uint8_t cmd[2]; - - switch (c) { - case LED_OFF: - cmd[0] = 0; - cmd[1] = 0; - break; - case LED_RED: - cmd[0] = 1; - cmd[1] = 0; - break; - case LED_GREEN: - cmd[0] = 0; - cmd[1] = 1; - break; - case LED_ORANGE: - cmd[0] = 1; - cmd[1] = 1; - break; - default: - return -EINVAL; - } - - fd = open("/var/lc15/leds/led0/brightness", O_WRONLY); - if (fd < 0) - return -ENODEV; - - rc = write(fd, cmd[0] ? "1" : "0", 2); - if (rc != 2) { - close(fd); - return -1; - } - close(fd); - - fd = open("/var/lc15/leds/led1/brightness", O_WRONLY); - if (fd < 0) - return -ENODEV; - - rc = write(fd, cmd[1] ? "1" : "0", 2); - if (rc != 2) { - close(fd); - return -1; - } - close(fd); - return 0; -} diff --git a/src/osmo-bts-litecell15/hw_misc.h b/src/osmo-bts-litecell15/hw_misc.h deleted file mode 100644 index 59ed04b7..00000000 --- a/src/osmo-bts-litecell15/hw_misc.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _HW_MISC_H -#define _HW_MISC_H - -enum lc15bts_led_color { - LED_OFF, - LED_RED, - LED_GREEN, - LED_ORANGE, -}; - -int lc15bts_led_set(enum lc15bts_led_color c); - -#endif diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c deleted file mode 100644 index b7c24c08..00000000 --- a/src/osmo-bts-litecell15/l1_if.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* Interface handler for NuRAN Wireless Litecell 1.5 L1 */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org> - * - * Based on sysmoBTS: - * (C) 2011-2014 by Harald Welte <laforge@gnumonks.org> - * (C) 2014 by Holger Hans Peter Freyther - * - * 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 <sys/types.h> -#include <sys/stat.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/rsl.h> -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/phy_link.h> -#include <osmo-bts/paging.h> -#include <osmo-bts/measurement.h> -#include <osmo-bts/pcu_if.h> -#include <osmo-bts/handover.h> -#include <osmo-bts/bts_model.h> -#include <osmo-bts/l1sap.h> -#include <osmo-bts/msg_utils.h> -#include <osmo-bts/dtx_dl_amr_fsm.h> -#include <osmo-bts/nm_common_fsm.h> - -#include <nrw/litecell15/litecell15.h> -#include <nrw/litecell15/gsml1prim.h> -#include <nrw/litecell15/gsml1const.h> -#include <nrw/litecell15/gsml1types.h> - -#include "lc15bts.h" -#include "l1_if.h" -#include "l1_transp.h" -#include "hw_misc.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_bid.h" -#include "utils.h" - -extern unsigned int dsp_trace; - -struct wait_l1_conf { - struct llist_head list; /* internal linked list */ - struct osmo_timer_list timer; /* timer for L1 timeout */ - unsigned int conf_prim_id; /* primitive we expect in response */ - HANDLE conf_hLayer3; /* layer 3 handle we expect in response */ - unsigned int is_sys_prim; /* is this a system (1) or L1 (0) primitive */ - l1if_compl_cb *cb; - void *cb_data; -}; - -static void release_wlc(struct wait_l1_conf *wlc) -{ - osmo_timer_del(&wlc->timer); - talloc_free(wlc); -} - -static void l1if_req_timeout(void *data) -{ - struct wait_l1_conf *wlc = data; - - if (wlc->is_sys_prim) - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for SYS primitive %s\n", - get_value_string(lc15bts_sysprim_names, wlc->conf_prim_id)); - else - LOGP(DL1C, LOGL_FATAL, "Timeout waiting for L1 primitive %s\n", - get_value_string(lc15bts_l1prim_names, wlc->conf_prim_id)); - exit(23); -} - -static HANDLE l1p_get_hLayer3(GsmL1_Prim_t *prim) -{ - switch (prim->id) { - case GsmL1_PrimId_MphInitReq: - return prim->u.mphInitReq.hLayer3; - case GsmL1_PrimId_MphCloseReq: - return prim->u.mphCloseReq.hLayer3; - case GsmL1_PrimId_MphConnectReq: - return prim->u.mphConnectReq.hLayer3; - case GsmL1_PrimId_MphDisconnectReq: - return prim->u.mphDisconnectReq.hLayer3; - case GsmL1_PrimId_MphActivateReq: - return prim->u.mphActivateReq.hLayer3; - case GsmL1_PrimId_MphDeactivateReq: - return prim->u.mphDeactivateReq.hLayer3; - case GsmL1_PrimId_MphConfigReq: - return prim->u.mphConfigReq.hLayer3; - case GsmL1_PrimId_MphMeasureReq: - return prim->u.mphMeasureReq.hLayer3; - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.hLayer3; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.hLayer3; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.hLayer3; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.hLayer3; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.hLayer3; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.hLayer3; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.hLayer3; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.hLayer3; - case GsmL1_PrimId_MphTimeInd: - case GsmL1_PrimId_MphSyncInd: - case GsmL1_PrimId_PhEmptyFrameReq: - case GsmL1_PrimId_PhDataReq: - case GsmL1_PrimId_PhConnectInd: - case GsmL1_PrimId_PhReadyToSendInd: - case GsmL1_PrimId_PhDataInd: - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", prim->id); - break; - } - return 0; -} - -static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - int is_system_prim, l1if_compl_cb *cb, void *data) -{ - struct wait_l1_conf *wlc; - struct osmo_wqueue *wqueue; - unsigned int timeout_secs; - - /* allocate new wsc and store reference to mutex and conf_id */ - wlc = talloc_zero(fl1h, struct wait_l1_conf); - wlc->cb = cb; - wlc->cb_data = data; - - /* Make sure we actually have received a REQUEST type primitive */ - if (is_system_prim == 0) { - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - - LOGP(DL1P, LOGL_INFO, "Tx L1 prim %s\n", - get_value_string(lc15bts_l1prim_names, l1p->id)); - - if (lc15bts_get_l1prim_type(l1p->id) != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "L1 Prim %s is not a Request!\n", - get_value_string(lc15bts_l1prim_names, l1p->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 0; - wlc->conf_prim_id = lc15bts_get_l1prim_conf(l1p->id); - wlc->conf_hLayer3 = l1p_get_hLayer3(l1p); - wqueue = &fl1h->write_q[MQ_L1_WRITE]; - timeout_secs = 30; - } else { - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx SYS prim %s\n", - get_value_string(lc15bts_sysprim_names, sysp->id)); - - if (lc15bts_get_sysprim_type(sysp->id) != L1P_T_REQ) { - LOGP(DL1C, LOGL_ERROR, "SYS Prim %s is not a Request!\n", - get_value_string(lc15bts_sysprim_names, sysp->id)); - talloc_free(wlc); - return -EINVAL; - } - wlc->is_sys_prim = 1; - wlc->conf_prim_id = lc15bts_get_sysprim_conf(sysp->id); - wqueue = &fl1h->write_q[MQ_SYS_WRITE]; - timeout_secs = 30; - } - - /* enqueue the message in the queue and add wsc to list */ - if (osmo_wqueue_enqueue(wqueue, msg) != 0) { - /* So we will get a timeout but the log message might help */ - LOGP(DL1C, LOGL_ERROR, "Write queue for %s full. dropping msg.\n", - is_system_prim ? "system primitive" : "gsm"); - msgb_free(msg); - } - llist_add(&wlc->list, &fl1h->wlc_list); - - /* schedule a timer for timeout_secs seconds. If DSP fails to respond, we terminate */ - wlc->timer.data = wlc; - wlc->timer.cb = l1if_req_timeout; - osmo_timer_schedule(&wlc->timer, timeout_secs, 0); - - return 0; -} - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 1, cb, data); -} - -int l1if_gsm_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *data) -{ - return _l1if_req_compl(fl1h, msg, 0, cb, data); -} - -/* allocate a msgb containing a GsmL1_Prim_t */ -struct msgb *l1p_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t)); - - return msg; -} - -/* allocate a msgb containing a Litecell15_Prim_t */ -struct msgb *sysp_msgb_alloc(void) -{ - struct msgb *msg = msgb_alloc(sizeof(Litecell15_Prim_t), "sys_prim"); - - if (msg) - msg->l1h = msgb_put(msg, sizeof(Litecell15_Prim_t)); - - return msg; -} - -static GsmL1_PhDataReq_t * -data_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = rts_ind->hLayer1; - data_req->u8Tn = rts_ind->u8Tn; - data_req->u32Fn = rts_ind->u32Fn; - data_req->sapi = rts_ind->sapi; - data_req->subCh = rts_ind->subCh; - data_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return data_req; -} - -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_rts_ind(GsmL1_Prim_t *l1p, - const GsmL1_PhReadyToSendInd_t *rts_ind) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = rts_ind->hLayer1; - empty_req->u8Tn = rts_ind->u8Tn; - empty_req->u32Fn = rts_ind->u32Fn; - empty_req->sapi = rts_ind->sapi; - empty_req->subCh = rts_ind->subCh; - empty_req->u8BlockNbr = rts_ind->u8BlockNbr; - - return empty_req; -} - -/* fill PH-DATA.req from l1sap primitive */ -static GsmL1_PhDataReq_t * -data_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, uint8_t sub_ch, - uint8_t block_nr, uint8_t len) -{ - GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq; - - l1p->id = GsmL1_PrimId_PhDataReq; - - /* copy fields from PH-RSS.ind */ - data_req->hLayer1 = (HANDLE)fl1->hLayer1; - data_req->u8Tn = tn; - data_req->u32Fn = fn; - data_req->sapi = sapi; - data_req->subCh = sub_ch; - data_req->u8BlockNbr = block_nr; - - data_req->msgUnitParam.u8Size = len; - - return data_req; -} - -/* fill PH-EMPTY_FRAME.req from l1sap primitive */ -static GsmL1_PhEmptyFrameReq_t * -empty_req_from_l1sap(GsmL1_Prim_t *l1p, struct lc15l1_hdl *fl1, - uint8_t tn, uint32_t fn, uint8_t sapi, - uint8_t subch, uint8_t block_nr) -{ - GsmL1_PhEmptyFrameReq_t *empty_req = &l1p->u.phEmptyFrameReq; - - l1p->id = GsmL1_PrimId_PhEmptyFrameReq; - - empty_req->hLayer1 = (HANDLE)fl1->hLayer1; - empty_req->u8Tn = tn; - empty_req->u32Fn = fn; - empty_req->sapi = sapi; - empty_req->subCh = subch; - empty_req->u8BlockNbr = block_nr; - - return empty_req; -} - -static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - struct msgb *l1msg = l1p_msgb_alloc(); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0; - uint8_t chan_nr, link_id; - int len; - - if (!msg) { - LOGPFN(DL1C, LOGL_FATAL, l1sap->u.data.fn, "PH-DATA.req without msg. Please fix!\n"); - abort(); - } - - len = msgb_l2len(msg); - - chan_nr = l1sap->u.data.chan_nr; - link_id = l1sap->u.data.link_id; - u32Fn = l1sap->u.data.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - subCh = 0x1f; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (L1SAP_IS_LINK_SACCH(link_id)) { - sapi = GsmL1_Sapi_Sacch; - if (!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_PDCH(chan_nr)) - subCh = l1sap_chan2ss(chan_nr); - } else if (L1SAP_IS_CHAN_TCHF(chan_nr) || L1SAP_IS_CHAN_PDCH(chan_nr)) { - if (ts_is_pdch(&trx->ts[u8Tn])) { - if (L1SAP_IS_PTCCH(u32Fn)) { - sapi = GsmL1_Sapi_Ptcch; - u8BlockNbr = L1SAP_FN2PTCCHBLOCK(u32Fn); - } else { - sapi = GsmL1_Sapi_Pdtch; - u8BlockNbr = L1SAP_FN2MACBLOCK(u32Fn); - } - } else { - sapi = GsmL1_Sapi_FacchF; - u8BlockNbr = (u32Fn % 13) >> 2; - } - } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_FacchH; - u8BlockNbr = (u32Fn % 26) >> 3; - } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH4(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) { - subCh = L1SAP_CHAN2SS_SDCCH8(chan_nr); - sapi = GsmL1_Sapi_Sdcch; - } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { - sapi = GsmL1_Sapi_Bcch; - } else if (L1SAP_IS_CHAN_CBCH(chan_nr)) { - sapi = GsmL1_Sapi_Cbch; - } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { - /* The sapi depends on DSP configuration, not - * on the actual SYSTEM INFORMATION 3. */ - u8BlockNbr = l1sap_fn2ccch_block(u32Fn); - if (u8BlockNbr >= num_agch(trx, "PH-DATA-REQ")) - sapi = GsmL1_Sapi_Pch; - else - sapi = GsmL1_Sapi_Agch; - } else { - LOGPFN(DL1C, LOGL_NOTICE, u32Fn, "unknown prim %d op %d " - "chan_nr %d link_id %d\n", l1sap->oph.primitive, - l1sap->oph.operation, chan_nr, link_id); - msgb_free(l1msg); - return -EINVAL; - } - - /* convert l1sap message to GsmL1 primitive, keep payload */ - if (len) { - /* data request */ - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr, len); - if (use_cache) - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, - lchan->tch.dtx.facch, msgb_l2len(msg)); - else if (dtx_dl_amr_enabled(lchan) && - ((lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) || - (lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F))) { - if (sapi == GsmL1_Sapi_FacchF) { - sapi = GsmL1_Sapi_TchF; - } - if (sapi == GsmL1_Sapi_FacchH) { - sapi = GsmL1_Sapi_TchH; - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - } - if (sapi == GsmL1_Sapi_TchH || sapi == GsmL1_Sapi_TchF) { - /* FACCH interruption of DTX silence */ - /* cache FACCH data */ - memcpy(lchan->tch.dtx.facch, msg->l2h, - msgb_l2len(msg)); - /* prepare ONSET or INH message */ - if(lchan->tch.dtx.dl_amr_fsm->state == ST_ONSET_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_Onset; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_U_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidUpdateInH; - else if(lchan->tch.dtx.dl_amr_fsm->state == ST_F1_INH_F) - l1p->u.phDataReq.msgUnitParam.u8Buffer[0] = - GsmL1_TchPlType_Amr_SidFirstInH; - /* ignored CMR/CMI pair */ - l1p->u.phDataReq.msgUnitParam.u8Buffer[1] = 0; - l1p->u.phDataReq.msgUnitParam.u8Buffer[2] = 0; - /* update length */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, - subCh, u8BlockNbr, 3); - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - } else if (dtx_dl_amr_enabled(lchan) && - lchan->tch.dtx.dl_amr_fsm->state == ST_FACCH) { - /* update FN so it can be checked by TCH silence - resume handler */ - lchan->tch.dtx.fn = LCHAN_FN_DUMMY; - } - else { - OSMO_ASSERT(msgb_l2len(msg) <= sizeof(l1p->u.phDataReq.msgUnitParam.u8Buffer)); - memcpy(l1p->u.phDataReq.msgUnitParam.u8Buffer, msg->l2h, - msgb_l2len(msg)); - } - LOGPFN(DL1P, LOGL_DEBUG, u32Fn, "PH-DATA.req(%s)\n", - osmo_hexdump(l1p->u.phDataReq.msgUnitParam.u8Buffer, - l1p->u.phDataReq.msgUnitParam.u8Size)); - } else { - /* empty frame */ - GsmL1_Prim_t *l1p = msgb_l1prim(l1msg); - - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - - /* send message to DSP's queue */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], l1msg) != 0) { - LOGPFN(DL1P, LOGL_ERROR, u32Fn, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(l1msg); - } else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) - ph_data_req(trx, msg, l1sap, true); - return 0; -} - -static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap, bool use_cache, bool marker) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - struct gsm_lchan *lchan; - uint32_t u32Fn; - uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi; - uint8_t chan_nr; - GsmL1_Prim_t *l1p; - struct msgb *nmsg = NULL; - int rc = -1; - - chan_nr = l1sap->u.tch.chan_nr; - u32Fn = l1sap->u.tch.fn; - u8Tn = L1SAP_CHAN2TS(chan_nr); - u8BlockNbr = (u32Fn % 13) >> 2; - if (L1SAP_IS_CHAN_TCHH(chan_nr)) { - subCh = L1SAP_CHAN2SS_TCHH(chan_nr); - sapi = GsmL1_Sapi_TchH; - } else { - subCh = 0x1f; - sapi = GsmL1_Sapi_TchF; - } - - lchan = get_lchan_by_chan_nr(trx, chan_nr); - - /* create new message and fill data */ - if (msg) { - msgb_pull(msg, sizeof(*l1sap)); - /* create new message */ - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - l1p = msgb_l1prim(nmsg); - rc = l1if_tch_encode(lchan, - l1p->u.phDataReq.msgUnitParam.u8Buffer, - &l1p->u.phDataReq.msgUnitParam.u8Size, - msg->data, msg->len, u32Fn, use_cache, - l1sap->u.tch.marker); - if (rc < 0) { - /* no data encoded for L1: smth will be generated below */ - msgb_free(nmsg); - nmsg = NULL; - } - } - - /* no message/data, we might generate an empty traffic msg or re-send - cached SID in case of DTX */ - if (!nmsg) - nmsg = gen_empty_tch_msg(lchan, u32Fn); - - /* no traffic message, we generate an empty msg */ - if (!nmsg) { - nmsg = l1p_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - } - - l1p = msgb_l1prim(nmsg); - - /* if we provide data, or if data is already in nmsg */ - if (l1p->u.phDataReq.msgUnitParam.u8Size) { - /* data request */ - data_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, - u8BlockNbr, - l1p->u.phDataReq.msgUnitParam.u8Size); - } else { - /* empty frame */ - if (trx->bts->dtxd && trx != trx->bts->c0) - lchan->tch.dtx.dl_active = true; - empty_req_from_l1sap(l1p, fl1, u8Tn, u32Fn, sapi, subCh, u8BlockNbr); - } - /* send message to DSP's queue */ - osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], nmsg); - if (dtx_is_first_p1(lchan)) - dtx_dispatch(lchan, E_FIRST); - else - dtx_int_signal(lchan); - - if (dtx_recursion(lchan)) /* DTX: send voice after ONSET was sent */ - return ph_tch_req(trx, l1sap->oph.msg, l1sap, true, false); - - return 0; -} - -static int mph_info_req(struct gsm_bts_trx *trx, struct msgb *msg, - struct osmo_phsap_prim *l1sap) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - uint8_t chan_nr; - struct gsm_lchan *lchan; - int rc = 0; - - switch (l1sap->u.info.type) { - case PRIM_INFO_ACT_CIPH: - chan_nr = l1sap->u.info.u.ciph_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.u.ciph_req.uplink) { - l1if_set_ciphering(fl1, lchan, 0); - lchan->ciph_state = LCHAN_CIPH_RX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink) { - l1if_set_ciphering(fl1, lchan, 1); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - } - if (l1sap->u.info.u.ciph_req.downlink - && l1sap->u.info.u.ciph_req.uplink) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - break; - case PRIM_INFO_ACTIVATE: - case PRIM_INFO_DEACTIVATE: - case PRIM_INFO_MODIFY: - chan_nr = l1sap->u.info.u.act_req.chan_nr; - lchan = get_lchan_by_chan_nr(trx, chan_nr); - if (l1sap->u.info.type == PRIM_INFO_ACTIVATE) - l1if_rsl_chan_act(lchan); - else if (l1sap->u.info.type == PRIM_INFO_MODIFY) { - if (lchan->ho.active == HANDOVER_WAIT_FRAME) - l1if_rsl_chan_mod(lchan); - else - l1if_rsl_mode_modify(lchan); - } else if (l1sap->u.info.u.act_req.sacch_only) - l1if_rsl_deact_sacch(lchan); - else - l1if_rsl_chan_rel(lchan); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown MPH-INFO.req %d\n", - l1sap->u.info.type); - rc = -EINVAL; - } - - return rc; -} - -/* primitive from common part */ -int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) -{ - struct msgb *msg = l1sap->oph.msg; - int rc = 0; - - /* called functions MUST NOT take ownership of msgb, as it is - * free()d below */ - switch (OSMO_PRIM_HDR(&l1sap->oph)) { - case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): - rc = ph_data_req(trx, msg, l1sap, false); - break; - case OSMO_PRIM(PRIM_TCH, PRIM_OP_REQUEST): - rc = ph_tch_req(trx, msg, l1sap, false, l1sap->u.tch.marker); - break; - case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_REQUEST): - rc = mph_info_req(trx, msg, l1sap); - break; - default: - LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", - l1sap->oph.primitive, l1sap->oph.operation); - rc = -EINVAL; - } - - msgb_free(msg); - - return rc; -} - -static int handle_mph_time_ind(struct lc15l1_hdl *fl1, - GsmL1_MphTimeInd_t *time_ind, - struct msgb *msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct osmo_phsap_prim l1sap; - uint32_t fn; - - /* increment the primitive count for the alive timer */ - fl1->alive_prim_cnt++; - - /* ignore every time indication, except for c0 */ - if (trx != bts->c0) { - msgb_free(msg); - return 0; - } - - fn = time_ind->u32Fn; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_TIME; - l1sap.u.info.u.time_ind.fn = fn; - - msgb_free(msg); - - return l1sap_up(trx, &l1sap); -} - -static enum gsm_phys_chan_config pick_pchan(struct gsm_bts_trx_ts *ts) -{ - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - if (ts->flags & TS_F_PDCH_ACTIVE) - return GSM_PCHAN_PDCH; - return GSM_PCHAN_TCH_F; - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return ts->dyn.pchan_is; - default: - return ts->pchan; - } -} - -static uint8_t chan_nr_by_sapi(struct gsm_bts_trx_ts *ts, - GsmL1_Sapi_t sapi, GsmL1_SubCh_t subCh, - uint8_t u8Tn, uint32_t u32Fn) -{ - uint8_t cbits = 0; - enum gsm_phys_chan_config pchan = pick_pchan(ts); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH); - - switch (sapi) { - case GsmL1_Sapi_Bcch: - cbits = 0x10; - break; - case GsmL1_Sapi_Cbch: - cbits = 0xc8 >> 3; /* Osmocom extension for CBCH via L1SAP */ - break; - case GsmL1_Sapi_Sacch: - switch(pchan) { - case GSM_PCHAN_TCH_F: - cbits = 0x01; - break; - case GSM_PCHAN_TCH_H: - cbits = 0x02 + subCh; - break; - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SACCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Sdcch: - switch(pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - cbits = 0x04 + subCh; - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - cbits = 0x08 + subCh; - break; - default: - LOGP(DL1C, LOGL_ERROR, "SDCCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_Agch: - case GsmL1_Sapi_Pch: - cbits = 0x12; - break; - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PDTCH for pchan %d?\n", - pchan); - return 0; - } - break; - case GsmL1_Sapi_TchF: - cbits = 0x01; - break; - case GsmL1_Sapi_TchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_FacchF: - cbits = 0x01; - break; - case GsmL1_Sapi_FacchH: - cbits = 0x02 + subCh; - break; - case GsmL1_Sapi_Ptcch: - if (!L1SAP_IS_PTCCH(u32Fn)) { - LOGP(DL1C, LOGL_FATAL, "Not expecting PTCCH at frame " - "number other than 12, got it at %u (%u). " - "Please fix!\n", u32Fn % 52, u32Fn); - abort(); - } - switch(pchan) { - case GSM_PCHAN_PDCH: - cbits = 0x01; - break; - default: - LOGP(DL1C, LOGL_ERROR, "PTCCH for pchan %d?\n", - pchan); - return 0; - } - break; - default: - return 0; - } - - /* not reached due to default case above */ - return (cbits << 3) | u8Tn; -} - -static const enum l1sap_common_sapi common_sapi_by_sapi_t[] = { - [GsmL1_Sapi_Idle] = L1SAP_COMMON_SAPI_IDLE, - [GsmL1_Sapi_Fcch] = L1SAP_COMMON_SAPI_FCCH, - [GsmL1_Sapi_Sch] = L1SAP_COMMON_SAPI_SCH, - [GsmL1_Sapi_Sacch] = L1SAP_COMMON_SAPI_SACCH, - [GsmL1_Sapi_Sdcch] = L1SAP_COMMON_SAPI_SDCCH, - [GsmL1_Sapi_Bcch] = L1SAP_COMMON_SAPI_BCCH, - [GsmL1_Sapi_Pch] = L1SAP_COMMON_SAPI_PCH, - [GsmL1_Sapi_Agch] = L1SAP_COMMON_SAPI_AGCH, - [GsmL1_Sapi_Cbch] = L1SAP_COMMON_SAPI_CBCH, - [GsmL1_Sapi_Rach] = L1SAP_COMMON_SAPI_RACH, - [GsmL1_Sapi_TchF] = L1SAP_COMMON_SAPI_TCH_F, - [GsmL1_Sapi_FacchF] = L1SAP_COMMON_SAPI_FACCH_F, - [GsmL1_Sapi_TchH] = L1SAP_COMMON_SAPI_TCH_H, - [GsmL1_Sapi_FacchH] = L1SAP_COMMON_SAPI_FACCH_H, - [GsmL1_Sapi_Nch] = L1SAP_COMMON_SAPI_NCH, - [GsmL1_Sapi_Pdtch] = L1SAP_COMMON_SAPI_PDTCH, - [GsmL1_Sapi_Pacch] = L1SAP_COMMON_SAPI_PACCH, - [GsmL1_Sapi_Pbcch] = L1SAP_COMMON_SAPI_PBCCH, - [GsmL1_Sapi_Pagch] = L1SAP_COMMON_SAPI_PAGCH, - [GsmL1_Sapi_Ppch] = L1SAP_COMMON_SAPI_PPCH, - [GsmL1_Sapi_Pnch] = L1SAP_COMMON_SAPI_PNCH, - [GsmL1_Sapi_Ptcch] = L1SAP_COMMON_SAPI_PTCCH, - [GsmL1_Sapi_Prach] = L1SAP_COMMON_SAPI_PRACH, -}; - -static enum l1sap_common_sapi get_common_sapi(GsmL1_Sapi_t sapi) -{ - if (sapi >= GsmL1_Sapi_NUM) - return L1SAP_COMMON_SAPI_UNKNOWN; - return common_sapi_by_sapi_t[sapi]; -} - -static void set_log_ctx_sapi(GsmL1_Sapi_t sapi) -{ - l1sap_log_ctx_sapi = get_common_sapi(sapi); - log_set_context(LOG_CTX_L1_SAPI, &l1sap_log_ctx_sapi); -} - -static int handle_ph_readytosend_ind(struct lc15l1_hdl *fl1, - GsmL1_PhReadyToSendInd_t *rts_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - struct gsm_bts *bts = trx->bts; - struct msgb *resp_msg; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - struct gsm_time g_time; - uint32_t t3p; - int rc; - struct osmo_phsap_prim *l1sap; - uint8_t chan_nr, link_id; - uint32_t fn; - - set_log_ctx_sapi(rts_ind->sapi); - - /* check if primitive should be handled by common part */ - chan_nr = chan_nr_by_sapi(&trx->ts[rts_ind->u8Tn], rts_ind->sapi, - rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn); - if (chan_nr) { - fn = rts_ind->u32Fn; - if (rts_ind->sapi == GsmL1_Sapi_Sacch) - link_id = LID_SACCH; - else - link_id = LID_DEDIC; - /* recycle the msgb and use it for the L1 primitive, - * which means that we (or our caller) must not free it */ - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - if (rts_ind->sapi == GsmL1_Sapi_TchF - || rts_ind->sapi == GsmL1_Sapi_TchH) { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_TCH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.tch.chan_nr = chan_nr; - l1sap->u.tch.fn = fn; - } else { - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - } - - return l1sap_up(trx, l1sap); - } - - gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); - - DEBUGPGT(DL1P, &g_time, "Rx PH-RTS.ind SAPI=%s\n", - get_value_string(lc15bts_l1sapi_names, rts_ind->sapi)); - - /* in all other cases, we need to allocate a new PH-DATA.ind - * primitive msgb and start to fill it */ - resp_msg = l1p_msgb_alloc(); - data_req = data_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - msu_param = &data_req->msgUnitParam; - - /* set default size */ - msu_param->u8Size = GSM_MACBLOCK_LEN; - - switch (rts_ind->sapi) { - case GsmL1_Sapi_Sch: - /* compute T3prime */ - t3p = (g_time.t3 - 1) / 10; - /* fill SCH burst with data */ - msu_param->u8Size = 4; - msu_param->u8Buffer[0] = (bts->bsic << 2) | (g_time.t1 >> 9); - msu_param->u8Buffer[1] = (g_time.t1 >> 1); - msu_param->u8Buffer[2] = (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p >> 1); - msu_param->u8Buffer[3] = (t3p & 1); - break; - case GsmL1_Sapi_Prach: - goto empty_frame; - break; - default: - memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN); - break; - } -tx: - - /* transmit */ - if (osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], resp_msg) != 0) { - LOGPGT(DL1C, LOGL_ERROR, &g_time, "MQ_L1_WRITE queue full. Dropping msg.\n"); - msgb_free(resp_msg); - } - - /* free the msgb, as we have not handed it to l1sap and thus - * need to release its memory */ - msgb_free(l1p_msg); - return 0; - -empty_frame: - /* in case we decide to send an empty frame... */ - empty_req_from_rts_ind(msgb_l1prim(resp_msg), rts_ind); - - goto tx; -} - -#define LOG_FMT_MEAS "Meas: RSSI %-3.2f dBm, Qual %-3.2f dB, BER %-3.2f, Timing %d" -#define LOG_PARAM_MEAS(meas_param) (meas_param)->fRssi, (meas_param)->fLinkQuality, (meas_param)->fBer, (meas_param)->i16BurstTiming - -static int process_meas_res(struct gsm_bts_trx *trx, uint8_t chan_nr, - GsmL1_MeasParam_t *m, uint32_t fn) -{ - struct osmo_phsap_prim l1sap; - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, - PRIM_OP_INDICATION, NULL); - l1sap.u.info.type = PRIM_INFO_MEAS; - l1sap.u.info.u.meas_ind.chan_nr = chan_nr; - l1sap.u.info.u.meas_ind.ta_offs_256bits = m->i16BurstTiming*64; - l1sap.u.info.u.meas_ind.ber10k = (unsigned int) (m->fBer * 10000); - l1sap.u.info.u.meas_ind.inv_rssi = (uint8_t) (m->fRssi * -1); - l1sap.u.info.u.meas_ind.fn = fn; - - /* l1sap wants to take msgb ownership. However, as there is no - * msg, it will msgb_free(l1sap.oph.msg == NULL) */ - return l1sap_up(trx, &l1sap); -} - -static int handle_ph_data_ind(struct lc15l1_hdl *fl1, GsmL1_PhDataInd_t *data_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - uint8_t chan_nr, link_id; - struct osmo_phsap_prim *l1sap; - uint32_t fn; - struct gsm_time g_time; - uint8_t *data, len; - int rc = 0; - int8_t rssi; - - set_log_ctx_sapi(data_ind->sapi); - - chan_nr = chan_nr_by_sapi(&trx->ts[data_ind->u8Tn], data_ind->sapi, - data_ind->subCh, data_ind->u8Tn, data_ind->u32Fn); - fn = data_ind->u32Fn; - link_id = (data_ind->sapi == GsmL1_Sapi_Sacch) ? LID_SACCH : LID_DEDIC; - gsm_fn2gsmtime(&g_time, fn); - - if (!chan_nr) { - LOGPGT(DL1C, LOGL_ERROR, &g_time, "PH-DATA-INDICATION for unknown sapi %s (%d)\n", - get_value_string(lc15bts_l1sapi_names, data_ind->sapi), data_ind->sapi); - msgb_free(l1p_msg); - return ENOTSUP; - } - - process_meas_res(trx, chan_nr, &data_ind->measParam, fn); - - - DEBUGPGT(DL1P, &g_time, "Rx PH-DATA.ind %s (hL2 %08x): %s, " LOG_FMT_MEAS "\n", - get_value_string(lc15bts_l1sapi_names, data_ind->sapi), (uint32_t)data_ind->hLayer2, - osmo_hexdump(data_ind->msgUnitParam.u8Buffer, data_ind->msgUnitParam.u8Size), - LOG_PARAM_MEAS(&data_ind->measParam)); - - /* check for TCH */ - if (data_ind->sapi == GsmL1_Sapi_TchF - || data_ind->sapi == GsmL1_Sapi_TchH) { - /* TCH speech frame handling */ - rc = l1if_tch_rx(trx, chan_nr, l1p_msg); - msgb_free(l1p_msg); - return rc; - } - - /* get rssi */ - rssi = (int8_t) (data_ind->measParam.fRssi); - /* get data pointer and length */ - data = data_ind->msgUnitParam.u8Buffer; - len = data_ind->msgUnitParam.u8Size; - /* pull lower header part before data */ - msgb_pull(l1p_msg, data - l1p_msg->data); - /* trim remaining data to it's size, to get rid of upper header part */ - rc = msgb_trim(l1p_msg, len); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1p_msg->l2h = l1p_msg->data; - /* push new l1 header */ - l1p_msg->l1h = msgb_push(l1p_msg, sizeof(*l1sap)); - /* fill header */ - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, - PRIM_OP_INDICATION, l1p_msg); - l1sap->u.data.link_id = link_id; - l1sap->u.data.chan_nr = chan_nr; - l1sap->u.data.fn = fn; - l1sap->u.data.rssi = rssi; - l1sap->u.data.ber10k = data_ind->measParam.fBer * 10000; - l1sap->u.data.ta_offs_256bits = data_ind->measParam.i16BurstTiming*64; - l1sap->u.data.lqual_cb = data_ind->measParam.fLinkQuality * 10; - - return l1sap_up(trx, l1sap); -} - -static int handle_ph_ra_ind(struct lc15l1_hdl *fl1, GsmL1_PhRaInd_t *ra_ind, - struct msgb *l1p_msg) -{ - struct gsm_bts_trx *trx = lc15l1_hdl_trx(fl1); - struct gsm_lchan *lchan; - struct osmo_phsap_prim *l1sap; - int rc; - struct ph_rach_ind_param rach_ind_param; - - set_log_ctx_sapi(ra_ind->sapi); - LOGPFN(DL1C, LOGL_DEBUG, ra_ind->u32Fn, "Rx PH-RA.ind, " LOG_FMT_MEAS "\n", - LOG_PARAM_MEAS(&ra_ind->measParam)); - - if ((ra_ind->msgUnitParam.u8Size != 1) && - (ra_ind->msgUnitParam.u8Size != 2)) { - LOGPFN(DL1P, LOGL_ERROR, ra_ind->u32Fn, "PH-RACH-INDICATION has %d bits\n", ra_ind->sapi); - msgb_free(l1p_msg); - return 0; - } - - /* We need to evaluate ra_ind before below msgb_trim(), since that invalidates *ra_ind. */ - rach_ind_param = (struct ph_rach_ind_param) { - /* .chan_nr set below */ - /* .ra set below */ - .acc_delay = 0, - .fn = ra_ind->u32Fn, - /* .is_11bit set below */ - /* .burst_type set below */ - .rssi = (int8_t) ra_ind->measParam.fRssi, - .ber10k = (unsigned int) (ra_ind->measParam.fBer * 10000.0), - .acc_delay_256bits = ra_ind->measParam.i16BurstTiming * 64, - .lqual_cb = (int16_t) ra_ind->measParam.fLinkQuality * 10, /* centiBels */ - }; - - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ra_ind->hLayer2); - if (!lchan || lchan->ts->pchan == GSM_PCHAN_CCCH || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4 || - lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH) - rach_ind_param.chan_nr = RSL_CHAN_RACH; - else - rach_ind_param.chan_nr = gsm_lchan2chan_nr(lchan); - - if (ra_ind->msgUnitParam.u8Size == 2) { - uint16_t temp; - uint16_t ra = ra_ind->msgUnitParam.u8Buffer[0]; - ra = ra << 3; - temp = (ra_ind->msgUnitParam.u8Buffer[1] & 0x7); - ra = ra | temp; - rach_ind_param.is_11bit = 1; - rach_ind_param.ra = ra; - } else { - rach_ind_param.is_11bit = 0; - rach_ind_param.ra = ra_ind->msgUnitParam.u8Buffer[0]; - } - - /* the old legacy full-bits acc_delay cannot express negative values */ - if (ra_ind->measParam.i16BurstTiming > 0) - rach_ind_param.acc_delay = ra_ind->measParam.i16BurstTiming >> 2; - - /* mapping of the burst type, the values are specific to - * osmo-bts-litecell15 */ - switch (ra_ind->burstType) { - case GsmL1_BurstType_Access_0: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_0; - break; - case GsmL1_BurstType_Access_1: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_1; - break; - case GsmL1_BurstType_Access_2: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_ACCESS_2; - break; - default: - rach_ind_param.burst_type = - GSM_L1_BURST_TYPE_NONE; - break; - } - - /* msgb_trim() invalidates ra_ind, make that abundantly clear: */ - ra_ind = NULL; - rc = msgb_trim(l1p_msg, sizeof(*l1sap)); - if (rc < 0) - MSGB_ABORT(l1p_msg, "No room for primitive data\n"); - l1sap = msgb_l1sap_prim(l1p_msg); - osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, - l1p_msg); - l1sap->u.rach_ind = rach_ind_param; - - return l1sap_up(trx, l1sap); -} - -/* handle any random indication from the L1 */ -static int l1if_handle_ind(struct lc15l1_hdl *fl1, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - int rc = 0; - - /* all the below called functions must take ownership of the msgb */ - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - rc = handle_mph_time_ind(fl1, &l1p->u.mphTimeInd, msg); - break; - case GsmL1_PrimId_MphSyncInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhConnectInd: - msgb_free(msg); - break; - case GsmL1_PrimId_PhReadyToSendInd: - rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd, - msg); - break; - case GsmL1_PrimId_PhDataInd: - rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg); - break; - case GsmL1_PrimId_PhRaInd: - rc = handle_ph_ra_ind(fl1, &l1p->u.phRaInd, msg); - break; - default: - msgb_free(msg); - } - - return rc; -} - -static inline int is_prim_compat(GsmL1_Prim_t *l1p, struct wait_l1_conf *wlc) -{ - if (wlc->is_sys_prim != 0) - return 0; - if (l1p->id != wlc->conf_prim_id) - return 0; - if (l1p_get_hLayer3(l1p) != wlc->conf_hLayer3) - return 0; - return 1; -} - -int l1if_handle_l1prim(int wq, struct lc15l1_hdl *fl1h, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - struct wait_l1_conf *wlc; - int rc; - - switch (l1p->id) { - case GsmL1_PrimId_MphTimeInd: - /* silent, don't clog the log file */ - break; - default: - LOGP(DL1P, LOGL_DEBUG, "Rx L1 prim %s on queue %d\n", - get_value_string(lc15bts_l1prim_names, l1p->id), wq); - } - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - if (is_prim_compat(l1p, wlc)) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(lc15l1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -int l1if_handle_sysprim(struct lc15l1_hdl *fl1h, struct msgb *msg) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - struct wait_l1_conf *wlc; - int rc; - - LOGP(DL1P, LOGL_DEBUG, "Rx SYS prim %s\n", - get_value_string(lc15bts_sysprim_names, sysp->id)); - - /* check if this is a resposne to a sync-waiting request */ - llist_for_each_entry(wlc, &fl1h->wlc_list, list) { - /* the limitation here is that we cannot have multiple callers - * sending the same primitive */ - if (wlc->is_sys_prim && sysp->id == wlc->conf_prim_id) { - llist_del(&wlc->list); - if (wlc->cb) { - /* call-back function must take - * ownership of msgb */ - rc = wlc->cb(lc15l1_hdl_trx(fl1h), msg, - wlc->cb_data); - } else { - rc = 0; - msgb_free(msg); - } - release_wlc(wlc); - return rc; - } - } - /* if we reach here, it is not a Conf for a pending Req */ - return l1if_handle_ind(fl1h, msg); -} - -static int activate_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - int on = 0; - unsigned int i; - - if (sysp->id == Litecell15_PrimId_ActivateRfCnf) - on = 1; - - if (on) - status = sysp->u.activateRfCnf.status; - else - status = sysp->u.deactivateRfCnf.status; - - LOGP(DL1C, LOGL_INFO, "Rx RF-%sACT.conf (status=%s)\n", on ? "" : "DE", - get_value_string(lc15bts_l1status_names, status)); - - struct bts_lc15_priv *bts_lc15 = trx->bts->model_priv; - - if (on) { - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "RF-ACT.conf with status %s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-ACT failure"); - } else { - if (bts_lc15->led_ctrl_mode == LC15_LED_CONTROL_BTS) - bts_update_status(BTS_STATUS_RF_ACTIVE, 1); - } - - /* signal availability */ - osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_SW_ACT, NULL); - osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_SW_ACT, NULL); - } else { - if (bts_lc15->led_ctrl_mode == LC15_LED_CONTROL_BTS) - bts_update_status(BTS_STATUS_RF_ACTIVE, 0); - osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_DISABLE, NULL); - osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_DISABLE, NULL); - } - - msgb_free(resp); - - return 0; -} - -/* activate or de-activate the entire RF-Frontend */ -int l1if_activate_rf(struct lc15l1_hdl *hdl, int on) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - struct phy_instance *pinst = hdl->phy_inst; - - if (on) { - sysp->id = Litecell15_PrimId_ActivateRfReq; - sysp->u.activateRfReq.msgq.u8UseTchMsgq = 0; - sysp->u.activateRfReq.msgq.u8UsePdtchMsgq = pcu_direct; - - sysp->u.activateRfReq.u8UnusedTsMode = pinst->u.lc15.pedestal_mode; - - sysp->u.activateRfReq.u8McCorrMode = 0; - - /* diversity mode: 0: SISO-A, 1: SISO-B, 2: MRC */ - sysp->u.activateRfReq.u8DiversityMode = pinst->u.lc15.diversity_mode; - - /* maximum cell size in quarter-bits, 90 == 12.456 km */ - sysp->u.activateRfReq.u8MaxCellSize = pinst->u.lc15.max_cell_size; - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - /* auto tx power adjustment mode 0:none, 1: automatic*/ - sysp->u.activateRfReq.u8EnAutoPowerAdjust = pinst->u.lc15.tx_pwr_adj_mode; -#endif - - } else { - sysp->id = Litecell15_PrimId_DeactivateRfReq; - } - - return l1if_req_compl(hdl, msg, activate_rf_compl_cb, NULL); -} - -static void mute_handle_ts(struct gsm_bts_trx_ts *ts, int is_muted) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ts->lchan); i++) { - struct gsm_lchan *lchan = &ts->lchan[i]; - - if (!is_muted) - continue; - - if (lchan->state != LCHAN_S_ACTIVE) - continue; - - /* skip channels that might be active for another reason */ - if (lchan->type == GSM_LCHAN_CCCH) - continue; - if (lchan->type == GSM_LCHAN_PDTCH) - continue; - - if (lchan->s <= 0) - continue; - - lchan->s = 0; - rsl_tx_conn_fail(lchan, RSL_ERR_RADIO_LINK_FAIL); - } -} - -static int mute_rf_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx RF-MUTE.conf with status %s\n", - get_value_string(lc15bts_l1status_names, status)); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 0); - } else { - int i; - - LOGP(DL1C, LOGL_INFO, "Rx RF-MUTE.conf with status=%s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_update_status(BTS_STATUS_RF_MUTE, fl1h->last_rf_mute[0]); - oml_mo_rf_lock_chg(&trx->mo, fl1h->last_rf_mute, 1); - - osmo_static_assert( - ARRAY_SIZE(trx->ts) >= ARRAY_SIZE(fl1h->last_rf_mute), - ts_array_size); - - for (i = 0; i < ARRAY_SIZE(fl1h->last_rf_mute); ++i) - mute_handle_ts(&trx->ts[i], fl1h->last_rf_mute[i]); - } - - msgb_free(resp); - - return 0; -} - -/* mute/unmute RF time slots */ -int l1if_mute_rf(struct lc15l1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx RF-MUTE.req (%d, %d, %d, %d, %d, %d, %d, %d)\n", - mute[0], mute[1], mute[2], mute[3], - mute[4], mute[5], mute[6], mute[7] - ); - - sysp->id = Litecell15_PrimId_MuteRfReq; - memcpy(sysp->u.muteRfReq.u8Mute, mute, sizeof(sysp->u.muteRfReq.u8Mute)); - /* save for later use */ - memcpy(hdl->last_rf_mute, mute, sizeof(hdl->last_rf_mute)); - - return l1if_req_compl(hdl, msg, cb ? cb : mute_rf_compl_cb, NULL); -} - -/* call-back on arrival of DSP+FPGA version + band capability */ -static int info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - Litecell15_SystemInfoCnf_t *sic = &sysp->u.systemInfoCnf; - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - int rc; - - fl1h->hw_info.dsp_version[0] = sic->dspVersion.major; - fl1h->hw_info.dsp_version[1] = sic->dspVersion.minor; - fl1h->hw_info.dsp_version[2] = sic->dspVersion.build; - - fl1h->hw_info.fpga_version[0] = sic->fpgaVersion.major; - fl1h->hw_info.fpga_version[1] = sic->fpgaVersion.minor; - fl1h->hw_info.fpga_version[2] = sic->fpgaVersion.build; - - LOGP(DL1C, LOGL_INFO, "DSP v%u.%u.%u, FPGA v%u.%u.%u\n", - sic->dspVersion.major, sic->dspVersion.minor, - sic->dspVersion.build, sic->fpgaVersion.major, - sic->fpgaVersion.minor, sic->fpgaVersion.build); - - if (!(fl1h->hw_info.band_support & trx->bts->band)) - LOGP(DL1C, LOGL_FATAL, "BTS band %s not supported by hw\n", - gsm_band_name(trx->bts->band)); - - /* Request the activation */ - l1if_activate_rf(fl1h, 1); - - /* load calibration tables */ - rc = calib_load(fl1h); - if (rc < 0) - LOGP(DL1C, LOGL_ERROR, "Operating without calibration; " - "unable to load tables!\n"); - - msgb_free(resp); - return 0; -} - -/* request DSP+FPGA code versions */ -static int l1if_get_info(struct lc15l1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - sysp->id = Litecell15_PrimId_SystemInfoReq; - - return l1if_req_compl(hdl, msg, info_compl_cb, NULL); -} - -static int reset_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status = sysp->u.layer1ResetCnf.status; - - LOGP(DL1C, LOGL_NOTICE, "Rx L1-RESET.conf (status=%s)\n", - get_value_string(lc15bts_l1status_names, status)); - - msgb_free(resp); - - /* If we're coming out of reset .. */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "L1-RESET.conf with status %s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_shutdown(trx->bts, "L1-RESET failure"); - } - - /* as we cannot get the current DSP trace flags, we simply - * set them to zero (or whatever dsp_trace_f has been initialized to */ - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f); - - /* obtain version information on DSP/FPGA and band capabilities */ - l1if_get_info(fl1h); - - return 0; -} - -int l1if_reset(struct lc15l1_hdl *hdl) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - sysp->id = Litecell15_PrimId_Layer1ResetReq; - - return l1if_req_compl(hdl, msg, reset_compl_cb, NULL); -} - -/* set the trace flags within the DSP */ -int l1if_set_trace_flags(struct lc15l1_hdl *hdl, uint32_t flags) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sysp = msgb_sysprim(msg); - - LOGP(DL1C, LOGL_INFO, "Tx SET-TRACE-FLAGS.req (0x%08x)\n", - flags); - - sysp->id = Litecell15_PrimId_SetTraceFlagsReq; - sysp->u.setTraceFlagsReq.u32Tf = flags; - - hdl->dsp_trace_f = flags; - - /* There is no confirmation we could wait for */ - if (osmo_wqueue_enqueue(&hdl->write_q[MQ_SYS_WRITE], msg) != 0) { - LOGP(DL1C, LOGL_ERROR, "MQ_SYS_WRITE queue full. Dropping msg\n"); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} - -static int get_hwinfo(struct lc15l1_hdl *fl1h) -{ - int rc; - - rc = lc15bts_rev_get(); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to obtain LC15BTS revision: %d\n", rc); - return rc; - } - fl1h->hw_info.ver_major = rc; - - rc = lc15bts_model_get(); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to obtain LC15BTS model: %d\n", rc); - return rc; - } - fl1h->hw_info.ver_minor = rc; - - rc = lc15bts_option_get(LC15BTS_OPTION_BAND); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "Failed to obtain LC15BTS_OPTION_BAND: %d\n", rc); - return rc; - } - - switch (rc) { - case LC15BTS_BAND_850: - fl1h->hw_info.band_support = GSM_BAND_850; - break; - case LC15BTS_BAND_900: - fl1h->hw_info.band_support = GSM_BAND_900; - break; - case LC15BTS_BAND_1800: - fl1h->hw_info.band_support = GSM_BAND_1800; - break; - case LC15BTS_BAND_1900: - fl1h->hw_info.band_support = GSM_BAND_1900; - break; - default: - LOGP(DL1C, LOGL_ERROR, "Unexpected LC15BTS_BAND value: %d\n", rc); - return -1; - } - - LOGP(DL1C, LOGL_INFO, "BTS hw support band %s\n", gsm_band_name(fl1h->hw_info.band_support)); - - return 0; -} - -struct lc15l1_hdl *l1if_open(struct phy_instance *pinst) -{ - struct lc15l1_hdl *fl1h; - int rc; - - LOGP(DL1C, LOGL_INFO, "Litecell 1.5 BTS L1IF compiled against API headers " - "v%u.%u.%u\n", LITECELL15_API_VERSION >> 16, - (LITECELL15_API_VERSION >> 8) & 0xff, - LITECELL15_API_VERSION & 0xff); - - fl1h = talloc_zero(pinst, struct lc15l1_hdl); - if (!fl1h) - return NULL; - INIT_LLIST_HEAD(&fl1h->wlc_list); - - fl1h->phy_inst = pinst; - fl1h->dsp_trace_f = pinst->u.lc15.dsp_trace_f; - - get_hwinfo(fl1h); - - rc = l1if_transport_open(MQ_SYS_WRITE, fl1h); - if (rc < 0) { - talloc_free(fl1h); - return NULL; - } - - rc = l1if_transport_open(MQ_L1_WRITE, fl1h); - if (rc < 0) { - l1if_transport_close(MQ_SYS_WRITE, fl1h); - talloc_free(fl1h); - return NULL; - } - - return fl1h; -} - -int l1if_close(struct lc15l1_hdl *fl1h) -{ - l1if_transport_close(MQ_L1_WRITE, fl1h); - l1if_transport_close(MQ_SYS_WRITE, fl1h); - return 0; -} - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) -static int dsp_alive_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - Litecell15_IsAliveCnf_t *sac = &sysp->u.isAliveCnf; - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - fl1h->hw_alive.dsp_alive_cnt++; - LOGP(DL1C, LOGL_DEBUG, "Rx SYS prim %s, status=%d (%d)\n", - get_value_string(lc15bts_sysprim_names, sysp->id), sac->status, trx->nr); - - msgb_free(resp); - return 0; -} - -static void dsp_alive_timer_cb(void *data) -{ - struct lc15l1_hdl *fl1h = data; - struct gsm_bts_trx *trx = fl1h->phy_inst->trx; - struct msgb *msg = sysp_msgb_alloc(); - int rc; - - Litecell15_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Litecell15_PrimId_IsAliveReq; - - if (fl1h->hw_alive.dsp_alive_cnt == 0) { - LOGP(DL1C, LOGL_ERROR, "Timeout waiting for SYS prim %s primitive (%d)\n", - get_value_string(lc15bts_sysprim_names, sys_prim->id + 1), trx->nr); - - if( fl1h->phy_inst->trx ){ - fl1h->phy_inst->trx->mo.obj_inst.trx_nr = fl1h->phy_inst->trx->nr; - } - } - - LOGP(DL1C, LOGL_DEBUG, "Tx SYS prim %s (%d)\n", - get_value_string(lc15bts_sysprim_names, sys_prim->id), trx->nr); - - rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id)); - return; - } - - /* restart timer */ - fl1h->hw_alive.dsp_alive_cnt = 0; - osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0); - - return; -} -#endif - -int bts_model_phy_link_open(struct phy_link *plink) -{ - struct phy_instance *pinst = phy_instance_by_num(plink, 0); - - OSMO_ASSERT(pinst); - - if (!pinst->trx) { - LOGP(DL1C, LOGL_NOTICE, "Ignoring phy link %d instance %d " - "because no TRX is associated with it\n", plink->num, pinst->num); - return 0; - } - phy_link_state_set(plink, PHY_LINK_CONNECTING); - - pinst->u.lc15.hdl = l1if_open(pinst); - if (!pinst->u.lc15.hdl) { - LOGP(DL1C, LOGL_FATAL, "Cannot open L1 interface\n"); - return -EIO; - } - - /* Set default PHY parameters */ - if (!pinst->u.lc15.max_cell_size) - pinst->u.lc15.max_cell_size = LC15_BTS_MAX_CELL_SIZE_DEFAULT; - - if (!pinst->u.lc15.diversity_mode) - pinst->u.lc15.diversity_mode = LC15_BTS_DIVERSITY_MODE_DEFAULT; - - if (!pinst->u.lc15.pedestal_mode) - pinst->u.lc15.pedestal_mode = LC15_BTS_PEDESTAL_MODE_DEFAULT; - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - if (!pinst->u.lc15.dsp_alive_period) - pinst->u.lc15.dsp_alive_period = LC15_BTS_DSP_ALIVE_TMR_DEFAULT; - - if (!pinst->u.lc15.tx_pwr_adj_mode) - pinst->u.lc15.tx_pwr_adj_mode = LC15_BTS_TX_PWR_ADJ_DEFAULT; - - if (!pinst->u.lc15.tx_pwr_red_8psk) - pinst->u.lc15.tx_pwr_red_8psk = LC15_BTS_TX_RED_PWR_8PSK_DEFAULT; - - if (!pinst->u.lc15.tx_c0_idle_pwr_red) - pinst->u.lc15.tx_c0_idle_pwr_red = LC15_BTS_TX_C0_IDLE_RED_PWR_DEFAULT; -#endif - - struct lc15l1_hdl *fl1h = pinst->u.lc15.hdl; - fl1h->dsp_trace_f = dsp_trace; - - l1if_reset(pinst->u.lc15.hdl); - - phy_link_state_set(plink, PHY_LINK_CONNECTED); - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - /* Send first IS_ALIVE primitive */ - struct msgb *msg = sysp_msgb_alloc(); - int rc; - - Litecell15_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Litecell15_PrimId_IsAliveReq; - - rc = l1if_req_compl(fl1h, msg, dsp_alive_compl_cb, NULL); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "Failed to send %s primitive\n", get_value_string(lc15bts_sysprim_names, sys_prim->id)); - return -EIO; - } - - /* initialize DSP heart beat alive timer */ - osmo_timer_setup(&fl1h->hw_alive.dsp_alive_timer, dsp_alive_timer_cb, fl1h); - fl1h->hw_alive.dsp_alive_cnt = 0; - fl1h->hw_alive.dsp_alive_period = pinst->u.lc15.dsp_alive_period; - osmo_timer_schedule(&fl1h->hw_alive.dsp_alive_timer, fl1h->hw_alive.dsp_alive_period, 0); -#endif - - return 0; -} diff --git a/src/osmo-bts-litecell15/l1_if.h b/src/osmo-bts-litecell15/l1_if.h deleted file mode 100644 index 655e63fb..00000000 --- a/src/osmo-bts-litecell15/l1_if.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef _L1_IF_H -#define _L1_IF_H - -#include <osmocom/core/select.h> -#include <osmocom/core/write_queue.h> -#include <osmocom/core/gsmtap_util.h> -#include <osmocom/core/timer.h> -#include <osmocom/gsm/gsm_utils.h> - -#include <osmo-bts/phy_link.h> - -#include <nrw/litecell15/gsml1prim.h> -#include <nrw/litecell15/gsml1types.h> - -#include <stdbool.h> - -enum { - MQ_SYS_READ, - MQ_L1_READ, - MQ_TCH_READ, - MQ_PDTCH_READ, - _NUM_MQ_READ -}; - -enum { - MQ_SYS_WRITE, - MQ_L1_WRITE, - MQ_TCH_WRITE, - MQ_PDTCH_WRITE, - _NUM_MQ_WRITE -}; - -/* gsm_bts->model_priv, specific to Litecell 1.5 BTS */ -struct bts_lc15_priv { - uint8_t led_ctrl_mode; /* 0: control by BTS, 1: not control by BTS */ - unsigned int rtp_drift_thres_ms; /* RTP timestamp drift detection threshold */ -}; - -struct calib_send_state { - FILE *fp; - const char *path; - int last_file_idx; -}; - -struct lc15l1_hdl { - struct gsm_time gsm_time; - HANDLE hLayer1; /* handle to the L1 instance in the DSP */ - uint32_t dsp_trace_f; /* currently operational DSP trace flags */ - struct llist_head wlc_list; - - struct phy_instance *phy_inst; - - struct osmo_timer_list alive_timer; - unsigned int alive_prim_cnt; - - struct osmo_fd read_ofd[_NUM_MQ_READ]; /* osmo file descriptors */ - struct osmo_wqueue write_q[_NUM_MQ_WRITE]; - - struct { - /* from DSP/FPGA after L1 Init */ - uint8_t dsp_version[3]; - uint8_t fpga_version[3]; - uint32_t band_support; - uint8_t ver_major; - uint8_t ver_minor; - } hw_info; - - struct calib_send_state st; - - uint8_t last_rf_mute[8]; - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - struct { - struct osmo_timer_list dsp_alive_timer; - unsigned int dsp_alive_cnt; - uint8_t dsp_alive_period; - } hw_alive; -#endif - -}; - -#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h) -#define msgb_sysprim(msg) ((Litecell15_Prim_t *)(msg)->l1h) - -typedef int l1if_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, void *data); - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); -int l1if_gsm_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - l1if_compl_cb *cb, void *cb_data); - -struct lc15l1_hdl *l1if_open(struct phy_instance *pinst); -int l1if_close(struct lc15l1_hdl *hdl); -int l1if_reset(struct lc15l1_hdl *hdl); -int l1if_activate_rf(struct lc15l1_hdl *hdl, int on); -int l1if_set_trace_flags(struct lc15l1_hdl *hdl, uint32_t flags); -int l1if_set_txpower(struct lc15l1_hdl *fl1h, float tx_power); -int l1if_mute_rf(struct lc15l1_hdl *hdl, uint8_t mute[8], l1if_compl_cb *cb); - -struct msgb *l1p_msgb_alloc(void); -struct msgb *sysp_msgb_alloc(void); - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan); -struct gsm_lchan *l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer); - -/* tch.c */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker); -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg); -int l1if_tch_fill(struct gsm_lchan *lchan, uint8_t *l1_buffer); -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn); - -/* ciphering */ -int l1if_set_ciphering(struct lc15l1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink); - -/* channel control */ -int l1if_rsl_chan_act(struct gsm_lchan *lchan); -int l1if_rsl_chan_rel(struct gsm_lchan *lchan); -int l1if_rsl_chan_mod(struct gsm_lchan *lchan); -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan); -int l1if_rsl_mode_modify(struct gsm_lchan *lchan); - -/* calibration loading */ -int calib_load(struct lc15l1_hdl *fl1h); - -/* public helpers for test */ -int bts_check_for_ciph_cmd(struct lc15l1_hdl *fl1h, - struct msgb *msg, struct gsm_lchan *lchan); -int l1if_ms_pwr_ctrl(struct gsm_lchan *lchan, const int uplink_target, - const uint8_t ms_power, const float rxLevel); - -static inline struct lc15l1_hdl *trx_lc15l1_hdl(const struct gsm_bts_trx *trx) -{ - const struct phy_instance *pinst = trx_phy_instance(trx); - OSMO_ASSERT(pinst); - return pinst->u.lc15.hdl; -} - -static inline struct gsm_bts_trx *lc15l1_hdl_trx(const struct lc15l1_hdl *fl1h) -{ - OSMO_ASSERT(fl1h->phy_inst); - return fl1h->phy_inst->trx; -} - -#endif /* _L1_IF_H */ diff --git a/src/osmo-bts-litecell15/l1_transp.h b/src/osmo-bts-litecell15/l1_transp.h deleted file mode 100644 index 7d6772e8..00000000 --- a/src/osmo-bts-litecell15/l1_transp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _L1_TRANSP_H -#define _L1_TRANSP_H - -#include <osmocom/core/msgb.h> - -/* functions a transport calls on arrival of primitive from BTS */ -int l1if_handle_l1prim(int wq, struct lc15l1_hdl *fl1h, struct msgb *msg); -int l1if_handle_sysprim(struct lc15l1_hdl *fl1h, struct msgb *msg); - -/* functions exported by a transport */ -int l1if_transport_open(int q, struct lc15l1_hdl *fl1h); -int l1if_transport_close(int q, struct lc15l1_hdl *fl1h); - -#endif /* _L1_TRANSP_H */ diff --git a/src/osmo-bts-litecell15/l1_transp_hw.c b/src/osmo-bts-litecell15/l1_transp_hw.c deleted file mode 100644 index ffe8613e..00000000 --- a/src/osmo-bts-litecell15/l1_transp_hw.c +++ /dev/null @@ -1,318 +0,0 @@ -/* Interface handler for Nuran Wireless Litecell 1.5 L1 (real hardware) */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte <laforge@gnumonks.org> - * - * 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 <assert.h> -#include <stdint.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/uio.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/select.h> -#include <osmocom/core/write_queue.h> -#include <osmocom/gsm/gsm_utils.h> - -#include <osmo-bts/logging.h> -#include <osmo-bts/gsm_data.h> - -#include <nrw/litecell15/litecell15.h> -#include <nrw/litecell15/gsml1prim.h> -#include <nrw/litecell15/gsml1const.h> -#include <nrw/litecell15/gsml1types.h> - -#include "lc15bts.h" -#include "l1_if.h" -#include "l1_transp.h" - - -#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/litecell15_dsp2arm_trx" -#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/litecell15_arm2dsp_trx" -#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_sig_dsp2arm_trx" -#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_sig_arm2dsp_trx" - -#define DEV_TCH_DSP2ARM_NAME "/dev/msgq/gsml1_tch_dsp2arm_trx" -#define DEV_TCH_ARM2DSP_NAME "/dev/msgq/gsml1_tch_arm2dsp_trx" -#define DEV_PDTCH_DSP2ARM_NAME "/dev/msgq/gsml1_pdtch_dsp2arm_trx" -#define DEV_PDTCH_ARM2DSP_NAME "/dev/msgq/gsml1_pdtch_arm2dsp_trx" - -static const char *rd_devnames[] = { - [MQ_SYS_READ] = DEV_SYS_DSP2ARM_NAME, - [MQ_L1_READ] = DEV_L1_DSP2ARM_NAME, - [MQ_TCH_READ] = DEV_TCH_DSP2ARM_NAME, - [MQ_PDTCH_READ] = DEV_PDTCH_DSP2ARM_NAME, -}; - -static const char *wr_devnames[] = { - [MQ_SYS_WRITE] = DEV_SYS_ARM2DSP_NAME, - [MQ_L1_WRITE] = DEV_L1_ARM2DSP_NAME, - [MQ_TCH_WRITE] = DEV_TCH_ARM2DSP_NAME, - [MQ_PDTCH_WRITE]= DEV_PDTCH_ARM2DSP_NAME, -}; - -/* - * Make sure that all structs we read fit into the LC15BTS_PRIM_SIZE - */ -osmo_static_assert(sizeof(GsmL1_Prim_t) + 128 <= LC15BTS_PRIM_SIZE, l1_prim) -osmo_static_assert(sizeof(Litecell15_Prim_t) + 128 <= LC15BTS_PRIM_SIZE, super_prim) - -static int wqueue_vector_cb(struct osmo_fd *fd, unsigned int what) -{ - struct osmo_wqueue *queue; - - queue = container_of(fd, struct osmo_wqueue, bfd); - - if (what & OSMO_FD_READ) - queue->read_cb(fd); - - if (what & OSMO_FD_EXCEPT) - queue->except_cb(fd); - - if (what & OSMO_FD_WRITE) { - struct iovec iov[5]; - struct msgb *msg, *tmp; - int written, count = 0; - - fd->when &= ~OSMO_FD_WRITE; - - llist_for_each_entry(msg, &queue->msg_queue, list) { - /* more writes than we have */ - if (count >= ARRAY_SIZE(iov)) - break; - - iov[count].iov_base = msg->l1h; - iov[count].iov_len = msgb_l1len(msg); - count += 1; - } - - /* TODO: check if all lengths are the same. */ - - - /* Nothing scheduled? This should not happen. */ - if (count == 0) { - if (!llist_empty(&queue->msg_queue)) - fd->when |= OSMO_FD_WRITE; - return 0; - } - - written = writev(fd->fd, iov, count); - if (written < 0) { - /* nothing written?! */ - if (!llist_empty(&queue->msg_queue)) - fd->when |= OSMO_FD_WRITE; - return 0; - } - - /* now delete the written entries */ - written = written / iov[0].iov_len; - count = 0; - llist_for_each_entry_safe(msg, tmp, &queue->msg_queue, list) { - queue->current_length -= 1; - - llist_del(&msg->list); - msgb_free(msg); - - count += 1; - if (count >= written) - break; - } - - if (!llist_empty(&queue->msg_queue)) - fd->when |= OSMO_FD_WRITE; - } - - return 0; -} - -static int prim_size_for_queue(int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return sizeof(Litecell15_Prim_t); - case MQ_L1_WRITE: - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: - return sizeof(GsmL1_Prim_t); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -} - -/* callback when there's something to read from the l1 msg_queue */ -static int read_dispatch_one(struct lc15l1_hdl *fl1h, struct msgb *msg, int queue) -{ - switch (queue) { - case MQ_SYS_WRITE: - return l1if_handle_sysprim(fl1h, msg); - case MQ_L1_WRITE: - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: - return l1if_handle_l1prim(queue, fl1h, msg); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n", - queue); - assert(false); - break; - } -}; - -static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - int i, rc; - - const uint32_t prim_size = prim_size_for_queue(ofd->priv_nr); - uint32_t count; - - struct iovec iov[3]; - struct msgb *msg[ARRAY_SIZE(iov)]; - - for (i = 0; i < ARRAY_SIZE(iov); ++i) { - msg[i] = msgb_alloc_headroom(prim_size + 128, 128, "1l_fd"); - msg[i]->l1h = msg[i]->data; - - iov[i].iov_base = msg[i]->l1h; - iov[i].iov_len = msgb_tailroom(msg[i]); - } - - rc = readv(ofd->fd, iov, ARRAY_SIZE(iov)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "failed to read from fd: %s\n", strerror(errno)); - /* N. B: we do not abort to let the cycle below cleanup allocated memory properly, - the return value is ignored by the caller anyway. - TODO: use libexplain's explain_readv() to provide detailed error description */ - count = 0; - } else - count = rc / prim_size; - - for (i = 0; i < count; ++i) { - msgb_put(msg[i], prim_size); - read_dispatch_one(ofd->data, msg[i], ofd->priv_nr); - } - - for (i = count; i < ARRAY_SIZE(iov); ++i) - msgb_free(msg[i]); - - return 1; -} - -/* callback when we can write to one of the l1 msg_queue devices */ -static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - int rc; - - rc = write(ofd->fd, msg->l1h, msgb_l1len(msg)); - if (rc < 0) { - LOGP(DL1C, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", - strerror(errno)); - return rc; - } else if (rc < msg->len) { - LOGP(DL1C, LOGL_ERROR, "short write to L1 msg_queue: " - "%u < %u\n", rc, msg->len); - return -EIO; - } - - return 0; -} - -int l1if_transport_open(int q, struct lc15l1_hdl *hdl) -{ - struct phy_link *plink = hdl->phy_inst->phy_link; - int rc; - char buf[PATH_MAX]; - - /* Step 1: Open all msg_queue file descriptors */ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_wqueue *wq = &hdl->write_q[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - snprintf(buf, sizeof(buf)-1, "%s%d", rd_devnames[q], plink->num); - buf[sizeof(buf)-1] = '\0'; - - rc = open(buf, O_RDONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "unable to open msg_queue %s: %s\n", - buf, strerror(errno)); - return rc; - } - osmo_fd_setup(read_ofd, rc, OSMO_FD_READ, l1if_fd_cb, hdl, q); - rc = osmo_fd_register(read_ofd); - if (rc < 0) { - close(read_ofd->fd); - read_ofd->fd = -1; - return rc; - } - - snprintf(buf, sizeof(buf)-1, "%s%d", wr_devnames[q], plink->num); - buf[sizeof(buf)-1] = '\0'; - - rc = open(buf, O_WRONLY); - if (rc < 0) { - LOGP(DL1C, LOGL_FATAL, "unable to open msg_queue %s: %s\n", - buf, strerror(errno)); - goto out_read; - } - osmo_wqueue_init(wq, 10); - wq->write_cb = l1fd_write_cb; - osmo_fd_setup(write_ofd, rc, OSMO_FD_WRITE, wqueue_vector_cb, hdl, q); - rc = osmo_fd_register(write_ofd); - if (rc < 0) { - close(write_ofd->fd); - write_ofd->fd = -1; - goto out_read; - } - - return 0; - -out_read: - close(hdl->read_ofd[q].fd); - osmo_fd_unregister(&hdl->read_ofd[q]); - - return rc; -} - -int l1if_transport_close(int q, struct lc15l1_hdl *hdl) -{ - struct osmo_fd *read_ofd = &hdl->read_ofd[q]; - struct osmo_fd *write_ofd = &hdl->write_q[q].bfd; - - osmo_fd_unregister(read_ofd); - close(read_ofd->fd); - read_ofd->fd = -1; - - osmo_fd_unregister(write_ofd); - close(write_ofd->fd); - write_ofd->fd = -1; - - return 0; -} diff --git a/src/osmo-bts-litecell15/lc15bts.c b/src/osmo-bts-litecell15/lc15bts.c deleted file mode 100644 index 0ba89a11..00000000 --- a/src/osmo-bts-litecell15/lc15bts.c +++ /dev/null @@ -1,353 +0,0 @@ -/* NuRAN Wireless Litecell 1.5 L1 API related definitions */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * based on: - * sysmobts.c - * (C) 2011 by Harald Welte <laforge@gnumonks.org> - * - * 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 <nrw/litecell15/litecell15.h> -#include <nrw/litecell15/gsml1const.h> -#include <nrw/litecell15/gsml1dbg.h> - -#include "lc15bts.h" - -enum l1prim_type lc15bts_get_l1prim_type(GsmL1_PrimId_t id) -{ - switch (id) { - case GsmL1_PrimId_MphInitReq: return L1P_T_REQ; - case GsmL1_PrimId_MphCloseReq: return L1P_T_REQ; - case GsmL1_PrimId_MphConnectReq: return L1P_T_REQ; - case GsmL1_PrimId_MphDisconnectReq: return L1P_T_REQ; - case GsmL1_PrimId_MphActivateReq: return L1P_T_REQ; - case GsmL1_PrimId_MphDeactivateReq: return L1P_T_REQ; - case GsmL1_PrimId_MphConfigReq: return L1P_T_REQ; - case GsmL1_PrimId_MphMeasureReq: return L1P_T_REQ; - case GsmL1_PrimId_MphInitCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphCloseCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphConnectCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphDisconnectCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphActivateCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphDeactivateCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphConfigCnf: return L1P_T_CONF; - case GsmL1_PrimId_MphMeasureCnf: return L1P_T_CONF; - case GsmL1_PrimId_PhEmptyFrameReq: return L1P_T_REQ; - case GsmL1_PrimId_PhDataReq: return L1P_T_REQ; - case GsmL1_PrimId_MphTimeInd: return L1P_T_IND; - case GsmL1_PrimId_MphSyncInd: return L1P_T_IND; - case GsmL1_PrimId_PhConnectInd: return L1P_T_IND; - case GsmL1_PrimId_PhReadyToSendInd: return L1P_T_IND; - case GsmL1_PrimId_PhDataInd: return L1P_T_IND; - case GsmL1_PrimId_PhRaInd: return L1P_T_IND; - default: return L1P_T_INVALID; - } -} - -const struct value_string lc15bts_l1prim_names[GsmL1_PrimId_NUM+1] = { - { GsmL1_PrimId_MphInitReq, "MPH-INIT.req" }, - { GsmL1_PrimId_MphCloseReq, "MPH-CLOSE.req" }, - { GsmL1_PrimId_MphConnectReq, "MPH-CONNECT.req" }, - { GsmL1_PrimId_MphDisconnectReq,"MPH-DISCONNECT.req" }, - { GsmL1_PrimId_MphActivateReq, "MPH-ACTIVATE.req" }, - { GsmL1_PrimId_MphDeactivateReq,"MPH-DEACTIVATE.req" }, - { GsmL1_PrimId_MphConfigReq, "MPH-CONFIG.req" }, - { GsmL1_PrimId_MphMeasureReq, "MPH-MEASURE.req" }, - { GsmL1_PrimId_MphInitCnf, "MPH-INIT.conf" }, - { GsmL1_PrimId_MphCloseCnf, "MPH-CLOSE.conf" }, - { GsmL1_PrimId_MphConnectCnf, "MPH-CONNECT.conf" }, - { GsmL1_PrimId_MphDisconnectCnf,"MPH-DISCONNECT.conf" }, - { GsmL1_PrimId_MphActivateCnf, "MPH-ACTIVATE.conf" }, - { GsmL1_PrimId_MphDeactivateCnf,"MPH-DEACTIVATE.conf" }, - { GsmL1_PrimId_MphConfigCnf, "MPH-CONFIG.conf" }, - { GsmL1_PrimId_MphMeasureCnf, "MPH-MEASURE.conf" }, - { GsmL1_PrimId_MphTimeInd, "MPH-TIME.ind" }, - { GsmL1_PrimId_MphSyncInd, "MPH-SYNC.ind" }, - { GsmL1_PrimId_PhEmptyFrameReq, "PH-EMPTY_FRAME.req" }, - { GsmL1_PrimId_PhDataReq, "PH-DATA.req" }, - { GsmL1_PrimId_PhConnectInd, "PH-CONNECT.ind" }, - { GsmL1_PrimId_PhReadyToSendInd,"PH-READY_TO_SEND.ind" }, - { GsmL1_PrimId_PhDataInd, "PH-DATA.ind" }, - { GsmL1_PrimId_PhRaInd, "PH-RA.ind" }, - { 0, NULL } -}; - -GsmL1_PrimId_t lc15bts_get_l1prim_conf(GsmL1_PrimId_t id) -{ - switch (id) { - case GsmL1_PrimId_MphInitReq: return GsmL1_PrimId_MphInitCnf; - case GsmL1_PrimId_MphCloseReq: return GsmL1_PrimId_MphCloseCnf; - case GsmL1_PrimId_MphConnectReq: return GsmL1_PrimId_MphConnectCnf; - case GsmL1_PrimId_MphDisconnectReq: return GsmL1_PrimId_MphDisconnectCnf; - case GsmL1_PrimId_MphActivateReq: return GsmL1_PrimId_MphActivateCnf; - case GsmL1_PrimId_MphDeactivateReq: return GsmL1_PrimId_MphDeactivateCnf; - case GsmL1_PrimId_MphConfigReq: return GsmL1_PrimId_MphConfigCnf; - case GsmL1_PrimId_MphMeasureReq: return GsmL1_PrimId_MphMeasureCnf; - default: return -1; // Weak - } -} - -enum l1prim_type lc15bts_get_sysprim_type(Litecell15_PrimId_t id) -{ - switch (id) { - case Litecell15_PrimId_SystemInfoReq: return L1P_T_REQ; - case Litecell15_PrimId_SystemInfoCnf: return L1P_T_CONF; - case Litecell15_PrimId_SystemFailureInd: return L1P_T_IND; - case Litecell15_PrimId_ActivateRfReq: return L1P_T_REQ; - case Litecell15_PrimId_ActivateRfCnf: return L1P_T_CONF; - case Litecell15_PrimId_DeactivateRfReq: return L1P_T_REQ; - case Litecell15_PrimId_DeactivateRfCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetTraceFlagsReq: return L1P_T_REQ; - case Litecell15_PrimId_Layer1ResetReq: return L1P_T_REQ; - case Litecell15_PrimId_Layer1ResetCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetCalibTblReq: return L1P_T_REQ; - case Litecell15_PrimId_SetCalibTblCnf: return L1P_T_CONF; - case Litecell15_PrimId_MuteRfReq: return L1P_T_REQ; - case Litecell15_PrimId_MuteRfCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetRxAttenReq: return L1P_T_REQ; - case Litecell15_PrimId_SetRxAttenCnf: return L1P_T_CONF; -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - case Litecell15_PrimId_IsAliveReq: return L1P_T_REQ; - case Litecell15_PrimId_IsAliveCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetMaxCellSizeReq: return L1P_T_REQ; - case Litecell15_PrimId_SetMaxCellSizeCnf: return L1P_T_CONF; - case Litecell15_PrimId_SetC0IdleSlotPowerReductionReq: return L1P_T_REQ; - case Litecell15_PrimId_SetC0IdleSlotPowerReductionCnf: return L1P_T_CONF; -#endif - default: return L1P_T_INVALID; - } -} - -const struct value_string lc15bts_sysprim_names[Litecell15_PrimId_NUM+1] = { - { Litecell15_PrimId_SystemInfoReq, "SYSTEM-INFO.req" }, - { Litecell15_PrimId_SystemInfoCnf, "SYSTEM-INFO.conf" }, - { Litecell15_PrimId_SystemFailureInd, "SYSTEM-FAILURE.ind" }, - { Litecell15_PrimId_ActivateRfReq, "ACTIVATE-RF.req" }, - { Litecell15_PrimId_ActivateRfCnf, "ACTIVATE-RF.conf" }, - { Litecell15_PrimId_DeactivateRfReq, "DEACTIVATE-RF.req" }, - { Litecell15_PrimId_DeactivateRfCnf, "DEACTIVATE-RF.conf" }, - { Litecell15_PrimId_SetTraceFlagsReq, "SET-TRACE-FLAGS.req" }, - { Litecell15_PrimId_Layer1ResetReq, "LAYER1-RESET.req" }, - { Litecell15_PrimId_Layer1ResetCnf, "LAYER1-RESET.conf" }, - { Litecell15_PrimId_SetCalibTblReq, "SET-CALIB.req" }, - { Litecell15_PrimId_SetCalibTblCnf, "SET-CALIB.cnf" }, - { Litecell15_PrimId_MuteRfReq, "MUTE-RF.req" }, - { Litecell15_PrimId_MuteRfCnf, "MUTE-RF.cnf" }, - { Litecell15_PrimId_SetRxAttenReq, "SET-RX-ATTEN.req" }, - { Litecell15_PrimId_SetRxAttenCnf, "SET-RX-ATTEN-CNF.cnf" }, -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - { Litecell15_PrimId_IsAliveReq, "IS-ALIVE.req" }, - { Litecell15_PrimId_IsAliveCnf, "IS-ALIVE-CNF.cnf" }, - { Litecell15_PrimId_SetMaxCellSizeReq, "SET-MAX-CELL-SIZE.req" }, - { Litecell15_PrimId_SetMaxCellSizeCnf, "SET-MAX-CELL-SIZE.cnf" }, - { Litecell15_PrimId_SetC0IdleSlotPowerReductionReq, "SET-C0-IDLE-PWR-RED.req" }, - { Litecell15_PrimId_SetC0IdleSlotPowerReductionCnf, "SET-C0-IDLE-PWR-RED.cnf" }, -#endif - { 0, NULL } -}; - -Litecell15_PrimId_t lc15bts_get_sysprim_conf(Litecell15_PrimId_t id) -{ - switch (id) { - case Litecell15_PrimId_SystemInfoReq: return Litecell15_PrimId_SystemInfoCnf; - case Litecell15_PrimId_ActivateRfReq: return Litecell15_PrimId_ActivateRfCnf; - case Litecell15_PrimId_DeactivateRfReq: return Litecell15_PrimId_DeactivateRfCnf; - case Litecell15_PrimId_Layer1ResetReq: return Litecell15_PrimId_Layer1ResetCnf; - case Litecell15_PrimId_SetCalibTblReq: return Litecell15_PrimId_SetCalibTblCnf; - case Litecell15_PrimId_MuteRfReq: return Litecell15_PrimId_MuteRfCnf; - case Litecell15_PrimId_SetRxAttenReq: return Litecell15_PrimId_SetRxAttenCnf; -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - case Litecell15_PrimId_IsAliveReq: return Litecell15_PrimId_IsAliveCnf; - case Litecell15_PrimId_SetMaxCellSizeReq: return Litecell15_PrimId_SetMaxCellSizeCnf; - case Litecell15_PrimId_SetC0IdleSlotPowerReductionReq: return Litecell15_PrimId_SetC0IdleSlotPowerReductionCnf; -#endif - default: return -1; // Weak - } -} - -const struct value_string lc15bts_l1sapi_names[GsmL1_Sapi_NUM+1] = { - { GsmL1_Sapi_Idle, "IDLE" }, - { GsmL1_Sapi_Fcch, "FCCH" }, - { GsmL1_Sapi_Sch, "SCH" }, - { GsmL1_Sapi_Sacch, "SACCH" }, - { GsmL1_Sapi_Sdcch, "SDCCH" }, - { GsmL1_Sapi_Bcch, "BCCH" }, - { GsmL1_Sapi_Pch, "PCH" }, - { GsmL1_Sapi_Agch, "AGCH" }, - { GsmL1_Sapi_Cbch, "CBCH" }, - { GsmL1_Sapi_Rach, "RACH" }, - { GsmL1_Sapi_TchF, "TCH/F" }, - { GsmL1_Sapi_FacchF, "FACCH/F" }, - { GsmL1_Sapi_TchH, "TCH/H" }, - { GsmL1_Sapi_FacchH, "FACCH/H" }, - { GsmL1_Sapi_Nch, "NCH" }, - { GsmL1_Sapi_Pdtch, "PDTCH" }, - { GsmL1_Sapi_Pacch, "PACCH" }, - { GsmL1_Sapi_Pbcch, "PBCCH" }, - { GsmL1_Sapi_Pagch, "PAGCH" }, - { GsmL1_Sapi_Ppch, "PPCH" }, - { GsmL1_Sapi_Pnch, "PNCH" }, - { GsmL1_Sapi_Ptcch, "PTCCH" }, - { GsmL1_Sapi_Prach, "PRACH" }, - { 0, NULL } -}; - -const struct value_string lc15bts_l1status_names[GSML1_STATUS_NUM+1] = { - { GsmL1_Status_Success, "Success" }, - { GsmL1_Status_Generic, "Generic error" }, - { GsmL1_Status_NoMemory, "Not enough memory" }, - { GsmL1_Status_Timeout, "Timeout" }, - { GsmL1_Status_InvalidParam, "Invalid parameter" }, - { GsmL1_Status_Busy, "Resource busy" }, - { GsmL1_Status_NoRessource, "No more resources" }, - { GsmL1_Status_Uninitialized, "Trying to use uninitialized resource" }, - { GsmL1_Status_NullInterface, "Trying to call a NULL interface" }, - { GsmL1_Status_NullFctnPtr, "Trying to call a NULL function ptr" }, - { GsmL1_Status_BadCrc, "Bad CRC" }, - { GsmL1_Status_BadUsf, "Bad USF" }, - { GsmL1_Status_InvalidCPS, "Invalid CPS field" }, - { GsmL1_Status_UnexpectedBurst, "Unexpected burst" }, - { GsmL1_Status_UnavailCodec, "AMR codec is unavailable" }, - { GsmL1_Status_CriticalError, "Critical error" }, - { GsmL1_Status_OverheatError, "Overheat error" }, - { GsmL1_Status_DeviceError, "Device error" }, - { GsmL1_Status_FacchError, "FACCH / TCH order error" }, - { GsmL1_Status_AlreadyDeactivated, "Lchan already deactivated" }, - { GsmL1_Status_TxBurstFifoOvrn, "FIFO overrun" }, - { GsmL1_Status_TxBurstFifoUndr, "FIFO underrun" }, - { GsmL1_Status_NotSynchronized, "Not synchronized" }, - { GsmL1_Status_Unsupported, "Unsupported feature" }, - { GsmL1_Status_ClockError, "System clock error" }, - { 0, NULL } -}; - -const struct value_string lc15bts_tracef_names[29] = { - { DBG_DEBUG, "DEBUG" }, - { DBG_L1WARNING, "L1_WARNING" }, - { DBG_ERROR, "ERROR" }, - { DBG_L1RXMSG, "L1_RX_MSG" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE" }, - { DBG_L1TXMSG, "L1_TX_MSG" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE" }, - { DBG_MPHCNF, "MPH_CNF" }, - { DBG_MPHIND, "MPH_IND" }, - { DBG_MPHREQ, "MPH_REQ" }, - { DBG_PHIND, "PH_IND" }, - { DBG_PHREQ, "PH_REQ" }, - { DBG_PHYRF, "PHY_RF" }, - { DBG_PHYRFMSGBYTE, "PHY_MSG_BYTE" }, - { DBG_MODE, "MODE" }, - { DBG_TDMAINFO, "TDMA_INFO" }, - { DBG_BADCRC, "BAD_CRC" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "DEVICE_MSG" }, - { DBG_RACHINFO, "RACH_INFO" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "MEMORY" }, - { DBG_PROFILING, "PROFILING" }, - { DBG_TESTCOMMENT, "TEST_COMMENT" }, - { DBG_TEST, "TEST" }, - { DBG_STATUS, "STATUS" }, - { 0, NULL } -}; - -const struct value_string lc15bts_tracef_docs[29] = { - { DBG_DEBUG, "Debug Region" }, - { DBG_L1WARNING, "L1 Warning Region" }, - { DBG_ERROR, "Error Region" }, - { DBG_L1RXMSG, "L1_RX_MSG Region" }, - { DBG_L1RXMSGBYTE, "L1_RX_MSG_BYTE Region" }, - { DBG_L1TXMSG, "L1_TX_MSG Region" }, - { DBG_L1TXMSGBYTE, "L1_TX_MSG_BYTE Region" }, - { DBG_MPHCNF, "MphConfirmation Region" }, - { DBG_MPHIND, "MphIndication Region" }, - { DBG_MPHREQ, "MphRequest Region" }, - { DBG_PHIND, "PhIndication Region" }, - { DBG_PHREQ, "PhRequest Region" }, - { DBG_PHYRF, "PhyRF Region" }, - { DBG_PHYRFMSGBYTE, "PhyRF Message Region" }, - { DBG_MODE, "Mode Region" }, - { DBG_TDMAINFO, "TDMA Info Region" }, - { DBG_BADCRC, "Bad CRC Region" }, - { DBG_PHINDBYTE, "PH_IND_BYTE" }, - { DBG_PHREQBYTE, "PH_REQ_BYTE" }, - { DBG_DEVICEMSG, "Device Message Region" }, - { DBG_RACHINFO, "RACH Info" }, - { DBG_LOGCHINFO, "LOG_CH_INFO" }, - { DBG_MEMORY, "Memory Region" }, - { DBG_PROFILING, "Profiling Region" }, - { DBG_TESTCOMMENT, "Test Comments" }, - { DBG_TEST, "Test Region" }, - { DBG_STATUS, "Status Region" }, - { 0, NULL } -}; - -const struct value_string lc15bts_tch_pl_names[] = { - { GsmL1_TchPlType_NA, "N/A" }, - { GsmL1_TchPlType_Fr, "FR" }, - { GsmL1_TchPlType_Hr, "HR" }, - { GsmL1_TchPlType_Efr, "EFR" }, - { GsmL1_TchPlType_Amr, "AMR(IF2)" }, - { GsmL1_TchPlType_Amr_SidBad, "AMR(SID BAD)" }, - { GsmL1_TchPlType_Amr_Onset, "AMR(ONSET)" }, - { GsmL1_TchPlType_Amr_Ratscch, "AMR(RATSCCH)" }, - { GsmL1_TchPlType_Amr_SidUpdateInH, "AMR(SID_UPDATE INH)" }, - { GsmL1_TchPlType_Amr_SidFirstP1, "AMR(SID_FIRST P1)" }, - { GsmL1_TchPlType_Amr_SidFirstP2, "AMR(SID_FIRST P2)" }, - { GsmL1_TchPlType_Amr_SidFirstInH, "AMR(SID_FIRST INH)" }, - { GsmL1_TchPlType_Amr_RatscchMarker, "AMR(RATSCCH MARK)" }, - { GsmL1_TchPlType_Amr_RatscchData, "AMR(RATSCCH DATA)" }, - { 0, NULL } -}; - -const struct value_string lc15bts_dir_names[] = { - { GsmL1_Dir_TxDownlink, "TxDL" }, - { GsmL1_Dir_TxUplink, "TxUL" }, - { GsmL1_Dir_RxUplink, "RxUL" }, - { GsmL1_Dir_RxDownlink, "RxDL" }, - { GsmL1_Dir_TxDownlink|GsmL1_Dir_RxUplink, "BOTH" }, - { 0, NULL } -}; - -const struct value_string lc15bts_chcomb_names[] = { - { GsmL1_LogChComb_0, "dummy" }, - { GsmL1_LogChComb_I, "tch_f" }, - { GsmL1_LogChComb_II, "tch_h" }, - { GsmL1_LogChComb_IV, "ccch" }, - { GsmL1_LogChComb_V, "ccch_sdcch4" }, - { GsmL1_LogChComb_VII, "sdcch8" }, - { GsmL1_LogChComb_XIII, "pdtch" }, - { 0, NULL } -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS] = { - [PDCH_CS_1] = 23, - [PDCH_CS_2] = 34, - [PDCH_CS_3] = 40, - [PDCH_CS_4] = 54, - [PDCH_MCS_1] = 27, - [PDCH_MCS_2] = 33, - [PDCH_MCS_3] = 42, - [PDCH_MCS_4] = 49, - [PDCH_MCS_5] = 60, - [PDCH_MCS_6] = 78, - [PDCH_MCS_7] = 118, - [PDCH_MCS_8] = 142, - [PDCH_MCS_9] = 154 -}; diff --git a/src/osmo-bts-litecell15/lc15bts.h b/src/osmo-bts-litecell15/lc15bts.h deleted file mode 100644 index ecfeb3da..00000000 --- a/src/osmo-bts-litecell15/lc15bts.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef LC15BTS_H -#define LC15BTS_H - -#include <stdlib.h> -#include <osmocom/core/utils.h> - -#include <nrw/litecell15/litecell15.h> -#include <nrw/litecell15/gsml1const.h> - -/* - * Depending on the firmware version either GsmL1_Prim_t or Litecell15_Prim_t - * is the bigger struct. For earlier firmware versions the GsmL1_Prim_t was the - * bigger struct. - */ -#define LC15BTS_PRIM_SIZE \ - (OSMO_MAX(sizeof(Litecell15_Prim_t), sizeof(GsmL1_Prim_t)) + 128) - -enum l1prim_type { - L1P_T_INVALID, /* this must be 0 to detect uninitialized elements */ - L1P_T_REQ, - L1P_T_CONF, - L1P_T_IND, -}; - - -enum lc15_diversity_mode{ - LC15_DIVERSITY_SISO_A = 0, - LC15_DIVERSITY_SISO_B, - LC15_DIVERSITY_MRC, -}; - -enum lc15_pedestal_mode{ - LC15_PEDESTAL_OFF = 0, - LC15_PEDESTAL_ON, -}; - -enum lc15_led_control_mode{ - LC15_LED_CONTROL_BTS = 0, - LC15_LED_CONTROL_EXT, -}; - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) -enum lc15_auto_pwr_adjust_mode{ - LC15_TX_PWR_ADJ_NONE = 0, - LC15_TX_PWR_ADJ_AUTO, -}; -#endif - -enum l1prim_type lc15bts_get_l1prim_type(GsmL1_PrimId_t id); -extern const struct value_string lc15bts_l1prim_names[GsmL1_PrimId_NUM+1]; -GsmL1_PrimId_t lc15bts_get_l1prim_conf(GsmL1_PrimId_t id); - -enum l1prim_type lc15bts_get_sysprim_type(Litecell15_PrimId_t id); -extern const struct value_string lc15bts_sysprim_names[Litecell15_PrimId_NUM+1]; -Litecell15_PrimId_t lc15bts_get_sysprim_conf(Litecell15_PrimId_t id); - -extern const struct value_string lc15bts_l1sapi_names[GsmL1_Sapi_NUM+1]; -extern const struct value_string lc15bts_l1status_names[GSML1_STATUS_NUM+1]; - -extern const struct value_string lc15bts_tracef_names[29]; -extern const struct value_string lc15bts_tracef_docs[29]; - -extern const struct value_string lc15bts_tch_pl_names[15]; - -extern const struct value_string lc15bts_clksrc_names[10]; - -extern const struct value_string lc15bts_dir_names[6]; - -enum pdch_cs { - PDCH_CS_1, - PDCH_CS_2, - PDCH_CS_3, - PDCH_CS_4, - PDCH_MCS_1, - PDCH_MCS_2, - PDCH_MCS_3, - PDCH_MCS_4, - PDCH_MCS_5, - PDCH_MCS_6, - PDCH_MCS_7, - PDCH_MCS_8, - PDCH_MCS_9, - _NUM_PDCH_CS -}; - -extern const uint8_t pdch_msu_size[_NUM_PDCH_CS]; - -/* LC15 default parameters */ -#define LC15_BTS_MAX_CELL_SIZE_DEFAULT 166 /* 166 qbits is default value */ -#define LC15_BTS_DIVERSITY_MODE_DEFAULT 0 /* SISO-A is default mode */ -#define LC15_BTS_PEDESTAL_MODE_DEFAULT 0 /* Unused TS is off by default */ -#define LC15_BTS_LED_CTRL_MODE_DEFAULT 0 /* LED is controlled by BTS by default */ -#define LC15_BTS_RTP_DRIFT_THRES_DEFAULT 0 /* Default RTP drift threshold is 0 ms (disabled) */ -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) -#define LC15_BTS_DSP_ALIVE_TMR_DEFAULT 5 /* Default DSP alive timer is 5 seconds */ -#define LC15_BTS_TX_PWR_ADJ_DEFAULT 0 /* Default Tx power auto adjustment is none */ -#define LC15_BTS_TX_RED_PWR_8PSK_DEFAULT 0 /* Default 8-PSK maximum power level is 0 dB */ -#define LC15_BTS_TX_C0_IDLE_RED_PWR_DEFAULT 0 /* Default C0 idle slot reduction power level is 0 dB */ -#endif - -#endif /* LC15BTS_H */ diff --git a/src/osmo-bts-litecell15/lc15bts_vty.c b/src/osmo-bts-litecell15/lc15bts_vty.c deleted file mode 100644 index 4a9d7908..00000000 --- a/src/osmo-bts-litecell15/lc15bts_vty.c +++ /dev/null @@ -1,638 +0,0 @@ -/* VTY interface for NuRAN Wireless Litecell 1.5 */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org> - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte <laforge@gnumonks.org> - * (C) 2012,2013 by Holger Hans Peter Freyther - * - * 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 Affero 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 <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <stdint.h> -#include <ctype.h> - -#include <arpa/inet.h> - -#include <osmocom/core/msgb.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/select.h> -#include <osmocom/core/rate_ctr.h> - -#include <osmocom/gsm/tlv.h> - -#include <osmocom/vty/vty.h> -#include <osmocom/vty/command.h> -#include <osmocom/vty/misc.h> - -#include <osmocom/ctrl/control_cmd.h> -#include <osmo-bts/signal.h> -#include <osmo-bts/oml.h> -#include <osmo-bts/bts.h> - -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/phy_link.h> -#include <osmo-bts/logging.h> -#include <osmo-bts/bts_model.h> -#include <osmo-bts/vty.h> -#include <osmo-bts/rsl.h> - -#include "lc15bts.h" -#include "l1_if.h" -#include "utils.h" - -extern int lchan_activate(struct gsm_lchan *lchan); -extern int rsl_tx_preproc_meas_res(struct gsm_lchan *lchan); - -#define TRX_STR "Transceiver related commands\n" "TRX number\n" - -#define SHOW_TRX_STR \ - SHOW_STR \ - TRX_STR -#define DSP_TRACE_F_STR "DSP Trace Flag\n" - -static const struct value_string lc15_diversity_mode_strs[] = { - { LC15_DIVERSITY_SISO_A, "siso-a" }, - { LC15_DIVERSITY_SISO_B, "siso-b" }, - { LC15_DIVERSITY_MRC, "mrc" }, - { 0, NULL } -}; - -static const struct value_string lc15_pedestal_mode_strs[] = { - { LC15_PEDESTAL_OFF, "off" }, - { LC15_PEDESTAL_ON, "on" }, - { 0, NULL } -}; - -static const struct value_string lc15_led_mode_strs[] = { - { LC15_LED_CONTROL_BTS, "bts" }, - { LC15_LED_CONTROL_EXT, "external" }, - { 0, NULL } -}; - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) -static const struct value_string lc15_auto_adj_pwr_strs[] = { - { LC15_TX_PWR_ADJ_NONE, "none" }, - { LC15_TX_PWR_ADJ_AUTO, "auto" }, - { 0, NULL } -}; -#endif - -/* configuration */ - -DEFUN(cfg_phy_cal_path, cfg_phy_cal_path_cmd, - "trx-calibration-path PATH", - "Set the path name to TRX calibration data\n" "Path name\n") -{ - struct phy_instance *pinst = vty->index; - - if (pinst->u.lc15.calib_path) - talloc_free(pinst->u.lc15.calib_path); - - pinst->u.lc15.calib_path = talloc_strdup(pinst, argv[0]); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_dsp_trace_f, cfg_phy_dsp_trace_f_cmd, - "HIDDEN", TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(lc15bts_tracef_names, argv[0]); - pinst->u.lc15.dsp_trace_f |= flag; - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_no_dsp_trace_f, cfg_phy_no_dsp_trace_f_cmd, - "HIDDEN", NO_STR TRX_STR) -{ - struct phy_instance *pinst = vty->index; - unsigned int flag; - - flag = get_string_value(lc15bts_tracef_names, argv[0]); - pinst->u.lc15.dsp_trace_f &= ~flag; - - return CMD_SUCCESS; -} - - -/* runtime */ - -DEFUN(show_dsp_trace_f, show_dsp_trace_f_cmd, - "show trx <0-0> dsp-trace-flags", - SHOW_TRX_STR "Display the current setting of the DSP trace flags") -{ - int trx_nr = atoi(argv[0]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(g_bts, trx_nr); - struct lc15l1_hdl *fl1h; - int i; - - if (!trx) - return CMD_WARNING; - - fl1h = trx_lc15l1_hdl(trx); - - vty_out(vty, "Litecell15 L1 DSP trace flags:%s", VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(lc15bts_tracef_names); i++) { - const char *endis; - - if (lc15bts_tracef_names[i].value == 0 && - lc15bts_tracef_names[i].str == NULL) - break; - - if (fl1h->dsp_trace_f & lc15bts_tracef_names[i].value) - endis = "enabled"; - else - endis = "disabled"; - - vty_out(vty, "DSP Trace %-15s %s%s", - lc15bts_tracef_names[i].str, endis, - VTY_NEWLINE); - } - - return CMD_SUCCESS; - -} - -DEFUN(dsp_trace_f, dsp_trace_f_cmd, "HIDDEN", TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct lc15l1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.lc15.hdl; - flag = get_string_value(lc15bts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f | flag); - - return CMD_SUCCESS; -} - -DEFUN(no_dsp_trace_f, no_dsp_trace_f_cmd, "HIDDEN", NO_STR TRX_STR) -{ - int phy_nr = atoi(argv[0]); - struct phy_instance *pinst; - struct lc15l1_hdl *fl1h; - unsigned int flag ; - - pinst = vty_get_phy_instance(vty, phy_nr, 0); - if (!pinst) - return CMD_WARNING; - - fl1h = pinst->u.lc15.hdl; - flag = get_string_value(lc15bts_tracef_names, argv[1]); - l1if_set_trace_flags(fl1h, fl1h->dsp_trace_f & ~flag); - - return CMD_SUCCESS; -} - -DEFUN(show_sys_info, show_sys_info_cmd, - "show phy <0-1> instance <0-0> system-information", - SHOW_TRX_STR "Display information about system\n") -{ - int phy_nr = atoi(argv[0]); - int inst_nr = atoi(argv[1]); - struct phy_link *plink = phy_link_by_num(phy_nr); - struct phy_instance *pinst; - struct lc15l1_hdl *fl1h; - int i; - - if (!plink) { - vty_out(vty, "Cannot find PHY link %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - pinst = phy_instance_by_num(plink, inst_nr); - if (!plink) { - vty_out(vty, "Cannot find PHY instance %u%s", - phy_nr, VTY_NEWLINE); - return CMD_WARNING; - } - fl1h = pinst->u.lc15.hdl; - - vty_out(vty, "DSP Version: %u.%u.%u, FPGA Version: %u.%u.%u%s", - fl1h->hw_info.dsp_version[0], - fl1h->hw_info.dsp_version[1], - fl1h->hw_info.dsp_version[2], - fl1h->hw_info.fpga_version[0], - fl1h->hw_info.fpga_version[1], - fl1h->hw_info.fpga_version[2], VTY_NEWLINE); - - vty_out(vty, "GSM Band Support: "); - for (i = 0; i < sizeof(fl1h->hw_info.band_support); i++) { - if (fl1h->hw_info.band_support & (1 << i)) - vty_out(vty, "%s ", gsm_band_name(1 << i)); - } - vty_out(vty, "%s", VTY_NEWLINE); - vty_out(vty, "Min Tx Power: %d dBm%s", fl1h->phy_inst->u.lc15.minTxPower, VTY_NEWLINE); - vty_out(vty, "Max Tx Power: %d dBm%s", fl1h->phy_inst->u.lc15.maxTxPower, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(activate_lchan, activate_lchan_cmd, - "trx <0-0> <0-7> (activate|deactivate) <0-7>", - TRX_STR - "Timeslot number\n" - "Activate Logical Channel\n" - "Deactivate Logical Channel\n" - "Logical Channel Number\n" ) -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[3]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(g_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - if (!strcmp(argv[2], "activate")) - lchan_activate(lchan); - else - lchan_deactivate(lchan); - - return CMD_SUCCESS; -} - -DEFUN(set_tx_power, set_tx_power_cmd, - "trx nr <0-1> tx-power <-110-100>", - TRX_STR - "TRX number \n" - "Set transmit power (override BSC)\n" - "Transmit power in dBm\n") -{ - int trx_nr = atoi(argv[0]); - int power = atoi(argv[1]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(g_bts, trx_nr); - - power_ramp_start(trx, to_mdB(power), 1, NULL); - - return CMD_SUCCESS; -} - -DEFUN(loopback, loopback_cmd, - "trx <0-0> <0-7> loopback <0-1>", - TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(g_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 1; - - return CMD_SUCCESS; -} - -DEFUN(no_loopback, no_loopback_cmd, - "no trx <0-0> <0-7> loopback <0-1>", - NO_STR TRX_STR - "Timeslot number\n" - "Set TCH loopback\n" - "Logical Channel Number\n") -{ - int trx_nr = atoi(argv[0]); - int ts_nr = atoi(argv[1]); - int lchan_nr = atoi(argv[2]); - struct gsm_bts_trx *trx = gsm_bts_trx_num(g_bts, trx_nr); - struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr]; - struct gsm_lchan *lchan = &ts->lchan[lchan_nr]; - - lchan->loopback = 0; - - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd, - "nominal-tx-power <0-40>", - "Set the nominal transmit output power in dBm\n" - "Nominal transmit output power level in dBm\n") -{ - int nominal_power = atoi(argv[0]); - struct gsm_bts_trx *trx = vty->index; - - if (( nominal_power > 40 ) || ( nominal_power < 0 )) { - vty_out(vty, "Nominal Tx power level must be between 0 and 40 dBm (%d) %s", - nominal_power, VTY_NEWLINE); - return CMD_WARNING; - } - - trx->nominal_power = nominal_power; - trx->power_params.trx_p_max_out_mdBm = to_mdB(nominal_power); - - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_max_cell_size, cfg_phy_max_cell_size_cmd, - "max-cell-size <0-166>", - "Set the maximum cell size in qbits\n") -{ - struct phy_instance *pinst = vty->index; - int cell_size = (uint8_t)atoi(argv[0]); - - if (( cell_size > 166 ) || ( cell_size < 0 )) { - vty_out(vty, "Max cell size must be between 0 and 166 qbits (%d) %s", - cell_size, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.lc15.max_cell_size = (uint8_t)cell_size; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_diversity_mode, cfg_phy_diversity_mode_cmd, - "diversity-mode (siso-a|siso-b|mrc)", - "Set reception diversity mode \n" - "Reception diversity mode can be (siso-a, siso-b, mrc)\n") -{ - struct phy_instance *pinst = vty->index; - int val = get_string_value(lc15_diversity_mode_strs, argv[0]); - - if((val < LC15_DIVERSITY_SISO_A) || (val > LC15_DIVERSITY_MRC)) { - vty_out(vty, "Invalid reception diversity mode %d%s", val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.lc15.diversity_mode = (uint8_t)val; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_pedestal_mode, cfg_phy_pedestal_mode_cmd, - "pedestal-mode (on|off)", - "Set unused time-slot transmission in pedestal mode\n" - "Transmission pedestal mode can be (off, on)\n") -{ - struct phy_instance *pinst = vty->index; - int val = get_string_value(lc15_pedestal_mode_strs, argv[0]); - - if((val < LC15_PEDESTAL_OFF) || (val > LC15_PEDESTAL_ON)) { - vty_out(vty, "Invalid unused time-slot transmission mode %d%s", val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.lc15.pedestal_mode = (uint8_t)val; - return CMD_SUCCESS; -} - -DEFUN(cfg_bts_led_mode, cfg_bts_led_mode_cmd, - "led-control-mode (bts|external)", - "Set LED controlled by BTS or external software\n" - "LED can be controlled by (bts, external)\n") -{ - struct gsm_bts *bts = vty->index; - int val = get_string_value(lc15_led_mode_strs, argv[0]); - - if((val < LC15_LED_CONTROL_BTS) || (val > LC15_LED_CONTROL_EXT)) { - vty_out(vty, "Invalid LED control mode %d%s", val, VTY_NEWLINE); - return CMD_WARNING; - } - - struct bts_lc15_priv *bts_lc15 = bts->model_priv; - bts_lc15->led_ctrl_mode = (uint8_t)val; - return CMD_SUCCESS; -} - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) -DEFUN(cfg_phy_dsp_alive_timer, cfg_phy_dsp_alive_timer_cmd, - "dsp-alive-period <0-60>", - "Set DSP alive timer period in second\n") -{ - struct phy_instance *pinst = vty->index; - uint8_t period = (uint8_t)atoi(argv[0]); - - if (( period > 60 ) || ( period < 0 )) { - vty_out(vty, "DSP heart beat alive timer period must be between 0 and 60 seconds (%d) %s", - period, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.lc15.dsp_alive_period = period; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_auto_tx_pwr_adj, cfg_phy_auto_tx_pwr_adj_cmd, - "pwr-adj-mode (none|auto)", - "Set output power adjustment mode\n") -{ - struct phy_instance *pinst = vty->index; - int val = get_string_value(lc15_auto_adj_pwr_strs, argv[0]); - - if((val < LC15_TX_PWR_ADJ_NONE) || (val > LC15_TX_PWR_ADJ_AUTO)) { - vty_out(vty, "Invalid output power adjustment mode %d%s", val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.lc15.tx_pwr_adj_mode = (uint8_t)val; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_tx_red_pwr_8psk, cfg_phy_tx_red_pwr_8psk_cmd, - "tx-red-pwr-8psk <0-40>", - "Set reduction output power for 8-PSK scheme in dB unit\n") -{ - struct phy_instance *pinst = vty->index; - int val = atoi(argv[0]); - - if ((val > 40) || (val < 0)) { - vty_out(vty, "Reduction Tx power level must be between 0 and 40 dB (%d) %s", - val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.lc15.tx_pwr_red_8psk = (uint8_t)val; - return CMD_SUCCESS; -} - -DEFUN(cfg_phy_c0_idle_red_pwr, cfg_phy_c0_idle_red_pwr_cmd, - "c0-idle-red-pwr <0-40>", - "Set reduction output power for C0 idle slot in dB unit\n") -{ - struct phy_instance *pinst = vty->index; - int val = atoi(argv[0]); - - if ((val > 40) || (val < 0)) { - vty_out(vty, "Reduction Tx power level must be between 0 and 40 dB (%d) %s", - val, VTY_NEWLINE); - return CMD_WARNING; - } - - pinst->u.lc15.tx_c0_idle_pwr_red = (uint8_t)val; - return CMD_SUCCESS; -} -#endif - -DEFUN(cfg_bts_rtp_drift_threshold, cfg_bts_rtp_drift_threshold_cmd, - "rtp-drift-threshold <0-10000>", - "RTP parameters\n" - "RTP timestamp drift threshold in ms\n") -{ - struct gsm_bts *bts = vty->index; - - struct bts_lc15_priv *bts_lc15 = bts->model_priv; - bts_lc15->rtp_drift_thres_ms = (unsigned int) atoi(argv[0]); - - return CMD_SUCCESS; -} - -void bts_model_config_write_bts(struct vty *vty, const struct gsm_bts *bts) -{ - const struct bts_lc15_priv *bts_lc15 = bts->model_priv; - vty_out(vty, " led-control-mode %s%s", - get_value_string(lc15_led_mode_strs, bts_lc15->led_ctrl_mode), VTY_NEWLINE); - - vty_out(vty, " rtp-drift-threshold %d%s", - bts_lc15->rtp_drift_thres_ms, VTY_NEWLINE); - -} - -void bts_model_config_write_trx(struct vty *vty, const struct gsm_bts_trx *trx) -{ - vty_out(vty, " nominal-tx-power %d%s", trx->nominal_power,VTY_NEWLINE); -} - -void bts_model_config_write_phy(struct vty *vty, const struct phy_link *plink) -{ -} - -void bts_model_config_write_phy_inst(struct vty *vty, const struct phy_instance *pinst) -{ - int i; - - for (i = 0; i < 32; i++) { - if (pinst->u.lc15.dsp_trace_f & (1 << i)) { - const char *name; - name = get_value_string(lc15bts_tracef_names, (1 << i)); - vty_out(vty, " dsp-trace-flag %s%s", name, - VTY_NEWLINE); - } - } - if (pinst->u.lc15.calib_path) - vty_out(vty, " trx-calibration-path %s%s", - pinst->u.lc15.calib_path, VTY_NEWLINE); - - vty_out(vty, " max-cell-size %d%s", - pinst->u.lc15.max_cell_size, VTY_NEWLINE); - - vty_out(vty, " diversity-mode %s%s", - get_value_string(lc15_diversity_mode_strs, pinst->u.lc15.diversity_mode), VTY_NEWLINE); - - vty_out(vty, " pedestal-mode %s%s", - get_value_string(lc15_pedestal_mode_strs, pinst->u.lc15.pedestal_mode) , VTY_NEWLINE); - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - vty_out(vty, " dsp-alive-period %d%s", - pinst->u.lc15.dsp_alive_period, VTY_NEWLINE); - - vty_out(vty, " pwr-adj-mode %s%s", - get_value_string(lc15_auto_adj_pwr_strs, pinst->u.lc15.tx_pwr_adj_mode), VTY_NEWLINE); - - vty_out(vty, " tx-red-pwr-8psk %d%s", - pinst->u.lc15.tx_pwr_red_8psk, VTY_NEWLINE); - - vty_out(vty, " c0-idle-red-pwr %d%s", - pinst->u.lc15.tx_c0_idle_pwr_red, VTY_NEWLINE); -#endif -} - -int bts_model_vty_init(void *ctx) -{ - /* runtime-patch the command strings with debug levels */ - dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(ctx, lc15bts_tracef_names, - "phy <0-0> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(ctx, lc15bts_tracef_docs, - TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - no_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(ctx, lc15bts_tracef_names, - "no phy <0-0> dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - no_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(ctx, lc15bts_tracef_docs, - NO_STR TRX_STR DSP_TRACE_F_STR, - "\n", "", 0); - - cfg_phy_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(ctx, - lc15bts_tracef_names, - "dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - cfg_phy_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(ctx, - lc15bts_tracef_docs, - DSP_TRACE_F_STR, - "\n", "", 0); - - cfg_phy_no_dsp_trace_f_cmd.string = vty_cmd_string_from_valstr(ctx, - lc15bts_tracef_names, - "no dsp-trace-flag (", - "|",")", VTY_DO_LOWER); - cfg_phy_no_dsp_trace_f_cmd.doc = vty_cmd_string_from_valstr(ctx, - lc15bts_tracef_docs, - NO_STR DSP_TRACE_F_STR, - "\n", "", 0); - - install_element_ve(&show_dsp_trace_f_cmd); - install_element_ve(&show_sys_info_cmd); - install_element_ve(&dsp_trace_f_cmd); - install_element_ve(&no_dsp_trace_f_cmd); - - install_element(ENABLE_NODE, &activate_lchan_cmd); - install_element(ENABLE_NODE, &set_tx_power_cmd); - - install_element(ENABLE_NODE, &loopback_cmd); - install_element(ENABLE_NODE, &no_loopback_cmd); - - install_element(BTS_NODE, &cfg_bts_auto_band_cmd); - install_element(BTS_NODE, &cfg_bts_no_auto_band_cmd); - install_element(BTS_NODE, &cfg_bts_led_mode_cmd); - install_element(BTS_NODE, &cfg_bts_rtp_drift_threshold_cmd); - - install_element(TRX_NODE, &cfg_trx_nominal_power_cmd); - - install_element(PHY_INST_NODE, &cfg_phy_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_no_dsp_trace_f_cmd); - install_element(PHY_INST_NODE, &cfg_phy_cal_path_cmd); - - install_element(PHY_INST_NODE, &cfg_phy_diversity_mode_cmd); - install_element(PHY_INST_NODE, &cfg_phy_pedestal_mode_cmd); - install_element(PHY_INST_NODE, &cfg_phy_max_cell_size_cmd); -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - install_element(PHY_INST_NODE, &cfg_phy_dsp_alive_timer_cmd); - install_element(PHY_INST_NODE, &cfg_phy_auto_tx_pwr_adj_cmd); - install_element(PHY_INST_NODE, &cfg_phy_tx_red_pwr_8psk_cmd); - install_element(PHY_INST_NODE, &cfg_phy_c0_idle_red_pwr_cmd); -#endif - return 0; -} - -int bts_model_ctrl_cmds_install(struct gsm_bts *bts) -{ - return 0; -} diff --git a/src/osmo-bts-litecell15/main.c b/src/osmo-bts-litecell15/main.c deleted file mode 100644 index 985d7dba..00000000 --- a/src/osmo-bts-litecell15/main.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Main program for NuRAN Wireless Litecell 1.5 BTS */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * Copyright (C) 2016 by Harald Welte <laforge@gnumonks.org> - * - * Based on sysmoBTS: - * (C) 2011-2013 by Harald Welte <laforge@gnumonks.org> - * - * 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 <stdlib.h> -#include <errno.h> -#include <getopt.h> -#include <limits.h> -#include <sys/signal.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sched.h> - -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/application.h> -#include <osmocom/vty/telnet_interface.h> -#include <osmocom/vty/logging.h> -#include <osmocom/vty/ports.h> - -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/logging.h> -#include <osmo-bts/bts.h> -#include <osmo-bts/vty.h> -#include <osmo-bts/bts_model.h> -#include <osmo-bts/pcu_if.h> -#include <osmo-bts/l1sap.h> - -static int write_status_file(char *status_file, char *status_str) -{ - FILE *outf; - char tmp[PATH_MAX+1]; - - snprintf(tmp, sizeof(tmp)-1, "/var/run/osmo-bts/%s", status_file); - tmp[PATH_MAX-1] = '\0'; - - outf = fopen(tmp, "w"); - if (!outf) - return -1; - - fprintf(outf, "%s\n", status_str); - - fclose(outf); - - return 0; -} - -/*NTQD: Change how rx_nr is handle in multi-trx*/ -#define LC15BTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" - -#include "utils.h" -#include "l1_if.h" -#include "hw_misc.h" -#include "misc/lc15bts_bid.h" - -unsigned int dsp_trace = 0x00000000; - -int bts_model_init(struct gsm_bts *bts) -{ - struct stat st; - - struct bts_lc15_priv *bts_lc15 = talloc(bts, struct bts_lc15_priv); - - bts->model_priv = bts_lc15; - bts->variant = BTS_OSMO_LITECELL15; - bts->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); - - /* specific default values for LC15 platform */ - bts_lc15->led_ctrl_mode = LC15_BTS_LED_CTRL_MODE_DEFAULT; - /* RTP drift threshold default */ - bts_lc15->rtp_drift_thres_ms = LC15_BTS_RTP_DRIFT_THRES_DEFAULT; - - if (stat(LC15BTS_RF_LOCK_PATH, &st) == 0) { - LOGP(DL1C, LOGL_NOTICE, "Not starting BTS due to RF_LOCK file present\n"); - exit(23); - } - - osmo_bts_set_feature(bts->features, BTS_FEAT_GPRS); - osmo_bts_set_feature(bts->features, BTS_FEAT_EGPRS); - osmo_bts_set_feature(bts->features, BTS_FEAT_OML_ALERTS); - osmo_bts_set_feature(bts->features, BTS_FEAT_AGCH_PCH_PROP); - osmo_bts_set_feature(bts->features, BTS_FEAT_SPEECH_F_V1); - osmo_bts_set_feature(bts->features, BTS_FEAT_SPEECH_H_V1); - osmo_bts_set_feature(bts->features, BTS_FEAT_SPEECH_F_EFR); - osmo_bts_set_feature(bts->features, BTS_FEAT_SPEECH_F_AMR); - osmo_bts_set_feature(bts->features, BTS_FEAT_SPEECH_H_AMR); - - bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MS_PWR_CTRL_DSP); - - return 0; -} - -int bts_model_trx_init(struct gsm_bts_trx *trx) -{ - trx->nominal_power = 40; - trx->power_params.trx_p_max_out_mdBm = to_mdB(trx->bts->c0->nominal_power); - return 0; -} - -void bts_model_phy_link_set_defaults(struct phy_link *plink) -{ -} - -void bts_model_phy_instance_set_defaults(struct phy_instance *pinst) -{ -} - -int bts_model_oml_estab(struct gsm_bts *bts) -{ - /* update status file */ - write_status_file("state", ""); - - return 0; -} - -void bts_update_status(enum bts_global_status which, int on) -{ - static uint64_t states = 0; - uint64_t old_states = states; - - if (on) - states |= (1ULL << which); - else - states &= ~(1ULL << which); - - LOGP(DL1C, LOGL_INFO, - "Set global status #%d to %d (%04llx -> %04llx)", - which, on, - (long long)old_states, (long long)states); -} - -void bts_model_print_help() -{ - printf( "\nModel specific options:\n" - " -w --hw-version Print the targeted HW Version\n" - " -M --pcu-direct Force PCU to access message queue for " - "PDCH dchannel directly\n" - " -p --dsp-trace Set DSP trace flags\n" - ); -} - -static void print_hwversion() -{ - printf(get_hwversion_desc()); - printf("\n"); -} - -int bts_model_handle_options(int argc, char **argv) -{ - int num_errors = 0; - - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { "dsp-trace", 1, 0, 'p' }, - { "hw-version", 0, 0, 'w' }, - { "pcu-direct", 0, 0, 'M' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "p:wM", - long_options, &option_idx); - if (c == -1) - break; - - switch (c) { - case 'p': - dsp_trace = strtoul(optarg, NULL, 16); - break; - case 'M': - pcu_direct = 1; - break; - case 'w': - print_hwversion(); - exit(0); - break; - default: - num_errors++; - break; - } - } - - return num_errors; -} - -void bts_model_abis_close(struct gsm_bts *bts) -{ - /* write to status file */ - write_status_file("state", "ABIS DOWN"); - - /* for now, we simply terminate the program and re-spawn */ - bts_shutdown(bts, "Abis close"); -} - -int main(int argc, char **argv) -{ - /* create status file with initial state */ - write_status_file("state", "ABIS DOWN"); - - return bts_main(argc, argv); -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_bid.c b/src/osmo-bts-litecell15/misc/lc15bts_bid.c deleted file mode 100644 index 9284b62e..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_bid.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * 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 <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <stdbool.h> - -#include "lc15bts_bid.h" - -#define BOARD_REV_SYSFS "/var/lc15/platform/revision" -#define BOARD_OPT_SYSFS "/var/lc15/platform/option" - -static const int option_type_mask[_NUM_OPTION_TYPES] = { - [LC15BTS_OPTION_OCXO] = 0x07, - [LC15BTS_OPTION_FPGA] = 0x03, - [LC15BTS_OPTION_PA] = 0x01, - [LC15BTS_OPTION_BAND] = 0x03, - [LC15BTS_OPTION_TX_ISO_BYP] = 0x01, - [LC15BTS_OPTION_RX_DUP_BYP] = 0x01, - [LC15BTS_OPTION_RX_PB_BYP] = 0x01, - [LC15BTS_OPTION_RX_DIV] = 0x01, - [LC15BTS_OPTION_RX1A] = 0x01, - [LC15BTS_OPTION_RX1B] = 0x01, - [LC15BTS_OPTION_RX2A] = 0x01, - [LC15BTS_OPTION_RX2B] = 0x01, - [LC15BTS_OPTION_DDR_32B] = 0x01, - [LC15BTS_OPTION_DDR_ECC] = 0x01, - [LC15BTS_OPTION_LOG_DET] = 0x01, - [LC15BTS_OPTION_DUAL_LOG_DET] = 0x01, -}; - -static const int option_type_shift[_NUM_OPTION_TYPES] = { - [LC15BTS_OPTION_OCXO] = 0, - [LC15BTS_OPTION_FPGA] = 3, - [LC15BTS_OPTION_PA] = 5, - [LC15BTS_OPTION_BAND] = 6, - [LC15BTS_OPTION_TX_ISO_BYP] = 8, - [LC15BTS_OPTION_RX_DUP_BYP] = 9, - [LC15BTS_OPTION_RX_PB_BYP] = 10, - [LC15BTS_OPTION_RX_DIV] = 11, - [LC15BTS_OPTION_RX1A] = 12, - [LC15BTS_OPTION_RX1B] = 13, - [LC15BTS_OPTION_RX2A] = 14, - [LC15BTS_OPTION_RX2B] = 15, - [LC15BTS_OPTION_DDR_32B] = 16, - [LC15BTS_OPTION_DDR_ECC] = 17, - [LC15BTS_OPTION_LOG_DET] = 18, - [LC15BTS_OPTION_DUAL_LOG_DET] = 19, -}; - - -static int board_rev = -1; -static int board_option = -1; - -static inline bool read_board(const char *src, const char *spec, void *dst) -{ - FILE *fp = fopen(src, "r"); - if (!fp) { - fprintf(stderr, "Failed to open %s due to '%s' error\n", src, strerror(errno)); - return false; - } - - if (fscanf(fp, spec, dst) != 1) { - fclose(fp); - fprintf(stderr, "Failed to read %s due to '%s' error\n", src, strerror(errno)); - return false; - } - fclose(fp); - return true; -} - -int lc15bts_rev_get(void) -{ - char rev; - - if (board_rev != -1) { - return board_rev; - } - - if (!read_board(BOARD_REV_SYSFS, "%c", &rev)) - return -1; - - board_rev = rev; - return board_rev; -} - -int lc15bts_model_get(void) -{ - int opt; - - if (board_option != -1) - return board_option; - - if (!read_board(BOARD_OPT_SYSFS, "%X", &opt)) - return -1; - - board_option = opt; - return board_option; -} - -int lc15bts_option_get(enum lc15bts_option_type type) -{ - int rc; - int option; - - if (type >= _NUM_OPTION_TYPES) { - return -EINVAL; - } - - if (board_option == -1) { - rc = lc15bts_model_get(); - if (rc < 0) return rc; - } - - option = (board_option >> option_type_shift[type]) - & option_type_mask[type]; - - return option; -} - -const char* get_hwversion_desc() -{ - int rev; - int model; - size_t len; - static char model_name[64] = {0, }; - len = snprintf(model_name, sizeof(model_name), "NuRAN Litecell 1.5 BTS"); - - rev = lc15bts_rev_get(); - if (rev >= 0) { - len += snprintf(model_name + len, sizeof(model_name) - len, - " Rev %c", (char)rev); - } - - model = lc15bts_model_get(); - if (model >= 0) { - snprintf(model_name + len, sizeof(model_name) - len, - "%s (%05X)", model_name, model); - } - return model_name; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_bid.h b/src/osmo-bts-litecell15/misc/lc15bts_bid.h deleted file mode 100644 index a71fdd7e..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_bid.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _LC15BTS_BOARD_H -#define _LC15BTS_BOARD_H - -#include <stdint.h> - -enum lc15bts_option_type { - LC15BTS_OPTION_OCXO, - LC15BTS_OPTION_FPGA, - LC15BTS_OPTION_PA, - LC15BTS_OPTION_BAND, - LC15BTS_OPTION_TX_ISO_BYP, - LC15BTS_OPTION_RX_DUP_BYP, - LC15BTS_OPTION_RX_PB_BYP, - LC15BTS_OPTION_RX_DIV, - LC15BTS_OPTION_RX1A, - LC15BTS_OPTION_RX1B, - LC15BTS_OPTION_RX2A, - LC15BTS_OPTION_RX2B, - LC15BTS_OPTION_DDR_32B, - LC15BTS_OPTION_DDR_ECC, - LC15BTS_OPTION_LOG_DET, - LC15BTS_OPTION_DUAL_LOG_DET, - _NUM_OPTION_TYPES -}; - -enum lc15bts_ocxo_type { - LC15BTS_OCXO_BILAY_NVG45AV2072, - LC15BTS_OCXO_TAITIEN_NJ26M003, - _NUM_OCXO_TYPES -}; - -enum lc15bts_fpga_type { - LC15BTS_FPGA_35T, - LC15BTS_FPGA_50T, - LC15BTS_FPGA_75T, - LC15BTS_FPGA_100T, - _NUM_FPGA_TYPES -}; - -enum lc15bts_gsm_band { - LC15BTS_BAND_850, - LC15BTS_BAND_900, - LC15BTS_BAND_1800, - LC15BTS_BAND_1900, -}; - -int lc15bts_rev_get(void); -int lc15bts_model_get(void); -int lc15bts_option_get(enum lc15bts_option_type type); -const char* get_hwversion_desc(); - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_bts.c b/src/osmo-bts-litecell15/misc/lc15bts_bts.c deleted file mode 100644 index 0343e930..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_bts.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2016 by NuRAN Wireless <support@nuranwireless.com> - * - * 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 <sys/ioctl.h> -#include <net/if.h> -#include <netdb.h> -#include <ifaddrs.h> -#include <netinet/in.h> -#include <netinet/ip.h> -#include "lc15bts_mgr.h" -#include "lc15bts_bts.h" - -static int check_eth_status(char *dev_name) -{ - int fd, rc; - struct ifreq ifr; - - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - if (fd < 0) - return fd; - - memset(&ifr, 0, sizeof(ifr)); - memcpy(&ifr.ifr_name, dev_name, sizeof(ifr.ifr_name)); - rc = ioctl(fd, SIOCGIFFLAGS, &ifr); - close(fd); - - if (rc < 0) - return rc; - - if ((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING)) - return 0; - - return 1; -} - -void check_bts_led_pattern(uint8_t *led) -{ - FILE *fp; - char str[64] = "\0"; - int rc; - - /* check for existing of BTS state file */ - if ((fp = fopen("/var/run/osmo-bts/state", "r")) == NULL) { - led[BLINK_PATTERN_INIT] = 1; - return; - } - - /* check Ethernet interface status */ - rc = check_eth_status("eth0"); - if (rc > 0) { - LOGP(DTEMP, LOGL_DEBUG,"External link is DOWN\n"); - led[BLINK_PATTERN_EXT_LINK_MALFUNC] = 1; - fclose(fp); - return; - } - - /* check for BTS is still alive */ - if (system("pidof osmo-bts-lc15 > /dev/null")) { - LOGP(DTEMP, LOGL_DEBUG,"BTS process has stopped\n"); - led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1; - fclose(fp); - return; - } - - /* check for BTS state */ - while (fgets(str, 64, fp) != NULL) { - LOGP(DTEMP, LOGL_DEBUG,"BTS state is %s\n", (strstr(str, "ABIS DOWN") != NULL) ? "DOWN" : "UP"); - if (strstr(str, "ABIS DOWN") != NULL) - led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1; - } - fclose(fp); - - return; -} - -int check_sensor_led_pattern( struct lc15bts_mgr_instance *mgr, uint8_t *led) -{ - if(mgr->alarms.temp_high == 1) - led[BLINK_PATTERN_TEMP_HIGH] = 1; - - if(mgr->alarms.temp_max == 1) - led[BLINK_PATTERN_TEMP_MAX] = 1; - - if(mgr->alarms.supply_low == 1) - led[BLINK_PATTERN_SUPPLY_VOLT_LOW] = 1; - - if(mgr->alarms.supply_min == 1) - led[BLINK_PATTERN_SUPPLY_VOLT_MIN] = 1; - - if(mgr->alarms.vswr_high == 1) - led[BLINK_PATTERN_VSWR_HIGH] = 1; - - if(mgr->alarms.vswr_max == 1) - led[BLINK_PATTERN_VSWR_MAX] = 1; - - if(mgr->alarms.supply_pwr_high == 1) - led[BLINK_PATTERN_SUPPLY_PWR_HIGH] = 1; - - if(mgr->alarms.supply_pwr_max == 1) - led[BLINK_PATTERN_SUPPLY_PWR_MAX] = 1; - - if(mgr->alarms.supply_pwr_max2 == 1) - led[BLINK_PATTERN_SUPPLY_PWR_MAX2] = 1; - - if(mgr->alarms.pa_pwr_high == 1) - led[BLINK_PATTERN_PA_PWR_HIGH] = 1; - - if(mgr->alarms.pa_pwr_max == 1) - led[BLINK_PATTERN_PA_PWR_MAX] = 1; - - if(mgr->alarms.gps_fix_lost == 1) - led[BLINK_PATTERN_GPS_FIX_LOST] = 1; - - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_bts.h b/src/osmo-bts-litecell15/misc/lc15bts_bts.h deleted file mode 100644 index 3918b870..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_bts.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _LC15BTS_BTS_H_ -#define _LC15BTS_BTS_H_ - -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <stdint.h> -#include <ctype.h> -#include <string.h> -#include <sys/signal.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <osmo-bts/logging.h> - -/* public function prototypes */ -void check_bts_led_pattern(uint8_t *led); -int check_sensor_led_pattern( struct lc15bts_mgr_instance *mgr, uint8_t *led); - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_clock.c b/src/osmo-bts-litecell15/misc/lc15bts_clock.c deleted file mode 100644 index 71701496..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_clock.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * 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 <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> - -#include "lc15bts_clock.h" - -#define CLKERR_ERR_SYSFS "/var/lc15/clkerr/clkerr1_average" -#define CLKERR_ACC_SYSFS "/var/lc15/clkerr/clkerr1_average_accuracy" -#define CLKERR_INT_SYSFS "/var/lc15/clkerr/clkerr1_average_interval" -#define CLKERR_FLT_SYSFS "/var/lc15/clkerr/clkerr1_fault" -#define CLKERR_RFS_SYSFS "/var/lc15/clkerr/refresh" -#define CLKERR_RST_SYSFS "/var/lc15/clkerr/reset" - -#define OCXODAC_VAL_SYSFS "/var/lc15/ocxo/voltage" -#define OCXODAC_ROM_SYSFS "/var/lc15/ocxo/eeprom" - -/* clock error */ -static int clkerr_fd_err = -1; -static int clkerr_fd_accuracy = -1; -static int clkerr_fd_interval = -1; -static int clkerr_fd_fault = -1; -static int clkerr_fd_refresh = -1; -static int clkerr_fd_reset = -1; - -/* ocxo dac */ -static int ocxodac_fd_value = -1; -static int ocxodac_fd_save = -1; - - -static int sysfs_read_val(int fd, int *val) -{ - int rc; - char szVal[32] = {0}; - - lseek( fd, 0, SEEK_SET ); - - rc = read(fd, szVal, sizeof(szVal) - 1); - if (rc < 0) { - return -errno; - } - - rc = sscanf(szVal, "%d", val); - if (rc != 1) { - return -1; - } - - return 0; -} - -static int sysfs_write_val(int fd, int val) -{ - int n, rc; - char szVal[32] = {0}; - - n = sprintf(szVal, "%d", val); - - lseek(fd, 0, SEEK_SET); - rc = write(fd, szVal, n+1); - if (rc < 0) { - return -errno; - } - return 0; -} - -static int sysfs_write_str(int fd, const char *str) -{ - int rc; - - lseek( fd, 0, SEEK_SET ); - rc = write(fd, str, strlen(str)+1); - if (rc < 0) { - return -errno; - } - return 0; -} - - -int lc15bts_clock_err_open(void) -{ - if (clkerr_fd_err < 0) { - clkerr_fd_err = open(CLKERR_ERR_SYSFS, O_RDONLY); - if (clkerr_fd_err < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_err; - } - } - - if (clkerr_fd_accuracy < 0) { - clkerr_fd_accuracy = open(CLKERR_ACC_SYSFS, O_RDONLY); - if (clkerr_fd_accuracy < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_accuracy; - } - } - - if (clkerr_fd_interval < 0) { - clkerr_fd_interval = open(CLKERR_INT_SYSFS, O_RDONLY); - if (clkerr_fd_interval < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_interval; - } - } - - if (clkerr_fd_fault < 0) { - clkerr_fd_fault = open(CLKERR_FLT_SYSFS, O_RDONLY); - if (clkerr_fd_fault < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_fault; - } - } - - if (clkerr_fd_refresh < 0) { - clkerr_fd_refresh = open(CLKERR_RFS_SYSFS, O_WRONLY); - if (clkerr_fd_refresh < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_refresh; - } - } - - if (clkerr_fd_reset < 0) { - clkerr_fd_reset = open(CLKERR_RST_SYSFS, O_WRONLY); - if (clkerr_fd_reset < 0) { - lc15bts_clock_err_close(); - return clkerr_fd_reset; - } - } - return 0; -} - -void lc15bts_clock_err_close(void) -{ - if (clkerr_fd_err >= 0) { - close(clkerr_fd_err); - clkerr_fd_err = -1; - } - - if (clkerr_fd_accuracy >= 0) { - close(clkerr_fd_accuracy); - clkerr_fd_accuracy = -1; - } - - if (clkerr_fd_interval >= 0) { - close(clkerr_fd_interval); - clkerr_fd_interval = -1; - } - - if (clkerr_fd_fault >= 0) { - close(clkerr_fd_fault); - clkerr_fd_fault = -1; - } - - if (clkerr_fd_refresh >= 0) { - close(clkerr_fd_refresh); - clkerr_fd_refresh = -1; - } - - if (clkerr_fd_reset >= 0) { - close(clkerr_fd_reset); - clkerr_fd_reset = -1; - } -} - -int lc15bts_clock_err_reset(void) -{ - return sysfs_write_val(clkerr_fd_reset, 1); -} - -int lc15bts_clock_err_get(int *fault, int *error_ppt, - int *accuracy_ppq, int *interval_sec) -{ - int rc; - - rc = sysfs_write_str(clkerr_fd_refresh, "once"); - if (rc < 0) { - return -1; - } - - rc = sysfs_read_val(clkerr_fd_fault, fault); - rc |= sysfs_read_val(clkerr_fd_err, error_ppt); - rc |= sysfs_read_val(clkerr_fd_accuracy, accuracy_ppq); - rc |= sysfs_read_val(clkerr_fd_interval, interval_sec); - if (rc) { - return -1; - } - return 0; -} - - -int lc15bts_clock_dac_open(void) -{ - if (ocxodac_fd_value < 0) { - ocxodac_fd_value = open(OCXODAC_VAL_SYSFS, O_RDWR); - if (ocxodac_fd_value < 0) { - lc15bts_clock_dac_close(); - return ocxodac_fd_value; - } - } - - if (ocxodac_fd_save < 0) { - ocxodac_fd_save = open(OCXODAC_ROM_SYSFS, O_WRONLY); - if (ocxodac_fd_save < 0) { - lc15bts_clock_dac_close(); - return ocxodac_fd_save; - } - } - return 0; -} - -void lc15bts_clock_dac_close(void) -{ - if (ocxodac_fd_value >= 0) { - close(ocxodac_fd_value); - ocxodac_fd_value = -1; - } - - if (ocxodac_fd_save >= 0) { - close(ocxodac_fd_save); - ocxodac_fd_save = -1; - } -} - -int lc15bts_clock_dac_get(int *dac_value) -{ - return sysfs_read_val(ocxodac_fd_value, dac_value); -} - -int lc15bts_clock_dac_set(int dac_value) -{ - return sysfs_write_val(ocxodac_fd_value, dac_value); -} - -int lc15bts_clock_dac_save(void) -{ - return sysfs_write_val(ocxodac_fd_save, 1); -} - - diff --git a/src/osmo-bts-litecell15/misc/lc15bts_clock.h b/src/osmo-bts-litecell15/misc/lc15bts_clock.h deleted file mode 100644 index d9673598..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_clock.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _LC15BTS_CLOCK_H -#define _LC15BTS_CLOCK_H - -int lc15bts_clock_err_open(void); -void lc15bts_clock_err_close(void); -int lc15bts_clock_err_reset(void); -int lc15bts_clock_err_get(int *fault, int *error_ppt, - int *accuracy_ppq, int *interval_sec); - -int lc15bts_clock_dac_open(void); -void lc15bts_clock_dac_close(void); -int lc15bts_clock_dac_get(int *dac_value); -int lc15bts_clock_dac_set(int dac_value); -int lc15bts_clock_dac_save(void); - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_led.c b/src/osmo-bts-litecell15/misc/lc15bts_led.c deleted file mode 100644 index a93d3fb0..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_led.c +++ /dev/null @@ -1,333 +0,0 @@ -/* Copyright (C) 2016 by NuRAN Wireless <support@nuranwireless.com> - * - * 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 "lc15bts_led.h" -#include "lc15bts_bts.h" -#include <osmocom/core/talloc.h> -#include <osmocom/core/linuxlist.h> - -static struct lc15bts_led led_entries[] = { - { - .name = "led0", - .fullname = "led red", - .path = "/var/lc15/leds/led0/brightness" - }, - { - .name = "led1", - .fullname = "led green", - .path = "/var/lc15/leds/led1/brightness" - } -}; - -static const struct value_string lc15bts_led_strs[] = { - { LC15BTS_LED_RED, "LED red" }, - { LC15BTS_LED_GREEN, "LED green" }, - { LC15BTS_LED_ORANGE, "LED orange" }, - { LC15BTS_LED_OFF, "LED off" }, - { 0, NULL } -}; - -static uint8_t led_priority[] = { - BLINK_PATTERN_INIT, - BLINK_PATTERN_INT_PROC_MALFUNC, - BLINK_PATTERN_SUPPLY_PWR_MAX, - BLINK_PATTERN_PA_PWR_MAX, - BLINK_PATTERN_VSWR_MAX, - BLINK_PATTERN_SUPPLY_VOLT_MIN, - BLINK_PATTERN_TEMP_MAX, - BLINK_PATTERN_SUPPLY_PWR_MAX2, - BLINK_PATTERN_EXT_LINK_MALFUNC, - BLINK_PATTERN_SUPPLY_VOLT_LOW, - BLINK_PATTERN_TEMP_HIGH, - BLINK_PATTERN_VSWR_HIGH, - BLINK_PATTERN_SUPPLY_PWR_HIGH, - BLINK_PATTERN_PA_PWR_HIGH, - BLINK_PATTERN_GPS_FIX_LOST, - BLINK_PATTERN_NORMAL -}; - - -char *blink_pattern_command[] = BLINK_PATTERN_COMMAND; - -static int lc15bts_led_write(char *path, char *str) -{ - int fd; - - if ((fd = open(path, O_WRONLY)) == -1) - { - return 0; - } - - write(fd, str, strlen(str)+1); - close(fd); - return 1; -} - -static void led_set_red() -{ - lc15bts_led_write(led_entries[0].path, "1"); - lc15bts_led_write(led_entries[1].path, "0"); -} - -static void led_set_green() -{ - lc15bts_led_write(led_entries[0].path, "0"); - lc15bts_led_write(led_entries[1].path, "1"); -} - -static void led_set_orange() -{ - lc15bts_led_write(led_entries[0].path, "1"); - lc15bts_led_write(led_entries[1].path, "1"); -} - -static void led_set_off() -{ - lc15bts_led_write(led_entries[0].path, "0"); - lc15bts_led_write(led_entries[1].path, "0"); -} - -static void led_sleep( struct lc15bts_mgr_instance *mgr, struct lc15bts_led_timer *led_timer, void (*led_timer_cb)(void *_data)) { - /* Cancel any pending timer */ - osmo_timer_del(&led_timer->timer); - /* Start LED timer */ - led_timer->timer.cb = led_timer_cb; - led_timer->timer.data = mgr; - mgr->lc15bts_leds.active_timer = led_timer->idx; - osmo_timer_schedule(&led_timer->timer, led_timer->param.sleep_sec, led_timer->param.sleep_usec); - LOGP(DTEMP, LOGL_DEBUG,"%s timer scheduled for %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_timer->idx), - led_timer->param.sleep_sec, - led_timer->param.sleep_usec); - - switch (led_timer->idx) { - case LC15BTS_LED_RED: - led_set_red(); - break; - case LC15BTS_LED_GREEN: - led_set_green(); - break; - case LC15BTS_LED_ORANGE: - led_set_orange(); - break; - case LC15BTS_LED_OFF: - led_set_off(); - break; - default: - led_set_off(); - } -} - -static void led_sleep_cb(void *_data) { - struct lc15bts_mgr_instance *mgr = _data; - struct lc15bts_led_timer_list *led_list; - - /* make sure the timer list is not empty */ - if (llist_empty(&mgr->lc15bts_leds.list)) - return; - - llist_for_each_entry(led_list, &mgr->lc15bts_leds.list, list) { - if (led_list->led_timer.idx == mgr->lc15bts_leds.active_timer) { - LOGP(DTEMP, LOGL_DEBUG,"Delete expired %s timer %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - /* Delete current timer */ - osmo_timer_del(&led_list->led_timer.timer); - /* Rotate the timer list */ - llist_move_tail(&led_list->list, &mgr->lc15bts_leds.list); - break; - } - } - - /* Execute next timer */ - led_list = llist_first_entry(&mgr->lc15bts_leds.list, struct lc15bts_led_timer_list, list); - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Execute %s timer %d sec + %d usec, total entries=%d\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec, - llist_count(&mgr->lc15bts_leds.list)); - - led_sleep(mgr, &led_list->led_timer, led_sleep_cb); - } - -} - -static void delete_led_timer_entries(struct lc15bts_mgr_instance *mgr) -{ - struct lc15bts_led_timer_list *led_list, *led_list2; - - if (llist_empty(&mgr->lc15bts_leds.list)) - return; - - llist_for_each_entry_safe(led_list, led_list2, &mgr->lc15bts_leds.list, list) { - /* Delete the timer in list */ - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Delete %s timer entry from list, %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - /* Delete current timer */ - osmo_timer_del(&led_list->led_timer.timer); - llist_del(&led_list->list); - talloc_free(led_list); - } - } - return; -} - -static int add_led_timer_entry(struct lc15bts_mgr_instance *mgr, char *cmdstr) -{ - double sec, int_sec, frac_sec; - struct lc15bts_sleep_time led_param; - - led_param.sleep_sec = 0; - led_param.sleep_usec = 0; - - if (strstr(cmdstr, "set red") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_RED; - else if (strstr(cmdstr, "set green") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_GREEN; - else if (strstr(cmdstr, "set orange") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_ORANGE; - else if (strstr(cmdstr, "set off") != NULL) - mgr->lc15bts_leds.led_idx = LC15BTS_LED_OFF; - else if (strstr(cmdstr, "sleep") != NULL) { - sec = atof(cmdstr + 6); - /* split time into integer and fractional of seconds */ - frac_sec = modf(sec, &int_sec) * 1000000.0; - led_param.sleep_sec = (int)int_sec; - led_param.sleep_usec = (int)frac_sec; - - if ((mgr->lc15bts_leds.led_idx >= LC15BTS_LED_RED) && (mgr->lc15bts_leds.led_idx < _LC15BTS_LED_MAX)) { - struct lc15bts_led_timer_list *led_list; - - /* allocate timer entry */ - led_list = talloc_zero(tall_mgr_ctx, struct lc15bts_led_timer_list); - if (led_list) { - led_list->led_timer.idx = mgr->lc15bts_leds.led_idx; - led_list->led_timer.param.sleep_sec = led_param.sleep_sec; - led_list->led_timer.param.sleep_usec = led_param.sleep_usec; - llist_add_tail(&led_list->list, &mgr->lc15bts_leds.list); - - LOGP(DTEMP, LOGL_DEBUG,"Add %s timer to list, %d sec + %d usec, total entries=%d\n", - get_value_string(lc15bts_led_strs, mgr->lc15bts_leds.led_idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec, - llist_count(&mgr->lc15bts_leds.list)); - } - } - } else - return -1; - - return 0; -} - -static int parse_led_pattern(char *pattern, struct lc15bts_mgr_instance *mgr) -{ - char str[1024]; - char *pstr; - char *sep; - int rc = 0; - - strcpy(str, pattern); - pstr = str; - while ((sep = strsep(&pstr, ";")) != NULL) { - rc = add_led_timer_entry(mgr, sep); - if (rc < 0) { - break; - } - - } - return rc; -} - -/*** led interface ***/ - -void led_set(struct lc15bts_mgr_instance *mgr, int pattern_id) -{ - int rc; - struct lc15bts_led_timer_list *led_list; - - if (pattern_id > BLINK_PATTERN_MAX_ITEM - 1) { - LOGP(DTEMP, LOGL_ERROR, "Invalid LED pattern : %d. LED pattern must be between %d..%d\n", - pattern_id, - BLINK_PATTERN_POWER_ON, - BLINK_PATTERN_MAX_ITEM - 1); - return; - } - if (pattern_id == mgr->lc15bts_leds.last_pattern_id) - return; - - mgr->lc15bts_leds.last_pattern_id = pattern_id; - - LOGP(DTEMP, LOGL_NOTICE, "blink pattern command : %d\n", pattern_id); - LOGP(DTEMP, LOGL_NOTICE, "%s\n", blink_pattern_command[pattern_id]); - - /* Empty existing LED timer in the list */ - delete_led_timer_entries(mgr); - - /* parse LED pattern */ - rc = parse_led_pattern(blink_pattern_command[pattern_id], mgr); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR,"LED pattern not found or invalid LED pattern\n"); - return; - } - - /* make sure the timer list is not empty */ - if (llist_empty(&mgr->lc15bts_leds.list)) - return; - - /* Start the first LED timer in the list */ - led_list = llist_first_entry(&mgr->lc15bts_leds.list, struct lc15bts_led_timer_list, list); - if (led_list) { - LOGP(DTEMP, LOGL_DEBUG,"Execute timer %s for %d sec + %d usec\n", - get_value_string(lc15bts_led_strs, led_list->led_timer.idx), - led_list->led_timer.param.sleep_sec, - led_list->led_timer.param.sleep_usec); - - led_sleep(mgr, &led_list->led_timer, led_sleep_cb); - } - -} - -void select_led_pattern(struct lc15bts_mgr_instance *mgr) -{ - int i; - uint8_t led[BLINK_PATTERN_MAX_ITEM] = {0}; - - /* set normal LED pattern at first */ - led[BLINK_PATTERN_NORMAL] = 1; - - /* check on-board sensors for new LED pattern */ - check_sensor_led_pattern(mgr, led); - - /* check BTS status for new LED pattern */ - check_bts_led_pattern(led); - - /* check by priority */ - for (i = 0; i < sizeof(led_priority)/sizeof(uint8_t); i++) { - if(led[led_priority[i]] == 1) { - led_set(mgr, led_priority[i]); - break; - } - } -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_led.h b/src/osmo-bts-litecell15/misc/lc15bts_led.h deleted file mode 100644 index b6d9d28b..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_led.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _LC15BTS_LED_H -#define _LC15BTS_LED_H - -#include <stdint.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <math.h> -#include <sys/stat.h> - -#include <osmo-bts/logging.h> -#include <osmocom/core/timer.h> -#include <osmocom/core/utils.h> - -#include "lc15bts_mgr.h" - -/* public function prototypes */ -void led_set(struct lc15bts_mgr_instance *mgr, int pattern_id); - -void select_led_pattern(struct lc15bts_mgr_instance *mgr); - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr.c b/src/osmo-bts-litecell15/misc/lc15bts_mgr.c deleted file mode 100644 index da21c9d0..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_mgr.c +++ /dev/null @@ -1,366 +0,0 @@ -/* Main program for NuRAN Wireless Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_mgr.c - * (C) 2012 by Harald Welte <laforge@gnumonks.org> - * (C) 2014 by Holger Hans Peter Freyther - * - * 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 <stdlib.h> -#include <errno.h> -#include <getopt.h> -#include <limits.h> -#include <sys/signal.h> -#include <sys/stat.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/application.h> -#include <osmocom/core/timer.h> -#include <osmocom/core/msgb.h> -#include <osmocom/vty/telnet_interface.h> -#include <osmocom/vty/logging.h> -#include <osmocom/vty/ports.h> - -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_mgr.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_bid.h" -#include "misc/lc15bts_power.h" -#include "misc/lc15bts_swd.h" - -#include "lc15bts_led.h" - -static int no_rom_write = 0; -static int daemonize = 0; -void *tall_mgr_ctx; - -/* every 6 hours means 365*4 = 1460 rom writes per year (max) */ -#define SENSOR_TIMER_SECS (6 * 3600) - -/* every 1 hours means 365*24 = 8760 rom writes per year (max) */ -#define HOURS_TIMER_SECS (1 * 3600) - - -/* the initial state */ -static struct lc15bts_mgr_instance manager = { - .config_file = "lc15bts-mgr.cfg", - .temp = { - .supply_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .soc_temp_limit = { - .thresh_warn_max = 95, - .thresh_crit_max = 100, - .thresh_warn_min = -40, - }, - .fpga_temp_limit = { - .thresh_warn_max = 95, - .thresh_crit_max = 100, - .thresh_warn_min = -40, - }, - .rmsdet_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .ocxo_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .tx0_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -20, - }, - .tx1_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -20, - }, - .pa0_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - }, - .pa1_temp_limit = { - .thresh_warn_max = 80, - .thresh_crit_max = 85, - .thresh_warn_min = -40, - } - }, - .volt = { - .supply_volt_limit = { - .thresh_warn_max = 30000, - .thresh_crit_max = 30500, - .thresh_warn_min = 19000, - .thresh_crit_min = 17500, - } - }, - .pwr = { - .supply_pwr_limit = { - .thresh_warn_max = 110, - .thresh_crit_max = 120, - }, - .pa0_pwr_limit = { - .thresh_warn_max = 50, - .thresh_crit_max = 60, - }, - .pa1_pwr_limit = { - .thresh_warn_max = 50, - .thresh_crit_max = 60, - } - }, - .vswr = { - .tx0_vswr_limit = { - .thresh_warn_max = 3000, - .thresh_crit_max = 5000, - }, - .tx1_vswr_limit = { - .thresh_warn_max = 3000, - .thresh_crit_max = 5000, - } - }, - .gps = { - .gps_fix_limit = { - .thresh_warn_max = 7, - } - }, - .state = { - .action_norm = SENSOR_ACT_NORM_PA0_ON | SENSOR_ACT_NORM_PA1_ON, - .action_warn = 0, - .action_crit = 0, - .action_comb = 0, - .state = STATE_NORMAL, - } -}; - -static struct osmo_timer_list sensor_timer; -static void check_sensor_timer_cb(void *unused) -{ - lc15bts_check_temp(no_rom_write); - lc15bts_check_power(no_rom_write); - lc15bts_check_vswr(no_rom_write); - osmo_timer_schedule(&sensor_timer, SENSOR_TIMER_SECS, 0); - /* TODO checks if lc15bts_check_temp/lc15bts_check_power/lc15bts_check_vswr went ok */ - lc15bts_swd_event(&manager, SWD_CHECK_SENSOR); -} - -static struct osmo_timer_list hours_timer; -static void hours_timer_cb(void *unused) -{ - lc15bts_update_hours(no_rom_write); - - osmo_timer_schedule(&hours_timer, HOURS_TIMER_SECS, 0); - /* TODO: validates if lc15bts_update_hours went correctly */ - lc15bts_swd_event(&manager, SWD_UPDATE_HOURS); -} - -static void print_help(void) -{ - printf("lc15bts-mgr [-nsD] [-d cat]\n"); - printf(" -n Do not write to ROM\n"); - printf(" -s Disable color\n"); - printf(" -d CAT enable debugging\n"); - printf(" -D daemonize\n"); - printf(" -c Specify the filename of the config file\n"); -} - -static int parse_options(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { - switch (opt) { - case 'n': - no_rom_write = 1; - break; - case 'h': - print_help(); - return -1; - case 's': - log_set_use_color(osmo_stderr_target, 0); - break; - case 'd': - log_parse_category_mask(osmo_stderr_target, optarg); - break; - case 'D': - daemonize = 1; - break; - case 'c': - manager.config_file = optarg; - break; - default: - return -1; - } - } - - return 0; -} - -static void signal_handler(int signal) -{ - fprintf(stderr, "signal %u received\n", signal); - - switch (signal) { - case SIGINT: - case SIGTERM: - lc15bts_check_temp(no_rom_write); - lc15bts_check_power(no_rom_write); - lc15bts_check_vswr(no_rom_write); - lc15bts_update_hours(no_rom_write); - exit(0); - break; - case SIGABRT: - case SIGUSR1: - case SIGUSR2: - talloc_report_full(tall_mgr_ctx, stderr); - break; - default: - break; - } -} - -static struct log_info_cat mgr_log_info_cat[] = { - [DTEMP] = { - .name = "DTEMP", - .description = "Temperature monitoring", - .color = "\033[1;35m", - .enabled = 1, .loglevel = LOGL_NOTICE, - }, - [DFW] = { - .name = "DFW", - .description = "Firmware management", - .color = "\033[1;36m", - .enabled = 1, .loglevel = LOGL_NOTICE, - }, - [DFIND] = { - .name = "DFIND", - .description = "ipaccess-find handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_NOTICE, - }, - [DCALIB] = { - .name = "DCALIB", - .description = "Calibration handling", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_NOTICE, - }, - [DSWD] = { - .name = "DSWD", - .description = "Software Watchdog", - .color = "\033[1;37m", - .enabled = 1, .loglevel = LOGL_NOTICE, - }, -}; - -static const struct log_info mgr_log_info = { - .cat = mgr_log_info_cat, - .num_cat = ARRAY_SIZE(mgr_log_info_cat), -}; - -int main(int argc, char **argv) -{ - int rc; - - tall_mgr_ctx = talloc_named_const(NULL, 1, "bts manager"); - msgb_talloc_ctx_init(tall_mgr_ctx, 0); - - osmo_init_logging2(tall_mgr_ctx, &mgr_log_info); - - osmo_init_ignore_signals(); - signal(SIGINT, &signal_handler); - signal(SIGTERM, &signal_handler); - signal(SIGUSR1, &signal_handler); - signal(SIGUSR2, &signal_handler); - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - lc15bts_mgr_vty_init(); - logging_vty_add_cmds(); - rc = lc15bts_mgr_parse_config(&manager); - if (rc < 0) { - LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); - exit(1); - } - - rc = telnet_init(tall_mgr_ctx, NULL, OSMO_VTY_PORT_BTSMGR); - if (rc < 0) { - fprintf(stderr, "Error initializing telnet\n"); - exit(1); - } - - INIT_LLIST_HEAD(&manager.lc15bts_leds.list); - INIT_LLIST_HEAD(&manager.alarms.list); - - /* Initialize the service watchdog notification for SWD_LAST event(s) */ - if (lc15bts_swd_init(&manager, (int)(SWD_LAST)) != 0) - exit(3); - - /* start temperature check timer */ - sensor_timer.cb = check_sensor_timer_cb; - check_sensor_timer_cb(NULL); - - /* start operational hours timer */ - hours_timer.cb = hours_timer_cb; - hours_timer_cb(NULL); - - /* Enable the PAs */ - rc = lc15bts_power_set(LC15BTS_POWER_PA0, 1); - if (rc < 0) { - exit(3); - } - - rc = lc15bts_power_set(LC15BTS_POWER_PA1, 1); - if (rc < 0) { - exit(3); - } - - /* handle broadcast messages for ipaccess-find */ - if (lc15bts_mgr_nl_init() != 0) - exit(3); - - /* Initialize the sensor control */ - lc15bts_mgr_sensor_init(&manager); - - if (lc15bts_mgr_calib_init(&manager) != 0) - exit(3); - - if (daemonize) { - rc = osmo_daemonize(); - if (rc < 0) { - perror("Error during daemonize"); - exit(1); - } - } - - while (1) { - log_reset_context(); - osmo_select_main(0); - lc15bts_swd_event(&manager, SWD_MAINLOOP); - } -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr.h b/src/osmo-bts-litecell15/misc/lc15bts_mgr.h deleted file mode 100644 index 4bfbdbc9..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_mgr.h +++ /dev/null @@ -1,422 +0,0 @@ -#ifndef _LC15BTS_MGR_H -#define _LC15BTS_MGR_H - -#include <osmocom/vty/vty.h> -#include <osmocom/vty/command.h> - -#include <osmocom/core/select.h> -#include <osmocom/core/timer.h> - -#include <stdint.h> - -#define LC15BTS_SENSOR_TIMER_DURATION 60 -#define LC15BTS_PREVENT_TIMER_DURATION 15 * 60 -#define LC15BTS_PREVENT_TIMER_SHORT_DURATION 5 * 60 -#define LC15BTS_PREVENT_TIMER_NONE 0 -#define LC15BTS_PREVENT_RETRY INT_MAX - 1 - -enum BLINK_PATTERN { - BLINK_PATTERN_POWER_ON = 0, //hardware set - BLINK_PATTERN_INIT, - BLINK_PATTERN_NORMAL, - BLINK_PATTERN_EXT_LINK_MALFUNC, - BLINK_PATTERN_INT_PROC_MALFUNC, - BLINK_PATTERN_SUPPLY_VOLT_LOW, - BLINK_PATTERN_SUPPLY_VOLT_MIN, - BLINK_PATTERN_VSWR_HIGH, - BLINK_PATTERN_VSWR_MAX, - BLINK_PATTERN_TEMP_HIGH, - BLINK_PATTERN_TEMP_MAX, - BLINK_PATTERN_SUPPLY_PWR_HIGH, - BLINK_PATTERN_SUPPLY_PWR_MAX, - BLINK_PATTERN_SUPPLY_PWR_MAX2, - BLINK_PATTERN_PA_PWR_HIGH, - BLINK_PATTERN_PA_PWR_MAX, - BLINK_PATTERN_GPS_FIX_LOST, - BLINK_PATTERN_MAX_ITEM -}; - -#define BLINK_PATTERN_COMMAND {\ - "set red; sleep 5.0",\ - "set orange; sleep 5.0",\ - "set green; sleep 2.5; set off; sleep 2.5",\ - "set red; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 2.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5 ",\ - "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set orange; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5 ",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set orange; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ - "set green; sleep 2.5; set off; sleep 0.5; set green; sleep 0.5; set off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\ -} - -enum { - DTEMP, - DFW, - DFIND, - DCALIB, - DSWD, -}; - -// TODO NTQD: Define new actions like reducing output power, limit ARM core speed, shutdown second TRX/PA, ... -enum { -#if 0 - SENSOR_ACT_PWR_CONTRL = 0x1, -#endif - SENSOR_ACT_PA0_OFF = 0x2, - SENSOR_ACT_PA1_OFF = 0x4, - SENSOR_ACT_BTS_SRV_OFF = 0x10, -}; - -/* actions only for normal state */ -enum { -#if 0 - SENSOR_ACT_NORM_PW_CONTRL = 0x1, -#endif - SENSOR_ACT_NORM_PA0_ON = 0x2, - SENSOR_ACT_NORM_PA1_ON = 0x4, - SENSOR_ACT_NORM_BTS_SRV_ON= 0x10, -}; - -enum lc15bts_sensor_state { - STATE_NORMAL, /* Everything is fine */ - STATE_WARNING_HYST, /* Go back to normal next? */ - STATE_WARNING, /* We are above the warning threshold */ - STATE_CRITICAL, /* We have an issue. Wait for below warning */ -}; - -enum lc15bts_leds_name { - LC15BTS_LED_RED = 0, - LC15BTS_LED_GREEN, - LC15BTS_LED_ORANGE, - LC15BTS_LED_OFF, - _LC15BTS_LED_MAX -}; - -struct lc15bts_led{ - char *name; - char *fullname; - char *path; -}; - -/** - * Temperature Limits. We separate from a threshold - * that will generate a warning and one that is so - * severe that an action will be taken. - */ -struct lc15bts_temp_limit { - int thresh_warn_max; - int thresh_crit_max; - int thresh_warn_min; -}; - -struct lc15bts_volt_limit { - int thresh_warn_max; - int thresh_crit_max; - int thresh_warn_min; - int thresh_crit_min; -}; - -struct lc15bts_pwr_limit { - int thresh_warn_max; - int thresh_crit_max; -}; - -struct lc15bts_vswr_limit { - int thresh_warn_max; - int thresh_crit_max; -}; - -struct lc15bts_gps_fix_limit { - int thresh_warn_max; -}; - -struct lc15bts_sleep_time { - int sleep_sec; - int sleep_usec; -}; - -struct lc15bts_led_timer { - uint8_t idx; - struct osmo_timer_list timer; - struct lc15bts_sleep_time param; -}; - -struct lc15bts_led_timer_list { - struct llist_head list; - struct lc15bts_led_timer led_timer; -}; - -struct lc15bts_preventive_list { - struct llist_head list; - struct lc15bts_sleep_time param; - int action_flag; -}; - -enum mgr_vty_node { - MGR_NODE = _LAST_OSMOVTY_NODE + 1, - - ACT_NORM_NODE, - ACT_WARN_NODE, - ACT_CRIT_NODE, - LIMIT_SUPPLY_TEMP_NODE, - LIMIT_SOC_NODE, - LIMIT_FPGA_NODE, - LIMIT_RMSDET_NODE, - LIMIT_OCXO_NODE, - LIMIT_TX0_TEMP_NODE, - LIMIT_TX1_TEMP_NODE, - LIMIT_PA0_TEMP_NODE, - LIMIT_PA1_TEMP_NODE, - LIMIT_SUPPLY_VOLT_NODE, - LIMIT_TX0_VSWR_NODE, - LIMIT_TX1_VSWR_NODE, - LIMIT_SUPPLY_PWR_NODE, - LIMIT_PA0_PWR_NODE, - LIMIT_PA1_PWR_NODE, - LIMIT_GPS_FIX_NODE, -}; - -enum mgr_vty_limit_type { - MGR_LIMIT_TYPE_TEMP = 0, - MGR_LIMIT_TYPE_VOLT, - MGR_LIMIT_TYPE_VSWR, - MGR_LIMIT_TYPE_PWR, - _MGR_LIMIT_TYPE_MAX, -}; - -struct lc15bts_mgr_instance { - const char *config_file; - - struct { - struct lc15bts_temp_limit supply_temp_limit; - struct lc15bts_temp_limit soc_temp_limit; - struct lc15bts_temp_limit fpga_temp_limit; - struct lc15bts_temp_limit rmsdet_temp_limit; - struct lc15bts_temp_limit ocxo_temp_limit; - struct lc15bts_temp_limit tx0_temp_limit; - struct lc15bts_temp_limit tx1_temp_limit; - struct lc15bts_temp_limit pa0_temp_limit; - struct lc15bts_temp_limit pa1_temp_limit; - } temp; - - struct { - struct lc15bts_volt_limit supply_volt_limit; - } volt; - - struct { - struct lc15bts_pwr_limit supply_pwr_limit; - struct lc15bts_pwr_limit pa0_pwr_limit; - struct lc15bts_pwr_limit pa1_pwr_limit; - } pwr; - - struct { - struct lc15bts_vswr_limit tx0_vswr_limit; - struct lc15bts_vswr_limit tx1_vswr_limit; - int tx0_last_vswr; - int tx1_last_vswr; - } vswr; - - struct { - struct lc15bts_gps_fix_limit gps_fix_limit; - time_t last_update; - } gps; - - struct { - int action_norm; - int action_warn; - int action_crit; - int action_comb; - - enum lc15bts_sensor_state state; - } state; - - struct { - int state; - int calib_from_loop; - struct osmo_timer_list calib_timeout; - } calib; - - struct { - int state; - int swd_from_loop; - unsigned long long int swd_events; - unsigned long long int swd_events_cache; - unsigned long long int swd_eventmasks; - int num_events; - struct osmo_timer_list swd_timeout; - } swd; - - struct { - uint8_t led_idx; - uint8_t last_pattern_id; - uint8_t active_timer; - struct llist_head list; - } lc15bts_leds; - - struct { - int is_up; - uint32_t last_seqno; - struct osmo_timer_list recon_timer; - struct ipa_client_conn *bts_conn; - uint32_t crit_flags; - uint32_t warn_flags; - } lc15bts_ctrl; - - struct lc15bts_alarms { - int temp_high; - int temp_max; - int supply_low; - int supply_min; - int vswr_high; - int vswr_max; - int supply_pwr_high; - int supply_pwr_max; - int supply_pwr_max2; - int pa_pwr_high; - int pa_pwr_max; - int gps_fix_lost; - struct llist_head list; - struct osmo_timer_list preventive_timer; - int preventive_duration; - int preventive_retry; - } alarms; - -}; - -enum lc15bts_mgr_fail_evt_rep_crit_sig { - /* Critical alarms */ - S_MGR_TEMP_SUPPLY_CRIT_MAX_ALARM = (1 << 0), - S_MGR_TEMP_SOC_CRIT_MAX_ALARM = (1 << 1), - S_MGR_TEMP_FPGA_CRIT_MAX_ALARM = (1 << 2), - S_MGR_TEMP_RMS_DET_CRIT_MAX_ALARM = (1 << 3), - S_MGR_TEMP_OCXO_CRIT_MAX_ALARM = (1 << 4), - S_MGR_TEMP_TRX0_CRIT_MAX_ALARM = (1 << 5), - S_MGR_TEMP_TRX1_CRIT_MAX_ALARM = (1 << 6), - S_MGR_TEMP_PA0_CRIT_MAX_ALARM = (1 << 7), - S_MGR_TEMP_PA1_CRIT_MAX_ALARM = (1 << 8), - S_MGR_SUPPLY_CRIT_MAX_ALARM = (1 << 9), - S_MGR_SUPPLY_CRIT_MIN_ALARM = (1 << 10), - S_MGR_VSWR0_CRIT_MAX_ALARM = (1 << 11), - S_MGR_VSWR1_CRIT_MAX_ALARM = (1 << 12), - S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM = (1 << 13), - S_MGR_PWR_PA0_CRIT_MAX_ALARM = (1 << 14), - S_MGR_PWR_PA1_CRIT_MAX_ALARM = (1 << 15), - _S_MGR_CRIT_ALARM_MAX, -}; - -enum lc15bts_mgr_fail_evt_rep_warn_sig { - /* Warning alarms */ - S_MGR_TEMP_SUPPLY_WARN_MIN_ALARM = (1 << 0), - S_MGR_TEMP_SUPPLY_WARN_MAX_ALARM = (1 << 2), - S_MGR_TEMP_SOC_WARN_MIN_ALARM = (1 << 3), - S_MGR_TEMP_SOC_WARN_MAX_ALARM = (1 << 4), - S_MGR_TEMP_FPGA_WARN_MIN_ALARM = (1 << 5), - S_MGR_TEMP_FPGA_WARN_MAX_ALARM = (1 << 6), - S_MGR_TEMP_RMS_DET_WARN_MIN_ALARM = (1 << 7), - S_MGR_TEMP_RMS_DET_WARN_MAX_ALARM = (1 << 8), - S_MGR_TEMP_OCXO_WARN_MIN_ALARM = (1 << 9), - S_MGR_TEMP_OCXO_WARN_MAX_ALARM = (1 << 10), - S_MGR_TEMP_TRX0_WARN_MIN_ALARM = (1 << 11), - S_MGR_TEMP_TRX0_WARN_MAX_ALARM = (1 << 12), - S_MGR_TEMP_TRX1_WARN_MIN_ALARM = (1 << 13), - S_MGR_TEMP_TRX1_WARN_MAX_ALARM = (1 << 14), - S_MGR_TEMP_PA0_WARN_MIN_ALARM = (1 << 15), - S_MGR_TEMP_PA0_WARN_MAX_ALARM = (1 << 16), - S_MGR_TEMP_PA1_WARN_MIN_ALARM = (1 << 17), - S_MGR_TEMP_PA1_WARN_MAX_ALARM = (1 << 18), - S_MGR_SUPPLY_WARN_MIN_ALARM = (1 << 19), - S_MGR_SUPPLY_WARN_MAX_ALARM = (1 << 20), - S_MGR_VSWR0_WARN_MAX_ALARM = (1 << 21), - S_MGR_VSWR1_WARN_MAX_ALARM = (1 << 22), - S_MGR_PWR_SUPPLY_WARN_MAX_ALARM = (1 << 23), - S_MGR_PWR_PA0_WARN_MAX_ALARM = (1 << 24), - S_MGR_PWR_PA1_WARN_MAX_ALARM = (1 << 25), - S_MGR_GPS_FIX_WARN_ALARM = (1 << 26), - _S_MGR_WARN_ALARM_MAX, -}; - -enum lc15bts_mgr_failure_event_causes { - /* Critical causes */ - NM_EVT_CAUSE_CRIT_TEMP_SUPPLY_MAX_FAIL = 0x4100, - NM_EVT_CAUSE_CRIT_TEMP_FPGA_MAX_FAIL = 0x4101, - NM_EVT_CAUSE_CRIT_TEMP_SOC_MAX_FAIL = 0x4102, - NM_EVT_CAUSE_CRIT_TEMP_RMS_DET_MAX_FAIL = 0x4103, - NM_EVT_CAUSE_CRIT_TEMP_OCXO_MAX_FAIL = 0x4104, - NM_EVT_CAUSE_CRIT_TEMP_TRX0_MAX_FAIL = 0x4105, - NM_EVT_CAUSE_CRIT_TEMP_TRX1_MAX_FAIL = 0x4106, - NM_EVT_CAUSE_CRIT_TEMP_PA0_MAX_FAIL = 0x4107, - NM_EVT_CAUSE_CRIT_TEMP_PA1_MAX_FAIL = 0x4108, - NM_EVT_CAUSE_CRIT_SUPPLY_MAX_FAIL = 0x4109, - NM_EVT_CAUSE_CRIT_SUPPLY_MIN_FAIL = 0x410A, - NM_EVT_CAUSE_CRIT_VSWR0_MAX_FAIL = 0x410B, - NM_EVT_CAUSE_CRIT_VSWR1_MAX_FAIL = 0x410C, - NM_EVT_CAUSE_CRIT_PWR_SUPPLY_MAX_FAIL = 0x410D, - NM_EVT_CAUSE_CRIT_PWR_PA0_MAX_FAIL = 0x410E, - NM_EVT_CAUSE_CRIT_PWR_PA1_MAX_FAIL = 0x410F, - /* Warning causes */ - NM_EVT_CAUSE_WARN_TEMP_SUPPLY_LOW_FAIL = 0x4400, - NM_EVT_CAUSE_WARN_TEMP_SUPPLY_HIGH_FAIL = 0x4401, - NM_EVT_CAUSE_WARN_TEMP_FPGA_LOW_FAIL = 0x4402, - NM_EVT_CAUSE_WARN_TEMP_FPGA_HIGH_FAIL = 0x4403, - NM_EVT_CAUSE_WARN_TEMP_SOC_LOW_FAIL = 0x4404, - NM_EVT_CAUSE_WARN_TEMP_SOC_HIGH_FAIL = 0x4405, - NM_EVT_CAUSE_WARN_TEMP_RMS_DET_LOW_FAIL = 0x4406, - NM_EVT_CAUSE_WARN_TEMP_RMS_DET_HIGH_FAIL= 0x4407, - NM_EVT_CAUSE_WARN_TEMP_OCXO_LOW_FAIL = 0x4408, - NM_EVT_CAUSE_WARN_TEMP_OCXO_HIGH_FAIL = 0x4409, - NM_EVT_CAUSE_WARN_TEMP_TRX0_LOW_FAIL = 0x440A, - NM_EVT_CAUSE_WARN_TEMP_TRX0_HIGH_FAIL = 0x440B, - NM_EVT_CAUSE_WARN_TEMP_TRX1_LOW_FAIL = 0x440C, - NM_EVT_CAUSE_WARN_TEMP_TRX1_HIGH_FAIL = 0x440D, - NM_EVT_CAUSE_WARN_TEMP_PA0_LOW_FAIL = 0x440E, - NM_EVT_CAUSE_WARN_TEMP_PA0_HIGH_FAIL = 0x440F, - NM_EVT_CAUSE_WARN_TEMP_PA1_LOW_FAIL = 0x4410, - NM_EVT_CAUSE_WARN_TEMP_PA1_HIGH_FAIL = 0x4411, - NM_EVT_CAUSE_WARN_SUPPLY_LOW_FAIL = 0x4412, - NM_EVT_CAUSE_WARN_SUPPLY_HIGH_FAIL = 0x4413, - NM_EVT_CAUSE_WARN_VSWR0_HIGH_FAIL = 0x4414, - NM_EVT_CAUSE_WANR_VSWR1_HIGH_FAIL = 0x4415, - NM_EVT_CAUSE_WARN_PWR_SUPPLY_HIGH_FAIL = 0x4416, - NM_EVT_CAUSE_WARN_PWR_PA0_HIGH_FAIL = 0x4417, - NM_EVT_CAUSE_WARN_PWR_PA1_HIGH_FAIL = 0x4418, - NM_EVT_CAUSE_WARN_GPS_FIX_FAIL = 0x4419, -}; - -/* This defines the list of notification events for systemd service watchdog. - all these events must be notified in a certain service defined timeslot - or the service (this app) would be restarted (only if related systemd service - unit file has WatchdogSec!=0). - WARNING: swd events must begin with event 0. Last events must be - SWD_LAST (max 64 events in this list). -*/ -enum mgr_swd_events { - SWD_MAINLOOP = 0, - SWD_CHECK_SENSOR, - SWD_UPDATE_HOURS, - SWD_CHECK_TEMP_SENSOR, - SWD_CHECK_LED_CTRL, - SWD_CHECK_CALIB, - SWD_CHECK_BTS_CONNECTION, - SWD_LAST -}; - -int lc15bts_mgr_vty_init(void); -int lc15bts_mgr_parse_config(struct lc15bts_mgr_instance *mgr); -int lc15bts_mgr_nl_init(void); -int lc15bts_mgr_sensor_init(struct lc15bts_mgr_instance *mgr); -const char *lc15bts_mgr_sensor_get_state(enum lc15bts_sensor_state state); - -int lc15bts_mgr_calib_init(struct lc15bts_mgr_instance *mgr); -int lc15bts_mgr_control_init(struct lc15bts_mgr_instance *mgr); -int lc15bts_mgr_calib_run(struct lc15bts_mgr_instance *mgr); -void lc15bts_mgr_dispatch_alarm(struct lc15bts_mgr_instance *mgr, const int cause, const char *key, const char *text); -extern void *tall_mgr_ctx; - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr_calib.c b/src/osmo-bts-litecell15/misc/lc15bts_mgr_calib.c deleted file mode 100644 index badb5455..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_mgr_calib.c +++ /dev/null @@ -1,292 +0,0 @@ -/* OCXO calibration control for Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_mgr_calib.c - * (C) 2014,2015 by Holger Hans Peter Freyther - * (C) 2014 by Harald Welte for the IPA code from the oml router - * - * 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 "misc/lc15bts_mgr.h" -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_clock.h" -#include "misc/lc15bts_swd.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_led.h" -#include "osmo-bts/msg_utils.h" - -#include <osmocom/core/logging.h> -#include <osmocom/core/select.h> - -#include <osmocom/ctrl/control_cmd.h> - -#include <osmocom/gsm/ipa.h> -#include <osmocom/gsm/protocol/ipaccess.h> - -#include <osmocom/abis/abis.h> -#include <osmocom/abis/e1_input.h> -#include <osmocom/abis/ipa.h> - -#include <time.h> - -static void calib_adjust(struct lc15bts_mgr_instance *mgr); -static void calib_state_reset(struct lc15bts_mgr_instance *mgr, int reason); -static void calib_loop_run(void *_data); - -static int ocxodac_saved_value = -1; - -enum calib_state { - CALIB_INITIAL, - CALIB_IN_PROGRESS, -}; - -enum calib_result { - CALIB_FAIL_START, - CALIB_FAIL_GPSFIX, - CALIB_FAIL_CLKERR, - CALIB_FAIL_OCXODAC, - CALIB_SUCCESS, -}; - -static void calib_start(struct lc15bts_mgr_instance *mgr) -{ - int rc; - - rc = lc15bts_clock_err_open(); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to open clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - - rc = lc15bts_clock_dac_open(); - if (rc != 0) { - LOGP(DCALIB, LOGL_ERROR, "Failed to open OCXO dac module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - - calib_adjust(mgr); -} - -static void calib_adjust(struct lc15bts_mgr_instance *mgr) -{ - int rc; - int fault; - int error_ppt; - int accuracy_ppq; - int interval_sec; - int dac_value; - int new_dac_value; - int dac_correction; - time_t now; - time_t last_gps_fix; - - rc = lc15bts_clock_err_get(&fault, &error_ppt, - &accuracy_ppq, &interval_sec); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to get clock error measurement %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - - /* get current time */ - now = time(NULL); - - /* first time after start of manager program */ - if (mgr->gps.last_update == 0) - mgr->gps.last_update = now; - - /* read last GPS 3D fix from storage */ - rc = lc15bts_par_get_gps_fix(&last_gps_fix); - if (rc < 0) { - LOGP(DCALIB, LOGL_NOTICE, "Last GPS 3D fix can not read (%d). Last GPS 3D fix sets to zero\n", rc); - last_gps_fix = 0; - } - - if (fault) { - LOGP(DCALIB, LOGL_NOTICE, "GPS has no fix\n"); - calib_state_reset(mgr, CALIB_FAIL_GPSFIX); - return; - } - - /* We got GPS 3D fix */ - LOGP(DCALIB, LOGL_DEBUG, "Got GPS 3D fix warn_flags=0x%08x, last=%lld, now=%lld\n", - mgr->lc15bts_ctrl.warn_flags, - (long long)last_gps_fix, - (long long)now); - - rc = lc15bts_clock_dac_get(&dac_value); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to get OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - - /* Set OCXO initial dac value */ - if (ocxodac_saved_value < 0) - ocxodac_saved_value = dac_value; - - LOGP(DCALIB, LOGL_NOTICE, - "Calibration ERR(%f PPB) ACC(%f PPB) INT(%d) DAC(%d)\n", - error_ppt / 1000., accuracy_ppq / 1000000., interval_sec, dac_value); - - /* Need integration time to correct */ - if (interval_sec) { - /* 1 unit of correction equal about 0.5 - 1 PPB correction */ - dac_correction = (int)(-error_ppt * 0.0015); - new_dac_value = dac_value + dac_correction; - - if (new_dac_value > 4095) - new_dac_value = 4095; - else if (new_dac_value < 0) - new_dac_value = 0; - - /* We have a fix, make sure the measured error is - meaningful (10 times the accuracy) */ - if ((new_dac_value != dac_value) && ((100l * abs(error_ppt)) > accuracy_ppq)) { - - LOGP(DCALIB, LOGL_NOTICE, - "Going to apply %d as new clock setting.\n", - new_dac_value); - - rc = lc15bts_clock_dac_set(new_dac_value); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to set OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - return; - } - rc = lc15bts_clock_err_reset(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to reset clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - return; - } - } - /* New conditions to store DAC value: - * - Resolution accuracy less or equal than 0.01PPB (or 10000 PPQ) - * - Error less or equal than 2PPB (or 2000PPT) - * - Solution different than the last one */ - else if (accuracy_ppq <= 10000) { - if((dac_value != ocxodac_saved_value) && (abs(error_ppt) < 2000)) { - LOGP(DCALIB, LOGL_NOTICE, "Saving OCXO DAC value to memory... val = %d\n", dac_value); - rc = lc15bts_clock_dac_save(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to save OCXO dac value %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_OCXODAC); - } else { - ocxodac_saved_value = dac_value; - } - } - - rc = lc15bts_clock_err_reset(); - if (rc < 0) { - LOGP(DCALIB, LOGL_ERROR, - "Failed to reset clock error module %d\n", rc); - calib_state_reset(mgr, CALIB_FAIL_CLKERR); - } - } - } else { - LOGP(DCALIB, LOGL_NOTICE, "Skipping this iteration, no integration time\n"); - } - - calib_state_reset(mgr, CALIB_SUCCESS); - return; -} - -static void calib_close(struct lc15bts_mgr_instance *mgr) -{ - lc15bts_clock_err_close(); - lc15bts_clock_dac_close(); -} - -static void calib_state_reset(struct lc15bts_mgr_instance *mgr, int outcome) -{ - if (mgr->calib.calib_from_loop) { - /* - * In case of success calibrate in two hours again - * and in case of a failure in some minutes. - * - * TODO NTQ: Select timeout based on last error and accuracy - */ - int timeout = 60; - //int timeout = 2 * 60 * 60; - //if (outcome != CALIB_SUCESS) } - // timeout = 5 * 60; - //} - - mgr->calib.calib_timeout.data = mgr; - mgr->calib.calib_timeout.cb = calib_loop_run; - osmo_timer_schedule(&mgr->calib.calib_timeout, timeout, 0); - /* TODO: do we want to notify if we got a calibration error, like no gps fix? */ - lc15bts_swd_event(mgr, SWD_CHECK_CALIB); - } - - mgr->calib.state = CALIB_INITIAL; - calib_close(mgr); -} - -static int calib_run(struct lc15bts_mgr_instance *mgr, int from_loop) -{ - if (mgr->calib.state != CALIB_INITIAL) { - LOGP(DCALIB, LOGL_ERROR, "Calib is already in progress.\n"); - return -1; - } - - mgr->calib.calib_from_loop = from_loop; - - /* From now on everything will be handled from the failure */ - mgr->calib.state = CALIB_IN_PROGRESS; - calib_start(mgr); - return 0; -} - -static void calib_loop_run(void *_data) -{ - int rc; - struct lc15bts_mgr_instance *mgr = _data; - - LOGP(DCALIB, LOGL_NOTICE, "Going to calibrate the system.\n"); - rc = calib_run(mgr, 1); - if (rc != 0) { - calib_state_reset(mgr, CALIB_FAIL_START); - } -} - -int lc15bts_mgr_calib_run(struct lc15bts_mgr_instance *mgr) -{ - return calib_run(mgr, 0); -} - -int lc15bts_mgr_calib_init(struct lc15bts_mgr_instance *mgr) -{ - mgr->calib.state = CALIB_INITIAL; - mgr->calib.calib_timeout.data = mgr; - mgr->calib.calib_timeout.cb = calib_loop_run; - osmo_timer_schedule(&mgr->calib.calib_timeout, 0, 0); - - return 0; -} - diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr_nl.c b/src/osmo-bts-litecell15/misc/lc15bts_mgr_nl.c deleted file mode 100644 index 3a617dd7..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_mgr_nl.c +++ /dev/null @@ -1,195 +0,0 @@ -/* NetworkListen for NuRAN Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_mgr_nl.c - * (C) 2014 by Holger Hans Peter Freyther - * - * 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 "misc/lc15bts_mgr.h" -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_nl.h" -#include "misc/lc15bts_par.h" -#include "misc/lc15bts_bid.h" - -#include <osmo-bts/logging.h> - -#include <osmocom/gsm/protocol/ipaccess.h> - -#include <osmocom/core/msgb.h> -#include <osmocom/core/socket.h> -#include <osmocom/core/select.h> - -#include <arpa/inet.h> - -#include <sys/types.h> -#include <sys/socket.h> - -#include <errno.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#define ETH0_ADDR_SYSFS "/var/lc15/net/eth0/address" - -static struct osmo_fd nl_fd; - -/* - * The TLV structure in IPA messages in UDP packages is a bit - * weird. First the header appears to have an extra NULL byte - * and second the L16 of the L16TV needs to include +1 for the - * tag. The default msgb/tlv and libosmo-abis routines do not - * provide this. - */ - -static void ipaccess_prepend_header_quirk(struct msgb *msg, int proto) -{ - struct ipaccess_head *hh; - - /* prepend the ip.access header */ - hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh) + 1); - hh->len = htons(msg->len - sizeof(*hh) - 1); - hh->proto = proto; -} - -static void quirk_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag, - const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, len + 2 + 1); - - *buf++ = (len + 1) >> 8; - *buf++ = (len + 1) & 0xff; - *buf++ = tag; - memcpy(buf, val, len); -} - -/* - * We don't look at the content of the request yet and lie - * about most of the responses. - */ -static void respond_to(struct sockaddr_in *src, struct osmo_fd *fd, - uint8_t *data, size_t len) -{ - static int fetched_info = 0; - static char mac_str[20] = {0, }; - static char model_name[64] = {0, }; - static char ser_str[20] = {0, }; - - struct sockaddr_in loc_addr; - int rc; - char loc_ip[INET_ADDRSTRLEN]; - struct msgb *msg = msgb_alloc_headroom(512, 128, "ipa get response"); - if (!msg) { - LOGP(DFIND, LOGL_ERROR, "Failed to allocate msgb\n"); - return; - } - - if (!fetched_info) { - int fd_eth; - int serno; - - /* fetch the MAC */ - fd_eth = open(ETH0_ADDR_SYSFS, O_RDONLY); - if (fd_eth >= 0) { - read(fd_eth, mac_str, sizeof(mac_str)-1); - mac_str[sizeof(mac_str)-1] = '\0'; - close(fd_eth); - } - - /* fetch the serial number */ - lc15bts_par_get_int(tall_mgr_ctx, LC15BTS_PAR_SERNR, &serno); - snprintf(ser_str, sizeof(ser_str), "%d", serno); - - strncpy(model_name, get_hwversion_desc(), sizeof(model_name)-1); - fetched_info = 1; - } - - if (source_for_dest(&src->sin_addr, &loc_addr.sin_addr) != 0) { - LOGP(DFIND, LOGL_ERROR, "Failed to determine local source\n"); - return; - } - - msgb_put_u8(msg, IPAC_MSGT_ID_RESP); - - /* append MAC addr */ - quirk_l16tv_put(msg, strlen(mac_str) + 1, IPAC_IDTAG_MACADDR, (uint8_t *) mac_str); - - /* append ip address */ - inet_ntop(AF_INET, &loc_addr.sin_addr, loc_ip, sizeof(loc_ip)); - quirk_l16tv_put(msg, strlen(loc_ip) + 1, IPAC_IDTAG_IPADDR, (uint8_t *) loc_ip); - - /* append the serial number */ - quirk_l16tv_put(msg, strlen(ser_str) + 1, IPAC_IDTAG_SERNR, (uint8_t *) ser_str); - - /* abuse some flags */ - quirk_l16tv_put(msg, strlen(model_name) + 1, IPAC_IDTAG_UNIT, (uint8_t *) model_name); - - /* ip.access nanoBTS would reply to port==3006 */ - ipaccess_prepend_header_quirk(msg, IPAC_PROTO_IPACCESS); - rc = sendto(fd->fd, msg->data, msg->len, 0, (struct sockaddr *)src, sizeof(*src)); - if (rc != msg->len) - LOGP(DFIND, LOGL_ERROR, - "Failed to send with rc(%d) errno(%d)\n", rc, errno); -} - -static int ipaccess_bcast(struct osmo_fd *fd, unsigned int what) -{ - uint8_t data[2048]; - char src[INET_ADDRSTRLEN]; - struct sockaddr_in addr = {}; - socklen_t len = sizeof(addr); - int rc; - - rc = recvfrom(fd->fd, data, sizeof(data), 0, - (struct sockaddr *) &addr, &len); - if (rc <= 0) { - LOGP(DFIND, LOGL_ERROR, - "Failed to read from socket errno(%d)\n", errno); - return -1; - } - - LOGP(DFIND, LOGL_DEBUG, - "Received request from: %s size %d\n", - inet_ntop(AF_INET, &addr.sin_addr, src, sizeof(src)), rc); - - if (rc < 6) - return 0; - - if (data[2] != IPAC_PROTO_IPACCESS || data[4] != IPAC_MSGT_ID_GET) - return 0; - - respond_to(&addr, fd, data + 6, rc - 6); - return 0; -} - -int lc15bts_mgr_nl_init(void) -{ - int rc; - - nl_fd.cb = ipaccess_bcast; - rc = osmo_sock_init_ofd(&nl_fd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, - "0.0.0.0", 3006, OSMO_SOCK_F_BIND); - if (rc < 0) { - perror("Socket creation"); - return -1; - } - - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c b/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c deleted file mode 100644 index 9665e1db..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c +++ /dev/null @@ -1,378 +0,0 @@ -/* Temperature control for NuRAN Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_mgr_temp.c - * (C) 2014 by Holger Hans Peter Freyther - * - * 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 <inttypes.h> -#include "misc/lc15bts_mgr.h" -#include "misc/lc15bts_misc.h" -#include "misc/lc15bts_temp.h" -#include "misc/lc15bts_power.h" -#include "misc/lc15bts_led.h" -#include "misc/lc15bts_swd.h" -#include "limits.h" - -#include <osmo-bts/logging.h> - -#include <osmocom/core/timer.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/linuxlist.h> - -struct lc15bts_mgr_instance *s_mgr; -static struct osmo_timer_list sensor_ctrl_timer; - -static const struct value_string state_names[] = { - { STATE_NORMAL, "NORMAL" }, - { STATE_WARNING_HYST, "WARNING (HYST)" }, - { STATE_WARNING, "WARNING" }, - { STATE_CRITICAL, "CRITICAL" }, - { 0, NULL } -}; - -const char *lc15bts_mgr_sensor_get_state(enum lc15bts_sensor_state state) -{ - return get_value_string(state_names, state); -} - -static int next_state(enum lc15bts_sensor_state current_state, int critical, int warning) -{ - int next_state = -1; - switch (current_state) { - case STATE_NORMAL: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - break; - case STATE_WARNING_HYST: - if (critical) - next_state = STATE_CRITICAL; - else if (warning) - next_state = STATE_WARNING; - else - next_state = STATE_NORMAL; - break; - case STATE_WARNING: - if (critical) - next_state = STATE_CRITICAL; - else if (!warning) - next_state = STATE_WARNING_HYST; - break; - case STATE_CRITICAL: - if (!critical && !warning) - next_state = STATE_WARNING; - break; - }; - - return next_state; -} - -static void handle_normal_actions(int actions) -{ - /* switch on the PA */ - if (actions & SENSOR_ACT_NORM_PA0_ON) { - if (lc15bts_power_set(LC15BTS_POWER_PA0, 1) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch on the PA #0\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched on the PA #0 as normal action.\n"); - } - } - - if (actions & SENSOR_ACT_NORM_PA1_ON) { - if (lc15bts_power_set(LC15BTS_POWER_PA1, 1) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch on the PA #1\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched on the PA #1 as normal action.\n"); - } - } - - if (actions & SENSOR_ACT_NORM_BTS_SRV_ON) { - LOGP(DTEMP, LOGL_NOTICE, - "Going to switch on the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl start osmo-bts.service"); - } -} - -static void handle_actions(int actions) -{ - /* switch off the PA */ - if (actions & SENSOR_ACT_PA1_OFF) { - if (lc15bts_power_set(LC15BTS_POWER_PA1, 0) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch off the PA #1. Stop BTS?\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched off the PA #1 due temperature.\n"); - } - } - - if (actions & SENSOR_ACT_PA0_OFF) { - if (lc15bts_power_set(LC15BTS_POWER_PA0, 0) != 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to switch off the PA #0. Stop BTS?\n"); - } else { - LOGP(DTEMP, LOGL_NOTICE, - "Switched off the PA #0 due temperature.\n"); - } - } - - if (actions & SENSOR_ACT_BTS_SRV_OFF) { - LOGP(DTEMP, LOGL_NOTICE, - "Going to switch off the BTS service\n"); - /* - * TODO: use/create something like nspawn that serializes - * and used SIGCHLD/waitpid to pick up the dead processes - * without invoking shell. - */ - system("/bin/systemctl stop osmo-bts.service"); - } -} - -/** - * Go back to normal! Depending on the configuration execute the normal - * actions that could (start to) undo everything we did in the other - * states. What is still missing is the power increase/decrease depending - * on the state. E.g. starting from WARNING_HYST we might want to slowly - * ramp up the output power again. - */ -static void execute_normal_act(struct lc15bts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System is back to normal state.\n"); - handle_normal_actions(manager->state.action_norm); -} - -static void execute_warning_act(struct lc15bts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached warning state.\n"); - handle_actions(manager->state.action_warn); -} - -static void execute_critical_act(struct lc15bts_mgr_instance *manager) -{ - LOGP(DTEMP, LOGL_NOTICE, "System has reached critical warning.\n"); - handle_actions(manager->state.action_crit); -} - -static void lc15bts_mgr_sensor_handle(struct lc15bts_mgr_instance *manager, - int critical, int warning) -{ - int new_state = next_state(manager->state.state, critical, warning); - - /* Nothing changed */ - if (new_state < 0) - return; - - LOGP(DTEMP, LOGL_NOTICE, "Moving from state %s to %s.\n", - get_value_string(state_names, manager->state.state), - get_value_string(state_names, new_state)); - manager->state.state = new_state; - switch (manager->state.state) { - case STATE_NORMAL: - execute_normal_act(manager); - break; - case STATE_WARNING_HYST: - /* do nothing? Maybe start to increase transmit power? */ - break; - case STATE_WARNING: - execute_warning_act(manager); - break; - case STATE_CRITICAL: - execute_critical_act(manager); - break; - }; -} - -static void sensor_ctrl_check(struct lc15bts_mgr_instance *mgr) -{ - int rc; - int temp = 0; - int warn_thresh_passed = 0; - int crit_thresh_passed = 0; - - LOGP(DTEMP, LOGL_DEBUG, "Going to check the temperature.\n"); - - /* Read the current supply temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the supply temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.supply_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.supply_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "Supply temperature is: %d\n", temp); - } - - /* Read the current SoC temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the SoC temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.soc_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.soc_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "SoC temperature is: %d\n", temp); - } - - /* Read the current fpga temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the fpga temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.fpga_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.fpga_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "FPGA temperature is: %d\n", temp); - } - - /* Read the current RMS detector temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the RMS detector temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.rmsdet_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.rmsdet_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "RMS detector temperature is: %d\n", temp); - } - - /* Read the current OCXO temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the OCXO temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.ocxo_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.ocxo_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "OCXO temperature is: %d\n", temp); - } - - /* Read the current TX #0 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the TX #0 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.tx0_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.tx0_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "TX #0 temperature is: %d\n", temp); - } - - /* Read the current TX #1 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the TX #1 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.tx1_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.tx1_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "TX #1 temperature is: %d\n", temp); - } - - /* Read the current PA #0 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the PA #0 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.pa0_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.pa0_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "PA #0 temperature is: %d\n", temp); - } - - /* Read the current PA #1 temperature */ - rc = lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, - "Failed to read the PA #1 temperature. rc=%d\n", rc); - warn_thresh_passed = crit_thresh_passed = 1; - } else { - temp = temp / 1000; - if (temp > mgr->temp.pa1_temp_limit.thresh_warn_max) - warn_thresh_passed = 1; - if (temp > mgr->temp.pa1_temp_limit.thresh_crit_max) - crit_thresh_passed = 1; - LOGP(DTEMP, LOGL_DEBUG, "PA #1 temperature is: %d\n", temp); - } - - lc15bts_mgr_sensor_handle(mgr, crit_thresh_passed, warn_thresh_passed); -} - -static void sensor_ctrl_check_cb(void *_data) -{ - struct lc15bts_mgr_instance *mgr = _data; - sensor_ctrl_check(mgr); - /* Check every minute? XXX make it configurable! */ - osmo_timer_schedule(&sensor_ctrl_timer, LC15BTS_SENSOR_TIMER_DURATION, 0); - LOGP(DTEMP, LOGL_DEBUG,"Check sensors timer expired\n"); - /* TODO: do we want to notify if some sensors could not be read? */ - lc15bts_swd_event(mgr, SWD_CHECK_TEMP_SENSOR); -} - -int lc15bts_mgr_sensor_init(struct lc15bts_mgr_instance *mgr) -{ - s_mgr = mgr; - sensor_ctrl_timer.cb = sensor_ctrl_check_cb; - sensor_ctrl_timer.data = s_mgr; - sensor_ctrl_check_cb(s_mgr); - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c b/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c deleted file mode 100644 index 424ff18f..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_mgr_vty.c - * (C) 2014 by sysmocom - s.f.m.c. GmbH - * - * All Rights Reserved - * - * Author: Alvaro Neira Ayuso <anayuso@sysmocom.de> - * - * 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 <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <stdint.h> -#include <ctype.h> -#include <string.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <inttypes.h> - -#include <osmocom/vty/vty.h> -#include <osmocom/vty/command.h> -#include <osmocom/vty/misc.h> - -#include <osmo-bts/logging.h> - -#include "lc15bts_misc.h" -#include "lc15bts_mgr.h" -#include "lc15bts_temp.h" -#include "lc15bts_power.h" -#include "lc15bts_led.h" -#include "btsconfig.h" - -static struct lc15bts_mgr_instance *s_mgr; - -static const char copyright[] = - "(C) 2012 by Harald Welte <laforge@gnumonks.org>\r\n" - "(C) 2014 by Holger Hans Peter Freyther\r\n" - "(C) 2015 by Yves Godin <support@nuranwireless.com>\r\n" - "License AGPLv3+: GNU AGPL version 2 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -static int go_to_parent(struct vty *vty) -{ - switch (vty->node) { - case MGR_NODE: - vty->node = CONFIG_NODE; - break; - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_SUPPLY_TEMP_NODE: - case LIMIT_SOC_NODE: - case LIMIT_FPGA_NODE: - case LIMIT_RMSDET_NODE: - case LIMIT_OCXO_NODE: - case LIMIT_TX0_TEMP_NODE: - case LIMIT_TX1_TEMP_NODE: - case LIMIT_PA0_TEMP_NODE: - case LIMIT_PA1_TEMP_NODE: - case LIMIT_SUPPLY_VOLT_NODE: - case LIMIT_TX0_VSWR_NODE: - case LIMIT_TX1_VSWR_NODE: - case LIMIT_SUPPLY_PWR_NODE: - case LIMIT_PA0_PWR_NODE: - case LIMIT_PA1_PWR_NODE: - vty->node = MGR_NODE; - break; - default: - vty->node = CONFIG_NODE; - } - return vty->node; -} - -static int is_config_node(struct vty *vty, int node) -{ - switch (node) { - case MGR_NODE: - case ACT_NORM_NODE: - case ACT_WARN_NODE: - case ACT_CRIT_NODE: - case LIMIT_SUPPLY_TEMP_NODE: - case LIMIT_SOC_NODE: - case LIMIT_FPGA_NODE: - case LIMIT_RMSDET_NODE: - case LIMIT_OCXO_NODE: - case LIMIT_TX0_TEMP_NODE: - case LIMIT_TX1_TEMP_NODE: - case LIMIT_PA0_TEMP_NODE: - case LIMIT_PA1_TEMP_NODE: - case LIMIT_SUPPLY_VOLT_NODE: - case LIMIT_TX0_VSWR_NODE: - case LIMIT_TX1_VSWR_NODE: - case LIMIT_SUPPLY_PWR_NODE: - case LIMIT_PA0_PWR_NODE: - case LIMIT_PA1_PWR_NODE: - return 1; - default: - return 0; - } -} - -static struct vty_app_info vty_info = { - .name = "lc15bts-mgr", - .version = PACKAGE_VERSION, - .go_parent_cb = go_to_parent, - .is_config_node = is_config_node, - .copyright = copyright, -}; - - -#define MGR_STR "Configure lc15bts-mgr\n" - -static struct cmd_node mgr_node = { - MGR_NODE, - "%s(lc15bts-mgr)# ", - 1, -}; - -static struct cmd_node act_norm_node = { - ACT_NORM_NODE, - "%s(actions-normal)# ", - 1, -}; - -static struct cmd_node act_warn_node = { - ACT_WARN_NODE, - "%s(actions-warn)# ", - 1, -}; - -static struct cmd_node act_crit_node = { - ACT_CRIT_NODE, - "%s(actions-critical)# ", - 1, -}; - -static struct cmd_node limit_supply_temp_node = { - LIMIT_SUPPLY_TEMP_NODE, - "%s(limit-supply-temp)# ", - 1, -}; - -static struct cmd_node limit_soc_node = { - LIMIT_SOC_NODE, - "%s(limit-soc)# ", - 1, -}; - -static struct cmd_node limit_fpga_node = { - LIMIT_FPGA_NODE, - "%s(limit-fpga)# ", - 1, -}; - -static struct cmd_node limit_rmsdet_node = { - LIMIT_RMSDET_NODE, - "%s(limit-rmsdet)# ", - 1, -}; - -static struct cmd_node limit_ocxo_node = { - LIMIT_OCXO_NODE, - "%s(limit-ocxo)# ", - 1, -}; - -static struct cmd_node limit_tx0_temp_node = { - LIMIT_TX0_TEMP_NODE, - "%s(limit-tx0-temp)# ", - 1, -}; -static struct cmd_node limit_tx1_temp_node = { - LIMIT_TX1_TEMP_NODE, - "%s(limit-tx1-temp)# ", - 1, -}; -static struct cmd_node limit_pa0_temp_node = { - LIMIT_PA0_TEMP_NODE, - "%s(limit-pa0-temp)# ", - 1, -}; -static struct cmd_node limit_pa1_temp_node = { - LIMIT_PA1_TEMP_NODE, - "%s(limit-pa1-temp)# ", - 1, -}; -static struct cmd_node limit_supply_volt_node = { - LIMIT_SUPPLY_VOLT_NODE, - "%s(limit-supply-volt)# ", - 1, -}; -static struct cmd_node limit_tx0_vswr_node = { - LIMIT_TX0_VSWR_NODE, - "%s(limit-tx0-vswr)# ", - 1, -}; -static struct cmd_node limit_tx1_vswr_node = { - LIMIT_TX1_VSWR_NODE, - "%s(limit-tx1-vswr)# ", - 1, -}; -static struct cmd_node limit_supply_pwr_node = { - LIMIT_SUPPLY_PWR_NODE, - "%s(limit-supply-pwr)# ", - 1, -}; -static struct cmd_node limit_pa0_pwr_node = { - LIMIT_PA0_PWR_NODE, - "%s(limit-pa0-pwr)# ", - 1, -}; -static struct cmd_node limit_pa1_pwr_node = { - LIMIT_PA1_PWR_NODE, - "%s(limit-pa1-pwr)# ", - 1, -}; - -static struct cmd_node limit_gps_fix_node = { - LIMIT_GPS_FIX_NODE, - "%s(limit-gps-fix)# ", - 1, -}; - -DEFUN(cfg_mgr, cfg_mgr_cmd, - "lc15bts-mgr", - MGR_STR) -{ - vty->node = MGR_NODE; - return CMD_SUCCESS; -} - -static void write_volt_limit(struct vty *vty, const char *name, - struct lc15bts_volt_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning min %d%s", - limit->thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " threshold critical min %d%s", - limit->thresh_crit_min, VTY_NEWLINE); -} - -static void write_vswr_limit(struct vty *vty, const char *name, - struct lc15bts_vswr_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning max %d%s", - limit->thresh_warn_max, VTY_NEWLINE); -} - -static void write_pwr_limit(struct vty *vty, const char *name, - struct lc15bts_pwr_limit *limit) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " threshold warning max %d%s", - limit->thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " threshold critical max %d%s", - limit->thresh_crit_max, VTY_NEWLINE); -} - -static void write_norm_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " %spa0-on%s", - (actions & SENSOR_ACT_NORM_PA0_ON) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %spa1-on%s", - (actions & SENSOR_ACT_NORM_PA1_ON) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-on%s", - (actions & SENSOR_ACT_NORM_BTS_SRV_ON) ? "" : "no ", VTY_NEWLINE); -} - -static void write_action(struct vty *vty, const char *name, int actions) -{ - vty_out(vty, " %s%s", name, VTY_NEWLINE); - vty_out(vty, " %spa0-off%s", - (actions & SENSOR_ACT_PA0_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %spa1-off%s", - (actions & SENSOR_ACT_PA1_OFF) ? "" : "no ", VTY_NEWLINE); - vty_out(vty, " %sbts-service-off%s", - (actions & SENSOR_ACT_BTS_SRV_OFF) ? "" : "no ", VTY_NEWLINE); -} - -static int config_write_mgr(struct vty *vty) -{ - vty_out(vty, "lc15bts-mgr%s", VTY_NEWLINE); - - write_volt_limit(vty, "limits supply_volt", &s_mgr->volt.supply_volt_limit); - write_pwr_limit(vty, "limits supply_pwr", &s_mgr->pwr.supply_pwr_limit); - write_vswr_limit(vty, "limits tx0_vswr", &s_mgr->vswr.tx0_vswr_limit); - write_vswr_limit(vty, "limits tx1_vswr", &s_mgr->vswr.tx1_vswr_limit); - - write_norm_action(vty, "actions normal", s_mgr->state.action_norm); - write_action(vty, "actions warn", s_mgr->state.action_warn); - write_action(vty, "actions critical", s_mgr->state.action_crit); - - return CMD_SUCCESS; -} - -static int config_write_dummy(struct vty *vty) -{ - return CMD_SUCCESS; -} - -#define CFG_LIMIT_TEMP(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->temp.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_TEMP(supply_temp, "SUPPLY TEMP\n", LIMIT_SUPPLY_TEMP_NODE, supply_temp_limit) -CFG_LIMIT_TEMP(soc_temp, "SOC TEMP\n", LIMIT_SOC_NODE, soc_temp_limit) -CFG_LIMIT_TEMP(fpga_temp, "FPGA TEMP\n", LIMIT_FPGA_NODE, fpga_temp_limit) -CFG_LIMIT_TEMP(rmsdet_temp, "RMSDET TEMP\n", LIMIT_RMSDET_NODE, rmsdet_temp_limit) -CFG_LIMIT_TEMP(ocxo_temp, "OCXO TEMP\n", LIMIT_OCXO_NODE, ocxo_temp_limit) -CFG_LIMIT_TEMP(tx0_temp, "TX0 TEMP\n", LIMIT_TX0_TEMP_NODE, tx0_temp_limit) -CFG_LIMIT_TEMP(tx1_temp, "TX1 TEMP\n", LIMIT_TX1_TEMP_NODE, tx1_temp_limit) -CFG_LIMIT_TEMP(pa0_temp, "PA0 TEMP\n", LIMIT_PA0_TEMP_NODE, pa0_temp_limit) -CFG_LIMIT_TEMP(pa1_temp, "PA1 TEMP\n", LIMIT_PA1_TEMP_NODE, pa1_temp_limit) -#undef CFG_LIMIT_TEMP - -#define CFG_LIMIT_VOLT(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->volt.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_VOLT(supply_volt, "SUPPLY VOLT\n", LIMIT_SUPPLY_VOLT_NODE, supply_volt_limit) -#undef CFG_LIMIT_VOLT - -#define CFG_LIMIT_VSWR(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->vswr.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_VSWR(tx0_vswr, "TX0 VSWR\n", LIMIT_TX0_VSWR_NODE, tx0_vswr_limit) -CFG_LIMIT_VSWR(tx1_vswr, "TX1 VSWR\n", LIMIT_TX1_VSWR_NODE, tx1_vswr_limit) -#undef CFG_LIMIT_VSWR - -#define CFG_LIMIT_PWR(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->pwr.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_PWR(supply_pwr, "SUPPLY PWR\n", LIMIT_SUPPLY_PWR_NODE, supply_pwr_limit) -CFG_LIMIT_PWR(pa0_pwr, "PA0 PWR\n", LIMIT_PA0_PWR_NODE, pa0_pwr_limit) -CFG_LIMIT_PWR(pa1_pwr, "PA1 PWR\n", LIMIT_PA1_PWR_NODE, pa1_pwr_limit) -#undef CFG_LIMIT_PWR - -#define CFG_LIMIT_GPS_FIX(name, expl, switch_to, variable) \ -DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd, \ - "limits " #name, \ - "Configure Limits\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->gps.variable; \ - return CMD_SUCCESS; \ -} - -CFG_LIMIT_GPS_FIX(gps_fix, "GPS FIX\n", LIMIT_GPS_FIX_NODE, gps_fix_limit) -#undef CFG_LIMIT_GPS_FIX - -DEFUN(cfg_limit_volt_warn_min, cfg_thresh_volt_warn_min_cmd, - "threshold warning min <0-48000>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct lc15bts_volt_limit *limit = vty->index; - limit->thresh_warn_min = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_volt_crit_min, cfg_thresh_volt_crit_min_cmd, - "threshold critical min <0-48000>", - "Threshold to reach\n" "Critical level\n" "Range\n") -{ - struct lc15bts_volt_limit *limit = vty->index; - limit->thresh_crit_min = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_vswr_warn_max, cfg_thresh_vswr_warn_max_cmd, - "threshold warning max <1000-200000>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct lc15bts_vswr_limit *limit = vty->index; - limit->thresh_warn_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_vswr_crit_max, cfg_thresh_vswr_crit_max_cmd, - "threshold critical max <1000-200000>", - "Threshold to reach\n" "Critical level\n" "Range\n") -{ - struct lc15bts_vswr_limit *limit = vty->index; - limit->thresh_crit_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_pwr_warn_max, cfg_thresh_pwr_warn_max_cmd, - "threshold warning max <0-200>", - "Threshold to reach\n" "Warning level\n" "Range\n") -{ - struct lc15bts_pwr_limit *limit = vty->index; - limit->thresh_warn_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_limit_pwr_crit_max, cfg_thresh_pwr_crit_max_cmd, - "threshold critical max <0-200>", - "Threshold to reach\n" "Critical level\n" "Range\n") -{ - struct lc15bts_pwr_limit *limit = vty->index; - limit->thresh_crit_max = atoi(argv[0]); - return CMD_SUCCESS; -} - -#define CFG_ACTION(name, expl, switch_to, variable) \ -DEFUN(cfg_action_##name, cfg_action_##name##_cmd, \ - "actions " #name, \ - "Configure Actions\n" expl) \ -{ \ - vty->node = switch_to; \ - vty->index = &s_mgr->state.variable; \ - return CMD_SUCCESS; \ -} -CFG_ACTION(normal, "Normal Actions\n", ACT_NORM_NODE, action_norm) -CFG_ACTION(warn, "Warning Actions\n", ACT_WARN_NODE, action_warn) -CFG_ACTION(critical, "Critical Actions\n", ACT_CRIT_NODE, action_crit) -#undef CFG_ACTION - -DEFUN(cfg_action_pa0_on, cfg_action_pa0_on_cmd, - "pa0-on", - "Switch the Power Amplifier #0 on\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_PA0_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa0_on, cfg_no_action_pa0_on_cmd, - "no pa0-on", - NO_STR "Switch the Power Amplifieri #0 on\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_PA0_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa1_on, cfg_action_pa1_on_cmd, - "pa1-on", - "Switch the Power Amplifier #1 on\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_PA1_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa1_on, cfg_no_action_pa1_on_cmd, - "no pa1-on", - NO_STR "Switch the Power Amplifieri #1 on\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_PA1_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_on, cfg_action_bts_srv_on_cmd, - "bts-service-on", - "Start the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_on, cfg_no_action_bts_srv_on_cmd, - "no bts-service-on", - NO_STR "Start the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_NORM_BTS_SRV_ON; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa0_off, cfg_action_pa0_off_cmd, - "pa0-off", - "Switch the Power Amplifier #0 off\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_PA0_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa0_off, cfg_no_action_pa0_off_cmd, - "no pa0-off", - NO_STR "Do not switch off the Power Amplifier #0\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_PA0_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_pa1_off, cfg_action_pa1_off_cmd, - "pa1-off", - "Switch the Power Amplifier #1 off\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_PA1_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_pa1_off, cfg_no_action_pa1_off_cmd, - "no pa1-off", - NO_STR "Do not switch off the Power Amplifier #1\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_PA1_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_action_bts_srv_off, cfg_action_bts_srv_off_cmd, - "bts-service-off", - "Stop the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action |= SENSOR_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(cfg_no_action_bts_srv_off, cfg_no_action_bts_srv_off_cmd, - "no bts-service-off", - NO_STR "Stop the systemd lc15bts.service\n") -{ - int *action = vty->index; - *action &= ~SENSOR_ACT_BTS_SRV_OFF; - return CMD_SUCCESS; -} - -DEFUN(show_mgr, show_mgr_cmd, "show manager", - SHOW_STR "Display information about the manager") -{ - int temp, volt, current, power, vswr; - vty_out(vty, "Warning alarm flags: 0x%08x%s", - s_mgr->lc15bts_ctrl.warn_flags, VTY_NEWLINE); - vty_out(vty, "Critical alarm flags: 0x%08x%s", - s_mgr->lc15bts_ctrl.crit_flags, VTY_NEWLINE); - vty_out(vty, "Preventive action retried: %d%s", - s_mgr->alarms.preventive_retry, VTY_NEWLINE); - vty_out(vty, "Temperature control state: %s%s", - lc15bts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE); - vty_out(vty, "Current Temperatures%s", VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp); - vty_out(vty, " Main Supply : %4.2f Celsius%s", - temp/ 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp); - vty_out(vty, " SoC : %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp); - vty_out(vty, " FPGA : %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp); - vty_out(vty, " RMSDet : %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp); - vty_out(vty, " OCXO : %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp); - vty_out(vty, " TX 0 : %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp); - vty_out(vty, " TX 1 : %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp); - vty_out(vty, " Power Amp #0: %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp); - vty_out(vty, " Power Amp #1: %4.2f Celsius%s", - temp / 1000.0f, - VTY_NEWLINE); - - vty_out(vty, "Power Status%s", VTY_NEWLINE); - lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_VOLTAGE, &volt); - lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_CURRENT, ¤t); - lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_POWER, &power); - vty_out(vty, " Main Supply : ON [%6.2f Vdc, %4.2f A, %6.2f W]%s", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - lc15bts_power_sensor_get(LC15BTS_POWER_PA0, - LC15BTS_POWER_VOLTAGE, &volt); - lc15bts_power_sensor_get(LC15BTS_POWER_PA0, - LC15BTS_POWER_CURRENT, ¤t); - lc15bts_power_sensor_get(LC15BTS_POWER_PA0, - LC15BTS_POWER_POWER, &power); - vty_out(vty, " Power Amp #0: %s [%6.2f Vdc, %4.2f A, %6.2f W]%s", - lc15bts_power_get(LC15BTS_POWER_PA0) ? "ON " : "OFF", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - lc15bts_power_sensor_get(LC15BTS_POWER_PA1, - LC15BTS_POWER_VOLTAGE, &volt); - lc15bts_power_sensor_get(LC15BTS_POWER_PA1, - LC15BTS_POWER_CURRENT, ¤t); - lc15bts_power_sensor_get(LC15BTS_POWER_PA1, - LC15BTS_POWER_POWER, &power); - vty_out(vty, " Power Amp #1: %s [%6.2f Vdc, %4.2f A, %6.2f W]%s", - lc15bts_power_get(LC15BTS_POWER_PA1) ? "ON " : "OFF", - volt /1000.0f, - current /1000.0f, - power /1000000.0f, - VTY_NEWLINE); - vty_out(vty, "VSWR Status%s", VTY_NEWLINE); - lc15bts_vswr_get(LC15BTS_VSWR_TX0, &vswr); - vty_out(vty, " VSWR TX 0: %f %s", - vswr / 1000.0f, - VTY_NEWLINE); - lc15bts_vswr_get(LC15BTS_VSWR_TX1, &vswr); - vty_out(vty, " VSWR TX 1: %f %s", - vswr / 1000.0f, - VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(show_thresh, show_thresh_cmd, "show thresholds", - SHOW_STR "Display information about the thresholds") -{ - vty_out(vty, "Temperature limits (Celsius)%s", VTY_NEWLINE); - vty_out(vty, " Main supply%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.supply_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.supply_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.supply_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " SoC%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.soc_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.soc_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.soc_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " FPGA%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.fpga_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " RMSDet%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " OCXO%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " TX0%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.tx0_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.tx0_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.tx0_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " TX1%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.tx1_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.tx1_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.tx1_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " PA0%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.pa0_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.pa0_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.pa0_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " PA1%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->temp.pa1_temp_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->temp.pa1_temp_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->temp.pa1_temp_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, "Power limits%s", VTY_NEWLINE); - vty_out(vty, " Main supply (mV)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->volt.supply_volt_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->volt.supply_volt_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " Warning min : %d%s",s_mgr->volt.supply_volt_limit.thresh_warn_min, VTY_NEWLINE); - vty_out(vty, " Critical min : %d%s",s_mgr->volt.supply_volt_limit.thresh_crit_min, VTY_NEWLINE); - vty_out(vty, " Main supply power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.supply_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.supply_pwr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " PA0 power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.pa0_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.pa0_pwr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " PA1 power (W)%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->pwr.pa1_pwr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->pwr.pa1_pwr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, "VSWR limits%s", VTY_NEWLINE); - vty_out(vty, " TX0%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->vswr.tx0_vswr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->vswr.tx0_vswr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, " TX1%s", VTY_NEWLINE); - vty_out(vty, " Critical max : %d%s",s_mgr->vswr.tx1_vswr_limit.thresh_crit_max, VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->vswr.tx1_vswr_limit.thresh_warn_max, VTY_NEWLINE); - vty_out(vty, "Days since last GPS 3D fix%s", VTY_NEWLINE); - vty_out(vty, " Warning max : %d%s",s_mgr->gps.gps_fix_limit.thresh_warn_max, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(calibrate_clock, calibrate_clock_cmd, - "calibrate clock", - "Calibration commands\n" - "Calibrate clock against GPS PPS\n") -{ - if (lc15bts_mgr_calib_run(s_mgr) < 0) { - vty_out(vty, "%%Failed to start calibration.%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; -} - -DEFUN(set_led_pattern, set_led_pattern_cmd, - "set led pattern <0-255>", - "Set LED pattern\n" - "Set LED pattern for debugging purpose only. This pattern will be overridden after 60 seconds by LED pattern of actual system state\n") -{ - int pattern_id = atoi(argv[0]); - - if ((pattern_id < 0) || (pattern_id > BLINK_PATTERN_MAX_ITEM)) { - vty_out(vty, "%%Invalid LED pattern ID. It must be in range of %d..%d %s", 0, BLINK_PATTERN_MAX_ITEM - 1, VTY_NEWLINE); - return CMD_WARNING; - } - - led_set(s_mgr, pattern_id); - return CMD_SUCCESS; -} - -DEFUN(force_mgr_state, force_mgr_state_cmd, - "force manager state <0-255>", - "Force BTS manager state\n" - "Force BTS manager state for debugging purpose only\n") -{ - int state = atoi(argv[0]); - - if ((state < 0) || (state > STATE_CRITICAL)) { - vty_out(vty, "%%Invalid BTS manager state. It must be in range of %d..%d %s", 0, STATE_CRITICAL, VTY_NEWLINE); - return CMD_WARNING; - } - - s_mgr->state.state = state; - return CMD_SUCCESS; -} - -#define LIMIT_TEMP(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_temp_##name##_##variable, limit_temp_##name##_##variable##_cmd, \ - "limit temp " #name " " #criticity " " #min_max " <-200-200>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->temp.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_warn_min, warning, min) -LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_warn_max, warning, max) -LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_crit_max, critical, max) -LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_warn_min, warning, min) -#undef LIMIT_TEMP - -#define LIMIT_VOLT(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_volt_##name##_##variable, limit_volt_##name##_##variable##_cmd, \ - "limit " #name " " #criticity " " #min_max " <0-48000>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->volt.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_max, warning, max) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_max, critical, max) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_min, warning, min) -LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_min, critical, min) -#undef LIMIT_VOLT - -#define LIMIT_PWR(name, limit, expl, variable, criticity, min_max) \ - DEFUN(limit_pwr_##name##_##variable, limit_pwr_##name##_##variable##_cmd, \ - "limit power " #name " " #criticity " " #min_max " <0-200>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->pwr.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_crit_max, critical, max) -LIMIT_PWR(pa0, pa0_pwr_limit, "PA0 PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(pa0, pa0_pwr_limit, "PA0 PWR\n", thresh_crit_max, critical, max) -LIMIT_PWR(pa1, pa1_pwr_limit, "PA1 PWR\n", thresh_warn_max, warning, max) -LIMIT_PWR(pa1, pa1_pwr_limit, "PA1 PWR\n", thresh_crit_max, critical, max) -#undef LIMIT_PWR - -#define LIMIT_VSWR(name, limit, expl, variable, criticity, min_max) \ -DEFUN(limit_vswr_##name##_##variable, limit_vswr_##name##_##variable##_cmd, \ - "limit vswr " #name " " #criticity " " #min_max " <1000-200000>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->vswr.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_VSWR(tx0, tx0_vswr_limit, "TX0 VSWR\n", thresh_warn_max, warning, max) -LIMIT_VSWR(tx0, tx0_vswr_limit, "TX0 VSWR\n", thresh_crit_max, critical, max) -LIMIT_VSWR(tx1, tx1_vswr_limit, "TX1 VSWR\n", thresh_warn_max, warning, max) -LIMIT_VSWR(tx1, tx1_vswr_limit, "TX1 VSWR\n", thresh_crit_max, critical, max) -#undef LIMIT_VSWR - -#define LIMIT_GPSFIX(limit, expl, variable, criticity, min_max) \ -DEFUN(limit_gpsfix_##variable, limit_gpsfix_##variable##_cmd, \ - "limit gpsfix " #criticity " " #min_max " <0-365>", \ - "Limit to reach\n" expl) \ -{ \ - s_mgr->gps.limit.variable = atoi(argv[0]); \ - return CMD_SUCCESS; \ -} - -LIMIT_GPSFIX(gps_fix_limit, "GPS FIX\n", thresh_warn_max, warning, max) -#undef LIMIT_GPSFIX - -static void register_limit(int limit, uint32_t unit) -{ - switch (unit) { - case MGR_LIMIT_TYPE_VOLT: - install_element(limit, &cfg_thresh_volt_warn_min_cmd); - install_element(limit, &cfg_thresh_volt_crit_min_cmd); - break; - case MGR_LIMIT_TYPE_VSWR: - install_element(limit, &cfg_thresh_vswr_warn_max_cmd); - install_element(limit, &cfg_thresh_vswr_crit_max_cmd); - break; - case MGR_LIMIT_TYPE_PWR: - install_element(limit, &cfg_thresh_pwr_warn_max_cmd); - install_element(limit, &cfg_thresh_pwr_crit_max_cmd); - break; - default: - break; - } -} - -static void register_normal_action(int act) -{ - install_element(act, &cfg_action_pa0_on_cmd); - install_element(act, &cfg_no_action_pa0_on_cmd); - install_element(act, &cfg_action_pa1_on_cmd); - install_element(act, &cfg_no_action_pa1_on_cmd); - install_element(act, &cfg_action_bts_srv_on_cmd); - install_element(act, &cfg_no_action_bts_srv_on_cmd); -} - -static void register_action(int act) -{ - install_element(act, &cfg_action_pa0_off_cmd); - install_element(act, &cfg_no_action_pa0_off_cmd); - install_element(act, &cfg_action_pa1_off_cmd); - install_element(act, &cfg_no_action_pa1_off_cmd); - install_element(act, &cfg_action_bts_srv_off_cmd); - install_element(act, &cfg_no_action_bts_srv_off_cmd); -} - -static void register_hidden_commands() -{ - install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_tx0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx0_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_tx1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx1_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_tx1_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_pa0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa0_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_temp_pa1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa1_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_temp_pa1_thresh_warn_min_cmd); - - install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_min_cmd); - install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_min_cmd); - - install_element(ENABLE_NODE, &limit_pwr_supply_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_supply_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_pwr_pa1_thresh_crit_max_cmd); - - install_element(ENABLE_NODE, &limit_vswr_tx0_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_vswr_tx0_thresh_crit_max_cmd); - install_element(ENABLE_NODE, &limit_vswr_tx1_thresh_warn_max_cmd); - install_element(ENABLE_NODE, &limit_vswr_tx1_thresh_crit_max_cmd); - - install_element(ENABLE_NODE, &limit_gpsfix_thresh_warn_max_cmd); -} - -int lc15bts_mgr_vty_init(void) -{ - vty_init(&vty_info); - - install_element_ve(&show_mgr_cmd); - install_element_ve(&show_thresh_cmd); - - install_element(ENABLE_NODE, &calibrate_clock_cmd); - - install_node(&mgr_node, config_write_mgr); - install_element(CONFIG_NODE, &cfg_mgr_cmd); - - /* install the limit nodes */ - install_node(&limit_supply_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_temp_cmd); - - install_node(&limit_soc_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_soc_temp_cmd); - - install_node(&limit_fpga_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_fpga_temp_cmd); - - install_node(&limit_rmsdet_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_rmsdet_temp_cmd); - - install_node(&limit_ocxo_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_ocxo_temp_cmd); - - install_node(&limit_tx0_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx0_temp_cmd); - - install_node(&limit_tx1_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx1_temp_cmd); - - install_node(&limit_pa0_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa0_temp_cmd); - - install_node(&limit_pa1_temp_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa1_temp_cmd); - - install_node(&limit_supply_volt_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_volt_cmd); - register_limit(LIMIT_SUPPLY_VOLT_NODE, MGR_LIMIT_TYPE_VOLT); - - install_node(&limit_tx0_vswr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx0_vswr_cmd); - register_limit(LIMIT_TX0_VSWR_NODE, MGR_LIMIT_TYPE_VSWR); - - install_node(&limit_tx1_vswr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_tx1_vswr_cmd); - register_limit(LIMIT_TX1_VSWR_NODE, MGR_LIMIT_TYPE_VSWR); - - install_node(&limit_supply_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_supply_pwr_cmd); - register_limit(LIMIT_SUPPLY_PWR_NODE, MGR_LIMIT_TYPE_PWR); - - install_node(&limit_pa0_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa0_pwr_cmd); - register_limit(LIMIT_PA0_PWR_NODE, MGR_LIMIT_TYPE_PWR); - - install_node(&limit_pa1_pwr_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_pa1_pwr_cmd); - register_limit(LIMIT_PA1_PWR_NODE, MGR_LIMIT_TYPE_PWR); - - install_node(&limit_gps_fix_node, config_write_dummy); - install_element(MGR_NODE, &cfg_limit_gps_fix_cmd); - - /* install the normal node */ - install_node(&act_norm_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_normal_cmd); - register_normal_action(ACT_NORM_NODE); - - /* install the warning and critical node */ - install_node(&act_warn_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_warn_cmd); - register_action(ACT_WARN_NODE); - - install_node(&act_crit_node, config_write_dummy); - install_element(MGR_NODE, &cfg_action_critical_cmd); - register_action(ACT_CRIT_NODE); - - /* install LED pattern command for debugging purpose */ - install_element_ve(&set_led_pattern_cmd); - install_element_ve(&force_mgr_state_cmd); - - register_hidden_commands(); - - return 0; -} - -int lc15bts_mgr_parse_config(struct lc15bts_mgr_instance *manager) -{ - int rc; - - s_mgr = manager; - rc = vty_read_config_file(s_mgr->config_file, NULL); - if (rc < 0) { - fprintf(stderr, "Failed to parse the config file: '%s'\n", - s_mgr->config_file); - return rc; - } - - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_misc.c b/src/osmo-bts-litecell15/misc/lc15bts_misc.c deleted file mode 100644 index 467b9d0a..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_misc.c +++ /dev/null @@ -1,383 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_misc.c - * (C) 2012 by Harald Welte <laforge@gnumonks.org> - * - * 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 <stdlib.h> -#include <string.h> -#include <errno.h> -#include <getopt.h> -#include <fcntl.h> -#include <limits.h> -#include <time.h> -#include <sys/signal.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/msgb.h> -#include <osmocom/core/application.h> -#include <osmocom/vty/telnet_interface.h> -#include <osmocom/vty/logging.h> - -#include "lc15bts_mgr.h" -#include "btsconfig.h" -#include "lc15bts_misc.h" -#include "lc15bts_par.h" -#include "lc15bts_mgr.h" -#include "lc15bts_temp.h" -#include "lc15bts_power.h" - -/********************************************************************* - * Temperature handling - *********************************************************************/ - -static const struct { - const char *name; - int has_max; - enum lc15bts_temp_sensor sensor; - enum lc15bts_par ee_par; -} temp_data[] = { - { - .name = "supply_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_SUPPLY, - .ee_par = LC15BTS_PAR_TEMP_SUPPLY_MAX, - }, { - .name = "soc_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_SOC, - .ee_par = LC15BTS_PAR_TEMP_SOC_MAX, - }, { - .name = "fpga_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_FPGA, - .ee_par = LC15BTS_PAR_TEMP_FPGA_MAX, - - }, { - .name = "rmsdet_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_RMSDET, - .ee_par = LC15BTS_PAR_TEMP_RMSDET_MAX, - }, { - .name = "ocxo_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_OCXO, - .ee_par = LC15BTS_PAR_TEMP_OCXO_MAX, - }, { - .name = "tx0_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_TX0, - .ee_par = LC15BTS_PAR_TEMP_TX0_MAX, - }, { - .name = "tx1_temp", - .has_max = 0, - .sensor = LC15BTS_TEMP_TX1, - .ee_par = LC15BTS_PAR_TEMP_TX1_MAX, - }, { - .name = "pa0_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_PA0, - .ee_par = LC15BTS_PAR_TEMP_PA0_MAX, - }, { - .name = "pa1_temp", - .has_max = 1, - .sensor = LC15BTS_TEMP_PA1, - .ee_par = LC15BTS_PAR_TEMP_PA1_MAX, - } -}; - -static const struct { - const char *name; - int has_max; - enum lc15bts_power_source sensor_source; - enum lc15bts_power_type sensor_type; - enum lc15bts_par ee_par; -} power_data[] = { - { - .name = "supply_volt", - .has_max = 1, - .sensor_source = LC15BTS_POWER_SUPPLY, - .sensor_type = LC15BTS_POWER_VOLTAGE, - .ee_par = LC15BTS_PAR_VOLT_SUPPLY_MAX, - }, { - .name = "supply_pwr", - .has_max = 1, - .sensor_source = LC15BTS_POWER_SUPPLY, - .sensor_type = LC15BTS_POWER_POWER, - .ee_par = LC15BTS_PAR_PWR_SUPPLY_MAX, - }, { - .name = "pa0_pwr", - .has_max = 1, - .sensor_source = LC15BTS_POWER_PA0, - .sensor_type = LC15BTS_POWER_POWER, - .ee_par = LC15BTS_PAR_PWR_PA0_MAX, - }, { - .name = "pa1_pwr", - .has_max = 1, - .sensor_source = LC15BTS_POWER_PA1, - .sensor_type = LC15BTS_POWER_POWER, - .ee_par = LC15BTS_PAR_PWR_PA1_MAX, - } -}; - -static const struct { - const char *name; - int has_max; - enum lc15bts_vswr_sensor sensor; - enum lc15bts_par ee_par; -} vswr_data[] = { - { - .name = "tx0_vswr", - .has_max = 0, - .sensor = LC15BTS_VSWR_TX0, - .ee_par = LC15BTS_PAR_VSWR_TX0_MAX, - }, { - .name = "tx1_vswr", - .has_max = 0, - .sensor = LC15BTS_VSWR_TX1, - .ee_par = LC15BTS_PAR_VSWR_TX1_MAX, - } -}; - -static const struct value_string power_unit_strs[] = { - { LC15BTS_POWER_POWER, "W" }, - { LC15BTS_POWER_VOLTAGE, "V" }, - { 0, NULL } -}; - -void lc15bts_check_temp(int no_rom_write) -{ - int temp_old[ARRAY_SIZE(temp_data)]; - int temp_cur[ARRAY_SIZE(temp_data)]; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(temp_data); i++) { - int ret; - rc = lc15bts_par_get_int(tall_mgr_ctx, temp_data[i].ee_par, &ret); - temp_old[i] = ret * 1000; - - lc15bts_temp_get(temp_data[i].sensor, &temp_cur[i]); - if (temp_cur[i] < 0 && temp_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading temperature (%d): unexpected value %d\n", - temp_data[i].sensor, temp_cur[i]); - continue; - } - - LOGP(DTEMP, LOGL_DEBUG, "Current %s temperature: %d.%d C\n", - temp_data[i].name, temp_cur[i]/1000, temp_cur[i]%1000); - - if (temp_cur[i] > temp_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "temperature: %d.%d C\n", temp_data[i].name, - temp_cur[i]/1000, temp_old[i]%1000); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, temp_data[i].ee_par, temp_cur[i]/1000); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max temp %d (%s)\n", temp_data[i].name, - rc, strerror(errno)); - } - } - } -} - -void lc15bts_check_power(int no_rom_write) -{ - int power_old[ARRAY_SIZE(power_data)]; - int power_cur[ARRAY_SIZE(power_data)]; - int i, rc; - int div_ratio; - - for (i = 0; i < ARRAY_SIZE(power_data); i++) { - int ret; - rc = lc15bts_par_get_int(tall_mgr_ctx, power_data[i].ee_par, &ret); - switch(power_data[i].sensor_type) { - case LC15BTS_POWER_VOLTAGE: - div_ratio = 1000; - break; - case LC15BTS_POWER_POWER: - div_ratio = 1000000; - break; - default: - div_ratio = 1000; - } - power_old[i] = ret * div_ratio; - - lc15bts_power_sensor_get(power_data[i].sensor_source, power_data[i].sensor_type, &power_cur[i]); - if (power_cur[i] < 0 && power_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading power (%d) (%d)\n", power_data[i].sensor_source, - power_data[i].sensor_type); - continue; - } - LOGP(DTEMP, LOGL_DEBUG, "Current %s power: %d.%d %s\n", - power_data[i].name, power_cur[i]/div_ratio, power_cur[i]%div_ratio, - get_value_string(power_unit_strs, power_data[i].sensor_type)); - - if (power_cur[i] > power_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "power: %d.%d %s\n", power_data[i].name, - power_cur[i]/div_ratio, power_cur[i]%div_ratio, - get_value_string(power_unit_strs, power_data[i].sensor_type)); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, power_data[i].ee_par, power_cur[i]/div_ratio); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max power %d (%s)\n", power_data[i].name, - rc, strerror(errno)); - } - } - } -} - -void lc15bts_check_vswr(int no_rom_write) -{ - int vswr_old[ARRAY_SIZE(vswr_data)]; - int vswr_cur[ARRAY_SIZE(vswr_data)]; - int i, rc; - - for (i = 0; i < ARRAY_SIZE(vswr_data); i++) { - int ret; - rc = lc15bts_par_get_int(tall_mgr_ctx, vswr_data[i].ee_par, &ret); - vswr_old[i] = ret * 1000; - - lc15bts_vswr_get(vswr_data[i].sensor, &vswr_cur[i]); - if (vswr_cur[i] < 0 && vswr_cur[i] > -1000) { - LOGP(DTEMP, LOGL_ERROR, "Error reading vswr (%d)\n", vswr_data[i].sensor); - continue; - } - - LOGP(DTEMP, LOGL_DEBUG, "Current %s vswr: %d.%d\n", - vswr_data[i].name, vswr_cur[i]/1000, vswr_cur[i]%1000); - - if (vswr_cur[i] > vswr_old[i]) { - LOGP(DTEMP, LOGL_NOTICE, "New maximum %s " - "vswr: %d.%d C\n", vswr_data[i].name, - vswr_cur[i]/1000, vswr_old[i]%1000); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, vswr_data[i].ee_par, vswr_cur[i]/1000); - if (rc < 0) - LOGP(DTEMP, LOGL_ERROR, "error writing new %s " - "max vswr %d (%s)\n", vswr_data[i].name, - rc, strerror(errno)); - } - } - } -} - -/********************************************************************* - * Hours handling - *********************************************************************/ -static time_t last_update; - -int lc15bts_update_hours(int no_rom_write) -{ - time_t now = time(NULL); - int rc, op_hrs; - - /* first time after start of manager program */ - if (last_update == 0) { - last_update = now; - - rc = lc15bts_par_get_int(tall_mgr_ctx, LC15BTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - return rc; - } - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - return 0; - } - - if (now >= last_update + 3600) { - rc = lc15bts_par_get_int(tall_mgr_ctx, LC15BTS_PAR_HOURS, &op_hrs); - if (rc < 0) { - LOGP(DTEMP, LOGL_ERROR, "Unable to read " - "operational hours: %d (%s)\n", rc, - strerror(errno)); - return rc; - } - - /* number of hours to increase */ - op_hrs += (now-last_update)/3600; - - LOGP(DTEMP, LOGL_INFO, "Total hours of Operation: %u\n", - op_hrs); - - if (!no_rom_write) { - rc = lc15bts_par_set_int(tall_mgr_ctx, LC15BTS_PAR_HOURS, op_hrs); - if (rc < 0) - return rc; - } - - last_update = now; - } - - return 0; -} - -/********************************************************************* - * Firmware reloading - *********************************************************************/ - -static const char *fw_sysfs[_NUM_FW] = { - [LC15BTS_FW_DSP0] = "/sys/kernel/debug/remoteproc/remoteproc0/recovery", - [LC15BTS_FW_DSP1] = "/sys/kernel/debug/remoteproc/remoteproc0/recovery", -}; - -int lc15bts_firmware_reload(enum lc15bts_firmware_type type) -{ - int fd; - int rc; - - switch (type) { - case LC15BTS_FW_DSP0: - case LC15BTS_FW_DSP1: - fd = open(fw_sysfs[type], O_WRONLY); - if (fd < 0) { - LOGP(DFW, LOGL_ERROR, "unable to open firmware device %s: %s\n", - fw_sysfs[type], strerror(errno)); - close(fd); - return fd; - } - rc = write(fd, "restart", 8); - if (rc < 8) { - LOGP(DFW, LOGL_ERROR, "short write during " - "fw write to %s\n", fw_sysfs[type]); - close(fd); - return -EIO; - } - close(fd); - default: - return -EINVAL; - } - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_misc.h b/src/osmo-bts-litecell15/misc/lc15bts_misc.h deleted file mode 100644 index 79e9e686..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_misc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _LC15BTS_MISC_H -#define _LC15BTS_MISC_H - -#include <stdint.h> - -void lc15bts_check_temp(int no_rom_write); -void lc15bts_check_power(int no_rom_write); -void lc15bts_check_vswr(int no_rom_write); - -int lc15bts_update_hours(int no_rom_write); - -enum lc15bts_firmware_type { - LC15BTS_FW_DSP0, - LC15BTS_FW_DSP1, - _NUM_FW -}; - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_nl.c b/src/osmo-bts-litecell15/misc/lc15bts_nl.c deleted file mode 100644 index 39f64aae..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_nl.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Helper for netlink */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_nl.c - * (C) 2014 by Holger Hans Peter Freyther - * - * 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 <arpa/inet.h> -#include <netinet/ip.h> - -#include <sys/socket.h> - -#include <linux/netlink.h> -#include <linux/rtnetlink.h> - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -/** - * In case one binds to 0.0.0.0/INADDR_ANY and wants to know which source - * address will be used when sending a message this function can be used. - * It will ask the routing code of the kernel for the PREFSRC - */ -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source) -{ - int fd, rc; - struct rtmsg *r; - struct rtattr *rta; - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[1024]; - } req; - - memset(&req, 0, sizeof(req)); - - fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE); - if (fd < 0) { - perror("nl socket"); - return -1; - } - - /* Send a rtmsg and ask for a response */ - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - req.n.nlmsg_type = RTM_GETROUTE; - req.n.nlmsg_seq = 1; - - /* Prepare the routing request */ - req.r.rtm_family = AF_INET; - - /* set the dest */ - rta = NLMSG_TAIL(&req.n); - rta->rta_type = RTA_DST; - rta->rta_len = RTA_LENGTH(sizeof(*dest)); - memcpy(RTA_DATA(rta), dest, sizeof(*dest)); - - /* update sizes for dest */ - req.r.rtm_dst_len = sizeof(*dest) * 8; - req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_ALIGN(rta->rta_len); - - rc = send(fd, &req, req.n.nlmsg_len, 0); - if (rc != req.n.nlmsg_len) { - perror("short write"); - close(fd); - return -2; - } - - - /* now receive a response and parse it */ - rc = recv(fd, &req, sizeof(req), 0); - if (rc <= 0) { - perror("short read"); - close(fd); - return -3; - } - - if (!NLMSG_OK(&req.n, rc) || req.n.nlmsg_type != RTM_NEWROUTE) { - close(fd); - return -4; - } - - r = NLMSG_DATA(&req.n); - rc -= NLMSG_LENGTH(sizeof(*r)); - rta = RTM_RTA(r); - while (RTA_OK(rta, rc)) { - if (rta->rta_type != RTA_PREFSRC) { - rta = RTA_NEXT(rta, rc); - continue; - } - - /* we are done */ - memcpy(loc_source, RTA_DATA(rta), RTA_PAYLOAD(rta)); - close(fd); - return 0; - } - - close(fd); - return -5; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_nl.h b/src/osmo-bts-litecell15/misc/lc15bts_nl.h deleted file mode 100644 index 340cf117..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_nl.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_nl.h - * (C) 2014 by Holger Hans Peter Freyther - * - * 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/>. - * - */ -#pragma once - -struct in_addr; - -int source_for_dest(const struct in_addr *dest, struct in_addr *loc_source); diff --git a/src/osmo-bts-litecell15/misc/lc15bts_par.c b/src/osmo-bts-litecell15/misc/lc15bts_par.c deleted file mode 100644 index af9d030f..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_par.c +++ /dev/null @@ -1,232 +0,0 @@ -/* lc15bts - access to hardware related parameters */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_par.c - * (C) 2012 by Harald Welte <laforge@gnumonks.org> - * - * 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 <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <osmocom/core/utils.h> -#include <osmocom/core/talloc.h> - -#include "lc15bts_par.h" - -const struct value_string lc15bts_par_names[_NUM_LC15BTS_PAR+1] = { - { LC15BTS_PAR_TEMP_SUPPLY_MAX, "temp-supply-max" }, - { LC15BTS_PAR_TEMP_SOC_MAX, "temp-soc-max" }, - { LC15BTS_PAR_TEMP_FPGA_MAX, "temp-fpga-max" }, - { LC15BTS_PAR_TEMP_RMSDET_MAX, "temp-rmsdet-max" }, - { LC15BTS_PAR_TEMP_OCXO_MAX, "temp-ocxo-max" }, - { LC15BTS_PAR_TEMP_TX0_MAX, "temp-tx0-max" }, - { LC15BTS_PAR_TEMP_TX1_MAX, "temp-tx1-max" }, - { LC15BTS_PAR_TEMP_PA0_MAX, "temp-pa0-max" }, - { LC15BTS_PAR_TEMP_PA1_MAX, "temp-pa1-max" }, - { LC15BTS_PAR_VOLT_SUPPLY_MAX, "volt-supply-max" }, - { LC15BTS_PAR_PWR_SUPPLY_MAX, "pwr-supply-max" }, - { LC15BTS_PAR_PWR_PA0_MAX, "pwr-pa0-max" }, - { LC15BTS_PAR_PWR_PA1_MAX, "pwr-pa1-max" }, - { LC15BTS_PAR_VSWR_TX0_MAX, "vswr-tx0-max" }, - { LC15BTS_PAR_VSWR_TX1_MAX, "vswr-tx1-max" }, - { LC15BTS_PAR_GPS_FIX, "gps-fix" }, - { LC15BTS_PAR_SERNR, "serial-nr" }, - { LC15BTS_PAR_HOURS, "hours-running" }, - { LC15BTS_PAR_BOOTS, "boot-count" }, - { LC15BTS_PAR_KEY, "key" }, - { 0, NULL } -}; - -int lc15bts_par_is_int(enum lc15bts_par par) -{ - switch (par) { - case LC15BTS_PAR_TEMP_SUPPLY_MAX: - case LC15BTS_PAR_TEMP_SOC_MAX: - case LC15BTS_PAR_TEMP_FPGA_MAX: - case LC15BTS_PAR_TEMP_RMSDET_MAX: - case LC15BTS_PAR_TEMP_OCXO_MAX: - case LC15BTS_PAR_TEMP_TX0_MAX: - case LC15BTS_PAR_TEMP_TX1_MAX: - case LC15BTS_PAR_TEMP_PA0_MAX: - case LC15BTS_PAR_TEMP_PA1_MAX: - case LC15BTS_PAR_VOLT_SUPPLY_MAX: - case LC15BTS_PAR_VSWR_TX0_MAX: - case LC15BTS_PAR_VSWR_TX1_MAX: - case LC15BTS_PAR_SERNR: - case LC15BTS_PAR_HOURS: - case LC15BTS_PAR_BOOTS: - case LC15BTS_PAR_PWR_SUPPLY_MAX: - case LC15BTS_PAR_PWR_PA0_MAX: - case LC15BTS_PAR_PWR_PA1_MAX: - return 1; - default: - return 0; - } -} - -FILE *lc15bts_par_get_path(void *ctx, enum lc15bts_par par, const char* mode) -{ - char *fpath; - FILE *fp; - - if (par >= _NUM_LC15BTS_PAR) - return NULL; - - fpath = talloc_asprintf(ctx, "%s/%s", USER_ROM_PATH, get_value_string(lc15bts_par_names, par)); - if (!fpath) - return NULL; - - fp = fopen(fpath, mode); - if (!fp) - fprintf(stderr, "Failed to open %s due to '%s' error\n", fpath, strerror(errno)); - - talloc_free(fpath); - - return fp; -} - -int lc15bts_par_get_int(void *ctx, enum lc15bts_par par, int *ret) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "r"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fscanf(fp, "%d", ret); - if (rc != 1) { - fclose(fp); - return -EIO; - } - fclose(fp); - return 0; -} - -int lc15bts_par_set_int(void *ctx, enum lc15bts_par par, int val) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "w"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fprintf(fp, "%d", val); - if (rc < 0) { - fclose(fp); - return -EIO; - } - - fsync(fileno(fp)); - fclose(fp); - return 0; -} - -int lc15bts_par_get_buf(void *ctx, enum lc15bts_par par, uint8_t *buf, unsigned int size) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "rb"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fread(buf, 1, size, fp); - - fclose(fp); - - return rc; -} - -int lc15bts_par_set_buf(void *ctx, enum lc15bts_par par, const uint8_t *buf, unsigned int size) -{ - FILE *fp = lc15bts_par_get_path(ctx, par, "wb"); - int rc; - - if (fp == NULL) { - return -errno; - } - - rc = fwrite(buf, 1, size, fp); - - fsync(fileno(fp)); - fclose(fp); - - return rc; -} - -int lc15bts_par_get_gps_fix(time_t *ret) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(lc15bts_par_names, LC15BTS_PAR_GPS_FIX)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "r"); - if (fp == NULL) { - return -errno; - } - - rc = fscanf(fp, "%lld", (long long *)ret); - if (rc != 1) { - fclose(fp); - return -EIO; - } - fclose(fp); - - return 0; -} - -int lc15bts_par_set_gps_fix(time_t val) -{ - char fpath[PATH_MAX]; - FILE *fp; - int rc; - - snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, get_value_string(lc15bts_par_names, LC15BTS_PAR_GPS_FIX)); - fpath[sizeof(fpath)-1] = '\0'; - - fp = fopen(fpath, "w"); - if (fp == NULL) { - return -errno; - } - - rc = fprintf(fp, "%lld", (long long)val); - if (rc < 0) { - fclose(fp); - return -EIO; - } - fsync(fileno(fp)); - fclose(fp); - - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_par.h b/src/osmo-bts-litecell15/misc/lc15bts_par.h deleted file mode 100644 index 74295653..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_par.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _LC15BTS_PAR_H -#define _LC15BTS_PAR_H - -#include <osmocom/core/utils.h> - -#define USER_ROM_PATH "/mnt/storage/var/run/lc15bts-mgr" - -enum lc15bts_par { - LC15BTS_PAR_TEMP_SUPPLY_MAX, - LC15BTS_PAR_TEMP_SOC_MAX, - LC15BTS_PAR_TEMP_FPGA_MAX, - LC15BTS_PAR_TEMP_RMSDET_MAX, - LC15BTS_PAR_TEMP_OCXO_MAX, - LC15BTS_PAR_TEMP_TX0_MAX, - LC15BTS_PAR_TEMP_TX1_MAX, - LC15BTS_PAR_TEMP_PA0_MAX, - LC15BTS_PAR_TEMP_PA1_MAX, - LC15BTS_PAR_VOLT_SUPPLY_MAX, - LC15BTS_PAR_PWR_SUPPLY_MAX, - LC15BTS_PAR_PWR_PA0_MAX, - LC15BTS_PAR_PWR_PA1_MAX, - LC15BTS_PAR_VSWR_TX0_MAX, - LC15BTS_PAR_VSWR_TX1_MAX, - LC15BTS_PAR_GPS_FIX, - LC15BTS_PAR_SERNR, - LC15BTS_PAR_HOURS, - LC15BTS_PAR_BOOTS, - LC15BTS_PAR_KEY, - _NUM_LC15BTS_PAR -}; - -extern const struct value_string lc15bts_par_names[_NUM_LC15BTS_PAR+1]; - -int lc15bts_par_get_int(void *ctx, enum lc15bts_par par, int *ret); -int lc15bts_par_set_int(void *ctx, enum lc15bts_par par, int val); -int lc15bts_par_get_buf(void *ctx, enum lc15bts_par par, uint8_t *buf, unsigned int size); -int lc15bts_par_set_buf(void *ctx, enum lc15bts_par par, const uint8_t *buf, unsigned int size); - -int lc15bts_par_is_int(enum lc15bts_par par); -int lc15bts_par_get_gps_fix(time_t *ret); -int lc15bts_par_set_gps_fix(time_t val); - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_power.c b/src/osmo-bts-litecell15/misc/lc15bts_power.c deleted file mode 100644 index 1a37d8e6..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_power.c +++ /dev/null @@ -1,210 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * 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 <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> - -#include "lc15bts_power.h" - -#define LC15BTS_PA_VOLTAGE 24000000 - -#define PA_SUPPLY_MIN_SYSFS "/var/lc15/pa-supply/min_microvolts" -#define PA_SUPPLY_MAX_SYSFS "/var/lc15/pa-supply/max_microvolts" - -static const char *power_enable_devs[_NUM_POWER_SOURCES] = { - [LC15BTS_POWER_PA0] = "/var/lc15/pa-state/pa0/state", - [LC15BTS_POWER_PA1] = "/var/lc15/pa-state/pa1/state", -}; - -static const char *power_sensor_devs[_NUM_POWER_SOURCES] = { - [LC15BTS_POWER_SUPPLY] = "/var/lc15/pwr-sense/main-supply/", - [LC15BTS_POWER_PA0] = "/var/lc15/pwr-sense/pa0/", - [LC15BTS_POWER_PA1] = "/var/lc15/pwr-sense/pa1/", -}; - -static const char *power_sensor_type_str[_NUM_POWER_TYPES] = { - [LC15BTS_POWER_POWER] = "power", - [LC15BTS_POWER_VOLTAGE] = "voltage", - [LC15BTS_POWER_CURRENT] = "current", -}; - -int lc15bts_power_sensor_get( - enum lc15bts_power_source source, - enum lc15bts_power_type type, - int *power) -{ - char buf[PATH_MAX]; - char pwrstr[10]; - int fd, rc; - - if (source >= _NUM_POWER_SOURCES) - return -EINVAL; - - if (type >= _NUM_POWER_TYPES) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s%s", power_sensor_devs[source], power_sensor_type_str[type]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, pwrstr, sizeof(pwrstr)); - pwrstr[sizeof(pwrstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *power = atoi(pwrstr); - return 0; -} - - -int lc15bts_power_set( - enum lc15bts_power_source source, - int en) -{ - int fd; - int rc; - - if ((source != LC15BTS_POWER_PA0) - && (source != LC15BTS_POWER_PA1) ) { - return -EINVAL; - } - - fd = open(PA_SUPPLY_MAX_SYSFS, O_WRONLY); - if (fd < 0) { - return fd; - } - rc = write(fd, "32000000", 9); - close( fd ); - - if (rc != 9) { - return -1; - } - - fd = open(PA_SUPPLY_MIN_SYSFS, O_WRONLY); - if (fd < 0) { - return fd; - } - - /* TODO NTQ: Make the voltage configurable */ - rc = write(fd, "24000000", 9); - close( fd ); - - if (rc != 9) { - return -1; - } - - fd = open(power_enable_devs[source], O_WRONLY); - if (fd < 0) { - return fd; - } - rc = write(fd, en?"1":"0", 2); - close( fd ); - - if (rc != 2) { - return -1; - } - - if (en) usleep(50*1000); - - return 0; -} - -int lc15bts_power_get( - enum lc15bts_power_source source) -{ - int fd; - int rc; - int retVal = 0; - char enstr[10]; - - fd = open(power_enable_devs[source], O_RDONLY); - if (fd < 0) { - return fd; - } - - rc = read(fd, enstr, sizeof(enstr)); - enstr[rc-1] = '\0'; - - close(fd); - - if (rc < 0) { - return rc; - } - if (rc == 0) { - return -EIO; - } - - rc = strcmp(enstr, "enabled"); - if(rc == 0) { - retVal = 1; - } - - return retVal; -} - -static const char *vswr_devs[_NUM_VSWR_SENSORS] = { - [LC15BTS_VSWR_TX0] = "/var/lc15/vswr/tx0/vswr", - [LC15BTS_VSWR_TX1] = "/var/lc15/vswr/tx1/vswr", -}; - -int lc15bts_vswr_get(enum lc15bts_vswr_sensor sensor, int *vswr) -{ - char buf[PATH_MAX]; - char vswrstr[8]; - int fd, rc; - - if (sensor < 0 || sensor >= _NUM_VSWR_SENSORS) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s", vswr_devs[sensor]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, vswrstr, sizeof(vswrstr)); - vswrstr[sizeof(vswrstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *vswr = atoi(vswrstr); - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_power.h b/src/osmo-bts-litecell15/misc/lc15bts_power.h deleted file mode 100644 index b48cfdcd..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_power.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _LC15BTS_POWER_H -#define _LC15BTS_POWER_H - -enum lc15bts_power_source { - LC15BTS_POWER_SUPPLY, - LC15BTS_POWER_PA0, - LC15BTS_POWER_PA1, - _NUM_POWER_SOURCES -}; - -enum lc15bts_power_type { - LC15BTS_POWER_POWER, - LC15BTS_POWER_VOLTAGE, - LC15BTS_POWER_CURRENT, - _NUM_POWER_TYPES -}; - -int lc15bts_power_sensor_get( - enum lc15bts_power_source source, - enum lc15bts_power_type type, - int *volt); - -int lc15bts_power_set( - enum lc15bts_power_source source, - int en); - -int lc15bts_power_get( - enum lc15bts_power_source source); - -enum lc15bts_vswr_sensor { - LC15BTS_VSWR_TX0, - LC15BTS_VSWR_TX1, - _NUM_VSWR_SENSORS -}; - -int lc15bts_vswr_get(enum lc15bts_vswr_sensor sensor, int *vswr); - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_swd.c b/src/osmo-bts-litecell15/misc/lc15bts_swd.c deleted file mode 100644 index eac64d66..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_swd.c +++ /dev/null @@ -1,178 +0,0 @@ -/* Systemd service wd notification for Litecell 1.5 BTS management daemon */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * 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 "misc/lc15bts_mgr.h" -#include "misc/lc15bts_swd.h" -#include <osmocom/core/logging.h> - -/* Needed for service watchdog notification */ -#include <systemd/sd-daemon.h> - -/* This is the period used to verify if all events have been registered to be allowed - to notify the systemd service watchdog -*/ -#define SWD_PERIOD 30 - -static void swd_start(struct lc15bts_mgr_instance *mgr); -static void swd_process(struct lc15bts_mgr_instance *mgr); -static void swd_close(struct lc15bts_mgr_instance *mgr); -static void swd_state_reset(struct lc15bts_mgr_instance *mgr, int reason); -static int swd_run(struct lc15bts_mgr_instance *mgr, int from_loop); -static void swd_loop_run(void *_data); - -enum swd_state { - SWD_INITIAL, - SWD_IN_PROGRESS, -}; - -enum swd_result { - SWD_FAIL_START, - SWD_FAIL_NOTIFY, - SWD_SUCCESS, -}; - -static void swd_start(struct lc15bts_mgr_instance *mgr) -{ - swd_process(mgr); -} - -static void swd_process(struct lc15bts_mgr_instance *mgr) -{ - int rc = 0, notify = 0; - - /* Did we get all needed conditions ? */ - if (mgr->swd.swd_eventmasks == mgr->swd.swd_events) { - /* Ping systemd service wd if enabled */ - rc = sd_notify(0, "WATCHDOG=1"); - LOGP(DSWD, LOGL_NOTICE, "Watchdog notification attempt\n"); - notify = 1; - } - else { - LOGP(DSWD, LOGL_NOTICE, "Missing watchdog events: e:0x%016llx,m:0x%016llx\n",mgr->swd.swd_events,mgr->swd.swd_eventmasks); - } - - if (rc < 0) { - LOGP(DSWD, LOGL_ERROR, - "Failed to notify system service watchdog: %d\n", rc); - swd_state_reset(mgr, SWD_FAIL_NOTIFY); - return; - } - else { - /* Did we notified the watchdog? */ - if (notify) { - mgr->swd.swd_events = 0; - /* Makes sure we really cleared it in case any event was notified at this same moment (it would be lost) */ - if (mgr->swd.swd_events != 0) - mgr->swd.swd_events = 0; - } - } - - swd_state_reset(mgr, SWD_SUCCESS); - return; -} - -static void swd_close(struct lc15bts_mgr_instance *mgr) -{ -} - -static void swd_state_reset(struct lc15bts_mgr_instance *mgr, int outcome) -{ - if (mgr->swd.swd_from_loop) { - mgr->swd.swd_timeout.data = mgr; - mgr->swd.swd_timeout.cb = swd_loop_run; - osmo_timer_schedule(&mgr->swd.swd_timeout, SWD_PERIOD, 0); - } - - mgr->swd.state = SWD_INITIAL; - swd_close(mgr); -} - -static int swd_run(struct lc15bts_mgr_instance *mgr, int from_loop) -{ - if (mgr->swd.state != SWD_INITIAL) { - LOGP(DSWD, LOGL_ERROR, "Swd is already in progress.\n"); - return -1; - } - - mgr->swd.swd_from_loop = from_loop; - - /* From now on everything will be handled from the failure */ - mgr->swd.state = SWD_IN_PROGRESS; - swd_start(mgr); - return 0; -} - -static void swd_loop_run(void *_data) -{ - int rc; - struct lc15bts_mgr_instance *mgr = _data; - - LOGP(DSWD, LOGL_NOTICE, "Going to check for watchdog notification.\n"); - rc = swd_run(mgr, 1); - if (rc != 0) { - swd_state_reset(mgr, SWD_FAIL_START); - } -} - -/* 'swd_num_events' configures the number of events to be monitored before notifying the - systemd service watchdog. It must be in the range of [1,64]. Events are notified - through the function 'lc15bts_swd_event' -*/ -int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events) -{ - /* Checks for a valid number of events to validate */ - if (swd_num_events < 1 || swd_num_events > 64) - return(-1); - - mgr->swd.state = SWD_INITIAL; - mgr->swd.swd_timeout.data = mgr; - mgr->swd.swd_timeout.cb = swd_loop_run; - osmo_timer_schedule(&mgr->swd.swd_timeout, 0, 0); - - if (swd_num_events == 64){ - mgr->swd.swd_eventmasks = 0xffffffffffffffffULL; - } - else { - mgr->swd.swd_eventmasks = ((1ULL << swd_num_events) - 1); - } - mgr->swd.swd_events = 0; - mgr->swd.num_events = swd_num_events; - - return 0; -} - -/* Notifies that the specified event 'swd_event' happened correctly; - the value must be in the range of [0,'swd_num_events'[ (see lc15bts_swd_init). - For example, if 'swd_num_events' was 64, 'swd_event' events are numbered 0 to 63. - WARNING: if this function can be used from multiple threads at the same time, - it must be protected with a kind of mutex to avoid losing event notification. -*/ -int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event) -{ - /* Checks for a valid specified event (smaller than max possible) */ - if ((int)(swd_event) < 0 || (int)(swd_event) >= mgr->swd.num_events) - return(-1); - - mgr->swd.swd_events = mgr->swd.swd_events | ((unsigned long long int)(1) << (int)(swd_event)); - - /* !!! Uncomment following line to debug events notification */ - LOGP(DSWD, LOGL_DEBUG,"Swd event notified: %d\n", (int)(swd_event)); - - return 0; -} diff --git a/src/osmo-bts-litecell15/misc/lc15bts_swd.h b/src/osmo-bts-litecell15/misc/lc15bts_swd.h deleted file mode 100644 index b78a2c2a..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_swd.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _LC15BTS_SWD_H -#define _LC15BTS_SWD_H - -int lc15bts_swd_init(struct lc15bts_mgr_instance *mgr, int swd_num_events); -int lc15bts_swd_event(struct lc15bts_mgr_instance *mgr, enum mgr_swd_events swd_event); - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_temp.c b/src/osmo-bts-litecell15/misc/lc15bts_temp.c deleted file mode 100644 index 45602dcc..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_temp.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * 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 <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> - -#include <osmocom/core/utils.h> - -#include "lc15bts_temp.h" - -static const char *temp_devs[_NUM_TEMP_SENSORS] = { - [LC15BTS_TEMP_SUPPLY] = "/var/lc15/temp/main-supply/temp", - [LC15BTS_TEMP_SOC] = "/var/lc15/temp/cpu/temp", - [LC15BTS_TEMP_FPGA] = "/var/lc15/temp/fpga/temp", - [LC15BTS_TEMP_RMSDET] = "/var/lc15/temp/rmsdet/temp", - [LC15BTS_TEMP_OCXO] = "/var/lc15/temp/ocxo/temp", - [LC15BTS_TEMP_TX0] = "/var/lc15/temp/tx0/temp", - [LC15BTS_TEMP_TX1] = "/var/lc15/temp/tx1/temp", - [LC15BTS_TEMP_PA0] = "/var/lc15/temp/pa0/temp", - [LC15BTS_TEMP_PA1] = "/var/lc15/temp/pa1/temp", -}; - -int lc15bts_temp_get(enum lc15bts_temp_sensor sensor, int *temp) -{ - char buf[PATH_MAX]; - char tempstr[8]; - int fd, rc; - - if (sensor < 0 || sensor >= _NUM_TEMP_SENSORS) - return -EINVAL; - - snprintf(buf, sizeof(buf)-1, "%s", temp_devs[sensor]); - buf[sizeof(buf)-1] = '\0'; - - fd = open(buf, O_RDONLY); - if (fd < 0) - return fd; - - rc = read(fd, tempstr, sizeof(tempstr)); - tempstr[sizeof(tempstr)-1] = '\0'; - if (rc < 0) { - close(fd); - return rc; - } - if (rc == 0) { - close(fd); - return -EIO; - } - close(fd); - *temp = atoi(tempstr); - return 0; -} - diff --git a/src/osmo-bts-litecell15/misc/lc15bts_temp.h b/src/osmo-bts-litecell15/misc/lc15bts_temp.h deleted file mode 100644 index 35d81f1b..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_temp.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _LC15BTS_TEMP_H -#define _LC15BTS_TEMP_H - -enum lc15bts_temp_sensor { - LC15BTS_TEMP_SUPPLY, - LC15BTS_TEMP_SOC, - LC15BTS_TEMP_FPGA, - LC15BTS_TEMP_RMSDET, - LC15BTS_TEMP_OCXO, - LC15BTS_TEMP_TX0, - LC15BTS_TEMP_TX1, - LC15BTS_TEMP_PA0, - LC15BTS_TEMP_PA1, - _NUM_TEMP_SENSORS -}; - -enum lc15bts_temp_type { - LC15BTS_TEMP_INPUT, - LC15BTS_TEMP_LOWEST, - LC15BTS_TEMP_HIGHEST, - LC15BTS_TEMP_FAULT, - _NUM_TEMP_TYPES -}; - -int lc15bts_temp_get(enum lc15bts_temp_sensor sensor, int *temp); - - -#endif diff --git a/src/osmo-bts-litecell15/misc/lc15bts_util.c b/src/osmo-bts-litecell15/misc/lc15bts_util.c deleted file mode 100644 index 430ce0f7..00000000 --- a/src/osmo-bts-litecell15/misc/lc15bts_util.c +++ /dev/null @@ -1,164 +0,0 @@ -/* lc15bts-util - access to hardware related parameters */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * sysmobts_misc.c - * (C) 2012-2013 by Harald Welte <laforge@gnumonks.org> - * - * 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 <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <getopt.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/msgb.h> - -#include "lc15bts_par.h" - -void *tall_util_ctx; - -enum act { - ACT_GET, - ACT_SET, -}; - -static enum act action; -static char *write_arg; -static int void_warranty; - -static void print_help() -{ - const struct value_string *par = lc15bts_par_names; - - printf("lc15bts-util [--void-warranty -r | -w value] param_name\n"); - printf("Possible param names:\n"); - - for (; par->str != NULL; par += 1) { - if (!lc15bts_par_is_int(par->value)) - continue; - printf(" %s\n", par->str); - } -} - -static int parse_options(int argc, char **argv) -{ - while (1) { - int option_idx = 0, c; - static const struct option long_options[] = { - { "help", 0, 0, 'h' }, - { "read", 0, 0, 'r' }, - { "void-warranty", 0, 0, 1000}, - { "write", 1, 0, 'w' }, - { 0, 0, 0, 0 } - }; - - c = getopt_long(argc, argv, "rw:h", - long_options, &option_idx); - if (c == -1) - break; - switch (c) { - case 'r': - action = ACT_GET; - break; - case 'w': - action = ACT_SET; - write_arg = optarg; - break; - case 'h': - print_help(); - return -1; - break; - case 1000: - printf("Will void warranty on write.\n"); - void_warranty = 1; - break; - default: - return -1; - } - } - - return 0; -} - -int main(int argc, char **argv) -{ - const char *parname; - enum lc15bts_par par; - int rc, val; - - tall_util_ctx = talloc_named_const(NULL, 1, "lc15 utils"); - msgb_talloc_ctx_init(tall_util_ctx, 0); - - rc = parse_options(argc, argv); - if (rc < 0) - exit(2); - - if (optind >= argc) { - fprintf(stderr, "You must specify the parameter name\n"); - exit(2); - } - parname = argv[optind]; - - rc = get_string_value(lc15bts_par_names, parname); - if (rc < 0) { - fprintf(stderr, "`%s' is not a valid parameter\n", parname); - exit(2); - } else - par = rc; - - switch (action) { - case ACT_GET: - rc = lc15bts_par_get_int(tall_util_ctx, par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("%d\n", val); - break; - case ACT_SET: - rc = lc15bts_par_get_int(tall_util_ctx, par, &val); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - if (val != 0xFFFF && val != 0xFF && val != 0xFFFFFFFF && !void_warranty) { - fprintf(stderr, "Parameter is already set!\r\n"); - goto err; - } - rc = lc15bts_par_set_int(tall_util_ctx, par, atoi(write_arg)); - if (rc < 0) { - fprintf(stderr, "Error %d\n", rc); - goto err; - } - printf("Success setting %s=%d\n", parname, - atoi(write_arg)); - break; - default: - fprintf(stderr, "Unsupported action\n"); - goto err; - } - - exit(0); - -err: - exit(1); -} - diff --git a/src/osmo-bts-litecell15/oml.c b/src/osmo-bts-litecell15/oml.c deleted file mode 100644 index 1fe7205a..00000000 --- a/src/osmo-bts-litecell15/oml.c +++ /dev/null @@ -1,2112 +0,0 @@ -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * (C) 2011 by Harald Welte <laforge@gnumonks.org> - * (C) 2013-2014 by Holger Hans Peter Freyther - * - * 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 <errno.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/fsm.h> - -#include <nrw/litecell15/gsml1prim.h> -#include <nrw/litecell15/gsml1const.h> -#include <nrw/litecell15/gsml1types.h> -#include <nrw/litecell15/litecell15.h> - -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/logging.h> -#include <osmo-bts/oml.h> -#include <osmo-bts/rsl.h> -#include <osmo-bts/amr.h> -#include <osmo-bts/bts.h> -#include <osmo-bts/bts_model.h> -#include <osmo-bts/phy_link.h> -#include <osmo-bts/handover.h> -#include <osmo-bts/l1sap.h> -#include <osmo-bts/nm_common_fsm.h> - -#include "l1_if.h" -#include "lc15bts.h" -#include "utils.h" - -static int mph_info_chan_confirm(struct gsm_lchan *lchan, - enum osmo_mph_info_type type, uint8_t cause) -{ - struct osmo_phsap_prim l1sap; - - memset(&l1sap, 0, sizeof(l1sap)); - osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_CONFIRM, - NULL); - l1sap.u.info.type = type; - l1sap.u.info.u.act_cnf.chan_nr = gsm_lchan2chan_nr(lchan); - l1sap.u.info.u.act_cnf.cause = cause; - - return l1sap_up(lchan->ts->trx, &l1sap); -} - -enum sapi_cmd_type { - SAPI_CMD_ACTIVATE, - SAPI_CMD_CONFIG_CIPHERING, - SAPI_CMD_CONFIG_LOGCH_PARAM, - SAPI_CMD_SACCH_REL_MARKER, - SAPI_CMD_REL_MARKER, - SAPI_CMD_DEACTIVATE, -}; - -struct sapi_cmd { - struct llist_head entry; - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; - enum sapi_cmd_type type; - int (*callback)(struct gsm_lchan *lchan, int status); -}; - -static const enum GsmL1_LogChComb_t pchan_to_logChComb[_GSM_PCHAN_MAX] = { - [GSM_PCHAN_NONE] = GsmL1_LogChComb_0, - [GSM_PCHAN_CCCH] = GsmL1_LogChComb_IV, - [GSM_PCHAN_CCCH_SDCCH4] = GsmL1_LogChComb_V, - [GSM_PCHAN_CCCH_SDCCH4_CBCH] = GsmL1_LogChComb_V, - [GSM_PCHAN_TCH_F] = GsmL1_LogChComb_I, - [GSM_PCHAN_TCH_H] = GsmL1_LogChComb_II, - [GSM_PCHAN_SDCCH8_SACCH8C] = GsmL1_LogChComb_VII, - [GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = GsmL1_LogChComb_VII, - [GSM_PCHAN_PDCH] = GsmL1_LogChComb_XIII, - [GSM_PCHAN_UNKNOWN] = GsmL1_LogChComb_0, - /* - * GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be - * part of this, only "real" pchan values will be looked up here. - * See the callers of ts_connect_as(). - */ -}; - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb); - -static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct lc15l1_hdl *gl1, - uint32_t hLayer3_uint32) -{ - HANDLE hLayer3; - prim->id = id; - - osmo_static_assert(sizeof(HANDLE) >= 4, l1p_handle_is_at_least_32bit); - hLayer3 = (void*)hLayer3_uint32; - - switch (id) { - case GsmL1_PrimId_MphInitReq: - //prim->u.mphInitReq.hLayer1 = (HANDLE)gl1->hLayer1; - prim->u.mphInitReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseReq: - prim->u.mphCloseReq.hLayer1 = gl1->hLayer1; - prim->u.mphCloseReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectReq: - prim->u.mphConnectReq.hLayer1 = gl1->hLayer1; - prim->u.mphConnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectReq: - prim->u.mphDisconnectReq.hLayer1 = gl1->hLayer1; - prim->u.mphDisconnectReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateReq: - prim->u.mphActivateReq.hLayer1 = gl1->hLayer1; - prim->u.mphActivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateReq: - prim->u.mphDeactivateReq.hLayer1 = gl1->hLayer1; - prim->u.mphDeactivateReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigReq: - prim->u.mphConfigReq.hLayer1 = gl1->hLayer1; - prim->u.mphConfigReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureReq: - prim->u.mphMeasureReq.hLayer1 = gl1->hLayer1; - prim->u.mphMeasureReq.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphInitCnf: - prim->u.mphInitCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphCloseCnf: - prim->u.mphCloseCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConnectCnf: - prim->u.mphConnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDisconnectCnf: - prim->u.mphDisconnectCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphActivateCnf: - prim->u.mphActivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphDeactivateCnf: - prim->u.mphDeactivateCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphConfigCnf: - prim->u.mphConfigCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphMeasureCnf: - prim->u.mphMeasureCnf.hLayer3 = hLayer3; - break; - case GsmL1_PrimId_MphTimeInd: - break; - case GsmL1_PrimId_MphSyncInd: - break; - case GsmL1_PrimId_PhEmptyFrameReq: - prim->u.phEmptyFrameReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_PhDataReq: - prim->u.phDataReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_PhConnectInd: - break; - case GsmL1_PrimId_PhReadyToSendInd: - break; - case GsmL1_PrimId_PhDataInd: - break; - case GsmL1_PrimId_PhRaInd: - break; - default: - LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", id); - break; - } - return &prim->u; -} - -static uint32_t l1p_handle_for_trx(struct gsm_bts_trx *trx) -{ - struct gsm_bts *bts = trx->bts; - - osmo_static_assert(sizeof(trx->nr) == 1, trx_nr_is_8bit); - osmo_static_assert(sizeof(bts->nr) == 1, bts_nr_is_8bit); - - return bts->nr << 24 - | trx->nr << 16; -} - -static uint32_t l1p_handle_for_ts(struct gsm_bts_trx_ts *ts) -{ - osmo_static_assert(sizeof(ts->nr) == 1, ts_nr_is_8bit); - - return l1p_handle_for_trx(ts->trx) - | ts->nr << 8; -} - - -static uint32_t l1p_handle_for_lchan(struct gsm_lchan *lchan) -{ - osmo_static_assert(sizeof(lchan->nr) == 1, lchan_nr_is_8bit); - - return l1p_handle_for_ts(lchan->ts) - | lchan->nr; -} - -GsmL1_Status_t prim_status(GsmL1_Prim_t *prim) -{ - switch (prim->id) { - case GsmL1_PrimId_MphInitCnf: - return prim->u.mphInitCnf.status; - case GsmL1_PrimId_MphCloseCnf: - return prim->u.mphCloseCnf.status; - case GsmL1_PrimId_MphConnectCnf: - return prim->u.mphConnectCnf.status; - case GsmL1_PrimId_MphDisconnectCnf: - return prim->u.mphDisconnectCnf.status; - case GsmL1_PrimId_MphActivateCnf: - return prim->u.mphActivateCnf.status; - case GsmL1_PrimId_MphDeactivateCnf: - return prim->u.mphDeactivateCnf.status; - case GsmL1_PrimId_MphConfigCnf: - return prim->u.mphConfigCnf.status; - case GsmL1_PrimId_MphMeasureCnf: - return prim->u.mphMeasureCnf.status; - default: - break; - } - return GsmL1_Status_Success; -} - -#if 0 -static int compl_cb_send_oml_msg(struct msgb *l1_msg, void *data) -{ - struct msgb *resp_msg = data; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - - if (prim_status(l1p) != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(lc15bts_l1prim_names, l1p->id), - get_value_string(lc15bts_l1status_names, cc->status)); - return 0; - } - - msgb_free(l1_msg); - - return abis_nm_sendmsg(msg); -} -#endif - -int lchan_activate(struct gsm_lchan *lchan); - -static int opstart_compl(struct gsm_abis_mo *mo, struct msgb *l1_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_Status_t status = prim_status(l1p); - struct gsm_bts_trx *trx = gsm_bts_trx_num(mo->bts, mo->obj_inst.trx_nr); - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, "Rx %s, status: %s\n", - get_value_string(lc15bts_l1prim_names, l1p->id), - get_value_string(lc15bts_l1status_names, status)); - msgb_free(l1_msg); - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_NACK, - (void*)(intptr_t)NM_NACK_CANT_PERFORM); - case NM_OC_CHANNEL: - return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi, NM_EV_OPSTART_NACK, - (void*)(intptr_t)NM_NACK_CANT_PERFORM); - default: - OSMO_ASSERT(0); - } - } - - msgb_free(l1_msg); - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_ACK, NULL); - case NM_OC_CHANNEL: - /* ugly hack to auto-activate all SAPIs for the BCCH/CCCH on TS0 */ - if (mo->obj_inst.trx_nr == 0 && - mo->obj_inst.ts_nr == 0) { - struct gsm_lchan *cbch = gsm_bts_get_cbch(mo->bts); - DEBUGP(DL1C, "====> trying to activate lchans of BCCH\n"); - mo->bts->c0->ts[0].lchan[CCCH_LCHAN].rel_act_kind = - LCHAN_REL_ACT_OML; - lchan_activate(&mo->bts->c0->ts[0].lchan[CCCH_LCHAN]); - if (cbch) { - cbch->rel_act_kind = LCHAN_REL_ACT_OML; - lchan_activate(cbch); - } - } - return osmo_fsm_inst_dispatch(trx->ts[mo->obj_inst.ts_nr].mo.fi, - NM_EV_OPSTART_ACK, NULL); - default: - OSMO_ASSERT(0); - } -} - -static int opstart_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_abis_mo *mo; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - - mo = &trx->ts[cnf->u8Tn].mo; - return opstart_compl(mo, l1_msg); -} - -static int trx_mute_on_init_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - GsmL1_Status_t status; - - status = sysp->u.muteRfCnf.status; - - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx RF-MUTE.conf status=%s\n", - get_value_string(lc15bts_l1status_names, status)); - bts_shutdown(trx->bts, "RF-MUTE failure"); - } - - msgb_free(resp); - - return 0; -} - -static int trx_init_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphInitCnf_t *ic = &l1p->u.mphInitCnf; - - LOGP(DL1C, LOGL_INFO, "Rx MPH-INIT.conf (status=%s)\n", - get_value_string(lc15bts_l1status_names, ic->status)); - - /* store layer1 handle */ - if (ic->status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_FATAL, "Rx MPH-INIT.conf status=%s\n", - get_value_string(lc15bts_l1status_names, ic->status)); - bts_shutdown(trx->bts, "MPH-INIT failure"); - } - - fl1h->hLayer1 = ic->hLayer1; - - /* If the TRX was already locked the MphInit would have undone it */ - if (trx->mo.nm_state.administrative == NM_STATE_LOCKED) - trx_rf_lock(trx, 1, trx_mute_on_init_cb); - - /* Begin to ramp up the power */ - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0, NULL); - - return opstart_compl(&trx->mo, l1_msg); -} - -int gsm_abis_mo_check_attr(const struct gsm_abis_mo *mo, const uint8_t *attr_ids, - unsigned int num_attr_ids) -{ - unsigned int i; - - if (!mo->nm_attr) - return 0; - - for (i = 0; i < num_attr_ids; i++) { - if (!TLVP_PRESENT(mo->nm_attr, attr_ids[i])) - return 0; - } - return 1; -} - -static const uint8_t trx_rqd_attr[] = { NM_ATT_RF_MAXPOWR_R }; - -/* initialize the layer1 */ -static int trx_init(struct gsm_bts_trx *trx) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct msgb *msg; - GsmL1_MphInitReq_t *mi_req; - GsmL1_DeviceParam_t *dev_par; - int rc, lc15_band; - - if (!gsm_abis_mo_check_attr(&trx->mo, trx_rqd_attr, - ARRAY_SIZE(trx_rqd_attr))) { - /* HACK: spec says we need to decline, but openbsc - * doesn't deal with this very well */ - return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_ACK, NULL); - //return osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_OPSTART_NACK, - // (void*)(intptr_t)NM_NACK_CANT_PERFORM); - } - - /* Update TRX band */ - rc = gsm_arfcn2band_rc(trx->arfcn, &trx->bts->band); - if (rc) { - /* FIXME: abort initialization? */ - LOGP(DL1C, LOGL_ERROR, "Could not pick GSM band " - "for ARFCN %u\n", trx->arfcn); - trx->bts->band = 0x00; - } - - lc15_band = lc15bts_select_lc15_band(trx, trx->arfcn); - if (lc15_band < 0) { - LOGP(DL1C, LOGL_ERROR, "Unsupported GSM band %s\n", - gsm_band_name(trx->bts->band)); - } - - msg = l1p_msgb_alloc(); - mi_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphInitReq, fl1h, - l1p_handle_for_trx(trx)); - dev_par = &mi_req->deviceParam; - dev_par->devType = GsmL1_DevType_TxdRxu; - dev_par->freqBand = lc15_band; - dev_par->u16Arfcn = trx->arfcn; - dev_par->u16BcchArfcn = trx->bts->c0->arfcn; - dev_par->u8NbTsc = trx->bts->bsic & 7; - dev_par->fRxPowerLevel = trx_ms_pwr_ctrl_is_osmo(trx) - ? 0.0 : trx->bts->ul_power_target; - - dev_par->fTxPowerLevel = 0.0; - LOGP(DL1C, LOGL_NOTICE, "Init TRX (Band %d, ARFCN %u, TSC %u, RxPower % 2f dBm, " - "TxPower % 2.2f dBm\n", dev_par->freqBand, dev_par->u16Arfcn, dev_par->u8NbTsc, - dev_par->fRxPowerLevel, dev_par->fTxPowerLevel); - - /* send MPH-INIT-REQ, wait for MPH-INIT-CNF */ - return l1if_gsm_req_compl(fl1h, msg, trx_init_compl_cb, NULL); -} - -uint32_t trx_get_hlayer1(const struct gsm_bts_trx *trx) -{ - const struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - return fl1h->hLayer1; -} - -static int trx_close_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - msgb_free(l1_msg); - bts_model_trx_close_cb(trx, 0); - return 0; -} - -void bts_model_trx_close(struct gsm_bts_trx *trx) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct msgb *msg; - int rc; - - msg = l1p_msgb_alloc(); - prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphCloseReq, fl1h, - l1p_handle_for_trx(trx)); - LOGP(DL1C, LOGL_NOTICE, "Close TRX %u\n", trx->nr); - - rc = l1if_gsm_req_compl(fl1h, msg, trx_close_compl_cb, NULL); - if (rc < 0) - bts_model_trx_close_cb(trx, rc); -} - -static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - uint8_t mute[8]; - int i; - - for (i = 0; i < ARRAY_SIZE(mute); ++i) - mute[i] = locked ? 1 : 0; - - return l1if_mute_rf(fl1h, mute, cb); -} - -int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8], - int success) -{ - if (success) { - int i; - int is_locked = 1; - - for (i = 0; i < 8; ++i) - if (!mute_state[i]) - is_locked = 0; - - mo->nm_state.administrative = - is_locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED; - mo->procedure_pending = 0; - return oml_mo_statechg_ack(mo); - } else { - mo->procedure_pending = 0; - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - } -} - -static int ts_connect_as(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config pchan, - l1if_compl_cb *cb, void *data) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(ts->trx); - GsmL1_MphConnectReq_t *cr; - - if (pchan == GSM_PCHAN_TCH_F_PDCH - || pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) { - LOGP(DL1C, LOGL_ERROR, - "%s Requested TS connect as %s," - " expected a specific pchan instead\n", - gsm_ts_and_pchan_name(ts), gsm_pchan_name(pchan)); - return -EINVAL; - } - - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - cr->logChComb = pchan_to_logChComb[pchan]; - - return l1if_gsm_req_compl(fl1h, msg, cb, NULL); -} - -static int ts_opstart(struct gsm_bts_trx_ts *ts) -{ - enum gsm_phys_chan_config pchan = ts->pchan; - switch (pchan) { - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - ts->dyn.pchan_is = ts->dyn.pchan_want = GSM_PCHAN_NONE; - /* First connect as NONE, until first RSL CHAN ACT. */ - pchan = GSM_PCHAN_NONE; - break; - case GSM_PCHAN_TCH_F_PDCH: - /* First connect as TCH/F, expecting PDCH ACT. */ - pchan = GSM_PCHAN_TCH_F; - break; - default: - /* simply use ts->pchan */ - break; - } - return ts_connect_as(ts, pchan, opstart_compl_cb, NULL); -} - -GsmL1_Sapi_t lchan_to_GsmL1_Sapi_t(const struct gsm_lchan *lchan) -{ - switch (lchan->type) { - case GSM_LCHAN_TCH_F: - return GsmL1_Sapi_TchF; - case GSM_LCHAN_TCH_H: - return GsmL1_Sapi_TchH; - default: - LOGP(DL1C, LOGL_NOTICE, "%s cannot determine L1 SAPI\n", - gsm_lchan_name(lchan)); - break; - } - return GsmL1_Sapi_Idle; -} - -GsmL1_SubCh_t lchan_to_GsmL1_SubCh_t(const struct gsm_lchan *lchan) -{ - enum gsm_phys_chan_config pchan = lchan->ts->pchan; - - if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) - pchan = lchan->ts->dyn.pchan_want; - - switch (pchan) { - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - if (lchan->type == GSM_LCHAN_CCCH) - return GsmL1_SubCh_NA; - /* fall-through */ - case GSM_PCHAN_TCH_H: - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - return lchan->nr; - case GSM_PCHAN_NONE: - case GSM_PCHAN_CCCH: - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_PDCH: - case GSM_PCHAN_UNKNOWN: - default: - /* case GSM_PCHAN_TCH_F_TCH_H_PDCH: is caught above */ - return GsmL1_SubCh_NA; - } - - return GsmL1_SubCh_NA; -} - -struct sapi_dir { - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; -}; - -static const struct sapi_dir ccch_sapis[] = { - { GsmL1_Sapi_Fcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Bcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Agch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchf_sapis[] = { - { GsmL1_Sapi_TchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchF, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir tchh_sapis[] = { - { GsmL1_Sapi_TchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_TchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_FacchH, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir sdcch_sapis[] = { - { GsmL1_Sapi_Sdcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sdcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Sacch, GsmL1_Dir_RxUplink }, -}; - -static const struct sapi_dir cbch_sapis[] = { - { GsmL1_Sapi_Cbch, GsmL1_Dir_TxDownlink }, - /* Does the CBCH really have a SACCH in Downlink? */ - { GsmL1_Sapi_Sacch, GsmL1_Dir_TxDownlink }, -}; - -static const struct sapi_dir pdtch_sapis[] = { - { GsmL1_Sapi_Pdtch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Pdtch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Ptcch, GsmL1_Dir_TxDownlink }, - { GsmL1_Sapi_Prach, GsmL1_Dir_RxUplink }, -#if 0 - { GsmL1_Sapi_Ptcch, GsmL1_Dir_RxUplink }, - { GsmL1_Sapi_Pacch, GsmL1_Dir_TxDownlink }, -#endif -}; - -static const struct sapi_dir ho_sapis[] = { - { GsmL1_Sapi_Rach, GsmL1_Dir_RxUplink }, -}; - -struct lchan_sapis { - const struct sapi_dir *sapis; - unsigned int num_sapis; -}; - -static const struct lchan_sapis sapis_for_lchan[_GSM_LCHAN_MAX] = { - [GSM_LCHAN_SDCCH] = { - .sapis = sdcch_sapis, - .num_sapis = ARRAY_SIZE(sdcch_sapis), - }, - [GSM_LCHAN_TCH_F] = { - .sapis = tchf_sapis, - .num_sapis = ARRAY_SIZE(tchf_sapis), - }, - [GSM_LCHAN_TCH_H] = { - .sapis = tchh_sapis, - .num_sapis = ARRAY_SIZE(tchh_sapis), - }, - [GSM_LCHAN_CCCH] = { - .sapis = ccch_sapis, - .num_sapis = ARRAY_SIZE(ccch_sapis), - }, - [GSM_LCHAN_PDTCH] = { - .sapis = pdtch_sapis, - .num_sapis = ARRAY_SIZE(pdtch_sapis), - }, - [GSM_LCHAN_CBCH] = { - .sapis = cbch_sapis, - .num_sapis = ARRAY_SIZE(cbch_sapis), - }, -}; - -static const struct lchan_sapis sapis_for_ho = { - .sapis = ho_sapis, - .num_sapis = ARRAY_SIZE(ho_sapis), -}; - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd); -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd); - -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir); -static int lchan_deactivate_sapis(struct gsm_lchan *lchan); - -/** - * Execute the first SAPI command of the queue. In case of the markers - * this method is re-entrant so we need to make sure to remove a command - * from the list before calling a function that will queue a command. - * - * \return 0 in case no Gsm Request was sent, 1 otherwise - */ -static int sapi_queue_exeute(struct gsm_lchan *lchan) -{ - int res; - struct sapi_cmd *cmd; - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - - switch (cmd->type) { - case SAPI_CMD_ACTIVATE: - mph_send_activate_req(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_CIPHERING: - mph_send_config_ciphering(lchan, cmd); - res = 1; - break; - case SAPI_CMD_CONFIG_LOGCH_PARAM: - mph_send_config_logchpar(lchan, cmd); - res = 1; - break; - case SAPI_CMD_SACCH_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_TxDownlink); - res |= check_sapi_release(lchan, GsmL1_Sapi_Sacch, - GsmL1_Dir_RxUplink); - break; - case SAPI_CMD_REL_MARKER: - llist_del(&cmd->entry); - talloc_free(cmd); - res = lchan_deactivate_sapis(lchan); - break; - case SAPI_CMD_DEACTIVATE: - mph_send_deactivate_req(lchan, cmd); - res = 1; - break; - default: - LOGP(DL1C, LOGL_NOTICE, - "Unimplemented command type %d\n", cmd->type); - llist_del(&cmd->entry); - talloc_free(cmd); - res = 0; - abort(); - break; - } - - return res; -} - -static void sapi_queue_send(struct gsm_lchan *lchan) -{ - int res; - - do { - res = sapi_queue_exeute(lchan); - } while (res == 0 && !llist_empty(&lchan->sapi_cmds)); -} - -static void sapi_queue_dispatch(struct gsm_lchan *lchan, int status) -{ - int end; - struct sapi_cmd *cmd = llist_entry(lchan->sapi_cmds.next, - struct sapi_cmd, entry); - llist_del(&cmd->entry); - end = llist_empty(&lchan->sapi_cmds); - - if (cmd->callback) - cmd->callback(lchan, status); - talloc_free(cmd); - - if (end || llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_DEBUG, - "%s End of SAPI cmd queue encountered.%s\n", - gsm_lchan_name(lchan), - llist_empty(&lchan->sapi_cmds) - ? " Queue is now empty." - : " More pending."); - return; - } - - sapi_queue_send(lchan); -} - -/** - * Queue and possible execute a SAPI command. Return 1 in case the command was - * already executed and 0 in case if it was only put into the queue - */ -static int queue_sapi_command(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - int start = llist_empty(&lchan->sapi_cmds); - llist_add_tail(&cmd->entry, &lchan->sapi_cmds); - - if (!start) - return 0; - - sapi_queue_send(lchan); - return 1; -} - -static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphActivateCnf_t *ic = &l1p->u.mphActivateCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful activation of L1 SAPI %s on TS %u\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_ASSIGNED; - } else { - LOGP(DL1C, LOGL_ERROR, "Error activating L1 SAPI %s on TS %u: %s\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(lc15bts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_ACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - - return 0; -} - -uint32_t l1if_lchan_to_hLayer(struct gsm_lchan *lchan) -{ - return 0xBB - | (lchan->nr << 8) - | (lchan->ts->nr << 16) - | (lchan->ts->trx->nr << 24); -} - -/* obtain a ptr to the lapdm_channel for a given hLayer */ -struct gsm_lchan * -l1if_hLayer_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer2) -{ - uint8_t magic = hLayer2 & 0xff; - uint8_t ts_nr = (hLayer2 >> 16) & 0xff; - uint8_t lchan_nr = (hLayer2 >> 8)& 0xff; - struct gsm_bts_trx_ts *ts; - - if (magic != 0xBB) - return NULL; - - /* FIXME: if we actually run on the BTS, the 32bit field is large - * enough to simply put a pointer inside. */ - if (ts_nr >= ARRAY_SIZE(trx->ts)) - return NULL; - - ts = &trx->ts[ts_nr]; - - if (lchan_nr >= ARRAY_SIZE(ts->lchan)) - return NULL; - - return &ts->lchan[lchan_nr]; -} - -/* we regularly check if the DSP L1 is still sending us primitives. - * if not, we simply stop the BTS program (and be re-spawned) */ -static void alive_timer_cb(void *data) -{ - struct lc15l1_hdl *fl1h = data; - - if (fl1h->alive_prim_cnt == 0) { - LOGP(DL1C, LOGL_FATAL, "DSP L1 is no longer sending primitives!\n"); - exit(23); - } - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); -} - -static void clear_amr_params(GsmL1_LogChParam_t *lch_par) -{ - int j; - /* common for the SIGN, V1 and EFR: */ - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_NA; - lch_par->tch.amrInitCodecMode = GsmL1_AmrCodecMode_Unset; - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; -} - -static void set_payload_format(GsmL1_LogChParam_t *lch_par) -{ - lch_par->tch.tchPlFmt = GsmL1_TchPlFmt_Rtp; -} - -static void lchan2lch_par(GsmL1_LogChParam_t *lch_par, struct gsm_lchan *lchan) -{ - struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr; - struct gsm48_multi_rate_conf *mr_conf = - (struct gsm48_multi_rate_conf *) amr_mrc->gsm48_ie; - int j; - - LOGP(DL1C, LOGL_INFO, "%s: %s tch_mode=0x%02x\n", - gsm_lchan_name(lchan), __FUNCTION__, lchan->tch_mode); - - switch (lchan->tch_mode) { - case GSM48_CMODE_SIGN: - /* we have to set some TCH payload type even if we don't - * know yet what codec we will use later on */ - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - lch_par->tch.tchPlType = GsmL1_TchPlType_Fr; - else - lch_par->tch.tchPlType = GsmL1_TchPlType_Hr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_EFR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Efr; - set_payload_format(lch_par); - clear_amr_params(lch_par); - break; - case GSM48_CMODE_SPEECH_AMR: - lch_par->tch.tchPlType = GsmL1_TchPlType_Amr; - set_payload_format(lch_par); - lch_par->tch.amrCmiPhase = GsmL1_AmrCmiPhase_Odd; /* FIXME? */ - lch_par->tch.amrInitCodecMode = amr_get_initial_mode(lchan); - - /* initialize to clean state */ - for (j = 0; j < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); j++) - lch_par->tch.amrActiveCodecSet[j] = GsmL1_AmrCodec_Unset; - - j = 0; - if (mr_conf->m4_75) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_4_75; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_15) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_15; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m5_90) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_5_9; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m6_70) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_6_7; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_40) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_4; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m7_95) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_7_95; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - - if (mr_conf->m10_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_10_2; - if (j >= ARRAY_SIZE(lch_par->tch.amrActiveCodecSet)) - break; - if (mr_conf->m12_2) - lch_par->tch.amrActiveCodecSet[j++] = GsmL1_AmrCodec_12_2; - break; - case GSM48_CMODE_DATA_14k5: - case GSM48_CMODE_DATA_12k0: - case GSM48_CMODE_DATA_6k0: - case GSM48_CMODE_DATA_3k6: - LOGP(DL1C, LOGL_ERROR, "%s: CSD not supported!\n", - gsm_lchan_name(lchan)); - break; - } -} - -static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - int sapi = cmd->sapi; - int dir = cmd->dir; - GsmL1_MphActivateReq_t *act_req; - GsmL1_LogChParam_t *lch_par; - - act_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphActivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - lch_par = &act_req->logChPrm; - act_req->u8Tn = lchan->ts->nr; - act_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - act_req->dir = dir; - act_req->sapi = sapi; - act_req->hLayer2 = (HANDLE *)l1if_lchan_to_hLayer(lchan); - act_req->hLayer3 = act_req->hLayer2; - - switch (act_req->sapi) { - case GsmL1_Sapi_Rach: - lch_par->rach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Agch: - lch_par->agch.u8NbrOfAgch = num_agch(lchan->ts->trx, lchan->name); - break; - case GsmL1_Sapi_TchH: - case GsmL1_Sapi_TchF: - lchan2lch_par(lch_par, lchan); - /* - * Be sure that every packet is received, even if it - * fails. In this case the length might be lower or 0. - */ - act_req->fBFILevel = -200.0f; - break; - case GsmL1_Sapi_Ptcch: - lch_par->ptcch.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Prach: - lch_par->prach.u8Bsic = lchan->ts->trx->bts->bsic; - break; - case GsmL1_Sapi_Sacch: - /* - * For the SACCH we need to set the u8MsPowerLevel when - * doing manual MS power control. - */ - if (trx_ms_pwr_ctrl_is_osmo(lchan->ts->trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - /* fall through */ - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - /* - * Be sure that every packet is received, even if it - * fails. In this case the length might be lower or 0. - */ - act_req->fBFILevel = -200.0f; - break; - default: - break; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-ACTIVATE.req (hL2=0x%08x, %s ", - gsm_lchan_name(lchan), (uint32_t)act_req->hLayer2, - get_value_string(lc15bts_l1sapi_names, act_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, act_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_act_compl_cb, NULL); -} - -static void sapi_clear_queue(struct llist_head *queue) -{ - struct sapi_cmd *next, *tmp; - - llist_for_each_entry_safe(next, tmp, queue, entry) { - llist_del(&next->entry); - talloc_free(next); - } -} - -static int sapi_activate_cb(struct gsm_lchan *lchan, int status) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - - /* FIXME: Error handling */ - if (status != GsmL1_Status_Success) { - LOGP(DL1C, LOGL_ERROR, - "%s act failed mark broken due status: %d\n", - gsm_lchan_name(lchan), status); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, RSL_ERR_PROCESSOR_OVERLOAD); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - if (lchan->state != LCHAN_S_ACT_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_ACTIVE); - mph_info_chan_confirm(lchan, PRIM_INFO_ACTIVATE, 0); - - /* set the initial ciphering parameters for both directions */ - l1if_set_ciphering(fl1h, lchan, 1); - l1if_set_ciphering(fl1h, lchan, 0); - if (lchan->encr.alg_id) - lchan->ciph_state = LCHAN_CIPH_RXTX_REQ; - else - lchan->ciph_state = LCHAN_CIPH_NONE; - - return 0; -} - -static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_ACTIVATE; - cmd->callback = sapi_activate_cb; - queue_sapi_command(lchan, cmd); -} - -int lchan_activate(struct gsm_lchan *lchan) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - lchan_set_state(lchan, LCHAN_S_ACT_REQ); - - if (!llist_empty(&lchan->sapi_cmds)) - LOGP(DL1C, LOGL_ERROR, - "%s Trying to activate lchan, but commands in queue\n", - gsm_lchan_name(lchan)); - - /* override the regular SAPIs if this is the first hand-over - * related activation of the LCHAN */ - if (lchan->ho.active == HANDOVER_ENABLED) - s4l = &sapis_for_ho; - - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - - if (sapi == GsmL1_Sapi_Sch) { - /* once we activate the SCH, we should get MPH-TIME.ind */ - fl1h->alive_timer.cb = alive_timer_cb; - fl1h->alive_timer.data = fl1h; - fl1h->alive_prim_cnt = 0; - osmo_timer_schedule(&fl1h->alive_timer, 5, 0); - } - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - -#warning "FIXME: Should this be in sapi_activate_cb?" - lchan_init_lapdm(lchan); - - return 0; -} - -const struct value_string lc15bts_l1cfgt_names[] = { - { GsmL1_ConfigParamId_SetNbTsc, "Set NB TSC" }, - { GsmL1_ConfigParamId_SetTxPowerLevel, "Set Tx power level" }, - { GsmL1_ConfigParamId_SetLogChParams, "Set logical channel params" }, - { GsmL1_ConfigParamId_SetCipheringParams,"Configure ciphering params" }, -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - { GsmL1_ConfigParamId_Set8pskPowerReduction, "Set 8PSK Tx power reduction" }, -#endif - { 0, NULL } -}; - -static void dump_lch_par(int logl, GsmL1_LogChParam_t *lch_par, GsmL1_Sapi_t sapi) -{ - int i; - - switch (sapi) { - case GsmL1_Sapi_Rach: - LOGPC(DL1C, logl, "BSIC=0x%08x", lch_par->rach.u8Bsic); - break; - case GsmL1_Sapi_Agch: - LOGPC(DL1C, logl, "BS_AG_BLKS_RES=%u ", - lch_par->agch.u8NbrOfAgch); - break; - case GsmL1_Sapi_Sacch: - LOGPC(DL1C, logl, "MS Power Level 0x%02x", - lch_par->sacch.u8MsPowerLevel); - break; - case GsmL1_Sapi_TchF: - case GsmL1_Sapi_TchH: - LOGPC(DL1C, logl, "amrCmiPhase=0x%02x amrInitCodec=0x%02x (", - lch_par->tch.amrCmiPhase, - lch_par->tch.amrInitCodecMode); - for (i = 0; i < ARRAY_SIZE(lch_par->tch.amrActiveCodecSet); i++) { - LOGPC(DL1C, logl, "%x ", - lch_par->tch.amrActiveCodecSet[i]); - } - break; - /* FIXME: PRACH / PTCCH */ - default: - break; - } - LOGPC(DL1C, logl, ")\n"); -} - -static int chmod_txpower_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_trx_name(trx), - get_value_string(lc15bts_l1cfgt_names, cc->cfgParamId)); - - LOGPC(DL1C, LOGL_INFO, "setTxPower %f dBm\n", - cc->cfgParams.setTxPowerLevel.fTxPowerLevel); - - power_trx_change_compl(trx, - (int) (cc->cfgParams.setTxPowerLevel.fTxPowerLevel * 1000)); - - msgb_free(l1_msg); - - return 0; -} - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) -static int chmod_txpower_backoff_8psk_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_trx_name(trx), - get_value_string(lc15bts_l1cfgt_names, cc->cfgParamId)); - - LOGPC(DL1C, LOGL_INFO, "Backoff %u dB\n", - cc->cfgParams.set8pskPowerReduction.u8PowerReduction); - - msgb_free(l1_msg); - - return 0; -} - -static int chmod_max_cell_size_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - Litecell15_SetMaxCellSizeCnf_t *sac = &sysp->u.setMaxCellSizeCnf; - - LOGP(DL1C, LOGL_INFO, "%s Rx SYS prim %s -> %s\n", - gsm_trx_name(trx), - get_value_string(lc15bts_sysprim_names, sysp->id), - get_value_string(lc15bts_l1status_names, sac->status)); - - msgb_free(resp); - - return 0; -} - -static int chmod_c0_idle_pwr_red_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, - void *data) -{ - Litecell15_Prim_t *sysp = msgb_sysprim(resp); - Litecell15_SetC0IdleSlotPowerReductionCnf_t *sac = &sysp->u.setC0IdleSlotPowerReductionCnf; - - LOGP(DL1C, LOGL_INFO, "%s Rx SYS prim %s -> %s\n", - gsm_trx_name(trx), - get_value_string(lc15bts_sysprim_names, sysp->id), - get_value_string(lc15bts_l1status_names, sac->status)); - - msgb_free(resp); - - return 0; -} -#endif - -static int chmod_modif_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConfigCnf_t *cc = &l1p->u.mphConfigCnf; - - /* get the lchan from the information we supplied */ - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)cc->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)cc->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.conf (%s) ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1cfgt_names, cc->cfgParamId)); - - switch (cc->cfgParamId) { - case GsmL1_ConfigParamId_SetLogChParams: - dump_lch_par(LOGL_INFO, - &cc->cfgParams.setLogChParams.logChParams, - cc->cfgParams.setLogChParams.sapi); - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetCipheringParams: - switch (lchan->ciph_state) { - case LCHAN_CIPH_RX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_REQ -> RX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF; - break; - case LCHAN_CIPH_RX_CONF_TX_REQ: - LOGPC(DL1C, LOGL_INFO, "RX_CONF_TX_REQ -> RXTX_CONF\n"); - lchan->ciph_state = LCHAN_CIPH_RXTX_CONF; - break; - case LCHAN_CIPH_RXTX_REQ: - LOGPC(DL1C, LOGL_INFO, "RXTX_REQ -> RX_CONF_TX_REQ\n"); - lchan->ciph_state = LCHAN_CIPH_RX_CONF_TX_REQ; - break; - case LCHAN_CIPH_NONE: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - default: - LOGPC(DL1C, LOGL_INFO, "unhandled state %u\n", lchan->ciph_state); - break; - } - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got ciphering conf with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - sapi_queue_dispatch(lchan, cc->status); - break; - case GsmL1_ConfigParamId_SetNbTsc: - default: - LOGPC(DL1C, LOGL_INFO, "\n"); - break; - } - -err: - msgb_free(l1_msg); - - return 0; -} - -static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct gsm_bts_trx *trx = lchan->ts->trx; - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - GsmL1_LogChParam_t *lch_par; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetLogChParams; - conf_req->cfgParams.setLogChParams.sapi = cmd->sapi; - conf_req->cfgParams.setLogChParams.u8Tn = lchan->ts->nr; - conf_req->cfgParams.setLogChParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - conf_req->cfgParams.setLogChParams.dir = cmd->dir; - conf_req->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - lch_par = &conf_req->cfgParams.setLogChParams.logChParams; - lchan2lch_par(lch_par, lchan); - - /* Update the MS Power Level */ - if (cmd->sapi == GsmL1_Sapi_Sacch && trx_ms_pwr_ctrl_is_osmo(trx)) - lch_par->sacch.u8MsPowerLevel = lchan->ms_power_ctrl.current; - - /* FIXME: update encryption */ - - LOGP(DL1C, LOGL_INFO, "%s MPH-CONFIG.req (%s) ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, - conf_req->cfgParams.setLogChParams.sapi)); - LOGPC(DL1C, LOGL_INFO, "cfgParams Tn=%u, subCh=%u, dir=0x%x ", - conf_req->cfgParams.setLogChParams.u8Tn, - conf_req->cfgParams.setLogChParams.subCh, - conf_req->cfgParams.setLogChParams.dir); - dump_lch_par(LOGL_INFO, - &conf_req->cfgParams.setLogChParams.logChParams, - conf_req->cfgParams.setLogChParams.sapi); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_logchpar_cmd(struct gsm_lchan *lchan, int dir, GsmL1_Sapi_t sapi) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->sapi = sapi; - cmd->type = SAPI_CMD_CONFIG_LOGCH_PARAM; - queue_sapi_command(lchan, cmd); -} - -static int tx_confreq_logchpar(struct gsm_lchan *lchan, uint8_t direction) -{ - enqueue_sapi_logchpar_cmd(lchan, direction, lchan_to_GsmL1_Sapi_t(lchan)); - return 0; -} - -int l1if_set_txpower(struct lc15l1_hdl *fl1h, float tx_power) -{ - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, 0); - conf_req->cfgParamId = GsmL1_ConfigParamId_SetTxPowerLevel; - conf_req->cfgParams.setTxPowerLevel.fTxPowerLevel = tx_power; - - return l1if_gsm_req_compl(fl1h, msg, chmod_txpower_compl_cb, NULL); -} - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) -int l1if_set_txpower_backoff_8psk(struct lc15l1_hdl *fl1h, uint8_t backoff) -{ - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConfigReq_t *conf_req; - - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, 0); - conf_req->cfgParamId = GsmL1_ConfigParamId_Set8pskPowerReduction; - conf_req->cfgParams.set8pskPowerReduction.u8PowerReduction = backoff; - - return l1if_gsm_req_compl(fl1h, msg, chmod_txpower_backoff_8psk_compl_cb, NULL); -} - -int l1if_set_max_cell_size(struct lc15l1_hdl *fl1h, uint8_t cell_size) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Litecell15_PrimId_SetMaxCellSizeReq; - sys_prim->u.setMaxCellSizeReq.u8MaxCellSize = cell_size; - - LOGP(DL1C, LOGL_INFO, "%s Set max cell size = %d qbits\n", - gsm_trx_name(fl1h->phy_inst->trx), - cell_size); - - return l1if_req_compl(fl1h, msg, chmod_max_cell_size_compl_cb, NULL); - -} - -int l1if_set_txpower_c0_idle_pwr_red(struct lc15l1_hdl *fl1h, uint8_t red) -{ - struct msgb *msg = sysp_msgb_alloc(); - Litecell15_Prim_t *sys_prim = msgb_sysprim(msg); - sys_prim->id = Litecell15_PrimId_SetC0IdleSlotPowerReductionReq; - sys_prim->u.setC0IdleSlotPowerReductionReq.u8PowerReduction = red; - - LOGP(DL1C, LOGL_INFO, "%s Set C0 idle slot power reduction = %d dB\n", - gsm_trx_name(fl1h->phy_inst->trx), - red); - - return l1if_req_compl(fl1h, msg, chmod_c0_idle_pwr_red_compl_cb, NULL); -} -#endif - -const enum GsmL1_CipherId_t rsl2l1_ciph[] = { - [0] = GsmL1_CipherId_A50, - [1] = GsmL1_CipherId_A50, - [2] = GsmL1_CipherId_A51, - [3] = GsmL1_CipherId_A52, - [4] = GsmL1_CipherId_A53, -}; - -static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - struct GsmL1_MphConfigReq_t *cfgr; - - cfgr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, - l1p_handle_for_lchan(lchan)); - - cfgr->cfgParamId = GsmL1_ConfigParamId_SetCipheringParams; - cfgr->cfgParams.setCipheringParams.u8Tn = lchan->ts->nr; - cfgr->cfgParams.setCipheringParams.subCh = lchan_to_GsmL1_SubCh_t(lchan); - cfgr->cfgParams.setCipheringParams.dir = cmd->dir; - cfgr->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - if (lchan->encr.alg_id >= ARRAY_SIZE(rsl2l1_ciph)) - return -EINVAL; - cfgr->cfgParams.setCipheringParams.cipherId = rsl2l1_ciph[lchan->encr.alg_id]; - - LOGP(DL1C, LOGL_NOTICE, "%s SET_CIPHERING (ALG=%u %s)\n", - gsm_lchan_name(lchan), - cfgr->cfgParams.setCipheringParams.cipherId, - get_value_string(lc15bts_dir_names, - cfgr->cfgParams.setCipheringParams.dir)); - - memcpy(cfgr->cfgParams.setCipheringParams.u8Kc, - lchan->encr.key, lchan->encr.key_len); - - return l1if_gsm_req_compl(fl1h, msg, chmod_modif_compl_cb, NULL); -} - -static void enqueue_sapi_ciphering_cmd(struct gsm_lchan *lchan, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->dir = dir; - cmd->type = SAPI_CMD_CONFIG_CIPHERING; - queue_sapi_command(lchan, cmd); -} - -int l1if_set_ciphering(struct lc15l1_hdl *fl1h, - struct gsm_lchan *lchan, - int dir_downlink) -{ - int dir; - - /* ignore the request when the channel is not active */ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - if (dir_downlink) - dir = GsmL1_Dir_TxDownlink; - else - dir = GsmL1_Dir_RxUplink; - - enqueue_sapi_ciphering_cmd(lchan, dir); - - return 0; -} - -int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - enqueue_sapi_logchpar_cmd(lchan, GsmL1_Dir_RxUplink, GsmL1_Sapi_Sacch); - return 0; -} - -int l1if_rsl_mode_modify(struct gsm_lchan *lchan) -{ - if (lchan->state != LCHAN_S_ACTIVE) - return -1; - - /* channel mode, encryption and/or multirate have changed */ - - /* update multi-rate config */ - tx_confreq_logchpar(lchan, GsmL1_Dir_RxUplink); - tx_confreq_logchpar(lchan, GsmL1_Dir_TxDownlink); - - /* FIXME: update encryption */ - - return 0; -} - -static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - enum lchan_sapi_state status; - struct sapi_cmd *cmd; - struct gsm_lchan *lchan; - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDeactivateCnf_t *ic = &l1p->u.mphDeactivateCnf; - - lchan = l1if_hLayer_to_lchan(trx, (uint32_t)ic->hLayer3); - if (!lchan) { - LOGP(DL1C, LOGL_ERROR, - "Failed to find lchan for hLayer3=0x%x\n", (uint32_t)ic->hLayer3); - goto err; - } - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.conf (%s ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, ic->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, ic->dir)); - - if (ic->status == GsmL1_Status_Success) { - DEBUGP(DL1C, "Successful deactivation of L1 SAPI %s on TS %u\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn); - status = LCHAN_SAPI_S_NONE; - } else { - LOGP(DL1C, LOGL_ERROR, "Error deactivating L1 SAPI %s on TS %u: %s\n", - get_value_string(lc15bts_l1sapi_names, ic->sapi), ic->u8Tn, - get_value_string(lc15bts_l1status_names, ic->status)); - status = LCHAN_SAPI_S_ERROR; - } - - if (ic->dir & GsmL1_Dir_TxDownlink) - lchan->sapis_dl[ic->sapi] = status; - if (ic->dir & GsmL1_Dir_RxUplink) - lchan->sapis_ul[ic->sapi] = status; - - - if (llist_empty(&lchan->sapi_cmds)) { - LOGP(DL1C, LOGL_ERROR, - "%s Got de-activation confirmation with empty queue\n", - gsm_lchan_name(lchan)); - goto err; - } - - cmd = llist_entry(lchan->sapi_cmds.next, struct sapi_cmd, entry); - if (cmd->sapi != ic->sapi || cmd->dir != ic->dir || - cmd->type != SAPI_CMD_DEACTIVATE) { - LOGP(DL1C, LOGL_ERROR, - "%s Confirmation mismatch (%d, %d) (%d, %d)\n", - gsm_lchan_name(lchan), cmd->sapi, cmd->dir, - ic->sapi, ic->dir); - goto err; - } - - sapi_queue_dispatch(lchan, ic->status); - -err: - msgb_free(l1_msg); - return 0; -} - -static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphDeactivateReq_t *deact_req; - - deact_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDeactivateReq, - fl1h, l1p_handle_for_lchan(lchan)); - deact_req->u8Tn = lchan->ts->nr; - deact_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); - deact_req->dir = cmd->dir; - deact_req->sapi = cmd->sapi; - deact_req->hLayer3 = (HANDLE)l1if_lchan_to_hLayer(lchan); - - LOGP(DL1C, LOGL_INFO, "%s MPH-DEACTIVATE.req (%s ", - gsm_lchan_name(lchan), - get_value_string(lc15bts_l1sapi_names, deact_req->sapi)); - LOGPC(DL1C, LOGL_INFO, "%s)\n", - get_value_string(lc15bts_dir_names, deact_req->dir)); - - /* send the primitive for all GsmL1_Sapi_* that match the LCHAN */ - return l1if_gsm_req_compl(fl1h, msg, lchan_deact_compl_cb, NULL); -} - -static int sapi_deactivate_cb(struct gsm_lchan *lchan, int status) -{ - /* FIXME: Error handling. There is no NACK... */ - if (status != GsmL1_Status_Success && lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s is now broken. Stopping the release.\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - sapi_clear_queue(&lchan->sapi_cmds); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - return -1; - } - - if (!llist_empty(&lchan->sapi_cmds)) - return 0; - - /* Don't send an REL ACK on SACCH deactivate */ - if (lchan->state != LCHAN_S_REL_REQ) - return 0; - - lchan_set_state(lchan, LCHAN_S_NONE); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - - /* Reactivate CCCH due to SI3 update in RSL */ - if (lchan->rel_act_kind == LCHAN_REL_ACT_REACT) { - lchan->rel_act_kind = LCHAN_REL_ACT_RSL; - lchan_activate(lchan); - } - return 0; -} - -static int enqueue_sapi_deact_cmd(struct gsm_lchan *lchan, int sapi, int dir) -{ - struct sapi_cmd *cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - - cmd->sapi = sapi; - cmd->dir = dir; - cmd->type = SAPI_CMD_DEACTIVATE; - cmd->callback = sapi_deactivate_cb; - return queue_sapi_command(lchan, cmd); -} - -/* - * Release the SAPI if it was allocated. E.g. the SACCH might be already - * deactivated or during a hand-over the TCH was not allocated yet. - */ -static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir) -{ - /* check if we should schedule a release */ - if (dir & GsmL1_Dir_TxDownlink) { - if (lchan->sapis_dl[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_dl[sapi] = LCHAN_SAPI_S_REL; - } else if (dir & GsmL1_Dir_RxUplink) { - if (lchan->sapis_ul[sapi] != LCHAN_SAPI_S_ASSIGNED) - return 0; - lchan->sapis_ul[sapi] = LCHAN_SAPI_S_REL; - } - - /* now schedule the command and maybe dispatch it */ - return enqueue_sapi_deact_cmd(lchan, sapi, dir); -} - -static int release_sapis_for_ho(struct gsm_lchan *lchan) -{ - int res = 0; - int i; - - const struct lchan_sapis *s4l = &sapis_for_ho; - - for (i = s4l->num_sapis-1; i >= 0; i--) - res |= check_sapi_release(lchan, - s4l->sapis[i].sapi, s4l->sapis[i].dir); - return res; -} - -static int lchan_deactivate_sapis(struct gsm_lchan *lchan) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(lchan->ts->trx); - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - int i, res; - - res = 0; - - /* The order matters.. the Facch needs to be released first */ - for (i = s4l->num_sapis-1; i >= 0; i--) { - /* Stop the alive timer once we deactivate the SCH */ - if (s4l->sapis[i].sapi == GsmL1_Sapi_Sch) - osmo_timer_del(&fl1h->alive_timer); - - /* Release if it was allocated */ - res |= check_sapi_release(lchan, s4l->sapis[i].sapi, s4l->sapis[i].dir); - } - - /* always attempt to disable the RACH burst */ - res |= release_sapis_for_ho(lchan); - - /* nothing was queued */ - if (res == 0) { - LOGP(DL1C, LOGL_ERROR, "%s all SAPIs already released?\n", - gsm_lchan_name(lchan)); - lchan_set_state(lchan, LCHAN_S_BROKEN); - mph_info_chan_confirm(lchan, PRIM_INFO_DEACTIVATE, 0); - } - - return res; -} - -static void enqueue_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to release all active SAPIs */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate(struct gsm_lchan *lchan) -{ - lchan_set_state(lchan, LCHAN_S_REL_REQ); - enqueue_rel_marker(lchan); - return 0; -} - -static void enqueue_sacch_rel_marker(struct gsm_lchan *lchan) -{ - struct sapi_cmd *cmd; - - /* remember we need to check if the SACCH is allocated */ - cmd = talloc_zero(lchan->ts->trx, struct sapi_cmd); - cmd->type = SAPI_CMD_SACCH_REL_MARKER; - queue_sapi_command(lchan, cmd); -} - -int bts_model_lchan_deactivate_sacch(struct gsm_lchan *lchan) -{ - enqueue_sacch_rel_marker(lchan); - return 0; -} - -/* callback from OML */ -int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type, - struct tlv_parsed *old_attr, struct tlv_parsed *new_attr, - void *obj) -{ - /* FIXME: more checks if the attributes are valid */ - - switch (msg_type) { - case NM_MT_SET_CHAN_ATTR: - /* our L1 only supports one global TSC for all channels - * one one TRX, so we need to make sure not to activate - * channels with a different TSC!! */ - if (TLVP_PRESENT(new_attr, NM_ATT_TSC) && - TLVP_LEN(new_attr, NM_ATT_TSC) >= 1 && - *TLVP_VAL(new_attr, NM_ATT_TSC) != (bts->bsic & 7)) { - LOGP(DOML, LOGL_ERROR, "Channel TSC %u != BSIC-TSC %u\n", - *TLVP_VAL(new_attr, NM_ATT_TSC), bts->bsic & 7); - return -NM_NACK_PARAM_RANGE; - } - break; - } - return 0; -} - -/* callback from OML */ -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int kind, void *obj) -{ - if (kind == NM_OC_RADIO_CARRIER) { - struct gsm_bts_trx *trx = obj; - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - /* convert max TA to max cell size in qbits */ - uint8_t cell_size = bts->max_ta << 2; - -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - /* We do not need to check for L1 handle - * because the max cell size parameter can receive before MphInit */ - if (fl1h->phy_inst->u.lc15.max_cell_size != cell_size) { - /* instruct L1 to apply max cell size */ - l1if_set_max_cell_size(fl1h, cell_size); - /* update current max cell size */ - fl1h->phy_inst->u.lc15.max_cell_size = cell_size; - } -#endif - - /* Did we go through MphInit yet? If yes fire and forget */ - if (fl1h->hLayer1) { - power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0, NULL); -#if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7) - if (fl1h->phy_inst->u.lc15.tx_pwr_red_8psk != trx->max_power_backoff_8psk) { - /* update current Tx power backoff for 8-PSK */ - fl1h->phy_inst->u.lc15.tx_pwr_red_8psk = trx->max_power_backoff_8psk; - /* instruct L1 to apply Tx power backoff for 8 PSK */ - l1if_set_txpower_backoff_8psk(fl1h, fl1h->phy_inst->u.lc15.tx_pwr_red_8psk); - } - - if (fl1h->phy_inst->u.lc15.tx_c0_idle_pwr_red != trx->c0_idle_power_red) { - /* update current C0 idle slot Tx power reduction */ - fl1h->phy_inst->u.lc15.tx_c0_idle_pwr_red = trx->c0_idle_power_red; - /* instruct L1 to apply C0 idle slot power reduction */ - l1if_set_txpower_c0_idle_pwr_red(fl1h, fl1h->phy_inst->u.lc15.tx_c0_idle_pwr_red); - } -#endif - } - } - /* FIXME: we actually need to send a ACK or NACK for the OML message */ - return oml_fom_ack_nack(msg, 0); -} - -/* callback from OML */ -int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj) -{ - struct gsm_bts_bb_trx *bb_transc; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - int rc; - - switch (mo->obj_class) { - case NM_OC_SITE_MANAGER: - rc = osmo_fsm_inst_dispatch(bts->site_mgr.mo.fi, NM_EV_OPSTART_ACK, NULL); - break; - case NM_OC_BTS: - rc = osmo_fsm_inst_dispatch(bts->mo.fi, NM_EV_OPSTART_ACK, NULL); - break; - case NM_OC_RADIO_CARRIER: - trx = (struct gsm_bts_trx *) obj; - rc = trx_init(trx); - break; - case NM_OC_BASEB_TRANSC: - bb_transc = (struct gsm_bts_bb_trx *) obj; - rc = osmo_fsm_inst_dispatch(bb_transc->mo.fi, NM_EV_OPSTART_ACK, NULL); - break; - case NM_OC_CHANNEL: - ts = (struct gsm_bts_trx_ts*) obj; - rc = ts_opstart(ts); - break; - case NM_OC_GPRS_NSE: - case NM_OC_GPRS_CELL: - case NM_OC_GPRS_NSVC: - oml_mo_state_chg(mo, NM_OPSTATE_ENABLED, -1); - rc = oml_mo_opstart_ack(mo); - if (mo->obj_class == NM_OC_BTS) { - oml_mo_state_chg(&bts->mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nse.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.cell.mo, -1, NM_AVSTATE_OK); - oml_mo_state_chg(&bts->gprs.nsvc[0].mo, -1, NM_AVSTATE_OK); - } - break; - default: - rc = oml_mo_opstart_nack(mo, NM_NACK_OBJCLASS_NOTSUPP); - } - return rc; -} - -int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, - void *obj, uint8_t adm_state) -{ - int rc = -EINVAL; - int granted = 0; - - switch (mo->obj_class) { - case NM_OC_RADIO_CARRIER: - - if (mo->procedure_pending) { - LOGP(DL1C, LOGL_ERROR, "Discarding adm change command: " - "pending procedure on RC %d\n", - ((struct gsm_bts_trx *)obj)->nr); - return 0; - } - mo->procedure_pending = 1; - switch (adm_state) { - case NM_STATE_LOCKED: - rc = trx_rf_lock(obj, 1, NULL); - break; - case NM_STATE_UNLOCKED: - rc = trx_rf_lock(obj, 0, NULL); - break; - default: - granted = 1; - break; - } - - if (!granted && rc == 0) - /* in progress, will send ack/nack after completion */ - return 0; - - mo->procedure_pending = 0; - - break; - default: - /* blindly accept all state changes */ - granted = 1; - break; - } - - if (granted) { - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); - } else - return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); - -} - -int l1if_rsl_chan_act(struct gsm_lchan *lchan) -{ - //uint8_t mode = *TLVP_VAL(tp, RSL_IE_CHAN_MODE); - //uint8_t type = *TLVP_VAL(tp, RSL_IE_ACT_TYPE); - lchan_activate(lchan); - return 0; -} - -/** - * Modify the given lchan in the handover scenario. This is a lot like - * second channel activation but with some additional activation. - */ -int l1if_rsl_chan_mod(struct gsm_lchan *lchan) -{ - const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type]; - unsigned int i; - - if (lchan->ho.active == HANDOVER_NONE) - return -1; - - LOGP(DHO, LOGL_ERROR, "%s modifying channel for handover\n", - gsm_lchan_name(lchan)); - - /* Give up listening to RACH bursts */ - release_sapis_for_ho(lchan); - - /* Activate the normal SAPIs */ - for (i = 0; i < s4l->num_sapis; i++) { - int sapi = s4l->sapis[i].sapi; - int dir = s4l->sapis[i].dir; - enqueue_sapi_act_cmd(lchan, sapi, dir); - } - - return 0; -} - -int l1if_rsl_chan_rel(struct gsm_lchan *lchan) -{ - /* A duplicate RF Release Request, ignore it */ - if (lchan->state == LCHAN_S_REL_REQ) { - LOGP(DL1C, LOGL_ERROR, "%s already in release request state.\n", - gsm_lchan_name(lchan)); - return 0; - } - - lchan_deactivate(lchan); - return 0; -} - -int l1if_rsl_deact_sacch(struct gsm_lchan *lchan) -{ - /* Only de-activate the SACCH if the lchan is active */ - if (lchan->state != LCHAN_S_ACTIVE) - return 0; - return bts_model_lchan_deactivate_sacch(lchan); -} - -int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) -{ - struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx); - - return l1if_activate_rf(fl1, 0); -} - -int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) -{ - return l1if_set_txpower(trx_lc15l1_hdl(trx), ((float) p_trxout_mdBm)/1000.0); -} - -static int ts_disconnect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphDisconnectCnf_t *cnf = &l1p->u.mphDisconnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - LOGP(DL1C, LOGL_DEBUG, "%s Rx mphDisconnectCnf\n", - gsm_lchan_name(ts->lchan)); - - cb_ts_disconnected(ts); - - msgb_free(l1_msg); - - return 0; -} - -int bts_model_ts_disconnect(struct gsm_bts_trx_ts *ts) -{ - struct msgb *msg = l1p_msgb_alloc(); - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(ts->trx); - GsmL1_MphDisconnectReq_t *cr; - - DEBUGP(DRSL, "%s TS disconnect\n", gsm_lchan_name(ts->lchan)); - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDisconnectReq, fl1h, - l1p_handle_for_ts(ts)); - cr->u8Tn = ts->nr; - - return l1if_gsm_req_compl(fl1h, msg, ts_disconnect_cb, NULL); -} - -static int ts_connect_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, - void *data) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1_msg); - GsmL1_MphConnectCnf_t *cnf = &l1p->u.mphConnectCnf; - struct gsm_bts_trx_ts *ts = &trx->ts[cnf->u8Tn]; - OSMO_ASSERT(cnf->u8Tn < TRX_NR_TS); - - DEBUGP(DL1C, "%s %s Rx mphConnectCnf flags=%s%s%s\n", - gsm_lchan_name(ts->lchan), - gsm_pchan_name(ts->pchan), - ts->flags & TS_F_PDCH_ACTIVE ? "ACTIVE " : "", - ts->flags & TS_F_PDCH_ACT_PENDING ? "ACT_PENDING " : "", - ts->flags & TS_F_PDCH_DEACT_PENDING ? "DEACT_PENDING " : ""); - - cb_ts_connected(ts, 0); - - msgb_free(l1_msg); - - return 0; -} - -void bts_model_ts_connect(struct gsm_bts_trx_ts *ts, - enum gsm_phys_chan_config as_pchan) -{ - int rc; - - rc = ts_connect_as(ts, as_pchan, ts_connect_cb, NULL); - if (rc) - cb_ts_connected(ts, rc); -} diff --git a/src/osmo-bts-litecell15/tch.c b/src/osmo-bts-litecell15/tch.c deleted file mode 100644 index 526b2ddf..00000000 --- a/src/osmo-bts-litecell15/tch.c +++ /dev/null @@ -1,533 +0,0 @@ -/* Traffic channel support for NuRAN Wireless Litecell 1.5 BTS L1 */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * (C) 2011-2012 by Harald Welte <laforge@gnumonks.org> - * - * 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 <stdbool.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/select.h> -#include <osmocom/core/timer.h> -#include <osmocom/core/bits.h> -#include <osmocom/gsm/gsm_utils.h> - -#include <osmo-bts/logging.h> -#include <osmo-bts/bts.h> -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/msg_utils.h> -#include <osmo-bts/measurement.h> -#include <osmo-bts/amr.h> -#include <osmo-bts/l1sap.h> -#include <osmo-bts/dtx_dl_amr_fsm.h> - -#include <nrw/litecell15/litecell15.h> -#include <nrw/litecell15/gsml1prim.h> -#include <nrw/litecell15/gsml1const.h> -#include <nrw/litecell15/gsml1types.h> - -#include "lc15bts.h" -#include "l1_if.h" - -static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_FR_BYTES); - memcpy(cur, l1_payload, GSM_FR_BYTES); - - lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_fr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - /* new L1 can deliver bits like we need them */ - memcpy(l1_payload, rtp_payload, GSM_FR_BYTES); - return GSM_FR_BYTES; -} - -static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, - uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - /* new L1 can deliver bits like we need them */ - cur = msgb_put(msg, GSM_EFR_BYTES); - memcpy(cur, l1_payload, GSM_EFR_BYTES); - enum osmo_amr_type ft; - enum osmo_amr_quality bfi; - uint8_t cmr; - int8_t sti, cmi; - osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti); - lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan); - - return msg; -} - -static int rtppayload_to_l1_efr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - memcpy(l1_payload, rtp_payload, payload_len); - - return payload_len; -} - -static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "L1 HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return NULL; - } - - cur = msgb_put(msg, GSM_HR_BYTES); - memcpy(cur, l1_payload, GSM_HR_BYTES); - - lchan_set_marker(osmo_hr_check_sid(l1_payload, payload_len), lchan); - - return msg; -} - -/*! \brief convert GSM-FR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, - unsigned int payload_len) -{ - - if (payload_len != GSM_HR_BYTES) { - LOGP(DL1P, LOGL_ERROR, "RTP HR frame length %u != expected %u\n", - payload_len, GSM_HR_BYTES); - return 0; - } - - memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); - - return GSM_HR_BYTES; -} - -static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_len, - struct gsm_lchan *lchan) -{ - struct msgb *msg; - uint8_t amr_if2_len = payload_len - 2; - uint8_t *cur; - - msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); - if (!msg) - return NULL; - - cur = msgb_put(msg, amr_if2_len); - memcpy(cur, l1_payload+2, amr_if2_len); - - /* - * Audiocode's MGW doesn't like receiving CMRs that are not - * the same as the previous one. This means we need to patch - * the content here. - */ - if ((cur[0] & 0xF0) == 0xF0) - cur[0]= lchan->tch.last_cmr << 4; - else - lchan->tch.last_cmr = cur[0] >> 4; - - return msg; -} - -/*! \brief convert AMR from RTP payload to L1 format - * \param[out] l1_payload payload part of L1 buffer - * \param[in] rtp_payload pointer to RTP payload data - * \param[in] payload_len length of \a rtp_payload - * \returns number of \a l1_payload bytes filled - */ -static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, - uint8_t payload_len, uint8_t ft) -{ - memcpy(l1_payload, rtp_payload, payload_len); - return payload_len; -} - -#define RTP_MSGB_ALLOC_SIZE 512 - -/*! \brief function for incoming RTP via TCH.req - * \param[in] rtp_pl buffer containing RTP payload - * \param[in] rtp_pl_len length of \a rtp_pl - * \param[in] use_cache Use cached payload instead of parsing RTP - * \param[in] marker RTP header Marker bit (indicates speech onset) - * \returns 0 if encoding result can be sent further to L1 without extra actions - * positive value if data is ready AND extra actions are required - * negative value otherwise (no data for L1 encoded) - * - * This function prepares a msgb with a L1 PH-DATA.req primitive and - * queues it into lchan->dl_tch_queue. - * - * Note that the actual L1 primitive header is not fully initialized - * yet, as things like the frame number, etc. are unknown at the time we - * pre-fill the primtive. - */ -int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, - const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn, - bool use_cache, bool marker) -{ - uint8_t *payload_type; - uint8_t *l1_payload, ft; - int rc = 0; - bool is_sid = false; - - DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(rtp_pl, rtp_pl_len)); - - payload_type = &data[0]; - l1_payload = &data[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) { - *payload_type = GsmL1_TchPlType_Fr; - rc = rtppayload_to_l1_fr(l1_payload, - rtp_pl, rtp_pl_len); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_fr_check_sid(rtp_pl, rtp_pl_len); - } else{ - *payload_type = GsmL1_TchPlType_Hr; - rc = rtppayload_to_l1_hr(l1_payload, - rtp_pl, rtp_pl_len); - if (rc && lchan->ts->trx->bts->dtxd) - is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len); - } - if (is_sid) - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, -1); - break; - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - rc = rtppayload_to_l1_efr(l1_payload, rtp_pl, - rtp_pl_len); - /* FIXME: detect and save EFR SID */ - break; - case GSM48_CMODE_SPEECH_AMR: - if (use_cache) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload, lchan->tch.dtx.cache, - lchan->tch.dtx.len, ft); - *len = lchan->tch.dtx.len + 1; - return 0; - } - - rc = dtx_dl_amr_fsm_step(lchan, rtp_pl, rtp_pl_len, fn, - l1_payload, marker, len, &ft); - if (rc < 0) - return rc; - if (!dtx_dl_amr_enabled(lchan)) { - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - } - - /* DTX DL-specific logic below: */ - switch (lchan->tch.dtx.dl_amr_fsm->state) { - case ST_ONSET_V: - *payload_type = GsmL1_TchPlType_Amr_Onset; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - *len = 3; - return 1; - case ST_VOICE: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F1: - if (lchan->type == GSM_LCHAN_TCH_H) { /* AMR HR */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP1; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, - rtp_pl_len, ft); - return 0; - } - /* AMR FR */ - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_SID_F2: - *payload_type = GsmL1_TchPlType_Amr; - rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len, - ft); - return 0; - case ST_F1_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidFirstInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_U_INH_V: - *payload_type = GsmL1_TchPlType_Amr_SidUpdateInH; - *len = 3; - dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0); - return 1; - case ST_SID_U: - case ST_U_NOINH: - return -EAGAIN; - case ST_FACCH: - return -EBADMSG; - default: - LOGP(DRTP, LOGL_ERROR, "Unhandled DTX DL AMR FSM state " - "%d\n", lchan->tch.dtx.dl_amr_fsm->state); - return -EINVAL; - } - break; - default: - /* we don't support CSD modes */ - rc = -1; - break; - } - - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, "%s unable to parse RTP payload\n", - gsm_lchan_name(lchan)); - return -EBADMSG; - } - - *len = rc + 1; - - DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan), - osmo_hexdump(data, *len)); - return 0; -} - -static int is_recv_only(uint8_t speech_mode) -{ - return (speech_mode & 0xF0) == (1 << 4); -} - -/*! \brief receive a traffic L1 primitive for a given lchan */ -int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr, struct msgb *l1p_msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(l1p_msg); - GsmL1_PhDataInd_t *data_ind = &l1p->u.phDataInd; - uint8_t *payload, payload_type, payload_len, sid_first[9] = { 0 }; - struct msgb *rmsg = NULL; - struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)].lchan[l1sap_chan2ss(chan_nr)]; - - if (is_recv_only(lchan->abis_ip.speech_mode)) - return -EAGAIN; - - if (data_ind->msgUnitParam.u8Size < 1) { - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "chan_nr %d Rx Payload size 0\n", chan_nr); - /* Push empty payload to upper layers */ - rmsg = msgb_alloc_headroom(256, 128, "L1P-to-RTP"); - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10, 0, 0, 0); - } - - payload_type = data_ind->msgUnitParam.u8Buffer[0]; - payload = data_ind->msgUnitParam.u8Buffer + 1; - payload_len = data_ind->msgUnitParam.u8Size - 1; - - switch (payload_type) { - case GsmL1_TchPlType_Fr: - case GsmL1_TchPlType_Efr: - if (lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Hr: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - break; - case GsmL1_TchPlType_Amr_Onset: - if (lchan->type != GSM_LCHAN_TCH_H && - lchan->type != GSM_LCHAN_TCH_F) - goto err_payload_match; - /* according to 3GPP TS 26.093 ONSET frames precede the first - speech frame of a speech burst - set the marker for next RTP - frame */ - lchan->rtp_tx_marker = true; - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P1 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstP2: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_P2 from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidFirstInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->rtp_tx_marker = true; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_FIRST_INH from L1 " - "(%d bytes)\n", payload_len); - break; - case GsmL1_TchPlType_Amr_SidUpdateInH: - if (lchan->type != GSM_LCHAN_TCH_H) - goto err_payload_match; - lchan->rtp_tx_marker = true; - LOGPFN(DL1P, LOGL_DEBUG, data_ind->u32Fn, "DTX: received SID_UPDATE_INH from L1 " - "(%d bytes)\n", payload_len); - break; - default: - LOGPFN(DL1P, LOGL_NOTICE, data_ind->u32Fn, "%s Rx Payload Type %s is unsupported\n", - gsm_lchan_name(lchan), - get_value_string(lc15bts_tch_pl_names, payload_type)); - break; - } - - - switch (payload_type) { - case GsmL1_TchPlType_Fr: - rmsg = l1_to_rtppayload_fr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Hr: - rmsg = l1_to_rtppayload_hr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Efr: - rmsg = l1_to_rtppayload_efr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Amr: - rmsg = l1_to_rtppayload_amr(payload, payload_len, lchan); - break; - case GsmL1_TchPlType_Amr_SidFirstP1: - memcpy(sid_first, payload, payload_len); - int len = osmo_amr_rtp_enc(sid_first, 0, AMR_SID, AMR_GOOD); - if (len < 0) - return 0; - rmsg = l1_to_rtppayload_amr(sid_first, len, lchan); - break; - } - - if (rmsg) - return add_l1sap_header(trx, rmsg, lchan, chan_nr, data_ind->u32Fn, - data_ind->measParam.fBer * 10000, - data_ind->measParam.fLinkQuality * 10, 0, 0, 0); - - return 0; - -err_payload_match: - LOGPFN(DL1P, LOGL_ERROR, data_ind->u32Fn, "%s Rx Payload Type %s incompatible with lchan\n", - gsm_lchan_name(lchan), get_value_string(lc15bts_tch_pl_names, payload_type)); - return -EINVAL; -} - -struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan, uint32_t fn) -{ - struct msgb *msg; - GsmL1_Prim_t *l1p; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - uint8_t *payload_type; - uint8_t *l1_payload; - int rc; - - msg = l1p_msgb_alloc(); - if (!msg) - return NULL; - - l1p = msgb_l1prim(msg); - data_req = &l1p->u.phDataReq; - msu_param = &data_req->msgUnitParam; - payload_type = &msu_param->u8Buffer[0]; - l1_payload = &msu_param->u8Buffer[1]; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_AMR: - if (lchan->type == GSM_LCHAN_TCH_H && - dtx_dl_amr_enabled(lchan)) { - /* we have to explicitly handle sending SID FIRST P2 for - AMR HR in here */ - *payload_type = GsmL1_TchPlType_Amr_SidFirstP2; - rc = dtx_dl_amr_fsm_step(lchan, NULL, 0, fn, l1_payload, - false, &(msu_param->u8Size), - NULL); - if (rc == 0) - return msg; - } - *payload_type = GsmL1_TchPlType_Amr; - break; - case GSM48_CMODE_SPEECH_V1: - if (lchan->type == GSM_LCHAN_TCH_F) - *payload_type = GsmL1_TchPlType_Fr; - else - *payload_type = GsmL1_TchPlType_Hr; - break; - case GSM48_CMODE_SPEECH_EFR: - *payload_type = GsmL1_TchPlType_Efr; - break; - default: - msgb_free(msg); - return NULL; - } - - rc = repeat_last_sid(lchan, l1_payload, fn); - if (!rc) { - msgb_free(msg); - return NULL; - } - msu_param->u8Size = rc; - - return msg; -} diff --git a/src/osmo-bts-litecell15/utils.c b/src/osmo-bts-litecell15/utils.c deleted file mode 100644 index 8d980ba8..00000000 --- a/src/osmo-bts-litecell15/utils.c +++ /dev/null @@ -1,118 +0,0 @@ -/* Helper utilities that are used in OMLs */ - -/* Copyright (C) 2015 by Yves Godin <support@nuranwireless.com> - * - * Based on sysmoBTS: - * (C) 2011-2013 by Harald Welte <laforge@gnumonks.org> - * (C) 2013 by Holger Hans Peter Freyther - * - * 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 "utils.h" - -#include <osmo-bts/bts.h> -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/logging.h> - -#include "lc15bts.h" -#include "l1_if.h" - -int band_lc152osmo(GsmL1_FreqBand_t band) -{ - switch (band) { - case GsmL1_FreqBand_850: - return GSM_BAND_850; - case GsmL1_FreqBand_900: - return GSM_BAND_900; - case GsmL1_FreqBand_1800: - return GSM_BAND_1800; - case GsmL1_FreqBand_1900: - return GSM_BAND_1900; - default: - return -1; - } -} - -static int band_osmo2lc15(struct gsm_bts_trx *trx, enum gsm_band osmo_band) -{ - struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx); - - /* check if the TRX hardware actually supports the given band */ - if (!(fl1h->hw_info.band_support & osmo_band)) - return -1; - - /* if yes, convert from osmcoom style band definition to L1 band */ - switch (osmo_band) { - case GSM_BAND_850: - return GsmL1_FreqBand_850; - case GSM_BAND_900: - return GsmL1_FreqBand_900; - case GSM_BAND_1800: - return GsmL1_FreqBand_1800; - case GSM_BAND_1900: - return GsmL1_FreqBand_1900; - default: - return -1; - } -} - -/** - * Select the band that matches the ARFCN. In general the ARFCNs - * for GSM1800 and GSM1900 overlap and one needs to specify the - * rightband. When moving between GSM900/GSM1800 and GSM850/1900 - * modifying the BTS configuration is a bit annoying. The auto-band - * configuration allows to ease with this transition. - */ -int lc15bts_select_lc15_band(struct gsm_bts_trx *trx, uint16_t arfcn) -{ - enum gsm_band band; - struct gsm_bts *bts = trx->bts; - int rc; - - if (!bts->auto_band) - return band_osmo2lc15(trx, bts->band); - - /* - * We need to check what will happen now. - */ - rc = gsm_arfcn2band_rc(arfcn, &band); - if (rc) /* wrong ARFCN, give up */ - return -1; - - /* if we are already on the right band return */ - if (band == bts->band) - return band_osmo2lc15(trx, bts->band); - - /* Check if it is GSM1800/GSM1900 */ - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_1900) - return band_osmo2lc15(trx, bts->band); - - /* - * Now to the actual autobauding. We just want DCS/DCS and - * PCS/PCS for PCS we check for 850/1800 though - */ - if ((band == GSM_BAND_900 && bts->band == GSM_BAND_1800) - || (band == GSM_BAND_1800 && bts->band == GSM_BAND_900) - || (band == GSM_BAND_850 && bts->band == GSM_BAND_1900)) - return band_osmo2lc15(trx, band); - if (band == GSM_BAND_1800 && bts->band == GSM_BAND_850) - return band_osmo2lc15(trx, GSM_BAND_1900); - - /* give up */ - return -1; -} diff --git a/src/osmo-bts-litecell15/utils.h b/src/osmo-bts-litecell15/utils.h deleted file mode 100644 index a2a22348..00000000 --- a/src/osmo-bts-litecell15/utils.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _UTILS_H -#define _UTILS_H - -#include <stdint.h> -#include "lc15bts.h" - -struct gsm_bts_trx; - -int band_lc152osmo(GsmL1_FreqBand_t band); - -int lc15bts_select_lc15_band(struct gsm_bts_trx *trx, uint16_t arfcn); - -#endif |