From: Max msuraev@sysmocom.de
Ignore cross-compilation bild byproducts. Enable subdir-objects to increase compatibility with newer automake. --- .gitignore | 2 ++ configure.ac | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore index 6cc9aa5..439f591 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ depcomp install-sh missing libtool +arm*linux*libtool +compile ltmain.sh
core diff --git a/configure.ac b/configure.ac index 5274022..7a97954 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_INIT([osmo-pcu], m4_esyscmd([./git-version-gen .tarball-version]), [osmocom-net-gprs@lists.osmocom.org])
-AM_INIT_AUTOMAKE([dist-bzip2]) +AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects]) AC_CONFIG_TESTDIR(tests)
dnl kernel style compile messages
From: Max msuraev@sysmocom.de
Move hardware-spicefic files into subdirectory similar to the way it's done in OsmoBTS to make adding more hardware support easier. Make DSP access option name generic. --- src/Makefile.am | 51 +++-- src/femtobts.c | 275 -------------------------- src/femtobts.h | 57 ------ src/osmo-bts-sysmo/femtobts.c | 275 ++++++++++++++++++++++++++ src/osmo-bts-sysmo/femtobts.h | 57 ++++++ src/osmo-bts-sysmo/sysmo_l1_fwd.c | 145 ++++++++++++++ src/osmo-bts-sysmo/sysmo_l1_hw.c | 216 +++++++++++++++++++++ src/osmo-bts-sysmo/sysmo_l1_if.c | 396 ++++++++++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/sysmo_l1_if.h | 91 +++++++++ src/osmobts_sock.cpp | 2 +- src/pcu_l1_if.cpp | 6 +- src/sysmo_l1_fwd.c | 145 -------------- src/sysmo_l1_hw.c | 216 --------------------- src/sysmo_l1_if.c | 396 -------------------------------------- src/sysmo_l1_if.h | 91 --------- 15 files changed, 1214 insertions(+), 1205 deletions(-) delete mode 100644 src/femtobts.c delete mode 100644 src/femtobts.h create mode 100644 src/osmo-bts-sysmo/femtobts.c create mode 100644 src/osmo-bts-sysmo/femtobts.h create mode 100644 src/osmo-bts-sysmo/sysmo_l1_fwd.c create mode 100644 src/osmo-bts-sysmo/sysmo_l1_hw.c create mode 100644 src/osmo-bts-sysmo/sysmo_l1_if.c create mode 100644 src/osmo-bts-sysmo/sysmo_l1_if.h delete mode 100644 src/sysmo_l1_fwd.c delete mode 100644 src/sysmo_l1_hw.c delete mode 100644 src/sysmo_l1_if.c delete mode 100644 src/sysmo_l1_if.h
diff --git a/src/Makefile.am b/src/Makefile.am index 6428bef..3049744 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,7 @@ AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOGSM_CFLAGS)
if ENABLE_SYSMODSP -AM_CPPFLAGS += -DENABLE_SYSMODSP +AM_CPPFLAGS += -DENABLE_DIRECT_PHY endif
AM_CXXFLAGS = -Wall -ldl -pthread @@ -64,11 +64,6 @@ bin_PROGRAMS = \
noinst_PROGRAMS =
-if ENABLE_SYSMODSP -noinst_PROGRAMS += \ - osmo-pcu-remote -endif - noinst_HEADERS = \ gprs_debug.h \ csn1.h \ @@ -83,8 +78,6 @@ noinst_HEADERS = \ bitvector.h \ pcu_vty.h \ pcu_vty_functions.h \ - sysmo_l1_if.h \ - femtobts.h \ tbf.h \ bts.h \ poll_controller.h \ @@ -101,30 +94,46 @@ noinst_HEADERS = \ osmo_pcu_SOURCES = pcu_main.cpp
if ENABLE_SYSMODSP -osmo_pcu_SOURCES += sysmo_l1_if.c \ - sysmo_l1_hw.c \ - femtobts.c - -osmo_pcu_remote_SOURCES = pcu_main.cpp \ - sysmo_l1_if.c \ - sysmo_l1_fwd.c \ - femtobts.c -endif +AM_CPPFLAGS += -I$(srcdir)/osmo-bts-sysmo
-osmo_pcu_LDADD = \ +EXTRA_DIST = \ + osmo-bts-sysmo/sysmo_l1_if.c \ + osmo-bts-sysmo/sysmo_l1_if.h \ + osmo-bts-sysmo/sysmo_l1_hw.c \ + osmo-bts-sysmo/femtobts.c \ + osmo-bts-sysmo/femtobts.h + +noinst_HEADERS += \ + osmo-bts-sysmo/sysmo_l1_if.h \ + osmo-bts-sysmo/femtobts.h + +noinst_PROGRAMS += \ + osmo-pcu-remote + +osmo_pcu_SOURCES += \ + osmo-bts-sysmo/sysmo_l1_if.c \ + osmo-bts-sysmo/sysmo_l1_hw.c \ + osmo-bts-sysmo/femtobts.c + +osmo_pcu_remote_SOURCES = \ + pcu_main.cpp \ + osmo-bts-sysmo/sysmo_l1_if.c \ + osmo-bts-sysmo/sysmo_l1_fwd.c \ + osmo-bts-sysmo/femtobts.c + +osmo_pcu_remote_LDADD = \ libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(COMMON_LA) +endif
-if ENABLE_SYSMODSP -osmo_pcu_remote_LDADD = \ +osmo_pcu_LDADD = \ libgprs.la \ $(LIBOSMOGB_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(COMMON_LA) -endif
#MOSTLYCLEANFILES += testSource testDestination diff --git a/src/femtobts.c b/src/femtobts.c deleted file mode 100644 index f6957d2..0000000 --- a/src/femtobts.c +++ /dev/null @@ -1,275 +0,0 @@ -/* sysmocom femtobts L1 API related definitions */ - -/* (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 <sysmocom/femtobts/superfemto.h> -#include <sysmocom/femtobts/gsml1const.h> -#include <sysmocom/femtobts/gsml1dbg.h> - -#include "femtobts.h" - -const enum l1prim_type femtobts_l1prim_type[GsmL1_PrimId_NUM] = { - [GsmL1_PrimId_MphInitReq] = L1P_T_REQ, - [GsmL1_PrimId_MphCloseReq] = L1P_T_REQ, - [GsmL1_PrimId_MphConnectReq] = L1P_T_REQ, - [GsmL1_PrimId_MphDisconnectReq] = L1P_T_REQ, - [GsmL1_PrimId_MphActivateReq] = L1P_T_REQ, - [GsmL1_PrimId_MphDeactivateReq] = L1P_T_REQ, - [GsmL1_PrimId_MphConfigReq] = L1P_T_REQ, - [GsmL1_PrimId_MphMeasureReq] = L1P_T_REQ, - [GsmL1_PrimId_MphInitCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphCloseCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphConnectCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphDisconnectCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphActivateCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphDeactivateCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphConfigCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphMeasureCnf] = L1P_T_CONF, - [GsmL1_PrimId_MphTimeInd] = L1P_T_IND, - [GsmL1_PrimId_MphSyncInd] = L1P_T_IND, - [GsmL1_PrimId_PhEmptyFrameReq] = L1P_T_REQ, - [GsmL1_PrimId_PhDataReq] = L1P_T_REQ, - [GsmL1_PrimId_PhConnectInd] = L1P_T_IND, - [GsmL1_PrimId_PhReadyToSendInd] = L1P_T_IND, - [GsmL1_PrimId_PhDataInd] = L1P_T_IND, - [GsmL1_PrimId_PhRaInd] = L1P_T_IND, -}; - -const struct value_string femtobts_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 } -}; - -const GsmL1_PrimId_t femtobts_l1prim_req2conf[GsmL1_PrimId_NUM] = { - [GsmL1_PrimId_MphInitReq] = GsmL1_PrimId_MphInitCnf, - [GsmL1_PrimId_MphCloseReq] = GsmL1_PrimId_MphCloseCnf, - [GsmL1_PrimId_MphConnectReq] = GsmL1_PrimId_MphConnectCnf, - [GsmL1_PrimId_MphDisconnectReq] = GsmL1_PrimId_MphDisconnectCnf, - [GsmL1_PrimId_MphActivateReq] = GsmL1_PrimId_MphActivateCnf, - [GsmL1_PrimId_MphDeactivateReq] = GsmL1_PrimId_MphDeactivateCnf, - [GsmL1_PrimId_MphConfigReq] = GsmL1_PrimId_MphConfigCnf, - [GsmL1_PrimId_MphMeasureReq] = GsmL1_PrimId_MphMeasureCnf, -}; - -const enum l1prim_type femtobts_sysprim_type[SuperFemto_PrimId_NUM] = { - [SuperFemto_PrimId_SystemInfoReq] = L1P_T_REQ, - [SuperFemto_PrimId_SystemInfoCnf] = L1P_T_CONF, - [SuperFemto_PrimId_SystemFailureInd] = L1P_T_IND, - [SuperFemto_PrimId_ActivateRfReq] = L1P_T_REQ, - [SuperFemto_PrimId_ActivateRfCnf] = L1P_T_CONF, - [SuperFemto_PrimId_DeactivateRfReq] = L1P_T_REQ, - [SuperFemto_PrimId_DeactivateRfCnf] = L1P_T_CONF, - [SuperFemto_PrimId_SetTraceFlagsReq] = L1P_T_REQ, - [SuperFemto_PrimId_RfClockInfoReq] = L1P_T_REQ, - [SuperFemto_PrimId_RfClockInfoCnf] = L1P_T_CONF, - [SuperFemto_PrimId_RfClockSetupReq] = L1P_T_REQ, - [SuperFemto_PrimId_RfClockSetupCnf] = L1P_T_CONF, - [SuperFemto_PrimId_Layer1ResetReq] = L1P_T_REQ, - [SuperFemto_PrimId_Layer1ResetCnf] = L1P_T_CONF, -}; - -const struct value_string femtobts_sysprim_names[SuperFemto_PrimId_NUM+1] = { - { SuperFemto_PrimId_SystemInfoReq, "SYSTEM-INFO.req" }, - { SuperFemto_PrimId_SystemInfoCnf, "SYSTEM-INFO.conf" }, - { SuperFemto_PrimId_SystemFailureInd, "SYSTEM-FAILURE.ind" }, - { SuperFemto_PrimId_ActivateRfReq, "ACTIVATE-RF.req" }, - { SuperFemto_PrimId_ActivateRfCnf, "ACTIVATE-RF.conf" }, - { SuperFemto_PrimId_DeactivateRfReq, "DEACTIVATE-RF.req" }, - { SuperFemto_PrimId_DeactivateRfCnf, "DEACTIVATE-RF.conf" }, - { SuperFemto_PrimId_SetTraceFlagsReq, "SET-TRACE-FLAGS.req" }, - { SuperFemto_PrimId_RfClockInfoReq, "RF-CLOCK-INFO.req" }, - { SuperFemto_PrimId_RfClockInfoCnf, "RF-CLOCK-INFO.conf" }, - { SuperFemto_PrimId_RfClockSetupReq, "RF-CLOCK-SETUP.req" }, - { SuperFemto_PrimId_RfClockSetupCnf, "RF-CLOCK-SETUP.conf" }, - { SuperFemto_PrimId_Layer1ResetReq, "LAYER1-RESET.req" }, - { SuperFemto_PrimId_Layer1ResetCnf, "LAYER1-RESET.conf" }, - { 0, NULL } -}; - -const SuperFemto_PrimId_t femtobts_sysprim_req2conf[SuperFemto_PrimId_NUM] = { - [SuperFemto_PrimId_SystemInfoReq] = SuperFemto_PrimId_SystemInfoCnf, - [SuperFemto_PrimId_ActivateRfReq] = SuperFemto_PrimId_ActivateRfCnf, - [SuperFemto_PrimId_DeactivateRfReq] = SuperFemto_PrimId_DeactivateRfCnf, - [SuperFemto_PrimId_RfClockInfoReq] = SuperFemto_PrimId_RfClockInfoCnf, - [SuperFemto_PrimId_RfClockSetupReq] = SuperFemto_PrimId_RfClockSetupCnf, - [SuperFemto_PrimId_Layer1ResetReq] = SuperFemto_PrimId_Layer1ResetCnf, -}; - -const struct value_string femtobts_l1sapi_names[GsmL1_Sapi_NUM+1] = { - { 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 femtobts_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" }, - { 0, NULL } -}; - -const struct value_string femtobts_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 femtobts_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 femtobts_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 femtobts_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/femtobts.h b/src/femtobts.h deleted file mode 100644 index 7e45578..0000000 --- a/src/femtobts.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FEMTOBTS_H -#define FEMTOBTS_H - -#include <stdlib.h> -#include <osmocom/core/utils.h> - -#include <sysmocom/femtobts/superfemto.h> -#include <sysmocom/femtobts/gsml1const.h> - -#ifdef L1_HAS_RTP_MODE -/* This is temporarily disabled, as AMR has some bugs in RTP mode */ -//#define USE_L1_RTP_MODE /* Tell L1 to use RTP mode */ -#endif - -enum l1prim_type { - L1P_T_REQ, - L1P_T_CONF, - L1P_T_IND, -}; - -const enum l1prim_type femtobts_l1prim_type[GsmL1_PrimId_NUM]; -const struct value_string femtobts_l1prim_names[GsmL1_PrimId_NUM+1]; -const GsmL1_PrimId_t femtobts_l1prim_req2conf[GsmL1_PrimId_NUM]; - -const enum l1prim_type femtobts_sysprim_type[SuperFemto_PrimId_NUM]; -const struct value_string femtobts_sysprim_names[SuperFemto_PrimId_NUM+1]; -const SuperFemto_PrimId_t femtobts_sysprim_req2conf[SuperFemto_PrimId_NUM]; - -const struct value_string femtobts_l1sapi_names[GsmL1_Sapi_NUM+1]; -const struct value_string femtobts_l1status_names[GSML1_STATUS_NUM+1]; - -const struct value_string femtobts_tracef_names[29]; - -const struct value_string femtobts_tch_pl_names[15]; - -const struct value_string femtobts_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 -}; - -const uint8_t pdch_msu_size[_NUM_PDCH_CS]; - -#endif /* FEMTOBTS_H */ diff --git a/src/osmo-bts-sysmo/femtobts.c b/src/osmo-bts-sysmo/femtobts.c new file mode 100644 index 0000000..f6957d2 --- /dev/null +++ b/src/osmo-bts-sysmo/femtobts.c @@ -0,0 +1,275 @@ +/* sysmocom femtobts L1 API related definitions */ + +/* (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 <sysmocom/femtobts/superfemto.h> +#include <sysmocom/femtobts/gsml1const.h> +#include <sysmocom/femtobts/gsml1dbg.h> + +#include "femtobts.h" + +const enum l1prim_type femtobts_l1prim_type[GsmL1_PrimId_NUM] = { + [GsmL1_PrimId_MphInitReq] = L1P_T_REQ, + [GsmL1_PrimId_MphCloseReq] = L1P_T_REQ, + [GsmL1_PrimId_MphConnectReq] = L1P_T_REQ, + [GsmL1_PrimId_MphDisconnectReq] = L1P_T_REQ, + [GsmL1_PrimId_MphActivateReq] = L1P_T_REQ, + [GsmL1_PrimId_MphDeactivateReq] = L1P_T_REQ, + [GsmL1_PrimId_MphConfigReq] = L1P_T_REQ, + [GsmL1_PrimId_MphMeasureReq] = L1P_T_REQ, + [GsmL1_PrimId_MphInitCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphCloseCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphConnectCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphDisconnectCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphActivateCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphDeactivateCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphConfigCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphMeasureCnf] = L1P_T_CONF, + [GsmL1_PrimId_MphTimeInd] = L1P_T_IND, + [GsmL1_PrimId_MphSyncInd] = L1P_T_IND, + [GsmL1_PrimId_PhEmptyFrameReq] = L1P_T_REQ, + [GsmL1_PrimId_PhDataReq] = L1P_T_REQ, + [GsmL1_PrimId_PhConnectInd] = L1P_T_IND, + [GsmL1_PrimId_PhReadyToSendInd] = L1P_T_IND, + [GsmL1_PrimId_PhDataInd] = L1P_T_IND, + [GsmL1_PrimId_PhRaInd] = L1P_T_IND, +}; + +const struct value_string femtobts_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 } +}; + +const GsmL1_PrimId_t femtobts_l1prim_req2conf[GsmL1_PrimId_NUM] = { + [GsmL1_PrimId_MphInitReq] = GsmL1_PrimId_MphInitCnf, + [GsmL1_PrimId_MphCloseReq] = GsmL1_PrimId_MphCloseCnf, + [GsmL1_PrimId_MphConnectReq] = GsmL1_PrimId_MphConnectCnf, + [GsmL1_PrimId_MphDisconnectReq] = GsmL1_PrimId_MphDisconnectCnf, + [GsmL1_PrimId_MphActivateReq] = GsmL1_PrimId_MphActivateCnf, + [GsmL1_PrimId_MphDeactivateReq] = GsmL1_PrimId_MphDeactivateCnf, + [GsmL1_PrimId_MphConfigReq] = GsmL1_PrimId_MphConfigCnf, + [GsmL1_PrimId_MphMeasureReq] = GsmL1_PrimId_MphMeasureCnf, +}; + +const enum l1prim_type femtobts_sysprim_type[SuperFemto_PrimId_NUM] = { + [SuperFemto_PrimId_SystemInfoReq] = L1P_T_REQ, + [SuperFemto_PrimId_SystemInfoCnf] = L1P_T_CONF, + [SuperFemto_PrimId_SystemFailureInd] = L1P_T_IND, + [SuperFemto_PrimId_ActivateRfReq] = L1P_T_REQ, + [SuperFemto_PrimId_ActivateRfCnf] = L1P_T_CONF, + [SuperFemto_PrimId_DeactivateRfReq] = L1P_T_REQ, + [SuperFemto_PrimId_DeactivateRfCnf] = L1P_T_CONF, + [SuperFemto_PrimId_SetTraceFlagsReq] = L1P_T_REQ, + [SuperFemto_PrimId_RfClockInfoReq] = L1P_T_REQ, + [SuperFemto_PrimId_RfClockInfoCnf] = L1P_T_CONF, + [SuperFemto_PrimId_RfClockSetupReq] = L1P_T_REQ, + [SuperFemto_PrimId_RfClockSetupCnf] = L1P_T_CONF, + [SuperFemto_PrimId_Layer1ResetReq] = L1P_T_REQ, + [SuperFemto_PrimId_Layer1ResetCnf] = L1P_T_CONF, +}; + +const struct value_string femtobts_sysprim_names[SuperFemto_PrimId_NUM+1] = { + { SuperFemto_PrimId_SystemInfoReq, "SYSTEM-INFO.req" }, + { SuperFemto_PrimId_SystemInfoCnf, "SYSTEM-INFO.conf" }, + { SuperFemto_PrimId_SystemFailureInd, "SYSTEM-FAILURE.ind" }, + { SuperFemto_PrimId_ActivateRfReq, "ACTIVATE-RF.req" }, + { SuperFemto_PrimId_ActivateRfCnf, "ACTIVATE-RF.conf" }, + { SuperFemto_PrimId_DeactivateRfReq, "DEACTIVATE-RF.req" }, + { SuperFemto_PrimId_DeactivateRfCnf, "DEACTIVATE-RF.conf" }, + { SuperFemto_PrimId_SetTraceFlagsReq, "SET-TRACE-FLAGS.req" }, + { SuperFemto_PrimId_RfClockInfoReq, "RF-CLOCK-INFO.req" }, + { SuperFemto_PrimId_RfClockInfoCnf, "RF-CLOCK-INFO.conf" }, + { SuperFemto_PrimId_RfClockSetupReq, "RF-CLOCK-SETUP.req" }, + { SuperFemto_PrimId_RfClockSetupCnf, "RF-CLOCK-SETUP.conf" }, + { SuperFemto_PrimId_Layer1ResetReq, "LAYER1-RESET.req" }, + { SuperFemto_PrimId_Layer1ResetCnf, "LAYER1-RESET.conf" }, + { 0, NULL } +}; + +const SuperFemto_PrimId_t femtobts_sysprim_req2conf[SuperFemto_PrimId_NUM] = { + [SuperFemto_PrimId_SystemInfoReq] = SuperFemto_PrimId_SystemInfoCnf, + [SuperFemto_PrimId_ActivateRfReq] = SuperFemto_PrimId_ActivateRfCnf, + [SuperFemto_PrimId_DeactivateRfReq] = SuperFemto_PrimId_DeactivateRfCnf, + [SuperFemto_PrimId_RfClockInfoReq] = SuperFemto_PrimId_RfClockInfoCnf, + [SuperFemto_PrimId_RfClockSetupReq] = SuperFemto_PrimId_RfClockSetupCnf, + [SuperFemto_PrimId_Layer1ResetReq] = SuperFemto_PrimId_Layer1ResetCnf, +}; + +const struct value_string femtobts_l1sapi_names[GsmL1_Sapi_NUM+1] = { + { 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 femtobts_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" }, + { 0, NULL } +}; + +const struct value_string femtobts_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 femtobts_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 femtobts_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 femtobts_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-sysmo/femtobts.h b/src/osmo-bts-sysmo/femtobts.h new file mode 100644 index 0000000..7e45578 --- /dev/null +++ b/src/osmo-bts-sysmo/femtobts.h @@ -0,0 +1,57 @@ +#ifndef FEMTOBTS_H +#define FEMTOBTS_H + +#include <stdlib.h> +#include <osmocom/core/utils.h> + +#include <sysmocom/femtobts/superfemto.h> +#include <sysmocom/femtobts/gsml1const.h> + +#ifdef L1_HAS_RTP_MODE +/* This is temporarily disabled, as AMR has some bugs in RTP mode */ +//#define USE_L1_RTP_MODE /* Tell L1 to use RTP mode */ +#endif + +enum l1prim_type { + L1P_T_REQ, + L1P_T_CONF, + L1P_T_IND, +}; + +const enum l1prim_type femtobts_l1prim_type[GsmL1_PrimId_NUM]; +const struct value_string femtobts_l1prim_names[GsmL1_PrimId_NUM+1]; +const GsmL1_PrimId_t femtobts_l1prim_req2conf[GsmL1_PrimId_NUM]; + +const enum l1prim_type femtobts_sysprim_type[SuperFemto_PrimId_NUM]; +const struct value_string femtobts_sysprim_names[SuperFemto_PrimId_NUM+1]; +const SuperFemto_PrimId_t femtobts_sysprim_req2conf[SuperFemto_PrimId_NUM]; + +const struct value_string femtobts_l1sapi_names[GsmL1_Sapi_NUM+1]; +const struct value_string femtobts_l1status_names[GSML1_STATUS_NUM+1]; + +const struct value_string femtobts_tracef_names[29]; + +const struct value_string femtobts_tch_pl_names[15]; + +const struct value_string femtobts_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 +}; + +const uint8_t pdch_msu_size[_NUM_PDCH_CS]; + +#endif /* FEMTOBTS_H */ diff --git a/src/osmo-bts-sysmo/sysmo_l1_fwd.c b/src/osmo-bts-sysmo/sysmo_l1_fwd.c new file mode 100644 index 0000000..535a7f0 --- /dev/null +++ b/src/osmo-bts-sysmo/sysmo_l1_fwd.c @@ -0,0 +1,145 @@ +/* Interface handler for Sysmocom L1 (forwarding) */ + +/* (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 <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/select.h> +#include <osmocom/core/write_queue.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/timer.h> +#include <osmocom/gsm/gsm_utils.h> + +#include <sysmocom/femtobts/superfemto.h> +#include <sysmocom/femtobts/gsml1prim.h> +#include <sysmocom/femtobts/gsml1const.h> +#include <sysmocom/femtobts/gsml1types.h> + +#include "gprs_debug.h" +#include "sysmo_l1_if.h" + + +#define L1FWD_L1_PORT 9999 +#define L1FWD_SYS_PORT 9998 +#define L1FWD_TCH_PORT 9997 +#define L1FWD_PDTCH_PORT 9996 + +static const uint16_t fwd_udp_ports[] = { + [MQ_SYS_WRITE] = L1FWD_SYS_PORT, + [MQ_L1_WRITE] = L1FWD_L1_PORT, + [MQ_TCH_WRITE] = L1FWD_TCH_PORT, + [MQ_PDTCH_WRITE]= L1FWD_PDTCH_PORT, +}; + +static int fwd_read_cb(struct osmo_fd *ofd) +{ + struct msgb *msg = msgb_alloc_headroom(sizeof(SuperFemto_Prim_t) + 128, + 128, "udp_rx"); + struct femtol1_hdl *fl1h = ofd->data; + int rc; + + if (!msg) + return -ENOMEM; + + msg->l1h = msg->data; + rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg)); + if (rc < 0) { + LOGP(DL1IF, LOGL_ERROR, "Short read from UDP\n"); + msgb_free(msg); + return rc; + } else if (rc == 0) { + LOGP(DL1IF, LOGL_ERROR, "Len=0 from UDP\n"); + msgb_free(msg); + return rc; + } + msgb_put(msg, rc); + + if (ofd->priv_nr == MQ_SYS_WRITE) + rc = l1if_handle_sysprim(fl1h, msg); + else + rc = l1if_handle_l1prim(ofd->priv_nr, fl1h, msg); + + return rc; +} + +static int prim_write_cb(struct osmo_fd *ofd, struct msgb *msg) +{ + /* write to the fd */ + return write(ofd->fd, msg->head, msg->len); +} + +int l1if_transport_open(int q, struct femtol1_hdl *fl1h) +{ + int rc; + char *bts_host = getenv("L1FWD_BTS_HOST"); + + printf("sizeof(GsmL1_Prim_t) = %zu\n", sizeof(GsmL1_Prim_t)); + printf("sizeof(SuperFemto_Prim_t) = %zu\n", sizeof(SuperFemto_Prim_t)); + + if (!bts_host) { + fprintf(stderr, "You have to set the L1FWD_BTS_HOST environment variable\n"); + exit(2); + } + + struct osmo_wqueue *wq = &fl1h->write_q[q]; + struct osmo_fd *ofd = &wq->bfd; + + osmo_wqueue_init(wq, 10); + wq->write_cb = prim_write_cb; + wq->read_cb = fwd_read_cb; + + ofd->data = fl1h; + ofd->priv_nr = q; + ofd->when |= BSC_FD_READ; + + rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, + bts_host, fwd_udp_ports[q], + OSMO_SOCK_F_CONNECT); + if (rc < 0) + return rc; + + return 0; +} + +int l1if_transport_close(int q, struct femtol1_hdl *fl1h) +{ + struct osmo_wqueue *wq = &fl1h->write_q[q]; + struct osmo_fd *ofd = &wq->bfd; + + osmo_wqueue_clear(wq); + osmo_fd_unregister(ofd); + close(ofd->fd); + + return 0; +} diff --git a/src/osmo-bts-sysmo/sysmo_l1_hw.c b/src/osmo-bts-sysmo/sysmo_l1_hw.c new file mode 100644 index 0000000..2c019be --- /dev/null +++ b/src/osmo-bts-sysmo/sysmo_l1_hw.c @@ -0,0 +1,216 @@ +/* Interface handler for Sysmocom L1 (real hardware) */ + +/* (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 <string.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/write_queue.h> +#include <osmocom/core/timer.h> +#include <osmocom/gsm/gsm_utils.h> + +#include <sysmocom/femtobts/superfemto.h> +#include <sysmocom/femtobts/gsml1prim.h> +#include <sysmocom/femtobts/gsml1const.h> +#include <sysmocom/femtobts/gsml1types.h> + +#include "gprs_debug.h" +#include "femtobts.h" +#include "sysmo_l1_if.h" + + +#ifdef HW_SYSMOBTS_V1 +#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/femtobts_dsp2arm" +#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/femtobts_arm2dsp" +#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_dsp2arm" +#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_arm2dsp" +#else +#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/superfemto_dsp2arm" +#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/superfemto_arm2dsp" +#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_sig_dsp2arm" +#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_sig_arm2dsp" + +#define DEV_TCH_DSP2ARM_NAME "/dev/msgq/gsml1_tch_dsp2arm" +#define DEV_TCH_ARM2DSP_NAME "/dev/msgq/gsml1_tch_arm2dsp" +#define DEV_PDTCH_DSP2ARM_NAME "/dev/msgq/gsml1_pdtch_dsp2arm1" //2 -- trx1 +#define DEV_PDTCH_ARM2DSP_NAME "/dev/msgq/gsml1_pdtch_arm2dsp1" //2 +#endif + +static const char *rd_devnames[] = { + [MQ_SYS_READ] = DEV_SYS_DSP2ARM_NAME, + [MQ_L1_READ] = DEV_L1_DSP2ARM_NAME, +#ifndef HW_SYSMOBTS_V1 + [MQ_TCH_READ] = DEV_TCH_DSP2ARM_NAME, + [MQ_PDTCH_READ] = DEV_PDTCH_DSP2ARM_NAME, +#endif +}; + +static const char *wr_devnames[] = { + [MQ_SYS_WRITE] = DEV_SYS_ARM2DSP_NAME, + [MQ_L1_WRITE] = DEV_L1_ARM2DSP_NAME, +#ifndef HW_SYSMOBTS_V1 + [MQ_TCH_WRITE] = DEV_TCH_ARM2DSP_NAME, + [MQ_PDTCH_WRITE]= DEV_PDTCH_ARM2DSP_NAME, +#endif +}; + +/* callback when there's something to read from the l1 msg_queue */ +static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what) +{ + //struct msgb *msg = l1p_msgb_alloc(); + struct msgb *msg = msgb_alloc_headroom(sizeof(SuperFemto_Prim_t) + 128, + 128, "1l_fd"); + struct femtol1_hdl *fl1h = ofd->data; + int rc; + + msg->l1h = msg->data; + rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg)); + if (rc < 0) { + if (rc != -1) + LOGP(DL1IF, LOGL_ERROR, "error reading from L1 msg_queue: %s\n", + strerror(errno)); + msgb_free(msg); + return rc; + } + msgb_put(msg, rc); + + switch (ofd->priv_nr) { + case MQ_SYS_WRITE: + if (rc != sizeof(SuperFemto_Prim_t)) + LOGP(DL1IF, LOGL_NOTICE, "%u != " + "sizeof(SuperFemto_Prim_t)\n", rc); + return l1if_handle_sysprim(fl1h, msg); + case MQ_L1_WRITE: +#ifndef HW_SYSMOBTS_V1 + case MQ_TCH_WRITE: + case MQ_PDTCH_WRITE: +#endif + if (rc != sizeof(GsmL1_Prim_t)) + LOGP(DL1IF, LOGL_NOTICE, "%u != " + "sizeof(GsmL1_Prim_t)\n", rc); + return l1if_handle_l1prim(ofd->priv_nr, fl1h, msg); + default: + /* The compiler can't know that priv_nr is an enum. Assist. */ + LOGP(DL1IF, LOGL_FATAL, "writing on a wrong queue: %d\n", + ofd->priv_nr); + exit(0); + break; + } +}; + +/* 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(DL1IF, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", + strerror(errno)); + return rc; + } else if (rc < msg->len) { + LOGP(DL1IF, 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 femtol1_hdl *hdl) +{ + int rc; + + /* 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; + + rc = open(rd_devnames[q], O_RDONLY); + if (rc < 0) { + LOGP(DL1IF, LOGL_FATAL, "unable to open msg_queue: %s\n", + strerror(errno)); + return rc; + } + read_ofd->fd = rc; + read_ofd->priv_nr = q; + read_ofd->data = hdl; + read_ofd->cb = l1if_fd_cb; + read_ofd->when = BSC_FD_READ; + rc = osmo_fd_register(read_ofd); + if (rc < 0) { + close(read_ofd->fd); + read_ofd->fd = -1; + return rc; + } + + rc = open(wr_devnames[q], O_WRONLY); + if (rc < 0) { + LOGP(DL1IF, LOGL_FATAL, "unable to open msg_queue: %s\n", + strerror(errno)); + goto out_read; + } + osmo_wqueue_init(wq, 10); + wq->write_cb = l1fd_write_cb; + write_ofd->fd = rc; + write_ofd->priv_nr = q; + write_ofd->data = hdl; + write_ofd->when = BSC_FD_WRITE; + 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 femtol1_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-sysmo/sysmo_l1_if.c b/src/osmo-bts-sysmo/sysmo_l1_if.c new file mode 100644 index 0000000..8572786 --- /dev/null +++ b/src/osmo-bts-sysmo/sysmo_l1_if.c @@ -0,0 +1,396 @@ + +#include <string.h> +#include <errno.h> + +#include <sysmocom/femtobts/superfemto.h> +#include <sysmocom/femtobts/gsml1prim.h> +#include <sysmocom/femtobts/gsml1const.h> +#include <sysmocom/femtobts/gsml1types.h> + +#include <osmocom/core/gsmtap.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/timer.h> +#include <sysmo_l1_if.h> +#include <gprs_debug.h> +#include <pcu_l1_if.h> + +extern void *tall_pcu_ctx; + +uint32_t l1if_ts_to_hLayer2(uint8_t trx, uint8_t ts) +{ + return (ts << 16) | (trx << 24); +} + +/* 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; +} + +static int l1if_req_pdch(struct femtol1_hdl *fl1h, struct msgb *msg) +{ + struct osmo_wqueue *wqueue = &fl1h->write_q[MQ_PDTCH_WRITE]; + + if (osmo_wqueue_enqueue(wqueue, msg) != 0) { + LOGP(DL1IF, LOGL_ERROR, "PDTCH queue full. dropping message.\n"); + msgb_free(msg); + } + + return 0; +} + +static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct femtol1_hdl *gl1) +{ + prim->id = id; + + /* for some reason the hLayer1 field is not always at the same position + * in the GsmL1_Prim_t, so we have to have this ugly case statement here... */ + switch (id) { + case GsmL1_PrimId_MphInitReq: + //prim->u.mphInitReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphCloseReq: + prim->u.mphCloseReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphConnectReq: + prim->u.mphConnectReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphDisconnectReq: + prim->u.mphDisconnectReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphActivateReq: + prim->u.mphActivateReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphDeactivateReq: + prim->u.mphDeactivateReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphConfigReq: + prim->u.mphConfigReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphMeasureReq: + prim->u.mphMeasureReq.hLayer1 = gl1->hLayer1; + break; + case GsmL1_PrimId_MphInitCnf: + case GsmL1_PrimId_MphCloseCnf: + case GsmL1_PrimId_MphConnectCnf: + case GsmL1_PrimId_MphDisconnectCnf: + case GsmL1_PrimId_MphActivateCnf: + case GsmL1_PrimId_MphDeactivateCnf: + case GsmL1_PrimId_MphConfigCnf: + case GsmL1_PrimId_MphMeasureCnf: + 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(DL1IF, LOGL_ERROR, "unknown L1 primitive %u\n", id); + break; + } + return &prim->u; +} + +struct sapi_dir { + GsmL1_Sapi_t sapi; + GsmL1_Dir_t dir; +}; + +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 +}; + + +/* connect PDTCH */ +int l1if_connect_pdch(void *obj, uint8_t ts) +{ + struct femtol1_hdl *fl1h = obj; + struct msgb *msg = l1p_msgb_alloc(); + GsmL1_MphConnectReq_t *cr; + + cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h); + cr->u8Tn = ts; + cr->logChComb = GsmL1_LogChComb_XIII; + + return l1if_req_pdch(fl1h, msg); +} + +static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1h, + GsmL1_PhReadyToSendInd_t *rts_ind) +{ + struct gsm_time g_time; + int rc = 0; + + gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); + + DEBUGP(DL1IF, "Rx PH-RTS.ind %02u/%02u/%02u SAPI=%s\n", + g_time.t1, g_time.t2, g_time.t3, + get_value_string(femtobts_l1sapi_names, rts_ind->sapi)); + + switch (rts_ind->sapi) { + case GsmL1_Sapi_Pdtch: + case GsmL1_Sapi_Pacch: + rc = pcu_rx_rts_req_pdtch((long)fl1h->priv, rts_ind->u8Tn, + rts_ind->u16Arfcn, rts_ind->u32Fn, rts_ind->u8BlockNbr); + case GsmL1_Sapi_Ptcch: + // FIXME + default: + break; + } + + return rc; +} + +static void get_meas(struct pcu_l1_meas *meas, const GsmL1_MeasParam_t *l1_meas) +{ + meas->rssi = (int8_t) (l1_meas->fRssi); + meas->have_rssi = 1; + meas->ber = (uint8_t) (l1_meas->fBer * 100); + meas->have_ber = 1; + meas->bto = (int16_t) (l1_meas->i16BurstTiming); + meas->have_bto = 1; + meas->link_qual = (int16_t) (l1_meas->fLinkQuality); + meas->have_link_qual = 1; +} + +static int handle_ph_data_ind(struct femtol1_hdl *fl1h, + GsmL1_PhDataInd_t *data_ind, struct msgb *l1p_msg) +{ + int rc = 0; + struct pcu_l1_meas meas = {0}; + + DEBUGP(DL1IF, "Rx PH-DATA.ind %s (hL2 %08x): %s\n", + get_value_string(femtobts_l1sapi_names, data_ind->sapi), + data_ind->hLayer2, + osmo_hexdump(data_ind->msgUnitParam.u8Buffer, + data_ind->msgUnitParam.u8Size)); + + pcu_rx_block_time(data_ind->u16Arfcn, data_ind->u32Fn, data_ind->u8Tn); + + /* + * TODO: Add proper bad frame handling here. This could be used + * to switch the used CS. Avoid a crash with the PCU right now + * feed "0 - 1" amount of data. + */ + if (data_ind->msgUnitParam.u8Size == 0) + return -1; + + gsmtap_send(fl1h->gsmtap, data_ind->u16Arfcn | GSMTAP_ARFCN_F_UPLINK, + data_ind->u8Tn, GSMTAP_CHANNEL_PACCH, 0, + data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1, + data_ind->msgUnitParam.u8Size-1); + + get_meas(&meas, &data_ind->measParam); + + switch (data_ind->sapi) { + case GsmL1_Sapi_Pdtch: + case GsmL1_Sapi_Pacch: + /* drop incomplete UL block */ + if (data_ind->msgUnitParam.u8Buffer[0] + != GsmL1_PdtchPlType_Full) + break; + /* PDTCH / PACCH frame handling */ + pcu_rx_data_ind_pdtch((long)fl1h->priv, data_ind->u8Tn, + data_ind->msgUnitParam.u8Buffer + 1, + data_ind->msgUnitParam.u8Size - 1, + data_ind->u32Fn, + &meas); + break; + case GsmL1_Sapi_Ptcch: + // FIXME + break; + default: + LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n", + get_value_string(femtobts_l1sapi_names, data_ind->sapi)); + break; + } + + return rc; +} + +#define MIN_QUAL_RACH 5.0f + +static int handle_ph_ra_ind(struct femtol1_hdl *fl1h, GsmL1_PhRaInd_t *ra_ind) +{ + uint8_t acc_delay; + + pcu_rx_ra_time(ra_ind->u16Arfcn, ra_ind->u32Fn, ra_ind->u8Tn); + + if (ra_ind->measParam.fLinkQuality < MIN_QUAL_RACH) + return 0; + + DEBUGP(DL1IF, "Rx PH-RA.ind"); + + /* check for under/overflow / sign */ + if (ra_ind->measParam.i16BurstTiming < 0) + acc_delay = 0; + else + acc_delay = ra_ind->measParam.i16BurstTiming >> 2; + + LOGP(DL1IF, LOGL_NOTICE, "got (P)RACH request, TA = %u (ignored)\n", + acc_delay); + +#warning "The (P)RACH request is just dropped here" + +#if 0 + if (acc_delay > bts->max_ta) { + LOGP(DL1C, LOGL_INFO, "ignoring RACH request %u > max_ta(%u)\n", + acc_delay, btsb->max_ta); + return 0; + } +#endif + + return 0; +} + + +/* handle any random indication from the L1 */ +int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg) +{ + GsmL1_Prim_t *l1p = msgb_l1prim(msg); + int rc = 0; + + LOGP(DL1IF, LOGL_DEBUG, "Rx L1 prim %s on queue %d\n", + get_value_string(femtobts_l1prim_names, l1p->id), wq); + + switch (l1p->id) { +#if 0 + case GsmL1_PrimId_MphTimeInd: + rc = handle_mph_time_ind(fl1h, &l1p->u.mphTimeInd); + break; + case GsmL1_PrimId_MphSyncInd: + break; + case GsmL1_PrimId_PhConnectInd: + break; +#endif + case GsmL1_PrimId_PhReadyToSendInd: + rc = handle_ph_readytosend_ind(fl1h, &l1p->u.phReadyToSendInd); + break; + case GsmL1_PrimId_PhDataInd: + rc = handle_ph_data_ind(fl1h, &l1p->u.phDataInd, msg); + break; + case GsmL1_PrimId_PhRaInd: + rc = handle_ph_ra_ind(fl1h, &l1p->u.phRaInd); + break; + default: + break; + } + + msgb_free(msg); + + return rc; +} + +int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg) +{ + return -ENOTSUP; +} + +/* send packet data request to L1 */ +int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn, + uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len) +{ + struct femtol1_hdl *fl1h = obj; + struct msgb *msg; + GsmL1_Prim_t *l1p; + GsmL1_PhDataReq_t *data_req; + GsmL1_MsgUnitParam_t *msu_param; + struct gsm_time g_time; + + gsm_fn2gsmtime(&g_time, fn); + + DEBUGP(DL1IF, "TX packet data %02u/%02u/%02u is_ptcch=%d ts=%d " + "block_nr=%d, arfcn=%d, len=%d\n", g_time.t1, g_time.t2, + g_time.t3, is_ptcch, ts, block_nr, arfcn, len); + + msg = l1p_msgb_alloc(); + l1p = msgb_l1prim(msg); + l1p->id = GsmL1_PrimId_PhDataReq; + data_req = &l1p->u.phDataReq; + data_req->hLayer1 = fl1h->hLayer1; + data_req->sapi = (is_ptcch) ? GsmL1_Sapi_Ptcch : GsmL1_Sapi_Pdtch; + data_req->subCh = GsmL1_SubCh_NA; + data_req->u8BlockNbr = block_nr; + data_req->u8Tn = ts; + data_req->u32Fn = fn; + msu_param = &data_req->msgUnitParam; + msu_param->u8Size = len; + memcpy(msu_param->u8Buffer, data, len); + + gsmtap_send(fl1h->gsmtap, arfcn, data_req->u8Tn, GSMTAP_CHANNEL_PACCH, + 0, data_req->u32Fn, 0, 0, + data_req->msgUnitParam.u8Buffer, + data_req->msgUnitParam.u8Size); + + + /* transmit */ + if (osmo_wqueue_enqueue(&fl1h->write_q[MQ_PDTCH_WRITE], msg) != 0) { + LOGP(DL1IF, LOGL_ERROR, "PDTCH queue full. dropping message.\n"); + msgb_free(msg); + } + + return 0; +} + +void *l1if_open_pdch(void *priv, uint32_t hlayer1) +{ + struct femtol1_hdl *fl1h; + int rc; + + fl1h = talloc_zero(tall_pcu_ctx, struct femtol1_hdl); + if (!fl1h) + return NULL; + + fl1h->hLayer1 = hlayer1; + fl1h->priv = priv; + fl1h->clk_cal = 0; + /* default clock source: OCXO */ + fl1h->clk_src = SuperFemto_ClkSrcId_Ocxo; + + rc = l1if_transport_open(MQ_PDTCH_WRITE, fl1h); + if (rc < 0) { + talloc_free(fl1h); + return NULL; + } + + fl1h->gsmtap = gsmtap_source_init("localhost", GSMTAP_UDP_PORT, 1); + if (fl1h->gsmtap) + gsmtap_source_add_sink(fl1h->gsmtap); + + return fl1h; +} + +int l1if_close_pdch(void *obj) +{ + struct femtol1_hdl *fl1h = obj; + if (fl1h) + l1if_transport_close(MQ_PDTCH_WRITE, fl1h); + talloc_free(fl1h); + return 0; +} + diff --git a/src/osmo-bts-sysmo/sysmo_l1_if.h b/src/osmo-bts-sysmo/sysmo_l1_if.h new file mode 100644 index 0000000..6b50d4e --- /dev/null +++ b/src/osmo-bts-sysmo/sysmo_l1_if.h @@ -0,0 +1,91 @@ +#ifndef _SYSMO_L1_IF_H +#define _SYSMO_L1_IF_H + +#include <osmocom/core/select.h> +#include <osmocom/core/write_queue.h> +#include <osmocom/core/gsmtap_util.h> +#include <osmocom/gsm/gsm_utils.h> +#include "femtobts.h" + +enum { + MQ_SYS_READ, + MQ_L1_READ, +#ifndef HW_SYSMOBTS_V1 + MQ_TCH_READ, + MQ_PDTCH_READ, +#endif + _NUM_MQ_READ +}; + +enum { + MQ_SYS_WRITE, + MQ_L1_WRITE, +#ifndef HW_SYSMOBTS_V1 + MQ_TCH_WRITE, + MQ_PDTCH_WRITE, +#endif + _NUM_MQ_WRITE +}; + +struct femtol1_hdl { + struct gsm_time gsm_time; + uint32_t hLayer1; /* handle to the L1 instance in the DSP */ + uint32_t dsp_trace_f; + int clk_cal; + uint8_t clk_src; + struct llist_head wlc_list; + + struct gsmtap_inst *gsmtap; + uint32_t gsmtap_sapi_mask; + + void *priv; /* user reference */ + + 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 { + uint8_t dsp_version[3]; + uint8_t fpga_version[3]; + uint32_t band_support; /* bitmask of GSM_BAND_* */ + } hw_info; +}; + +#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h) +#define msgb_sysprim(msg) ((SuperFemto_Prim_t *)(msg)->l1h) + +typedef int l1if_compl_cb(struct msgb *l1_msg, void *data); + +/* send a request primitive to the L1 and schedule completion call-back */ +int l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, + int is_system_prim, l1if_compl_cb *cb, void *data); + +int l1if_reset(struct femtol1_hdl *hdl); +int l1if_activate_rf(struct femtol1_hdl *hdl, int on); +int l1if_set_trace_flags(struct femtol1_hdl *hdl, uint32_t flags); +int l1if_set_txpower(struct femtol1_hdl *fl1h, float tx_power); + +struct msgb *l1p_msgb_alloc(void); +struct msgb *sysp_msgb_alloc(void); + +uint32_t l1if_lchan_to_hLayer2(struct gsm_lchan *lchan); +struct gsm_lchan *l1if_hLayer2_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer2); + +int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg); +int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg); + +/* tch.c */ +int l1if_tch_rx(struct gsm_lchan *lchan, 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); + +/* + * The implementation of these functions is selected by either compiling and + * linking sysmo_l1_hw.c or sysmo_l1_fwd.c + */ +int l1if_transport_open(int q, struct femtol1_hdl *hdl); +int l1if_transport_close(int q, struct femtol1_hdl *hdl); + +#endif /* _SYSMO_L1_IF_H */ diff --git a/src/osmobts_sock.cpp b/src/osmobts_sock.cpp index b42f042..21a404f 100644 --- a/src/osmobts_sock.cpp +++ b/src/osmobts_sock.cpp @@ -100,7 +100,7 @@ static void pcu_sock_close(struct pcu_sock_state *state, int lost)
/* disable all slots, kick all TBFs */ for (trx = 0; trx < 8; trx++) { -#ifdef ENABLE_SYSMODSP +#ifdef ENABLE_DIRECT_PHY if (bts->trx[trx].fl1h) { l1if_close_pdch(bts->trx[trx].fl1h); bts->trx[trx].fl1h = NULL; diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index 9d7dbee..a19b957 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -124,7 +124,7 @@ static int pcu_tx_data_req(uint8_t trx, uint8_t ts, uint8_t sapi, void pcu_l1if_tx_pdtch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn, uint32_t fn, uint8_t block_nr) { -#ifdef ENABLE_SYSMODSP +#ifdef ENABLE_DIRECT_PHY struct gprs_rlcmac_bts *bts = bts_main_data();
if (bts->trx[trx].fl1h) @@ -430,7 +430,7 @@ bssgp_failed: bts->trx[trx].arfcn = info_ind->trx[trx].arfcn; if ((info_ind->flags & PCU_IF_FLAG_SYSMO) && info_ind->trx[trx].hlayer1) { -#ifdef ENABLE_SYSMODSP +#ifdef ENABLE_DIRECT_PHY LOGP(DL1IF, LOGL_DEBUG, " TRX %d hlayer1=%x\n", trx, info_ind->trx[trx].hlayer1); if (!bts->trx[trx].fl1h) @@ -455,7 +455,7 @@ bssgp_failed: if ((info_ind->trx[trx].pdch_mask & (1 << ts))) { /* FIXME: activate dynamically at RLCMAC */ if (!pdch->is_enabled()) { -#ifdef ENABLE_SYSMODSP +#ifdef ENABLE_DIRECT_PHY if ((info_ind->flags & PCU_IF_FLAG_SYSMO)) l1if_connect_pdch( diff --git a/src/sysmo_l1_fwd.c b/src/sysmo_l1_fwd.c deleted file mode 100644 index 535a7f0..0000000 --- a/src/sysmo_l1_fwd.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Interface handler for Sysmocom L1 (forwarding) */ - -/* (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 <stdint.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/select.h> -#include <osmocom/core/write_queue.h> -#include <osmocom/core/msgb.h> -#include <osmocom/core/socket.h> -#include <osmocom/core/timer.h> -#include <osmocom/gsm/gsm_utils.h> - -#include <sysmocom/femtobts/superfemto.h> -#include <sysmocom/femtobts/gsml1prim.h> -#include <sysmocom/femtobts/gsml1const.h> -#include <sysmocom/femtobts/gsml1types.h> - -#include "gprs_debug.h" -#include "sysmo_l1_if.h" - - -#define L1FWD_L1_PORT 9999 -#define L1FWD_SYS_PORT 9998 -#define L1FWD_TCH_PORT 9997 -#define L1FWD_PDTCH_PORT 9996 - -static const uint16_t fwd_udp_ports[] = { - [MQ_SYS_WRITE] = L1FWD_SYS_PORT, - [MQ_L1_WRITE] = L1FWD_L1_PORT, - [MQ_TCH_WRITE] = L1FWD_TCH_PORT, - [MQ_PDTCH_WRITE]= L1FWD_PDTCH_PORT, -}; - -static int fwd_read_cb(struct osmo_fd *ofd) -{ - struct msgb *msg = msgb_alloc_headroom(sizeof(SuperFemto_Prim_t) + 128, - 128, "udp_rx"); - struct femtol1_hdl *fl1h = ofd->data; - int rc; - - if (!msg) - return -ENOMEM; - - msg->l1h = msg->data; - rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg)); - if (rc < 0) { - LOGP(DL1IF, LOGL_ERROR, "Short read from UDP\n"); - msgb_free(msg); - return rc; - } else if (rc == 0) { - LOGP(DL1IF, LOGL_ERROR, "Len=0 from UDP\n"); - msgb_free(msg); - return rc; - } - msgb_put(msg, rc); - - if (ofd->priv_nr == MQ_SYS_WRITE) - rc = l1if_handle_sysprim(fl1h, msg); - else - rc = l1if_handle_l1prim(ofd->priv_nr, fl1h, msg); - - return rc; -} - -static int prim_write_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - /* write to the fd */ - return write(ofd->fd, msg->head, msg->len); -} - -int l1if_transport_open(int q, struct femtol1_hdl *fl1h) -{ - int rc; - char *bts_host = getenv("L1FWD_BTS_HOST"); - - printf("sizeof(GsmL1_Prim_t) = %zu\n", sizeof(GsmL1_Prim_t)); - printf("sizeof(SuperFemto_Prim_t) = %zu\n", sizeof(SuperFemto_Prim_t)); - - if (!bts_host) { - fprintf(stderr, "You have to set the L1FWD_BTS_HOST environment variable\n"); - exit(2); - } - - struct osmo_wqueue *wq = &fl1h->write_q[q]; - struct osmo_fd *ofd = &wq->bfd; - - osmo_wqueue_init(wq, 10); - wq->write_cb = prim_write_cb; - wq->read_cb = fwd_read_cb; - - ofd->data = fl1h; - ofd->priv_nr = q; - ofd->when |= BSC_FD_READ; - - rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, - bts_host, fwd_udp_ports[q], - OSMO_SOCK_F_CONNECT); - if (rc < 0) - return rc; - - return 0; -} - -int l1if_transport_close(int q, struct femtol1_hdl *fl1h) -{ - struct osmo_wqueue *wq = &fl1h->write_q[q]; - struct osmo_fd *ofd = &wq->bfd; - - osmo_wqueue_clear(wq); - osmo_fd_unregister(ofd); - close(ofd->fd); - - return 0; -} diff --git a/src/sysmo_l1_hw.c b/src/sysmo_l1_hw.c deleted file mode 100644 index 8351d68..0000000 --- a/src/sysmo_l1_hw.c +++ /dev/null @@ -1,216 +0,0 @@ -/* Interface handler for Sysmocom L1 (real hardware) */ - -/* (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 <string.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/write_queue.h> -#include <osmocom/core/timer.h> -#include <osmocom/gsm/gsm_utils.h> - -#include <sysmocom/femtobts/superfemto.h> -#include <sysmocom/femtobts/gsml1prim.h> -#include <sysmocom/femtobts/gsml1const.h> -#include <sysmocom/femtobts/gsml1types.h> - -#include "gprs_debug.h" -#include "femtobts.h" -#include "sysmo_l1_if.h" - - -#ifdef HW_SYSMOBTS_V1 -#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/femtobts_dsp2arm" -#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/femtobts_arm2dsp" -#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_dsp2arm" -#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_arm2dsp" -#else -#define DEV_SYS_DSP2ARM_NAME "/dev/msgq/superfemto_dsp2arm" -#define DEV_SYS_ARM2DSP_NAME "/dev/msgq/superfemto_arm2dsp" -#define DEV_L1_DSP2ARM_NAME "/dev/msgq/gsml1_sig_dsp2arm" -#define DEV_L1_ARM2DSP_NAME "/dev/msgq/gsml1_sig_arm2dsp" - -#define DEV_TCH_DSP2ARM_NAME "/dev/msgq/gsml1_tch_dsp2arm" -#define DEV_TCH_ARM2DSP_NAME "/dev/msgq/gsml1_tch_arm2dsp" -#define DEV_PDTCH_DSP2ARM_NAME "/dev/msgq/gsml1_pdtch_dsp2arm" -#define DEV_PDTCH_ARM2DSP_NAME "/dev/msgq/gsml1_pdtch_arm2dsp" -#endif - -static const char *rd_devnames[] = { - [MQ_SYS_READ] = DEV_SYS_DSP2ARM_NAME, - [MQ_L1_READ] = DEV_L1_DSP2ARM_NAME, -#ifndef HW_SYSMOBTS_V1 - [MQ_TCH_READ] = DEV_TCH_DSP2ARM_NAME, - [MQ_PDTCH_READ] = DEV_PDTCH_DSP2ARM_NAME, -#endif -}; - -static const char *wr_devnames[] = { - [MQ_SYS_WRITE] = DEV_SYS_ARM2DSP_NAME, - [MQ_L1_WRITE] = DEV_L1_ARM2DSP_NAME, -#ifndef HW_SYSMOBTS_V1 - [MQ_TCH_WRITE] = DEV_TCH_ARM2DSP_NAME, - [MQ_PDTCH_WRITE]= DEV_PDTCH_ARM2DSP_NAME, -#endif -}; - -/* callback when there's something to read from the l1 msg_queue */ -static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - //struct msgb *msg = l1p_msgb_alloc(); - struct msgb *msg = msgb_alloc_headroom(sizeof(SuperFemto_Prim_t) + 128, - 128, "1l_fd"); - struct femtol1_hdl *fl1h = ofd->data; - int rc; - - msg->l1h = msg->data; - rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg)); - if (rc < 0) { - if (rc != -1) - LOGP(DL1IF, LOGL_ERROR, "error reading from L1 msg_queue: %s\n", - strerror(errno)); - msgb_free(msg); - return rc; - } - msgb_put(msg, rc); - - switch (ofd->priv_nr) { - case MQ_SYS_WRITE: - if (rc != sizeof(SuperFemto_Prim_t)) - LOGP(DL1IF, LOGL_NOTICE, "%u != " - "sizeof(SuperFemto_Prim_t)\n", rc); - return l1if_handle_sysprim(fl1h, msg); - case MQ_L1_WRITE: -#ifndef HW_SYSMOBTS_V1 - case MQ_TCH_WRITE: - case MQ_PDTCH_WRITE: -#endif - if (rc != sizeof(GsmL1_Prim_t)) - LOGP(DL1IF, LOGL_NOTICE, "%u != " - "sizeof(GsmL1_Prim_t)\n", rc); - return l1if_handle_l1prim(ofd->priv_nr, fl1h, msg); - default: - /* The compiler can't know that priv_nr is an enum. Assist. */ - LOGP(DL1IF, LOGL_FATAL, "writing on a wrong queue: %d\n", - ofd->priv_nr); - exit(0); - break; - } -}; - -/* 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(DL1IF, LOGL_ERROR, "error writing to L1 msg_queue: %s\n", - strerror(errno)); - return rc; - } else if (rc < msg->len) { - LOGP(DL1IF, 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 femtol1_hdl *hdl) -{ - int rc; - - /* 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; - - rc = open(rd_devnames[q], O_RDONLY); - if (rc < 0) { - LOGP(DL1IF, LOGL_FATAL, "unable to open msg_queue: %s\n", - strerror(errno)); - return rc; - } - read_ofd->fd = rc; - read_ofd->priv_nr = q; - read_ofd->data = hdl; - read_ofd->cb = l1if_fd_cb; - read_ofd->when = BSC_FD_READ; - rc = osmo_fd_register(read_ofd); - if (rc < 0) { - close(read_ofd->fd); - read_ofd->fd = -1; - return rc; - } - - rc = open(wr_devnames[q], O_WRONLY); - if (rc < 0) { - LOGP(DL1IF, LOGL_FATAL, "unable to open msg_queue: %s\n", - strerror(errno)); - goto out_read; - } - osmo_wqueue_init(wq, 10); - wq->write_cb = l1fd_write_cb; - write_ofd->fd = rc; - write_ofd->priv_nr = q; - write_ofd->data = hdl; - write_ofd->when = BSC_FD_WRITE; - 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 femtol1_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/sysmo_l1_if.c b/src/sysmo_l1_if.c deleted file mode 100644 index 8572786..0000000 --- a/src/sysmo_l1_if.c +++ /dev/null @@ -1,396 +0,0 @@ - -#include <string.h> -#include <errno.h> - -#include <sysmocom/femtobts/superfemto.h> -#include <sysmocom/femtobts/gsml1prim.h> -#include <sysmocom/femtobts/gsml1const.h> -#include <sysmocom/femtobts/gsml1types.h> - -#include <osmocom/core/gsmtap.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/timer.h> -#include <sysmo_l1_if.h> -#include <gprs_debug.h> -#include <pcu_l1_if.h> - -extern void *tall_pcu_ctx; - -uint32_t l1if_ts_to_hLayer2(uint8_t trx, uint8_t ts) -{ - return (ts << 16) | (trx << 24); -} - -/* 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; -} - -static int l1if_req_pdch(struct femtol1_hdl *fl1h, struct msgb *msg) -{ - struct osmo_wqueue *wqueue = &fl1h->write_q[MQ_PDTCH_WRITE]; - - if (osmo_wqueue_enqueue(wqueue, msg) != 0) { - LOGP(DL1IF, LOGL_ERROR, "PDTCH queue full. dropping message.\n"); - msgb_free(msg); - } - - return 0; -} - -static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct femtol1_hdl *gl1) -{ - prim->id = id; - - /* for some reason the hLayer1 field is not always at the same position - * in the GsmL1_Prim_t, so we have to have this ugly case statement here... */ - switch (id) { - case GsmL1_PrimId_MphInitReq: - //prim->u.mphInitReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphCloseReq: - prim->u.mphCloseReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphConnectReq: - prim->u.mphConnectReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphDisconnectReq: - prim->u.mphDisconnectReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphActivateReq: - prim->u.mphActivateReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphDeactivateReq: - prim->u.mphDeactivateReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphConfigReq: - prim->u.mphConfigReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphMeasureReq: - prim->u.mphMeasureReq.hLayer1 = gl1->hLayer1; - break; - case GsmL1_PrimId_MphInitCnf: - case GsmL1_PrimId_MphCloseCnf: - case GsmL1_PrimId_MphConnectCnf: - case GsmL1_PrimId_MphDisconnectCnf: - case GsmL1_PrimId_MphActivateCnf: - case GsmL1_PrimId_MphDeactivateCnf: - case GsmL1_PrimId_MphConfigCnf: - case GsmL1_PrimId_MphMeasureCnf: - 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(DL1IF, LOGL_ERROR, "unknown L1 primitive %u\n", id); - break; - } - return &prim->u; -} - -struct sapi_dir { - GsmL1_Sapi_t sapi; - GsmL1_Dir_t dir; -}; - -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 -}; - - -/* connect PDTCH */ -int l1if_connect_pdch(void *obj, uint8_t ts) -{ - struct femtol1_hdl *fl1h = obj; - struct msgb *msg = l1p_msgb_alloc(); - GsmL1_MphConnectReq_t *cr; - - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h); - cr->u8Tn = ts; - cr->logChComb = GsmL1_LogChComb_XIII; - - return l1if_req_pdch(fl1h, msg); -} - -static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1h, - GsmL1_PhReadyToSendInd_t *rts_ind) -{ - struct gsm_time g_time; - int rc = 0; - - gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); - - DEBUGP(DL1IF, "Rx PH-RTS.ind %02u/%02u/%02u SAPI=%s\n", - g_time.t1, g_time.t2, g_time.t3, - get_value_string(femtobts_l1sapi_names, rts_ind->sapi)); - - switch (rts_ind->sapi) { - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - rc = pcu_rx_rts_req_pdtch((long)fl1h->priv, rts_ind->u8Tn, - rts_ind->u16Arfcn, rts_ind->u32Fn, rts_ind->u8BlockNbr); - case GsmL1_Sapi_Ptcch: - // FIXME - default: - break; - } - - return rc; -} - -static void get_meas(struct pcu_l1_meas *meas, const GsmL1_MeasParam_t *l1_meas) -{ - meas->rssi = (int8_t) (l1_meas->fRssi); - meas->have_rssi = 1; - meas->ber = (uint8_t) (l1_meas->fBer * 100); - meas->have_ber = 1; - meas->bto = (int16_t) (l1_meas->i16BurstTiming); - meas->have_bto = 1; - meas->link_qual = (int16_t) (l1_meas->fLinkQuality); - meas->have_link_qual = 1; -} - -static int handle_ph_data_ind(struct femtol1_hdl *fl1h, - GsmL1_PhDataInd_t *data_ind, struct msgb *l1p_msg) -{ - int rc = 0; - struct pcu_l1_meas meas = {0}; - - DEBUGP(DL1IF, "Rx PH-DATA.ind %s (hL2 %08x): %s\n", - get_value_string(femtobts_l1sapi_names, data_ind->sapi), - data_ind->hLayer2, - osmo_hexdump(data_ind->msgUnitParam.u8Buffer, - data_ind->msgUnitParam.u8Size)); - - pcu_rx_block_time(data_ind->u16Arfcn, data_ind->u32Fn, data_ind->u8Tn); - - /* - * TODO: Add proper bad frame handling here. This could be used - * to switch the used CS. Avoid a crash with the PCU right now - * feed "0 - 1" amount of data. - */ - if (data_ind->msgUnitParam.u8Size == 0) - return -1; - - gsmtap_send(fl1h->gsmtap, data_ind->u16Arfcn | GSMTAP_ARFCN_F_UPLINK, - data_ind->u8Tn, GSMTAP_CHANNEL_PACCH, 0, - data_ind->u32Fn, 0, 0, data_ind->msgUnitParam.u8Buffer+1, - data_ind->msgUnitParam.u8Size-1); - - get_meas(&meas, &data_ind->measParam); - - switch (data_ind->sapi) { - case GsmL1_Sapi_Pdtch: - case GsmL1_Sapi_Pacch: - /* drop incomplete UL block */ - if (data_ind->msgUnitParam.u8Buffer[0] - != GsmL1_PdtchPlType_Full) - break; - /* PDTCH / PACCH frame handling */ - pcu_rx_data_ind_pdtch((long)fl1h->priv, data_ind->u8Tn, - data_ind->msgUnitParam.u8Buffer + 1, - data_ind->msgUnitParam.u8Size - 1, - data_ind->u32Fn, - &meas); - break; - case GsmL1_Sapi_Ptcch: - // FIXME - break; - default: - LOGP(DL1IF, LOGL_NOTICE, "Rx PH-DATA.ind for unknown L1 SAPI %s\n", - get_value_string(femtobts_l1sapi_names, data_ind->sapi)); - break; - } - - return rc; -} - -#define MIN_QUAL_RACH 5.0f - -static int handle_ph_ra_ind(struct femtol1_hdl *fl1h, GsmL1_PhRaInd_t *ra_ind) -{ - uint8_t acc_delay; - - pcu_rx_ra_time(ra_ind->u16Arfcn, ra_ind->u32Fn, ra_ind->u8Tn); - - if (ra_ind->measParam.fLinkQuality < MIN_QUAL_RACH) - return 0; - - DEBUGP(DL1IF, "Rx PH-RA.ind"); - - /* check for under/overflow / sign */ - if (ra_ind->measParam.i16BurstTiming < 0) - acc_delay = 0; - else - acc_delay = ra_ind->measParam.i16BurstTiming >> 2; - - LOGP(DL1IF, LOGL_NOTICE, "got (P)RACH request, TA = %u (ignored)\n", - acc_delay); - -#warning "The (P)RACH request is just dropped here" - -#if 0 - if (acc_delay > bts->max_ta) { - LOGP(DL1C, LOGL_INFO, "ignoring RACH request %u > max_ta(%u)\n", - acc_delay, btsb->max_ta); - return 0; - } -#endif - - return 0; -} - - -/* handle any random indication from the L1 */ -int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg) -{ - GsmL1_Prim_t *l1p = msgb_l1prim(msg); - int rc = 0; - - LOGP(DL1IF, LOGL_DEBUG, "Rx L1 prim %s on queue %d\n", - get_value_string(femtobts_l1prim_names, l1p->id), wq); - - switch (l1p->id) { -#if 0 - case GsmL1_PrimId_MphTimeInd: - rc = handle_mph_time_ind(fl1h, &l1p->u.mphTimeInd); - break; - case GsmL1_PrimId_MphSyncInd: - break; - case GsmL1_PrimId_PhConnectInd: - break; -#endif - case GsmL1_PrimId_PhReadyToSendInd: - rc = handle_ph_readytosend_ind(fl1h, &l1p->u.phReadyToSendInd); - break; - case GsmL1_PrimId_PhDataInd: - rc = handle_ph_data_ind(fl1h, &l1p->u.phDataInd, msg); - break; - case GsmL1_PrimId_PhRaInd: - rc = handle_ph_ra_ind(fl1h, &l1p->u.phRaInd); - break; - default: - break; - } - - msgb_free(msg); - - return rc; -} - -int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg) -{ - return -ENOTSUP; -} - -/* send packet data request to L1 */ -int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn, - uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len) -{ - struct femtol1_hdl *fl1h = obj; - struct msgb *msg; - GsmL1_Prim_t *l1p; - GsmL1_PhDataReq_t *data_req; - GsmL1_MsgUnitParam_t *msu_param; - struct gsm_time g_time; - - gsm_fn2gsmtime(&g_time, fn); - - DEBUGP(DL1IF, "TX packet data %02u/%02u/%02u is_ptcch=%d ts=%d " - "block_nr=%d, arfcn=%d, len=%d\n", g_time.t1, g_time.t2, - g_time.t3, is_ptcch, ts, block_nr, arfcn, len); - - msg = l1p_msgb_alloc(); - l1p = msgb_l1prim(msg); - l1p->id = GsmL1_PrimId_PhDataReq; - data_req = &l1p->u.phDataReq; - data_req->hLayer1 = fl1h->hLayer1; - data_req->sapi = (is_ptcch) ? GsmL1_Sapi_Ptcch : GsmL1_Sapi_Pdtch; - data_req->subCh = GsmL1_SubCh_NA; - data_req->u8BlockNbr = block_nr; - data_req->u8Tn = ts; - data_req->u32Fn = fn; - msu_param = &data_req->msgUnitParam; - msu_param->u8Size = len; - memcpy(msu_param->u8Buffer, data, len); - - gsmtap_send(fl1h->gsmtap, arfcn, data_req->u8Tn, GSMTAP_CHANNEL_PACCH, - 0, data_req->u32Fn, 0, 0, - data_req->msgUnitParam.u8Buffer, - data_req->msgUnitParam.u8Size); - - - /* transmit */ - if (osmo_wqueue_enqueue(&fl1h->write_q[MQ_PDTCH_WRITE], msg) != 0) { - LOGP(DL1IF, LOGL_ERROR, "PDTCH queue full. dropping message.\n"); - msgb_free(msg); - } - - return 0; -} - -void *l1if_open_pdch(void *priv, uint32_t hlayer1) -{ - struct femtol1_hdl *fl1h; - int rc; - - fl1h = talloc_zero(tall_pcu_ctx, struct femtol1_hdl); - if (!fl1h) - return NULL; - - fl1h->hLayer1 = hlayer1; - fl1h->priv = priv; - fl1h->clk_cal = 0; - /* default clock source: OCXO */ - fl1h->clk_src = SuperFemto_ClkSrcId_Ocxo; - - rc = l1if_transport_open(MQ_PDTCH_WRITE, fl1h); - if (rc < 0) { - talloc_free(fl1h); - return NULL; - } - - fl1h->gsmtap = gsmtap_source_init("localhost", GSMTAP_UDP_PORT, 1); - if (fl1h->gsmtap) - gsmtap_source_add_sink(fl1h->gsmtap); - - return fl1h; -} - -int l1if_close_pdch(void *obj) -{ - struct femtol1_hdl *fl1h = obj; - if (fl1h) - l1if_transport_close(MQ_PDTCH_WRITE, fl1h); - talloc_free(fl1h); - return 0; -} - diff --git a/src/sysmo_l1_if.h b/src/sysmo_l1_if.h deleted file mode 100644 index 6b50d4e..0000000 --- a/src/sysmo_l1_if.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef _SYSMO_L1_IF_H -#define _SYSMO_L1_IF_H - -#include <osmocom/core/select.h> -#include <osmocom/core/write_queue.h> -#include <osmocom/core/gsmtap_util.h> -#include <osmocom/gsm/gsm_utils.h> -#include "femtobts.h" - -enum { - MQ_SYS_READ, - MQ_L1_READ, -#ifndef HW_SYSMOBTS_V1 - MQ_TCH_READ, - MQ_PDTCH_READ, -#endif - _NUM_MQ_READ -}; - -enum { - MQ_SYS_WRITE, - MQ_L1_WRITE, -#ifndef HW_SYSMOBTS_V1 - MQ_TCH_WRITE, - MQ_PDTCH_WRITE, -#endif - _NUM_MQ_WRITE -}; - -struct femtol1_hdl { - struct gsm_time gsm_time; - uint32_t hLayer1; /* handle to the L1 instance in the DSP */ - uint32_t dsp_trace_f; - int clk_cal; - uint8_t clk_src; - struct llist_head wlc_list; - - struct gsmtap_inst *gsmtap; - uint32_t gsmtap_sapi_mask; - - void *priv; /* user reference */ - - 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 { - uint8_t dsp_version[3]; - uint8_t fpga_version[3]; - uint32_t band_support; /* bitmask of GSM_BAND_* */ - } hw_info; -}; - -#define msgb_l1prim(msg) ((GsmL1_Prim_t *)(msg)->l1h) -#define msgb_sysprim(msg) ((SuperFemto_Prim_t *)(msg)->l1h) - -typedef int l1if_compl_cb(struct msgb *l1_msg, void *data); - -/* send a request primitive to the L1 and schedule completion call-back */ -int l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, - int is_system_prim, l1if_compl_cb *cb, void *data); - -int l1if_reset(struct femtol1_hdl *hdl); -int l1if_activate_rf(struct femtol1_hdl *hdl, int on); -int l1if_set_trace_flags(struct femtol1_hdl *hdl, uint32_t flags); -int l1if_set_txpower(struct femtol1_hdl *fl1h, float tx_power); - -struct msgb *l1p_msgb_alloc(void); -struct msgb *sysp_msgb_alloc(void); - -uint32_t l1if_lchan_to_hLayer2(struct gsm_lchan *lchan); -struct gsm_lchan *l1if_hLayer2_to_lchan(struct gsm_bts_trx *trx, uint32_t hLayer2); - -int l1if_handle_sysprim(struct femtol1_hdl *fl1h, struct msgb *msg); -int l1if_handle_l1prim(int wq, struct femtol1_hdl *fl1h, struct msgb *msg); - -/* tch.c */ -int l1if_tch_rx(struct gsm_lchan *lchan, 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); - -/* - * The implementation of these functions is selected by either compiling and - * linking sysmo_l1_hw.c or sysmo_l1_fwd.c - */ -int l1if_transport_open(int q, struct femtol1_hdl *hdl); -int l1if_transport_close(int q, struct femtol1_hdl *hdl); - -#endif /* _SYSMO_L1_IF_H */
On 26 Jan 2016, at 16:22, suraev@alumni.ntnu.no wrote:
From: Max msuraev@sysmocom.de
Move hardware-spicefic files into subdirectory similar to the way it's done in OsmoBTS to make adding more hardware support easier. Make DSP access option name generic.
typo in specific, please send with -M to detect renames. Do not mix changes. We have nothing to hide here so please do not mix a huge rename with a change of the defines.
thanks holger