Added GSM network support.
This turns LCR into a GSM mobile switching center. More infos will follow.
This commit is contained in:
parent
64143650bc
commit
20a671d768
22
Makefile.am
22
Makefile.am
|
@ -43,8 +43,18 @@ INSTALLATION_DEFINES = \
|
|||
-DLOG_DIR="\"$(LOGdir)\"" \
|
||||
-DEXTENSION_DATA="\"$(EXTENSIONdir)\""
|
||||
|
||||
INCLUDES = $(all_includes) -I/usr/include/mISDNuser $(INSTALLATION_DEFINES)
|
||||
if ENABLE_GSM
|
||||
|
||||
GSM_INCLUDE = -DWITH_GSM
|
||||
|
||||
GSM_SOURCE = gsm_audio.c gsm.cpp gsm_conf.c bootstrap.c
|
||||
|
||||
GSM_LIB = /usr/local/lib/libgsm.a /usr/local/lib/libbsc.a /usr/local/lib/libvty.a -ldbi -lcrypt
|
||||
|
||||
#gsm_audio.po: gsm_audio.c gsm_audio.h
|
||||
# $(CC) -D_GNU_SOURCE -fPIC -c gsm_audio.c -o gsm_audio.po
|
||||
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = lcradmin gentones genwave
|
||||
|
||||
|
@ -74,7 +84,9 @@ install-exec-hook:
|
|||
$(INSTALL) chan_lcr.so $(astmoddir)
|
||||
endif
|
||||
|
||||
lcr_SOURCES = action.cpp mISDN.cpp tones.c \
|
||||
INCLUDES = $(all_includes) $(GSM_INCLUDE) -Wall -I/usr/include/mISDNuser $(INSTALLATION_DEFINES)
|
||||
|
||||
lcr_SOURCES = $(GSM_SOURCE) action.cpp mISDN.cpp tones.c \
|
||||
action_efi.cpp crypt.cpp mail.c trace.c \
|
||||
action_vbox.cpp dss1.cpp main.c \
|
||||
vbox.cpp alawulaw.c endpoint.cpp interface.c message.c \
|
||||
|
@ -83,7 +95,8 @@ lcr_SOURCES = action.cpp mISDN.cpp tones.c \
|
|||
callerid.c joinremote.cpp route.c \
|
||||
cause.c socket_server.c
|
||||
|
||||
lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread
|
||||
lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread $(GSM_LIB)
|
||||
|
||||
|
||||
lcradmin_SOURCES = lcradmin.c cause.c options.c
|
||||
genextension_SOURCES = genext.c options.c extension.c
|
||||
|
@ -111,6 +124,9 @@ install-data-hook:
|
|||
@if test -a $(CONFIGdir)/routing.conf ; then \
|
||||
echo "NOTE: routing.conf already exists, not changed." ; else \
|
||||
cp -v default/routing.conf $(CONFIGdir) ; fi
|
||||
@if test -a $(CONFIGdir)/gsm.conf ; then \
|
||||
echo "NOTE: gsm.conf already exists, not changed." ; else \
|
||||
cp -v default/gsm.conf $(CONFIGdir) ; fi
|
||||
@if test -a $(CONFIGdir)/numbering_int.conf ; then \
|
||||
echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi
|
||||
@if test -a $(CONFIGdir)/numbering_ext.conf ; then \
|
||||
|
|
53
Makefile.in
53
Makefile.in
|
@ -75,18 +75,30 @@ gentones_LDADD = $(LDADD)
|
|||
genwave_SOURCES = genwave.c
|
||||
genwave_OBJECTS = genwave.$(OBJEXT)
|
||||
genwave_LDADD = $(LDADD)
|
||||
am_lcr_OBJECTS = action.$(OBJEXT) mISDN.$(OBJEXT) tones.$(OBJEXT) \
|
||||
action_efi.$(OBJEXT) crypt.$(OBJEXT) mail.$(OBJEXT) \
|
||||
trace.$(OBJEXT) action_vbox.$(OBJEXT) dss1.$(OBJEXT) \
|
||||
main.$(OBJEXT) vbox.$(OBJEXT) alawulaw.$(OBJEXT) \
|
||||
endpoint.$(OBJEXT) interface.$(OBJEXT) message.$(OBJEXT) \
|
||||
apppbx.$(OBJEXT) endpointapp.$(OBJEXT) join.$(OBJEXT) \
|
||||
options.$(OBJEXT) extension.$(OBJEXT) joinpbx.$(OBJEXT) \
|
||||
port.$(OBJEXT) callerid.$(OBJEXT) joinremote.$(OBJEXT) \
|
||||
route.$(OBJEXT) cause.$(OBJEXT) socket_server.$(OBJEXT)
|
||||
am__lcr_SOURCES_DIST = gsm_audio.c gsm.cpp gsm_conf.c bootstrap.c \
|
||||
action.cpp mISDN.cpp tones.c action_efi.cpp crypt.cpp mail.c \
|
||||
trace.c action_vbox.cpp dss1.cpp main.c vbox.cpp alawulaw.c \
|
||||
endpoint.cpp interface.c message.c apppbx.cpp endpointapp.cpp \
|
||||
join.cpp options.c extension.c joinpbx.cpp port.cpp callerid.c \
|
||||
joinremote.cpp route.c cause.c socket_server.c
|
||||
@ENABLE_GSM_TRUE@am__objects_1 = gsm_audio.$(OBJEXT) gsm.$(OBJEXT) \
|
||||
@ENABLE_GSM_TRUE@ gsm_conf.$(OBJEXT) bootstrap.$(OBJEXT)
|
||||
am_lcr_OBJECTS = $(am__objects_1) action.$(OBJEXT) mISDN.$(OBJEXT) \
|
||||
tones.$(OBJEXT) action_efi.$(OBJEXT) crypt.$(OBJEXT) \
|
||||
mail.$(OBJEXT) trace.$(OBJEXT) action_vbox.$(OBJEXT) \
|
||||
dss1.$(OBJEXT) main.$(OBJEXT) vbox.$(OBJEXT) \
|
||||
alawulaw.$(OBJEXT) endpoint.$(OBJEXT) interface.$(OBJEXT) \
|
||||
message.$(OBJEXT) apppbx.$(OBJEXT) endpointapp.$(OBJEXT) \
|
||||
join.$(OBJEXT) options.$(OBJEXT) extension.$(OBJEXT) \
|
||||
joinpbx.$(OBJEXT) port.$(OBJEXT) callerid.$(OBJEXT) \
|
||||
joinremote.$(OBJEXT) route.$(OBJEXT) cause.$(OBJEXT) \
|
||||
socket_server.$(OBJEXT)
|
||||
lcr_OBJECTS = $(am_lcr_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
lcr_DEPENDENCIES = $(am__DEPENDENCIES_1)
|
||||
@ENABLE_GSM_TRUE@am__DEPENDENCIES_2 = /usr/local/lib/libgsm.a \
|
||||
@ENABLE_GSM_TRUE@ /usr/local/lib/libbsc.a \
|
||||
@ENABLE_GSM_TRUE@ /usr/local/lib/libvty.a
|
||||
lcr_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
|
||||
am_lcradmin_OBJECTS = lcradmin.$(OBJEXT) cause.$(OBJEXT) \
|
||||
options.$(OBJEXT)
|
||||
lcradmin_OBJECTS = $(am_lcradmin_OBJECTS)
|
||||
|
@ -103,7 +115,8 @@ CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
|||
SOURCES = $(chan_lcr_so_SOURCES) $(genextension_SOURCES) genrc.c \
|
||||
gentones.c genwave.c $(lcr_SOURCES) $(lcradmin_SOURCES)
|
||||
DIST_SOURCES = $(chan_lcr_so_SOURCES) $(genextension_SOURCES) genrc.c \
|
||||
gentones.c genwave.c $(lcr_SOURCES) $(lcradmin_SOURCES)
|
||||
gentones.c genwave.c $(am__lcr_SOURCES_DIST) \
|
||||
$(lcradmin_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
@ -142,6 +155,8 @@ ECHO_T = @ECHO_T@
|
|||
EGREP = @EGREP@
|
||||
ENABLE_ASTERISK_CHANNEL_DRIVER_FALSE = @ENABLE_ASTERISK_CHANNEL_DRIVER_FALSE@
|
||||
ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE = @ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@
|
||||
ENABLE_GSM_FALSE = @ENABLE_GSM_FALSE@
|
||||
ENABLE_GSM_TRUE = @ENABLE_GSM_TRUE@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
@ -224,11 +239,14 @@ INSTALLATION_DEFINES = \
|
|||
-DLOG_DIR="\"$(LOGdir)\"" \
|
||||
-DEXTENSION_DATA="\"$(EXTENSIONdir)\""
|
||||
|
||||
INCLUDES = $(all_includes) -I/usr/include/mISDNuser $(INSTALLATION_DEFINES)
|
||||
@ENABLE_GSM_TRUE@GSM_INCLUDE = -DWITH_GSM
|
||||
@ENABLE_GSM_TRUE@GSM_SOURCE = gsm_audio.c gsm.cpp gsm_conf.c bootstrap.c
|
||||
@ENABLE_GSM_TRUE@GSM_LIB = /usr/local/lib/libgsm.a /usr/local/lib/libbsc.a /usr/local/lib/libvty.a -ldbi -lcrypt
|
||||
@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@chan_lcr_so_SOURCES =
|
||||
@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@chan_lcr_so_LDFLAGS = -shared
|
||||
@ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE@chan_lcr_so_LDADD = chan_lcr.po bchannel.po options.po callerid.po
|
||||
lcr_SOURCES = action.cpp mISDN.cpp tones.c \
|
||||
INCLUDES = $(all_includes) $(GSM_INCLUDE) -Wall -I/usr/include/mISDNuser $(INSTALLATION_DEFINES)
|
||||
lcr_SOURCES = $(GSM_SOURCE) action.cpp mISDN.cpp tones.c \
|
||||
action_efi.cpp crypt.cpp mail.c trace.c \
|
||||
action_vbox.cpp dss1.cpp main.c \
|
||||
vbox.cpp alawulaw.c endpoint.cpp interface.c message.c \
|
||||
|
@ -237,7 +255,7 @@ lcr_SOURCES = action.cpp mISDN.cpp tones.c \
|
|||
callerid.c joinremote.cpp route.c \
|
||||
cause.c socket_server.c
|
||||
|
||||
lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread
|
||||
lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread $(GSM_LIB)
|
||||
lcradmin_SOURCES = lcradmin.c cause.c options.c
|
||||
genextension_SOURCES = genext.c options.c extension.c
|
||||
|
||||
|
@ -387,6 +405,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/action_vbox.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alawulaw.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apppbx.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bootstrap.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callerid.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cause.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypt.Po@am__quote@
|
||||
|
@ -398,6 +417,9 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genrc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gentones.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genwave.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_audio.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_conf.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/join.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joinpbx.Po@am__quote@
|
||||
|
@ -764,6 +786,9 @@ install-data-hook:
|
|||
@if test -a $(CONFIGdir)/routing.conf ; then \
|
||||
echo "NOTE: routing.conf already exists, not changed." ; else \
|
||||
cp -v default/routing.conf $(CONFIGdir) ; fi
|
||||
@if test -a $(CONFIGdir)/gsm.conf ; then \
|
||||
echo "NOTE: gsm.conf already exists, not changed." ; else \
|
||||
cp -v default/gsm.conf $(CONFIGdir) ; fi
|
||||
@if test -a $(CONFIGdir)/numbering_int.conf ; then \
|
||||
echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi
|
||||
@if test -a $(CONFIGdir)/numbering_ext.conf ; then \
|
||||
|
|
5
README
5
README
|
@ -487,3 +487,8 @@ Changes after Version 1.4 release
|
|||
-> Improved forking
|
||||
-> Execution action can now be done on call init or on call hangup.
|
||||
|
||||
New release Version 1.5
|
||||
- Added GSM network support.
|
||||
-> Requires OpenBSC, GSM codec, and a BS11 base station.
|
||||
-> For more refer to www.linux-call-router.de.
|
||||
|
||||
|
|
34
apppbx.cpp
34
apppbx.cpp
|
@ -827,7 +827,6 @@ void EndpointAppPBX::out_setup(void)
|
|||
{
|
||||
struct dialing_info dialinginfo;
|
||||
class Port *port;
|
||||
// class pdss1 *pdss1;
|
||||
struct port_list *portlist;
|
||||
struct lcr_msg *message;
|
||||
int anycall = 0;
|
||||
|
@ -987,9 +986,16 @@ void EndpointAppPBX::out_setup(void)
|
|||
}
|
||||
/* creating INTERNAL port */
|
||||
SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
|
||||
port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
|
||||
if (!mISDNport->gsm)
|
||||
port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
|
||||
else
|
||||
#ifdef WITH_GSM
|
||||
port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
|
||||
#else
|
||||
port = NULL;
|
||||
#endif
|
||||
if (!port)
|
||||
FATAL("No memory for DSS1 Port instance\n");
|
||||
FATAL("No memory for Port instance\n");
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
|
||||
memset(&dialinginfo, 0, sizeof(dialinginfo));
|
||||
SCPY(dialinginfo.id, e_dialinginfo.id);
|
||||
|
@ -1104,8 +1110,9 @@ void EndpointAppPBX::out_setup(void)
|
|||
{
|
||||
/* creating EXTERNAL port*/
|
||||
SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
|
||||
if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode)))
|
||||
FATAL("No memory for DSS1 Port instance\n");
|
||||
port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
|
||||
if (!port)
|
||||
FATAL("No memory for Port instance\n");
|
||||
earlyb = mISDNport->earlyb;
|
||||
} else
|
||||
{
|
||||
|
@ -1200,8 +1207,16 @@ void EndpointAppPBX::out_setup(void)
|
|||
}
|
||||
/* creating EXTERNAL port*/
|
||||
SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
|
||||
if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode)))
|
||||
FATAL("No memory for DSS1 Port instance\n");
|
||||
if (!mISDNport->gsm)
|
||||
port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
|
||||
else
|
||||
#ifdef WITH_GSM
|
||||
port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
|
||||
#else
|
||||
port = NULL;
|
||||
#endif
|
||||
if (!port)
|
||||
FATAL("No memory for Port instance\n");
|
||||
earlyb = mISDNport->earlyb;
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
|
||||
memset(&dialinginfo, 0, sizeof(dialinginfo));
|
||||
|
@ -1215,7 +1230,6 @@ void EndpointAppPBX::out_setup(void)
|
|||
delete port;
|
||||
goto check_anycall_extern;
|
||||
}
|
||||
// dss1 = (class Pdss1 *)port;
|
||||
//printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
|
||||
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
|
||||
memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
|
||||
|
@ -2103,7 +2117,7 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
|
|||
if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
|
||||
{
|
||||
e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
|
||||
if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
|
||||
if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT || portlist->port_type==PORT_TYPE_GSM_OUT) /* external extension answered */
|
||||
{
|
||||
port = find_port_id(portlist->port_id);
|
||||
if (port)
|
||||
|
@ -3626,7 +3640,7 @@ void EndpointAppPBX::pick_join(char *extensions)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
|
||||
if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT || port->p_type==PORT_TYPE_GSM_OUT)
|
||||
&& port->p_state==PORT_STATE_OUT_ALERTING)
|
||||
if (match_list(extensions, eapp->e_ext.number))
|
||||
{
|
||||
|
|
|
@ -0,0 +1,948 @@
|
|||
/* Bootstrapping GSM - taken from bsc_hack.c */
|
||||
|
||||
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <getopt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <openbsc/openbsc.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/gsm_04_08.h>
|
||||
#include <openbsc/db.h>
|
||||
#include <openbsc/timer.h>
|
||||
#include <openbsc/select.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/misdn.h>
|
||||
#include <openbsc/telnet_interface.h>
|
||||
#include <openbsc/paging.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
|
||||
/* The following definitions are for OM and NM packets that we cannot yet
|
||||
* generate by code but we just pass on */
|
||||
|
||||
// BTS Site Manager, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: BTS Site Manager
|
||||
Instance 1: FF
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
sAbisExternalTime: 2007/09/08 14:36:11
|
||||
omLAPDRelTimer: 30sec
|
||||
shortLAPDIntTimer: 5sec
|
||||
emergencyTimer1: 10 minutes
|
||||
emergencyTimer2: 0 minutes
|
||||
*/
|
||||
|
||||
unsigned char msg_1[] =
|
||||
{
|
||||
0xD0, 0x00, 0xFF, 0xFF, 0xFF,
|
||||
NM_ATT_BS11_ABIS_EXT_TIME, 0x07, 0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE,
|
||||
0x02, 0x00, 0x1E,
|
||||
0xE8, 0x01, 0x05,
|
||||
0x42, 0x02, 0x00, 0x0A,
|
||||
0x44, 0x02, 0x00, 0x00
|
||||
};
|
||||
|
||||
// BTS, SET BTS ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: BTS
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET BTS ATTRIBUTES
|
||||
bsIdentityCode / BSIC:
|
||||
PLMN_colour_code: 7h
|
||||
BS_colour_code: 7h
|
||||
BTS Air Timer T3105: 4 ,unit 10 ms
|
||||
btsIsHopping: FALSE
|
||||
periodCCCHLoadIndication: 1sec
|
||||
thresholdCCCHLoadIndication: 0%
|
||||
cellAllocationNumber: 00h = GSM 900
|
||||
enableInterferenceClass: 00h = Disabled
|
||||
fACCHQual: 6 (FACCH stealing flags minus 1)
|
||||
intaveParameter: 31 SACCH multiframes
|
||||
interferenceLevelBoundaries:
|
||||
Interference Boundary 1: 0Ah
|
||||
Interference Boundary 2: 0Fh
|
||||
Interference Boundary 3: 14h
|
||||
Interference Boundary 4: 19h
|
||||
Interference Boundary 5: 1Eh
|
||||
mSTxPwrMax: 11
|
||||
GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
|
||||
DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
|
||||
PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
|
||||
30=33dBm, 31=32dBm
|
||||
ny1:
|
||||
Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
|
||||
powerOutputThresholds:
|
||||
Out Power Fault Threshold: -10 dB
|
||||
Red Out Power Threshold: - 6 dB
|
||||
Excessive Out Power Threshold: 5 dB
|
||||
rACHBusyThreshold: -127 dBm
|
||||
rACHLoadAveragingSlots: 250 ,number of RACH burst periods
|
||||
rfResourceIndicationPeriod: 125 SACCH multiframes
|
||||
T200:
|
||||
SDCCH: 044 in 5 ms
|
||||
FACCH/Full rate: 031 in 5 ms
|
||||
FACCH/Half rate: 041 in 5 ms
|
||||
SACCH with TCH SAPI0: 090 in 10 ms
|
||||
SACCH with SDCCH: 090 in 10 ms
|
||||
SDCCH with SAPI3: 090 in 5 ms
|
||||
SACCH with TCH SAPI3: 135 in 10 ms
|
||||
tSync: 9000 units of 10 msec
|
||||
tTrau: 9000 units of 10 msec
|
||||
enableUmLoopTest: 00h = disabled
|
||||
enableExcessiveDistance: 00h = Disabled
|
||||
excessiveDistance: 64km
|
||||
hoppingMode: 00h = baseband hopping
|
||||
cellType: 00h = Standard Cell
|
||||
BCCH ARFCN / bCCHFrequency: 1
|
||||
*/
|
||||
|
||||
unsigned char msg_2[] =
|
||||
{
|
||||
0x41, 0x01, 0x00, 0xFF, 0xFF,
|
||||
NM_ATT_BSIC, 0x3F,
|
||||
NM_ATT_BTS_AIR_TIMER, 0x04,
|
||||
NM_ATT_BS11_BTSLS_HOPPING, 0x00,
|
||||
NM_ATT_CCCH_L_I_P, 0x01,
|
||||
NM_ATT_CCCH_L_T, 0x00,
|
||||
NM_ATT_BS11_CELL_ALLOC_NR, 0x00,
|
||||
NM_ATT_BS11_ENA_INTERF_CLASS, 0x00,
|
||||
NM_ATT_BS11_FACCH_QUAL, 0x06,
|
||||
NM_ATT_INTAVE_PARAM, 0x1F,
|
||||
NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B,
|
||||
NM_ATT_CCCH_L_T, 0x23,
|
||||
NM_ATT_GSM_TIME, 0x28, 0x00,
|
||||
NM_ATT_ADM_STATE, 0x03,
|
||||
NM_ATT_RACH_B_THRESH, 0x7F,
|
||||
NM_ATT_LDAVG_SLOTS, 0x00, 0xFA,
|
||||
NM_ATT_BS11_RF_RES_IND_PER, 0x7D,
|
||||
NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87,
|
||||
NM_ATT_BS11_TSYNC, 0x23, 0x28,
|
||||
NM_ATT_BS11_TTRAU, 0x23, 0x28,
|
||||
NM_ATT_TEST_DUR, 0x01, 0x00,
|
||||
NM_ATT_OUTST_ALARM, 0x01, 0x00,
|
||||
NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40,
|
||||
NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00,
|
||||
NM_ATT_BS11_PLL, 0x01, 0x00,
|
||||
NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/,
|
||||
};
|
||||
|
||||
// Handover Recognition, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Illegal Contents GSM Formatted O&M Msg
|
||||
Object Class: Handover Recognition
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
enableDelayPowerBudgetHO: 00h = Disabled
|
||||
enableDistanceHO: 00h = Disabled
|
||||
enableInternalInterCellHandover: 00h = Disabled
|
||||
enableInternalIntraCellHandover: 00h = Disabled
|
||||
enablePowerBudgetHO: 00h = Disabled
|
||||
enableRXLEVHO: 00h = Disabled
|
||||
enableRXQUALHO: 00h = Disabled
|
||||
hoAveragingDistance: 8 SACCH multiframes
|
||||
hoAveragingLev:
|
||||
A_LEV_HO: 8 SACCH multiframes
|
||||
W_LEV_HO: 1 SACCH multiframes
|
||||
hoAveragingPowerBudget: 16 SACCH multiframes
|
||||
hoAveragingQual:
|
||||
A_QUAL_HO: 8 SACCH multiframes
|
||||
W_QUAL_HO: 2 SACCH multiframes
|
||||
hoLowerThresholdLevDL: (10 - 110) dBm
|
||||
hoLowerThresholdLevUL: (5 - 110) dBm
|
||||
hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
|
||||
hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
|
||||
hoThresholdLevDLintra : (20 - 110) dBm
|
||||
hoThresholdLevULintra: (20 - 110) dBm
|
||||
hoThresholdMsRangeMax: 20 km
|
||||
nCell: 06h
|
||||
timerHORequest: 3 ,unit 2 SACCH multiframes
|
||||
*/
|
||||
|
||||
unsigned char msg_3[] =
|
||||
{
|
||||
0xD0, 0xA1, 0x00, 0xFF, 0xFF,
|
||||
0xD0, 0x00,
|
||||
0x64, 0x00,
|
||||
0x67, 0x00,
|
||||
0x68, 0x00,
|
||||
0x6A, 0x00,
|
||||
0x6C, 0x00,
|
||||
0x6D, 0x00,
|
||||
0x6F, 0x08,
|
||||
0x70, 0x08, 0x01,
|
||||
0x71, 0x10, 0x10, 0x10,
|
||||
0x72, 0x08, 0x02,
|
||||
0x73, 0x0A,
|
||||
0x74, 0x05,
|
||||
0x75, 0x06,
|
||||
0x76, 0x06,
|
||||
0x78, 0x14,
|
||||
0x79, 0x14,
|
||||
0x7A, 0x14,
|
||||
0x7D, 0x06,
|
||||
0x92, 0x03, 0x20, 0x01, 0x00,
|
||||
0x45, 0x01, 0x00,
|
||||
0x48, 0x01, 0x00,
|
||||
0x5A, 0x01, 0x00,
|
||||
0x5B, 0x01, 0x05,
|
||||
0x5E, 0x01, 0x1A,
|
||||
0x5F, 0x01, 0x20,
|
||||
0x9D, 0x01, 0x00,
|
||||
0x47, 0x01, 0x00,
|
||||
0x5C, 0x01, 0x64,
|
||||
0x5D, 0x01, 0x1E,
|
||||
0x97, 0x01, 0x20,
|
||||
0xF7, 0x01, 0x3C,
|
||||
};
|
||||
|
||||
// Power Control, SET ATTRIBUTES
|
||||
|
||||
/*
|
||||
Object Class: Power Control
|
||||
BTS relat. Number: 0
|
||||
Instance 2: FF
|
||||
Instance 3: FF
|
||||
SET ATTRIBUTES
|
||||
enableMsPowerControl: 00h = Disabled
|
||||
enablePowerControlRLFW: 00h = Disabled
|
||||
pcAveragingLev:
|
||||
A_LEV_PC: 4 SACCH multiframes
|
||||
W_LEV_PC: 1 SACCH multiframes
|
||||
pcAveragingQual:
|
||||
A_QUAL_PC: 4 SACCH multiframes
|
||||
W_QUAL_PC: 2 SACCH multiframes
|
||||
pcLowerThresholdLevDL: 0Fh
|
||||
pcLowerThresholdLevUL: 0Ah
|
||||
pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
|
||||
pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
|
||||
pcRLFThreshold: 0Ch
|
||||
pcUpperThresholdLevDL: 14h
|
||||
pcUpperThresholdLevUL: 0Fh
|
||||
pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
|
||||
pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
|
||||
powerConfirm: 2 ,unit 2 SACCH multiframes
|
||||
powerControlInterval: 2 ,unit 2 SACCH multiframes
|
||||
powerIncrStepSize: 02h = 4 dB
|
||||
powerRedStepSize: 01h = 2 dB
|
||||
radioLinkTimeoutBs: 64 SACCH multiframes
|
||||
enableBSPowerControl: 00h = disabled
|
||||
*/
|
||||
|
||||
unsigned char msg_4[] =
|
||||
{
|
||||
0xD0, 0xA2, 0x00, 0xFF, 0xFF,
|
||||
NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
|
||||
NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
|
||||
0x7E, 0x04, 0x01,
|
||||
0x7F, 0x04, 0x02,
|
||||
0x80, 0x0F,
|
||||
0x81, 0x0A,
|
||||
0x82, 0x05,
|
||||
0x83, 0x05,
|
||||
0x84, 0x0C,
|
||||
0x85, 0x14,
|
||||
0x86, 0x0F,
|
||||
0x87, 0x04,
|
||||
0x88, 0x04,
|
||||
0x89, 0x02,
|
||||
0x8A, 0x02,
|
||||
0x8B, 0x02,
|
||||
0x8C, 0x01,
|
||||
0x8D, 0x40,
|
||||
0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
|
||||
};
|
||||
|
||||
|
||||
// Transceiver, SET TRX ATTRIBUTES (TRX 0)
|
||||
|
||||
/*
|
||||
Object Class: Transceiver
|
||||
BTS relat. Number: 0
|
||||
Tranceiver number: 0
|
||||
Instance 3: FF
|
||||
SET TRX ATTRIBUTES
|
||||
aRFCNList (HEX): 0001
|
||||
txPwrMaxReduction: 00h = 30dB
|
||||
radioMeasGran: 254 SACCH multiframes
|
||||
radioMeasRep: 01h = enabled
|
||||
memberOfEmergencyConfig: 01h = TRUE
|
||||
trxArea: 00h = TRX doesn't belong to a concentric cell
|
||||
*/
|
||||
|
||||
unsigned char msg_6[] =
|
||||
{
|
||||
0x44, 0x02, 0x00, 0x00, 0xFF,
|
||||
NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/,
|
||||
NM_ATT_RF_MAXPOWR_R, 0x00,
|
||||
NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0xFE,
|
||||
NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01,
|
||||
NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01,
|
||||
NM_ATT_BS11_TRX_AREA, 0x01, 0x00,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_bts[] = {
|
||||
NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73,
|
||||
NM_ATT_INTAVE_PARAM, 0x06,
|
||||
NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10,
|
||||
NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8,
|
||||
NM_ATT_MAX_TA, 0x3f,
|
||||
NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */
|
||||
NM_ATT_CCCH_L_T, 10, /* percent */
|
||||
NM_ATT_CCCH_L_I_P, 1, /* seconds */
|
||||
NM_ATT_RACH_B_THRESH, 0x0a,
|
||||
NM_ATT_LDAVG_SLOTS, 0x03, 0xe8,
|
||||
NM_ATT_BTS_AIR_TIMER, 0x80,
|
||||
NM_ATT_NY1, 0x0a,
|
||||
NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
|
||||
NM_ATT_BSIC, 0x20,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_radio[] = {
|
||||
NM_ATT_RF_MAXPOWR_R, 0x0c,
|
||||
NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
|
||||
};
|
||||
|
||||
static unsigned char nanobts_attr_e0[] = {
|
||||
0x85, 0x00,
|
||||
0x81, 0x0b, 0xbb, /* TCP PORT for RSL */
|
||||
};
|
||||
|
||||
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
|
||||
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
|
||||
/* This is currently only required on nanoBTS */
|
||||
|
||||
switch (evt) {
|
||||
case EVT_STATECHG_OPER:
|
||||
switch (obj_class) {
|
||||
case NM_OC_SITE_MANAGER:
|
||||
bts = container_of(obj, struct gsm_bts, site_mgr);
|
||||
if (old_state->operational != 2 && new_state->operational == 2) {
|
||||
abis_nm_opstart(bts, NM_OC_SITE_MANAGER, 0xff, 0xff, 0xff);
|
||||
}
|
||||
break;
|
||||
case NM_OC_BTS:
|
||||
bts = (struct gsm_bts *)obj;
|
||||
if (new_state->availability == 5) {
|
||||
abis_nm_set_bts_attr(bts, nanobts_attr_bts,
|
||||
sizeof(nanobts_attr_bts));
|
||||
abis_nm_opstart(bts, NM_OC_BTS,
|
||||
bts->nr, 0xff, 0xff);
|
||||
abis_nm_chg_adm_state(bts, NM_OC_BTS,
|
||||
bts->nr, 0xff, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
}
|
||||
break;
|
||||
case NM_OC_RADIO_CARRIER:
|
||||
trx = (struct gsm_bts_trx *)obj;
|
||||
if (new_state->availability == 3) {
|
||||
abis_nm_set_radio_attr(trx, nanobts_attr_radio,
|
||||
sizeof(nanobts_attr_radio));
|
||||
abis_nm_opstart(trx->bts, NM_OC_RADIO_CARRIER,
|
||||
trx->bts->nr, trx->nr, 0xff);
|
||||
abis_nm_chg_adm_state(trx->bts, NM_OC_RADIO_CARRIER,
|
||||
trx->bts->nr, trx->nr, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
}
|
||||
break;
|
||||
case NM_OC_CHANNEL:
|
||||
ts = (struct gsm_bts_trx_ts *)obj;
|
||||
trx = (struct gsm_bts_trx *)ts->trx;
|
||||
if (new_state->availability == 5) {
|
||||
if (ts->nr == 0 && trx == trx->bts->c0)
|
||||
abis_nm_set_channel_attr(ts, NM_CHANC_BCCH_CBCH);
|
||||
else
|
||||
abis_nm_set_channel_attr(ts, NM_CHANC_TCHFull);
|
||||
abis_nm_opstart(trx->bts, NM_OC_CHANNEL,
|
||||
trx->bts->nr, trx->nr, ts->nr);
|
||||
abis_nm_chg_adm_state(trx->bts, NM_OC_CHANNEL,
|
||||
trx->bts->nr, trx->nr, ts->nr,
|
||||
NM_STATE_UNLOCKED);
|
||||
}
|
||||
break;
|
||||
case NM_OC_BASEB_TRANSC:
|
||||
trx = container_of(obj, struct gsm_bts_trx, bb_transc);
|
||||
if (new_state->availability == 5) {
|
||||
abis_nm_ipaccess_msg(trx->bts, 0xe0, NM_OC_BASEB_TRANSC,
|
||||
trx->bts->nr, trx->nr, 0xff,
|
||||
nanobts_attr_e0, sizeof(nanobts_attr_e0));
|
||||
abis_nm_opstart(trx->bts, NM_OC_BASEB_TRANSC,
|
||||
trx->bts->nr, trx->nr, 0xff);
|
||||
abis_nm_chg_adm_state(trx->bts, NM_OC_BASEB_TRANSC,
|
||||
trx->bts->nr, trx->nr, 0xff,
|
||||
NM_STATE_UNLOCKED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVT_STATECHG_ADM:
|
||||
DEBUGP(DMM, "Unhandled state change in %s:%d\n", __func__, __LINE__);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bootstrap_om_nanobts(struct gsm_bts *bts)
|
||||
{
|
||||
/* We don't do callback based bootstrapping, but event driven (see above) */
|
||||
}
|
||||
|
||||
static void bootstrap_om_bs11(struct gsm_bts *bts)
|
||||
{
|
||||
struct gsm_bts_trx *trx = &bts->trx[0];
|
||||
|
||||
/* stop sending event reports */
|
||||
abis_nm_event_reports(bts, 0);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
|
||||
abis_nm_raw_msg(bts, sizeof(msg_2), msg_2); /* set BTS attr */
|
||||
abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
|
||||
abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
|
||||
|
||||
/* Connect signalling of bts0/trx0 to e1_0/ts1/64kbps */
|
||||
abis_nm_conn_terr_sign(trx, 0, 1, 0xff);
|
||||
set_ts_e1link(&trx->ts[0], 0, 1, 0xff);
|
||||
abis_nm_raw_msg(bts, sizeof(msg_6), msg_6); /* SET TRX ATTRIBUTES */
|
||||
|
||||
/* Use TEI 1 for signalling */
|
||||
abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x01);
|
||||
abis_nm_set_channel_attr(&trx->ts[0], NM_CHANC_SDCCH_CBCH);
|
||||
|
||||
#ifdef HAVE_TRX1
|
||||
/* TRX 1 */
|
||||
abis_nm_conn_terr_sign(&bts->trx[1], 0, 1, 0xff);
|
||||
/* FIXME: TRX ATTRIBUTE */
|
||||
abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x02);
|
||||
#endif
|
||||
|
||||
/* SET CHANNEL ATTRIBUTE TS1 */
|
||||
abis_nm_set_channel_attr(&trx->ts[1], NM_CHANC_TCHFull);
|
||||
/* Connect traffic of bts0/trx0/ts1 to e1_0/ts2/b */
|
||||
set_ts_e1link(&trx->ts[1], 0, 2, 1);
|
||||
abis_nm_conn_terr_traf(&trx->ts[1], 0, 2, 1);
|
||||
|
||||
/* SET CHANNEL ATTRIBUTE TS2 */
|
||||
abis_nm_set_channel_attr(&trx->ts[2], NM_CHANC_TCHFull);
|
||||
/* Connect traffic of bts0/trx0/ts2 to e1_0/ts2/c */
|
||||
set_ts_e1link(&trx->ts[2], 0, 2, 2);
|
||||
abis_nm_conn_terr_traf(&trx->ts[2], 0, 2, 2);
|
||||
|
||||
/* SET CHANNEL ATTRIBUTE TS3 */
|
||||
abis_nm_set_channel_attr(&trx->ts[3], NM_CHANC_TCHFull);
|
||||
/* Connect traffic of bts0/trx0/ts3 to e1_0/ts2/d */
|
||||
set_ts_e1link(&trx->ts[3], 0, 2, 3);
|
||||
abis_nm_conn_terr_traf(&trx->ts[3], 0, 2, 3);
|
||||
|
||||
/* SET CHANNEL ATTRIBUTE TS4 */
|
||||
abis_nm_set_channel_attr(&trx->ts[4], NM_CHANC_TCHFull);
|
||||
/* Connect traffic of bts0/trx0/ts4 to e1_0/ts3/a */
|
||||
set_ts_e1link(&trx->ts[4], 0, 3, 0);
|
||||
abis_nm_conn_terr_traf(&trx->ts[4], 0, 3, 0);
|
||||
|
||||
/* SET CHANNEL ATTRIBUTE TS5 */
|
||||
abis_nm_set_channel_attr(&trx->ts[5], NM_CHANC_TCHFull);
|
||||
/* Connect traffic of bts0/trx0/ts5 to e1_0/ts3/b */
|
||||
set_ts_e1link(&trx->ts[5], 0, 3, 1);
|
||||
abis_nm_conn_terr_traf(&trx->ts[5], 0, 3, 1);
|
||||
|
||||
/* SET CHANNEL ATTRIBUTE TS6 */
|
||||
abis_nm_set_channel_attr(&trx->ts[6], NM_CHANC_TCHFull);
|
||||
/* Connect traffic of bts0/trx0/ts6 to e1_0/ts3/c */
|
||||
set_ts_e1link(&trx->ts[6], 0, 3, 2);
|
||||
abis_nm_conn_terr_traf(&trx->ts[6], 0, 3, 2);
|
||||
|
||||
/* SET CHANNEL ATTRIBUTE TS7 */
|
||||
abis_nm_set_channel_attr(&trx->ts[7], NM_CHANC_TCHFull);
|
||||
/* Connect traffic of bts0/trx0/ts7 to e1_0/ts3/d */
|
||||
set_ts_e1link(&trx->ts[7], 0, 3, 3);
|
||||
abis_nm_conn_terr_traf(&trx->ts[7], 0, 3, 3);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
/* restart sending event reports */
|
||||
abis_nm_event_reports(bts, 1);
|
||||
}
|
||||
|
||||
static void bootstrap_om(struct gsm_bts *bts)
|
||||
{
|
||||
fprintf(stdout, "bootstrapping OML\n");
|
||||
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
bootstrap_om_bs11(bts);
|
||||
break;
|
||||
case GSM_BTS_TYPE_NANOBTS_900:
|
||||
case GSM_BTS_TYPE_NANOBTS_1800:
|
||||
bootstrap_om_nanobts(bts);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unable to bootstrap OML: Unknown BTS type %d\n", bts->type);
|
||||
}
|
||||
}
|
||||
|
||||
static int shutdown_om(struct gsm_bts *bts)
|
||||
{
|
||||
/* stop sending event reports */
|
||||
abis_nm_event_reports(bts, 0);
|
||||
|
||||
/* begin DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 1);
|
||||
|
||||
/* end DB transmission */
|
||||
abis_nm_bs11_db_transmission(bts, 0);
|
||||
|
||||
/* Reset BTS Site manager resource */
|
||||
abis_nm_bs11_reset_resource(bts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bcch_info {
|
||||
u_int8_t type;
|
||||
u_int8_t len;
|
||||
const u_int8_t *data;
|
||||
};
|
||||
|
||||
/*
|
||||
SYSTEM INFORMATION TYPE 1
|
||||
Cell channel description
|
||||
Format-ID bit map 0
|
||||
CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
|
||||
RACH Control Parameters
|
||||
maximum 7 retransmissions
|
||||
8 slots used to spread transmission
|
||||
cell not barred for access
|
||||
call reestablishment not allowed
|
||||
Access Control Class = 0000
|
||||
*/
|
||||
static u_int8_t si1[] = {
|
||||
/* header */0x55, 0x06, 0x19,
|
||||
/* ccdesc */0x04 /*0x00*/, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*0x01*/,
|
||||
/* rach */0xD5, 0x00, 0x00,
|
||||
/* s1 reset*/0x2B
|
||||
};
|
||||
|
||||
/*
|
||||
SYSTEM INFORMATION TYPE 2
|
||||
Neighbour Cells Description
|
||||
EXT-IND: Carries the complete BA
|
||||
BA-IND = 0
|
||||
Format-ID bit map 0
|
||||
CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
NCC permitted (NCC) = FF
|
||||
RACH Control Parameters
|
||||
maximum 7 retransmissions
|
||||
8 slots used to spread transmission
|
||||
cell not barred for access
|
||||
call reestablishment not allowed
|
||||
Access Control Class = 0000
|
||||
*/
|
||||
static u_int8_t si2[] = {
|
||||
/* header */0x59, 0x06, 0x1A,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* ncc */0xFF,
|
||||
/* rach*/0xD5, 0x00, 0x00
|
||||
};
|
||||
|
||||
/*
|
||||
SYSTEM INFORMATION TYPE 3
|
||||
Cell identity = 00001 (1h)
|
||||
Location area identification
|
||||
Mobile Country Code (MCC): 001
|
||||
Mobile Network Code (MNC): 01
|
||||
Location Area Code (LAC): 00001 (1h)
|
||||
Control Channel Description
|
||||
Attach-detach: MSs in the cell are not allowed to apply IMSI attach /detach
|
||||
0 blocks reserved for access grant
|
||||
1 channel used for CCCH, with SDCCH
|
||||
5 multiframes period for PAGING REQUEST
|
||||
Time-out T3212 = 0
|
||||
Cell Options BCCH
|
||||
Power control indicator: not set
|
||||
MSs shall not use uplink DTX
|
||||
Radio link timeout = 36
|
||||
Cell Selection Parameters
|
||||
Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
|
||||
max.TX power level MS may use for CCH = 2 <- according to GSM05.05 39dBm (max)
|
||||
Additional Reselect Parameter Indication (ACS) = only SYSTEM INFO 4: The SI rest octets, if present, shall be used to derive the value of PI and possibly C2 parameters
|
||||
Half rate support (NECI): New establishment causes are not supported
|
||||
min.RX signal level for MS = 0
|
||||
RACH Control Parameters
|
||||
maximum 7 retransmissions
|
||||
8 slots used to spread transmission
|
||||
cell not barred for access
|
||||
call reestablishment not allowed
|
||||
Access Control Class = 0000
|
||||
SI 3 Rest Octets
|
||||
Cell Bar Qualify (CBQ): 0
|
||||
Cell Reselect Offset = 0 dB
|
||||
Temporary Offset = 0 dB
|
||||
Penalty Time = 20 s
|
||||
System Information 2ter Indicator (2TI): 0 = not available
|
||||
Early Classmark Sending Control (ECSC): 0 = forbidden
|
||||
Scheduling Information is not sent in SYSTEM INFORMATION TYPE 9 on the BCCH
|
||||
*/
|
||||
static u_int8_t si3[] = {
|
||||
/* header */0x49, 0x06, 0x1B,
|
||||
/* cell */0x00, 0x01,
|
||||
/* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
|
||||
/* desc */0x01, 0x03, 0x00,
|
||||
/* option*/0x28,
|
||||
/* selection*/0x62, 0x00,
|
||||
/* rach */0xD5, 0x00, 0x00,
|
||||
/* reset*/0x80, 0x00, 0x00, 0x2B
|
||||
};
|
||||
|
||||
/*
|
||||
SYSTEM INFORMATION TYPE 4
|
||||
Location area identification
|
||||
Mobile Country Code (MCC): 001
|
||||
Mobile Network Code (MNC): 01
|
||||
Location Area Code (LAC): 00001 (1h)
|
||||
Cell Selection Parameters
|
||||
Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
|
||||
max.TX power level MS may use for CCH = 2
|
||||
Additional Reselect Parameter Indication (ACS) = only SYSTEM INFO 4: The SI rest octets, if present, shall be used to derive the value of PI and possibly C2 parameters
|
||||
Half rate support (NECI): New establishment causes are not supported
|
||||
min.RX signal level for MS = 0
|
||||
RACH Control Parameters
|
||||
maximum 7 retransmissions
|
||||
8 slots used to spread transmission
|
||||
cell not barred for access
|
||||
call reestablishment not allowed
|
||||
Access Control Class = 0000
|
||||
Channel Description
|
||||
Type = SDCCH/4[2]
|
||||
Timeslot Number: 0
|
||||
Training Sequence Code: 7h
|
||||
ARFCN: 1
|
||||
SI Rest Octets
|
||||
Cell Bar Qualify (CBQ): 0
|
||||
Cell Reselect Offset = 0 dB
|
||||
Temporary Offset = 0 dB
|
||||
Penalty Time = 20 s
|
||||
*/
|
||||
static u_int8_t si4[] = {
|
||||
/* header */0x41, 0x06, 0x1C,
|
||||
/* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
|
||||
/* sel */0x62, 0x00,
|
||||
/* rach*/0xD5, 0x00, 0x00,
|
||||
/* var */0x64, 0x30, 0xE0, HARDCODED_ARFCN/*0x01*/, 0x80, 0x00, 0x00,
|
||||
0x2B, 0x2B, 0x2B
|
||||
};
|
||||
|
||||
/*
|
||||
SYSTEM INFORMATION TYPE 5
|
||||
Neighbour Cells Description
|
||||
EXT-IND: Carries the complete BA
|
||||
BA-IND = 0
|
||||
Format-ID bit map 0
|
||||
CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
*/
|
||||
|
||||
static u_int8_t si5[] = {
|
||||
/* header without l2 len*/0x06, 0x1D,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
// SYSTEM INFORMATION TYPE 6
|
||||
|
||||
/*
|
||||
SACCH FILLING
|
||||
System Info Type: SYSTEM INFORMATION 6
|
||||
L3 Information (Hex): 06 1E 00 01 xx xx 10 00 01 28 FF
|
||||
|
||||
SYSTEM INFORMATION TYPE 6
|
||||
Cell identity = 00001 (1h)
|
||||
Location area identification
|
||||
Mobile Country Code (MCC): 001
|
||||
Mobile Network Code (MNC): 01
|
||||
Location Area Code (LAC): 00001 (1h)
|
||||
Cell Options SACCH
|
||||
Power control indicator: not set
|
||||
MSs shall not use uplink DTX on a TCH-F. MS shall not use uplink DTX on TCH-H.
|
||||
Radio link timeout = 36
|
||||
NCC permitted (NCC) = FF
|
||||
*/
|
||||
|
||||
static u_int8_t si6[] = {
|
||||
/* header */0x06, 0x1E,
|
||||
/* cell id*/ 0x00, 0x01,
|
||||
/* lai */ 0x00, 0xF1, 0x10, 0x00, 0x01,
|
||||
/* options */ 0x28,
|
||||
/* ncc */ 0xFF,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const struct bcch_info bcch_infos[] = {
|
||||
{
|
||||
RSL_SYSTEM_INFO_1,
|
||||
sizeof(si1),
|
||||
si1,
|
||||
}, {
|
||||
RSL_SYSTEM_INFO_2,
|
||||
sizeof(si2),
|
||||
si2,
|
||||
}, {
|
||||
RSL_SYSTEM_INFO_3,
|
||||
sizeof(si3),
|
||||
si3,
|
||||
}, {
|
||||
RSL_SYSTEM_INFO_4,
|
||||
sizeof(si4),
|
||||
si4,
|
||||
},
|
||||
};
|
||||
|
||||
static_assert(sizeof(si1) == sizeof(struct gsm48_system_information_type_1), type1)
|
||||
static_assert(sizeof(si2) == sizeof(struct gsm48_system_information_type_2), type2)
|
||||
static_assert(sizeof(si3) == sizeof(struct gsm48_system_information_type_3), type3)
|
||||
static_assert(sizeof(si4) >= sizeof(struct gsm48_system_information_type_4), type4)
|
||||
static_assert(sizeof(si5) == sizeof(struct gsm48_system_information_type_5), type5)
|
||||
static_assert(sizeof(si6) >= sizeof(struct gsm48_system_information_type_6), type6)
|
||||
|
||||
/* set all system information types */
|
||||
static int set_system_infos(struct gsm_bts_trx *trx)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bcch_infos); i++) {
|
||||
rsl_bcch_info(trx, bcch_infos[i].type,
|
||||
bcch_infos[i].data,
|
||||
bcch_infos[i].len);
|
||||
}
|
||||
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_5, si5, sizeof(si5));
|
||||
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_6, si6, sizeof(si6));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inform anyone...
|
||||
*/
|
||||
static void bsc_hack_channel_allocated(struct gsm_lchan *lchan) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Patch the various SYSTEM INFORMATION tables to update
|
||||
* the LAI
|
||||
*/
|
||||
static void patch_tables(struct gsm_bts *bts)
|
||||
{
|
||||
u_int8_t arfcn_low = bts->trx[0].arfcn & 0xff;
|
||||
u_int8_t arfcn_high = (bts->trx[0].arfcn >> 8) & 0x0f;
|
||||
/* covert the raw packet to the struct */
|
||||
struct gsm48_system_information_type_3 *type_3 =
|
||||
(struct gsm48_system_information_type_3*)&si3;
|
||||
struct gsm48_system_information_type_4 *type_4 =
|
||||
(struct gsm48_system_information_type_4*)&si4;
|
||||
struct gsm48_system_information_type_6 *type_6 =
|
||||
(struct gsm48_system_information_type_6*)&si6;
|
||||
struct gsm48_loc_area_id lai;
|
||||
|
||||
gsm0408_generate_lai(&lai, bts->network->country_code,
|
||||
bts->network->network_code, bts->location_area_code);
|
||||
|
||||
/* assign the MCC and MNC */
|
||||
type_3->lai = lai;
|
||||
type_4->lai = lai;
|
||||
type_6->lai = lai;
|
||||
|
||||
/* patch ARFCN into BTS Attributes */
|
||||
msg_2[74] &= 0xf0;
|
||||
msg_2[74] |= arfcn_high;
|
||||
msg_2[75] = arfcn_low;
|
||||
nanobts_attr_bts[42] &= 0xf0;
|
||||
nanobts_attr_bts[42] |= arfcn_high;
|
||||
nanobts_attr_bts[43] = arfcn_low;
|
||||
|
||||
/* patch ARFCN into TRX Attributes */
|
||||
msg_6[7] &= 0xf0;
|
||||
msg_6[7] |= arfcn_high;
|
||||
msg_6[8] = arfcn_low;
|
||||
nanobts_attr_radio[5] &= 0xf0;
|
||||
nanobts_attr_radio[5] |= arfcn_high;
|
||||
nanobts_attr_radio[6] = arfcn_low;
|
||||
|
||||
type_4->data[2] &= 0xf0;
|
||||
type_4->data[2] |= arfcn_high;
|
||||
type_4->data[3] = arfcn_low;
|
||||
|
||||
/* patch Control Channel Description 10.5.2.11 */
|
||||
type_3->control_channel_desc = bts->chan_desc;
|
||||
}
|
||||
|
||||
|
||||
static void bootstrap_rsl(struct gsm_bts_trx *trx)
|
||||
{
|
||||
fprintf(stdout, "bootstrapping RSL MCC=%u MNC=%u\n", trx->bts->network->country_code, trx->bts->network->network_code);
|
||||
set_system_infos(trx);
|
||||
}
|
||||
|
||||
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
|
||||
{
|
||||
switch (event) {
|
||||
case EVT_E1_TEI_UP:
|
||||
switch (type) {
|
||||
case E1INP_SIGN_OML:
|
||||
bootstrap_om(trx->bts);
|
||||
break;
|
||||
case E1INP_SIGN_RSL:
|
||||
bootstrap_rsl(trx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVT_E1_TEI_DN:
|
||||
fprintf(stderr, "Lost some E1 TEI link\n");
|
||||
/* FIXME: deal with TEI or L1 link loss */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *bootstrap_network(int (*mncc_recv)(void *, int, void *),int bts_type, int mcc, int mnc, int lac, int arfcn, int cardnr, int release_l2, char *name_short, char *name_long, char *hlr, int allow_all)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct gsm_network *gsmnet;
|
||||
|
||||
/* open database */
|
||||
if (db_init(hlr)) {
|
||||
fprintf(stderr, "DB: Failed to init HLR database '%s'. Please check the option settings.\n", hlr);
|
||||
return NULL;
|
||||
}
|
||||
if (db_prepare()) {
|
||||
fprintf(stderr, "DB: Failed to prepare database.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* seed the PRNG for TMSI */
|
||||
srand(time(NULL));
|
||||
|
||||
/* initialize our data structures */
|
||||
gsmnet = gsm_network_init(1, (gsm_bts_type)bts_type, mcc, mnc, mncc_recv);
|
||||
if (!gsmnet)
|
||||
return 0;
|
||||
|
||||
gsmnet->name_long = name_long;
|
||||
gsmnet->name_short = name_short;
|
||||
bts = &gsmnet->bts[0];
|
||||
bts->location_area_code = lac;
|
||||
bts->trx[0].arfcn = arfcn;
|
||||
|
||||
/* Control Channel Description */
|
||||
memset(&bts->chan_desc, 0, sizeof(struct gsm48_control_channel_descr));
|
||||
bts->chan_desc.att = 1;
|
||||
bts->chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
|
||||
bts->chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
|
||||
bts->chan_desc.t3212 = 0;
|
||||
|
||||
patch_tables(bts);
|
||||
|
||||
paging_init(bts);
|
||||
bts->paging.channel_allocated = bsc_hack_channel_allocated;
|
||||
|
||||
telnet_init(gsmnet, 4242);
|
||||
|
||||
/* E1 mISDN input setup */
|
||||
if (bts_type == GSM_BTS_TYPE_BS11) {
|
||||
if (e1_config(bts, cardnr, release_l2))
|
||||
return NULL;
|
||||
} else {
|
||||
if (ia_config(bts))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (allow_all)
|
||||
gsm0408_allow_everyone(1);
|
||||
|
||||
return gsmnet;
|
||||
}
|
||||
|
||||
int shutdown_net(void *network)
|
||||
{
|
||||
struct gsm_network *net = (struct gsm_network *)network;
|
||||
unsigned int i;
|
||||
for (i = 0; i < net->num_bts; i++) {
|
||||
int rc;
|
||||
rc = shutdown_om(&net->bts[i]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
void *bootstrap_network(int (*mncc_recv)(void *, int, void *),int bts_type, int mcc, int mnc, int lac, int arfcn, int cardnr, int release_l2, char *name_short, char *name_long, char *hlr, int allow_all);
|
||||
int shutdown_net(void *network);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.63 for lcr 1.4.
|
||||
# Generated by GNU Autoconf 2.63 for lcr 1.5.
|
||||
#
|
||||
# Report bugs to <andreas@eversberg.eu>.
|
||||
#
|
||||
|
@ -596,8 +596,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='lcr'
|
||||
PACKAGE_TARNAME='lcr'
|
||||
PACKAGE_VERSION='1.4'
|
||||
PACKAGE_STRING='lcr 1.4'
|
||||
PACKAGE_VERSION='1.5'
|
||||
PACKAGE_STRING='lcr 1.5'
|
||||
PACKAGE_BUGREPORT='andreas@eversberg.eu'
|
||||
|
||||
ac_unique_file="main.c"
|
||||
|
@ -640,6 +640,8 @@ ac_includes_default="\
|
|||
ac_subst_vars='LTLIBOBJS
|
||||
POW_LIB
|
||||
LIBOBJS
|
||||
ENABLE_GSM_FALSE
|
||||
ENABLE_GSM_TRUE
|
||||
LIBCRYPTO
|
||||
ENABLE_ASTERISK_CHANNEL_DRIVER_FALSE
|
||||
ENABLE_ASTERISK_CHANNEL_DRIVER_TRUE
|
||||
|
@ -732,6 +734,7 @@ enable_option_checking
|
|||
enable_dependency_tracking
|
||||
with_asterisk
|
||||
with_ssl
|
||||
with_gsm
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
host_alias
|
||||
|
@ -1297,7 +1300,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures lcr 1.4 to adapt to many kinds of systems.
|
||||
\`configure' configures lcr 1.5 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1363,7 +1366,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of lcr 1.4:";;
|
||||
short | recursive ) echo "Configuration of lcr 1.5:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1382,6 +1385,8 @@ Optional Packages:
|
|||
|
||||
--with-ssl compile with ssl support (libcrypto) [default=check]
|
||||
|
||||
--with-gsm compile with OpenBSC support (libbsc) [default=no]
|
||||
|
||||
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
|
@ -1461,7 +1466,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
lcr configure 1.4
|
||||
lcr configure 1.5
|
||||
generated by GNU Autoconf 2.63
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
|
@ -1475,7 +1480,7 @@ cat >config.log <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by lcr $as_me 1.4, which was
|
||||
It was created by lcr $as_me 1.5, which was
|
||||
generated by GNU Autoconf 2.63. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -4033,7 +4038,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=lcr
|
||||
VERSION=1.4
|
||||
VERSION=1.5
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -6253,6 +6258,27 @@ fi
|
|||
fi
|
||||
|
||||
|
||||
# check for gsm
|
||||
|
||||
# Check whether --with-gsm was given.
|
||||
if test "${with_gsm+set}" = set; then
|
||||
withval=$with_gsm;
|
||||
else
|
||||
with_gsm=no
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
if test "x$with_gsm" != "xno" ; then
|
||||
ENABLE_GSM_TRUE=
|
||||
ENABLE_GSM_FALSE='#'
|
||||
else
|
||||
ENABLE_GSM_TRUE='#'
|
||||
ENABLE_GSM_FALSE=
|
||||
fi
|
||||
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
{ $as_echo "$as_me:$LINENO: checking for main in -lm" >&5
|
||||
|
@ -9756,6 +9782,13 @@ $as_echo "$as_me: error: conditional \"ENABLE_ASTERISK_CHANNEL_DRIVER\" was neve
|
|||
Usually this means the macro was only invoked conditionally." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
if test -z "${ENABLE_GSM_TRUE}" && test -z "${ENABLE_GSM_FALSE}"; then
|
||||
{ { $as_echo "$as_me:$LINENO: error: conditional \"ENABLE_GSM\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." >&5
|
||||
$as_echo "$as_me: error: conditional \"ENABLE_GSM\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
: ${CONFIG_STATUS=./config.status}
|
||||
ac_write_fail=0
|
||||
|
@ -10078,7 +10111,7 @@ exec 6>&1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by lcr $as_me 1.4, which was
|
||||
This file was extended by lcr $as_me 1.5, which was
|
||||
generated by GNU Autoconf 2.63. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -10141,7 +10174,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
|||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_version="\\
|
||||
lcr config.status 1.4
|
||||
lcr config.status 1.5
|
||||
configured by $0, generated by GNU Autoconf 2.63,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
|
14
configure.ac
14
configure.ac
|
@ -24,7 +24,7 @@ dnl Boston, MA 02110-1301, USA.
|
|||
dnl This keeps being the first instruction.
|
||||
dnl Change the 2nd argument if the version increases
|
||||
dnl 1st + 2nd argument is used for distribution package name
|
||||
AC_INIT(lcr, 1.4, andreas@eversberg.eu)
|
||||
AC_INIT(lcr, 1.5, andreas@eversberg.eu)
|
||||
AC_PREREQ(2.59)
|
||||
AC_CONFIG_SRCDIR([main.c])
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
@ -32,7 +32,7 @@ AM_CONFIG_HEADER(config.h)
|
|||
# fix warnings from autoconf + automake
|
||||
AC_GNU_SOURCE
|
||||
# AC_USE_SYSTEM_EXTENSIONS
|
||||
AM_INIT_AUTOMAKE(lcr,1.4)
|
||||
AM_INIT_AUTOMAKE(lcr,1.5)
|
||||
|
||||
|
||||
|
||||
|
@ -95,6 +95,16 @@ AS_IF([test "x$with_ssl" != xno],
|
|||
]
|
||||
)
|
||||
|
||||
# check for gsm
|
||||
AC_ARG_WITH([gsm],
|
||||
[AS_HELP_STRING([--with-gsm],
|
||||
[compile with OpenBSC support (libbsc) @<:@default=no@:>@])
|
||||
],
|
||||
[],
|
||||
[with_gsm=no])
|
||||
|
||||
AM_CONDITIONAL(ENABLE_GSM, test "x$with_gsm" != "xno" )
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB([m], [main])
|
||||
AC_CHECK_LIB([ncurses], [main])
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# LCR GSM options
|
||||
#################
|
||||
|
||||
# Enable debugging of OpenBSC library.
|
||||
# Refer to OpenBSC project for debugging options.
|
||||
# By default, debugging is turned off.
|
||||
#debug DRLL:DCC:DMM:DRR:DRSL:DNM
|
||||
|
||||
# Two Loopback interfaces for audio transfer between OpenBSC and mISDN.
|
||||
# The first interface must provide B-channelis for each call mobile call.
|
||||
# The seond interface links them to LCR.
|
||||
# Use 30 B-channels unless you need more due to many TRXs.
|
||||
# -> Load with: "modprobe mISDN_l1loop pri=1 nchannel=30"
|
||||
# By default "mISDN_l1loop.1" and "mISDN_l1loop.2" is used.
|
||||
#interface-bsc mISDN_l1loop.1
|
||||
#interface-lcr mISDN_l1loop.2
|
||||
|
||||
# GSM network names.
|
||||
# This name is presented to the mobile station.
|
||||
# By default 'LCR' is used.
|
||||
#long-name Linux-Call-Router
|
||||
#short-name LCR
|
||||
|
||||
# Give the GSM country code.
|
||||
# The country code is different from the PSTN country code. E.g Germany uses
|
||||
# 262 instead of 49. Use this for IMSI catching.
|
||||
# This will override the default value of 1 = 'test country';
|
||||
#mcc 001
|
||||
|
||||
# Give the GSM network code.
|
||||
# The network code is different from the PSTN network codes. Change this if
|
||||
# you run different test networks in the same locations.
|
||||
# This will override the default value of 1 = 'test network';
|
||||
#mnc 01
|
||||
|
||||
# Give the location area code.
|
||||
# The location area code is not known to the author of LCR. Don't change it!
|
||||
#lac 1
|
||||
|
||||
# Give database of Home Location Register (HLR)
|
||||
# HLR stores all subscribers. It will be used to grant access to the network.
|
||||
# It is an Sqlite3 database. Refer to OpenBSC project for handling.
|
||||
# The database is located at /usr/local/lcr by default.
|
||||
#hlr hlr.sqlite3
|
||||
|
||||
# Authorization of unknown subscribers.
|
||||
# To allow all subscribers to access the network, use this option.
|
||||
# By default, subscribers are only accepted if allowed in the HLR
|
||||
allow-all
|
||||
|
||||
# To keep layer 2 connection to BS11 when quitting, use this option.
|
||||
# It is only usefull for developing. TRX will stay on.
|
||||
# Warning: Keeping layer 2 link may prevent emergency calls. (See below)
|
||||
# Layer 2 will only be kept, if lcr was killed manually.
|
||||
#keep-l2
|
||||
|
||||
# You must define a list of your BTS'.
|
||||
# Usage: 'bts bs11 <card> <frequency> [<frequency 2>]
|
||||
# The keyword 'bts' is used to specify a BTS. Multiple BTS' may be defined.
|
||||
# The 'bs11' keyword specifies a BS11 BTS connected to an E1 card.
|
||||
# The frequency is given for the first TRX (tranceiver).
|
||||
# In case of a second tranceiver, give frequency 2.
|
||||
bts bs11 9 123
|
||||
|
||||
# Shutdown on emergency calls:
|
||||
# This option will prevent a shutdown if an emergency call is received. In
|
||||
# case of an emergency, a mobile phone may log onto you GSM network and may
|
||||
# use it to set up an emergency call.
|
||||
# The received emergency call will have 'emergency' as dialed number. But this
|
||||
# number can't be dialed on PSTN networks without chaning.
|
||||
# If you disable shutdown, be sure to provide routing of emergency calls to
|
||||
# emergency facility. If you can't do that, don't touch it!
|
||||
#no-emergency-shutdown
|
||||
|
|
@ -136,6 +136,24 @@
|
|||
#portnum 0
|
||||
#dialmax 20
|
||||
|
||||
|
||||
# A special case for GSM interface.
|
||||
# Don't remove/change the settings, they will cause undefined behaviour
|
||||
# of LCR. The actual interface is defined in gsm.conf.
|
||||
# You may add 'extension' and 'mns' keywords to turn all your subscribers
|
||||
# in you GSM network to internal 'extensions'.
|
||||
# The MSN numbers will equal the subscriber number.
|
||||
#[GSM]
|
||||
#gsm
|
||||
#nt
|
||||
#layer1hold no
|
||||
#layer2hold no
|
||||
#tones yes
|
||||
#earlyb no
|
||||
#channel-in free
|
||||
#channel-out any
|
||||
|
||||
|
||||
# Hint: Enter "lcr interface" for quick help on interface options.
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define DEBUG_BCHANNEL 0x0008
|
||||
#define DEBUG_PORT 0x0100
|
||||
#define DEBUG_ISDN 0x0110
|
||||
#define DEBUG_GSM 0x0120
|
||||
#define DEBUG_VBOX 0x0180
|
||||
#define DEBUG_EPOINT 0x0200
|
||||
#define DEBUG_JOIN 0x0400
|
||||
|
@ -96,3 +97,16 @@
|
|||
# Rights must have 0 in front, if octal values above are used.
|
||||
#socketrights 0700
|
||||
|
||||
# Enable GSM network capability.
|
||||
# This option turns LCR into a GSM network. Additional options are specified
|
||||
# in 'gsm.conf'. You also need openbsc at compile time and of yourse -
|
||||
# a base station transceiver. For more refer to LCR home page.
|
||||
#
|
||||
# !!! DANGER !!!
|
||||
# Running a GSM network may disturb other networks and may be prossecuted by
|
||||
# law of your country.
|
||||
# Running a GSM network may prevent mobile users from making EMERGENCY CALLS.
|
||||
# Be sure to allow emergency calls to be routed to emergency facilities.
|
||||
#
|
||||
#gsm
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ Endpoint::Endpoint(unsigned int port_id, unsigned int join_id)
|
|||
port = find_port_id(port_id);
|
||||
if (port)
|
||||
{
|
||||
if ((port->p_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1)
|
||||
if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
|
||||
earlyb = ((class PmISDN *)port)->p_m_mISDNport->earlyb;
|
||||
if (!portlist_new(port_id, port->p_type, earlyb))
|
||||
FATAL("No memory for portlist.\n");
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
struct bts_conf {
|
||||
int type; /* type of BTS */
|
||||
int card; /* E1 card number of BS11 BTS */
|
||||
int numtrx; /* up to 8 TRXs */
|
||||
int frequency[8]; /* up to 8 frequencies for TRXs */
|
||||
};
|
||||
|
||||
struct gsm_conf {
|
||||
char debug[128]; /* debug info */
|
||||
char interface_bsc[64]; /* loopback interface BSC side */
|
||||
char interface_lcr[64]; /* loopback interface LCR side */
|
||||
char short_name[64]; /* short network name */
|
||||
char long_name[64]; /* long network name */
|
||||
int mcc; /* mobile country code */
|
||||
int mnc; /* mobile network code */
|
||||
int lac; /* location area code */
|
||||
char hlr[64]; /* database name */
|
||||
int allow_all; /* accept unknown subscribers */
|
||||
int keep_l2; /* keep layer 2 after exit */
|
||||
int numbts; /* number of BTS' */
|
||||
struct bts_conf bts[8]; /* configure BTS' */
|
||||
int noemergshut; /* don't shut down on emergency */
|
||||
};
|
||||
|
||||
struct lcr_gsm {
|
||||
void *network; /* OpenBSC network handle */
|
||||
struct gsm_conf conf; /* gsm.conf options */
|
||||
int gsm_sock; /* loopback interface BSC side */
|
||||
int gsm_port; /* loopback interface port number */
|
||||
};
|
||||
|
||||
extern struct lcr_gsm *gsm;
|
||||
|
||||
/* GSM port class */
|
||||
class Pgsm : public PmISDN
|
||||
{
|
||||
public:
|
||||
Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
|
||||
~Pgsm();
|
||||
|
||||
unsigned int p_m_g_callref; /* ref by OpenBSC */
|
||||
unsigned int p_m_g_mode; /* data/transparent mode */
|
||||
int p_m_g_gsm_b_sock; /* gsm bchannel socket */
|
||||
int p_m_g_gsm_b_index; /* gsm bchannel socket index to use */
|
||||
int p_m_g_gsm_b_active; /* gsm bchannel socket is activated */
|
||||
struct lcr_msg *p_m_g_notify_pending; /* queue for NOTIFY if not connected */
|
||||
void *p_m_g_encoder, *p_m_g_decoder; /* gsm handle */
|
||||
signed short p_m_g_rxdata[160]; /* receive audio buffer */
|
||||
int p_m_g_rxpos; /* position in audio buffer 0..159 */
|
||||
int p_m_g_tch_connected; /* indicates if audio is connected */
|
||||
|
||||
void bchannel_close(void);
|
||||
int bchannel_open(int index);
|
||||
void bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len);
|
||||
void bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len);
|
||||
|
||||
void trau_send(void *_tf);
|
||||
void trau_receive(void *_frame);
|
||||
|
||||
int hunt_bchannel(void);
|
||||
void setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *gsm);
|
||||
void alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
|
||||
void message_setup(unsigned int epoint_id, int message_id, union parameter *param);
|
||||
void message_notify(unsigned int epoint_id, int message_id, union parameter *param);
|
||||
void message_alerting(unsigned int epoint_id, int message_id, union parameter *param);
|
||||
void message_connect(unsigned int epoint_id, int message_id, union parameter *param);
|
||||
void message_disconnect(unsigned int epoint_id, int message_id, union parameter *param);
|
||||
void message_release(unsigned int epoint_id, int message_id, union parameter *param);
|
||||
int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
|
||||
int handler(void);
|
||||
};
|
||||
|
||||
extern char *gsm_conf_error;
|
||||
int gsm_conf(struct gsm_conf *gsm_conf);
|
||||
int handle_gsm(void);
|
||||
int gsm_exit(int rc);
|
||||
int gsm_init(void);
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*****************************************************************************\
|
||||
** **
|
||||
** LCR **
|
||||
** **
|
||||
**---------------------------------------------------------------------------**
|
||||
** Copyright: Andreas Eversberg **
|
||||
** **
|
||||
** gsm audio **
|
||||
** **
|
||||
\*****************************************************************************/
|
||||
|
||||
extern "C" {
|
||||
#include "/usr/local/include/gsm.h"
|
||||
|
||||
|
||||
/* create gsm instance */
|
||||
void *gsm_audio_create(void)
|
||||
{
|
||||
int value = 1;
|
||||
gsm handle;
|
||||
|
||||
handle = gsm_create();
|
||||
if (handle)
|
||||
gsm_option(handle, GSM_OPT_WAV49, &value);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/* free gsm instance */
|
||||
void gsm_audio_destroy(void *arg)
|
||||
{
|
||||
gsm_destroy((gsm)arg);
|
||||
}
|
||||
|
||||
/* decode frame into samples, return error */
|
||||
int gsm_audio_decode(void *arg, unsigned char *frame, signed short *samples)
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
gsm_option((gsm)arg, GSM_OPT_FRAME_INDEX, &value);
|
||||
return gsm_decode((gsm)arg, (gsm_byte *)frame, (gsm_signal *)samples);
|
||||
}
|
||||
|
||||
/* encode samples into frame */
|
||||
void gsm_audio_encode(void *arg, signed short *samples, unsigned char *frame)
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
gsm_option((gsm)arg, GSM_OPT_FRAME_INDEX, &value);
|
||||
gsm_encode((gsm)arg, (gsm_signal *)samples, (gsm_byte *)frame);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
void *gsm_audio_create(void);
|
||||
void gsm_audio_destroy(void *arg);
|
||||
int gsm_audio_decode(void *arg, unsigned char *frame, signed short *samples);
|
||||
void gsm_audio_encode(void *arg, signed short *samples, unsigned char *frame);
|
||||
|
|
@ -0,0 +1,280 @@
|
|||
/*****************************************************************************\
|
||||
** **
|
||||
** PBX4Linux **
|
||||
** **
|
||||
**---------------------------------------------------------------------------**
|
||||
** Copyright: Andreas Eversberg **
|
||||
** **
|
||||
** reading options.conf and filling structure **
|
||||
** **
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "main.h"
|
||||
#include "openbsc/openbsc.h"
|
||||
|
||||
|
||||
char *gsm_conf_error = "";
|
||||
|
||||
/* read options
|
||||
*
|
||||
* read options from options.conf
|
||||
*/
|
||||
int gsm_conf(struct gsm_conf *gsm_conf)
|
||||
{
|
||||
FILE *fp=NULL;
|
||||
char filename[128];
|
||||
char *p;
|
||||
char option[32];
|
||||
char params[11][256];
|
||||
int pnum;
|
||||
unsigned int line,i;
|
||||
char buffer[256];
|
||||
|
||||
/* set defaults */
|
||||
SCPY(gsm_conf->debug, "");
|
||||
SCPY(gsm_conf->interface_bsc, "mISDN_l1loop.1");
|
||||
SCPY(gsm_conf->interface_lcr, "mISDN_l1loop.2");
|
||||
SCPY(gsm_conf->short_name, "LCR");
|
||||
SCPY(gsm_conf->long_name, "Linux-Call-Router");
|
||||
gsm_conf->mcc = 1;
|
||||
gsm_conf->mnc = 1;
|
||||
gsm_conf->lac = 1;
|
||||
SCPY(gsm_conf->hlr, "hlr.sqlite3");
|
||||
gsm_conf->allow_all = 0;
|
||||
gsm_conf->keep_l2 = 0;
|
||||
gsm_conf->numbts = 0;
|
||||
//gsm_conf->bts[xx]
|
||||
gsm_conf->noemergshut = 0;
|
||||
|
||||
SPRINT(filename, "%s/gsm.conf", CONFIG_DATA);
|
||||
|
||||
if (!(fp=fopen(filename,"r")))
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Cannot open %s\n",filename);
|
||||
return(0);
|
||||
}
|
||||
|
||||
line=0;
|
||||
while((fgets(buffer,sizeof(buffer),fp)))
|
||||
{
|
||||
line++;
|
||||
buffer[sizeof(buffer)-1]=0;
|
||||
if (buffer[0]) buffer[strlen(buffer)-1]=0;
|
||||
p=buffer;
|
||||
|
||||
while(*p <= 32) /* skip spaces */
|
||||
{
|
||||
if (*p == 0)
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
if (*p==0 || *p=='#') /* ignore comments and empty line */
|
||||
continue;
|
||||
|
||||
option[0]=0;
|
||||
i=0; /* read option */
|
||||
while(*p > 32)
|
||||
{
|
||||
if (i+1 >= sizeof(option))
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): option too long.\n",filename,line);
|
||||
goto error;
|
||||
}
|
||||
option[i+1] = '\0';
|
||||
option[i++] = *p++;
|
||||
}
|
||||
|
||||
while(*p <= 32) /* skip spaces */
|
||||
{
|
||||
if (*p == 0)
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
|
||||
params[0][0] = 0;
|
||||
pnum = 0;
|
||||
while(*p!=0 && *p!='#' && pnum < 10) /* param */
|
||||
{
|
||||
i=0; /* read param */
|
||||
while(*p > 32)
|
||||
{
|
||||
if (i+1 >= sizeof(params[pnum]))
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): param too long.\n",filename,line);
|
||||
goto error;
|
||||
}
|
||||
params[pnum][i+1] = '\0';
|
||||
params[pnum][i++] = *p++;
|
||||
}
|
||||
while(*p <= 32) /* skip spaces */
|
||||
{
|
||||
if (*p == 0)
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
pnum++;
|
||||
params[pnum][0] = 0;
|
||||
}
|
||||
|
||||
/* at this point we have option and param */
|
||||
|
||||
/* check option */
|
||||
if (!strcmp(option,"debug"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
|
||||
goto error;
|
||||
}
|
||||
SCPY(gsm_conf->debug, params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"interface-bsc"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
SCPY(gsm_conf->interface_bsc, params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"interface-lcr"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
SCPY(gsm_conf->interface_lcr, params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"short-name"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
SCPY(gsm_conf->short_name, params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"long-name"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
SCPY(gsm_conf->long_name, params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"mcc"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
gsm_conf->mcc = atoi(params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"mnc"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
gsm_conf->mnc = atoi(params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"lac"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
gsm_conf->lac = atoi(params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"hlr"))
|
||||
{
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
|
||||
goto error;
|
||||
}
|
||||
SCPY(gsm_conf->hlr, params[0]);
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"allow-all"))
|
||||
{
|
||||
gsm_conf->allow_all = 1;
|
||||
} else
|
||||
if (!strcmp(option,"keep-l2"))
|
||||
{
|
||||
gsm_conf->keep_l2 = 1;
|
||||
|
||||
} else
|
||||
if (!strcmp(option,"no-mergency-shutdown"))
|
||||
{
|
||||
gsm_conf->noemergshut = 1;
|
||||
} else
|
||||
if (!strcmp(option,"bts"))
|
||||
{
|
||||
if (gsm_conf->numbts == 8)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): too many BTS defined.\n",filename,line);
|
||||
goto error;
|
||||
}
|
||||
if (params[0][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter <bts-type> for option %s missing.\n",filename,line,option);
|
||||
goto error;
|
||||
}
|
||||
if (params[1][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter <card number> for option %s missing.\n",filename,line,option);
|
||||
goto error;
|
||||
}
|
||||
if (params[2][0]==0)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter <frequency> for option %s missing.\n",filename,line,option);
|
||||
goto error;
|
||||
}
|
||||
if (!strcmp(params[0], "bs11"))
|
||||
{
|
||||
gsm_conf->bts[gsm_conf->numbts].type = GSM_BTS_TYPE_BS11;
|
||||
} else {
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): unknown BTS type '%s'.\n",filename,line,params[0]);
|
||||
goto error;
|
||||
}
|
||||
gsm_conf->bts[gsm_conf->numbts].card = atoi(params[1]);
|
||||
gsm_conf->bts[gsm_conf->numbts].numtrx = 0;
|
||||
while (params[gsm_conf->bts[gsm_conf->numbts].numtrx+2][0])
|
||||
{
|
||||
if (gsm_conf->bts[gsm_conf->numbts].numtrx == 8)
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): too many frequencies defined.\n",filename,line);
|
||||
goto error;
|
||||
}
|
||||
gsm_conf->bts[gsm_conf->numbts].frequency[gsm_conf->bts[gsm_conf->numbts].numtrx++] = atoi(params[gsm_conf->bts[gsm_conf->numbts].numtrx+2]);
|
||||
}
|
||||
gsm_conf->numbts++;
|
||||
} else
|
||||
{
|
||||
SPRINT(gsm_conf_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (fp) fclose(fp);
|
||||
return(1);
|
||||
error:
|
||||
if (fp) fclose(fp);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
55
interface.c
55
interface.c
|
@ -342,6 +342,12 @@ static int inter_portname(struct interface *interface, char *filename, int line,
|
|||
SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
|
||||
return(-1);
|
||||
}
|
||||
/* check for use as GSM */
|
||||
if (ifport->gsm)
|
||||
{
|
||||
SPRINT(interface_error, "Error in %s (line %d): Interface already used for GSM.\n", filename, line);
|
||||
return(-1);
|
||||
}
|
||||
ifport = ifport->next;
|
||||
}
|
||||
searchif = searchif->next;
|
||||
|
@ -943,6 +949,48 @@ static int inter_dialmax(struct interface *interface, char *filename, int line,
|
|||
ifport->dialmax = atoi(value);
|
||||
return(0);
|
||||
}
|
||||
static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
|
||||
{
|
||||
#ifndef WITH_GSM
|
||||
SPRINT(interface_error, "Error in %s (line %d): GSM not compiled in.\n", filename, line);
|
||||
return(-1);
|
||||
#else
|
||||
struct interface_port *ifport;
|
||||
struct interface *searchif;
|
||||
|
||||
/* check gsm */
|
||||
if (!gsm)
|
||||
{
|
||||
SPRINT(interface_error, "Error in %s (line %d): GSM is not activated.\n", filename, line);
|
||||
return(-1);
|
||||
}
|
||||
searchif = interface_newlist;
|
||||
while(searchif)
|
||||
{
|
||||
ifport = searchif->ifport;
|
||||
while(ifport)
|
||||
{
|
||||
if (ifport->gsm)
|
||||
{
|
||||
SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses gsm\n", filename, line, value);
|
||||
return(-1);
|
||||
}
|
||||
ifport = ifport->next;
|
||||
}
|
||||
searchif = searchif->next;
|
||||
}
|
||||
|
||||
/* set portname */
|
||||
if (inter_portname(interface, filename, line, "portname", gsm->conf.interface_lcr))
|
||||
return(-1);
|
||||
/* goto end of chain again to set gsmflag*/
|
||||
ifport = interface->ifport;
|
||||
while(ifport->next)
|
||||
ifport = ifport->next;
|
||||
ifport->gsm = 1;
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -1061,6 +1109,11 @@ struct interface_param interface_param[] = {
|
|||
{"dialmax", &inter_dialmax, "<digits>",
|
||||
"Limits the number of digits in setup/information message."},
|
||||
|
||||
{"gsm", &inter_gsm, "",
|
||||
"Sets up GSM interface for using OpenBSC.\n"
|
||||
"This interface must be a loopback interface. The second loopback interface\n"
|
||||
"must be assigned to OpenBSC"},
|
||||
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -1412,7 +1465,7 @@ void load_port(struct interface_port *ifport)
|
|||
struct mISDNport *mISDNport;
|
||||
|
||||
/* open new port */
|
||||
mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l1hold, ifport->l2hold, ifport->interface);
|
||||
mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l1hold, ifport->l2hold, ifport->interface, ifport->gsm);
|
||||
if (mISDNport)
|
||||
{
|
||||
/* link port */
|
||||
|
|
|
@ -51,6 +51,7 @@ struct interface_port {
|
|||
int tespecial; /* special TE-mode behavior */
|
||||
int l1hold; /* hold layer 1 (1=on, 0=off) */
|
||||
int l2hold; /* hold layer 2 (1=force, -1=disable, 0=default) */
|
||||
int gsm; /* interface is an GSM interface */
|
||||
int channel_force; /* forces channel by protocol */
|
||||
int nodtmf; /* disables DTMF */
|
||||
struct select_channel *out_channel; /* list of channels to select */
|
||||
|
|
|
@ -1836,7 +1836,7 @@ int main(int argc, char *argv[])
|
|||
int mode;
|
||||
int sock, conn;
|
||||
struct sockaddr_un sock_address;
|
||||
const char *ret;
|
||||
const char *ret = "invalid mode";
|
||||
|
||||
|
||||
/* show options */
|
||||
|
|
370
mISDN.cpp
370
mISDN.cpp
|
@ -1947,106 +1947,109 @@ int mISDN_handler(void)
|
|||
}
|
||||
|
||||
/* handle queued up-messages (d-channel) */
|
||||
while ((mb = mdequeue(&mISDNport->upqueue)))
|
||||
if (!mISDNport->gsm)
|
||||
{
|
||||
l3m = &mb->l3;
|
||||
switch(l3m->type)
|
||||
while ((mb = mdequeue(&mISDNport->upqueue)))
|
||||
{
|
||||
case MPH_ACTIVATE_IND:
|
||||
if (mISDNport->l1link != 1)
|
||||
l3m = &mb->l3;
|
||||
switch(l3m->type)
|
||||
{
|
||||
l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
|
||||
end_trace();
|
||||
mISDNport->l1link = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MPH_DEACTIVATE_IND:
|
||||
if (mISDNport->l1link != 0)
|
||||
{
|
||||
l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
|
||||
end_trace();
|
||||
mISDNport->l1link = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MPH_INFORMATION_IND:
|
||||
PDEBUG(DEBUG_ISDN, "Received MPH_INFORMATION_IND for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
|
||||
switch (l3m->pid)
|
||||
{
|
||||
case L1_SIGNAL_LOS_ON:
|
||||
mISDNport->los = 1;
|
||||
break;
|
||||
case L1_SIGNAL_LOS_OFF:
|
||||
mISDNport->los = 0;
|
||||
break;
|
||||
case L1_SIGNAL_AIS_ON:
|
||||
mISDNport->ais = 1;
|
||||
break;
|
||||
case L1_SIGNAL_AIS_OFF:
|
||||
mISDNport->ais = 0;
|
||||
break;
|
||||
case L1_SIGNAL_RDI_ON:
|
||||
mISDNport->rdi = 1;
|
||||
break;
|
||||
case L1_SIGNAL_RDI_OFF:
|
||||
mISDNport->rdi = 0;
|
||||
break;
|
||||
case L1_SIGNAL_SLIP_TX:
|
||||
mISDNport->slip_tx++;
|
||||
break;
|
||||
case L1_SIGNAL_SLIP_RX:
|
||||
mISDNport->slip_rx++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MT_L2ESTABLISH:
|
||||
l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
|
||||
add_trace("tei", NULL, "%d", l3m->pid);
|
||||
end_trace();
|
||||
mISDNport->l2link = 1;
|
||||
if (l3m->pid < 128)
|
||||
mISDNport->l2mask[l3m->pid >> 3] |= (1 << (l3m->pid & 7));
|
||||
if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
|
||||
{
|
||||
if (mISDNport->l2establish)
|
||||
case MPH_ACTIVATE_IND:
|
||||
if (mISDNport->l1link != 1)
|
||||
{
|
||||
mISDNport->l2establish = 0;
|
||||
PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
|
||||
l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
|
||||
end_trace();
|
||||
mISDNport->l1link = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case MPH_DEACTIVATE_IND:
|
||||
if (mISDNport->l1link != 0)
|
||||
{
|
||||
l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
|
||||
end_trace();
|
||||
mISDNport->l1link = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MT_L2RELEASE:
|
||||
if (l3m->pid < 128)
|
||||
mISDNport->l2mask[l3m->pid >> 3] &= ~(1 << (l3m->pid & 7));
|
||||
if (!mISDNport->l2establish)
|
||||
{
|
||||
l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
|
||||
case MPH_INFORMATION_IND:
|
||||
PDEBUG(DEBUG_ISDN, "Received MPH_INFORMATION_IND for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
|
||||
switch (l3m->pid)
|
||||
{
|
||||
case L1_SIGNAL_LOS_ON:
|
||||
mISDNport->los = 1;
|
||||
break;
|
||||
case L1_SIGNAL_LOS_OFF:
|
||||
mISDNport->los = 0;
|
||||
break;
|
||||
case L1_SIGNAL_AIS_ON:
|
||||
mISDNport->ais = 1;
|
||||
break;
|
||||
case L1_SIGNAL_AIS_OFF:
|
||||
mISDNport->ais = 0;
|
||||
break;
|
||||
case L1_SIGNAL_RDI_ON:
|
||||
mISDNport->rdi = 1;
|
||||
break;
|
||||
case L1_SIGNAL_RDI_OFF:
|
||||
mISDNport->rdi = 0;
|
||||
break;
|
||||
case L1_SIGNAL_SLIP_TX:
|
||||
mISDNport->slip_tx++;
|
||||
break;
|
||||
case L1_SIGNAL_SLIP_RX:
|
||||
mISDNport->slip_rx++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MT_L2ESTABLISH:
|
||||
l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
|
||||
add_trace("tei", NULL, "%d", l3m->pid);
|
||||
end_trace();
|
||||
/* down if not nt-ptmp */
|
||||
if (!mISDNport->ntmode || mISDNport->ptp)
|
||||
mISDNport->l2link = 0;
|
||||
}
|
||||
if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
|
||||
{
|
||||
if (!mISDNport->l2establish && mISDNport->l2hold)
|
||||
mISDNport->l2link = 1;
|
||||
if (l3m->pid < 128)
|
||||
mISDNport->l2mask[l3m->pid >> 3] |= (1 << (l3m->pid & 7));
|
||||
if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
|
||||
{
|
||||
PDEBUG(DEBUG_ISDN, "set timer and establish.\n");
|
||||
time(&mISDNport->l2establish);
|
||||
mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
|
||||
if (mISDNport->l2establish)
|
||||
{
|
||||
mISDNport->l2establish = 0;
|
||||
PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* l3-data is sent to LCR */
|
||||
stack2manager(mISDNport, l3m->type, l3m->pid, l3m);
|
||||
case MT_L2RELEASE:
|
||||
if (l3m->pid < 128)
|
||||
mISDNport->l2mask[l3m->pid >> 3] &= ~(1 << (l3m->pid & 7));
|
||||
if (!mISDNport->l2establish)
|
||||
{
|
||||
l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
|
||||
add_trace("tei", NULL, "%d", l3m->pid);
|
||||
end_trace();
|
||||
/* down if not nt-ptmp */
|
||||
if (!mISDNport->ntmode || mISDNport->ptp)
|
||||
mISDNport->l2link = 0;
|
||||
}
|
||||
if (!mISDNport->gsm && (!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
|
||||
{
|
||||
if (!mISDNport->l2establish && mISDNport->l2hold)
|
||||
{
|
||||
PDEBUG(DEBUG_ISDN, "set timer and establish.\n");
|
||||
time(&mISDNport->l2establish);
|
||||
mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* l3-data is sent to LCR */
|
||||
stack2manager(mISDNport, l3m->type, l3m->pid, l3m);
|
||||
}
|
||||
/* free message */
|
||||
free_l3_msg(l3m);
|
||||
}
|
||||
/* free message */
|
||||
free_l3_msg(l3m);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -2062,7 +2065,7 @@ int mISDN_handler(void)
|
|||
if (now-mISDNport->l2establish > 5)
|
||||
{
|
||||
mISDNport->l2establish = 0;
|
||||
if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
|
||||
if (!mISDNport->gsm && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
|
||||
{
|
||||
|
||||
PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
|
||||
|
@ -2109,7 +2112,6 @@ int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3
|
|||
mt_assign_pid = pid;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* queue message, create, if required */
|
||||
if (!l3m)
|
||||
{
|
||||
|
@ -2124,11 +2126,32 @@ int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mISDN_getportbyname(int sock, int cnt, char *portname)
|
||||
{
|
||||
struct mISDN_devinfo devinfo;
|
||||
int port = 0, ret;
|
||||
|
||||
/* resolve name */
|
||||
while (port < cnt)
|
||||
{
|
||||
devinfo.id = port;
|
||||
ret = ioctl(sock, IMGETDEVINFO, &devinfo);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!strcasecmp(devinfo.name, portname))
|
||||
break;
|
||||
port++;
|
||||
}
|
||||
if (port == cnt)
|
||||
return -EIO;
|
||||
|
||||
return (port);
|
||||
}
|
||||
|
||||
/*
|
||||
* global function to add a new card (port)
|
||||
*/
|
||||
struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt, int te_special, int l1hold, int l2hold, struct interface *interface)
|
||||
struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt, int te_special, int l1hold, int l2hold, struct interface *interface, int gsm)
|
||||
{
|
||||
int ret;
|
||||
struct mISDNport *mISDNport, **mISDNportp;
|
||||
|
@ -2154,24 +2177,13 @@ struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt
|
|||
}
|
||||
if (port < 0)
|
||||
{
|
||||
/* resolve name */
|
||||
port = 0;
|
||||
while (port < cnt)
|
||||
port = mISDN_getportbyname(mISDNsocket, cnt, portname);
|
||||
if (port < 0)
|
||||
{
|
||||
devinfo.id = port;
|
||||
ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", port, ret);
|
||||
return(NULL);
|
||||
}
|
||||
if (!strcasecmp(devinfo.name, portname))
|
||||
break;
|
||||
port++;
|
||||
}
|
||||
if (port == cnt)
|
||||
{
|
||||
PERROR_RUNTIME("Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", portname);
|
||||
if (gsm)
|
||||
PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname);
|
||||
else
|
||||
PERROR_RUNTIME("Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", portname);
|
||||
return(NULL);
|
||||
}
|
||||
// note: 'port' has still the port number
|
||||
|
@ -2274,14 +2286,48 @@ struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt
|
|||
}
|
||||
}
|
||||
|
||||
/* check for continous channelmap with no bchannel on slot 16 */
|
||||
if (test_channelmap(0, devinfo.channelmap))
|
||||
{
|
||||
PERROR_RUNTIME("Port %d provides channel 0, but we cannot access it!\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
i = 1;
|
||||
while(i < (int)devinfo.nrbchan + 1)
|
||||
{
|
||||
if (i == 16) {
|
||||
if (test_channelmap(i, devinfo.channelmap))
|
||||
{
|
||||
PERROR("Port %d provides bchannel 16. Pleas upgrade mISDN, if this port is mISDN loopback interface.\n", port);
|
||||
return(NULL);
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (!test_channelmap(i, devinfo.channelmap))
|
||||
{
|
||||
PERROR_RUNTIME("Port %d has no channel on slot %d!\n", port, i);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* add mISDNport structure */
|
||||
mISDNportp = &mISDNport_first;
|
||||
while(*mISDNportp)
|
||||
mISDNportp = &((*mISDNportp)->next);
|
||||
mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
|
||||
mISDNport->l1link = -1;
|
||||
mISDNport->l2link = -1;
|
||||
if (gsm)
|
||||
{
|
||||
/* gsm audio is always active */
|
||||
mISDNport->l1link = 1;
|
||||
mISDNport->l2link = 1;
|
||||
} else
|
||||
{
|
||||
mISDNport->l1link = -1;
|
||||
mISDNport->l2link = -1;
|
||||
}
|
||||
mISDNport->gsm = gsm;
|
||||
pmemuse++;
|
||||
*mISDNportp = mISDNport;
|
||||
|
||||
|
@ -2307,7 +2353,6 @@ struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt
|
|||
}
|
||||
|
||||
/* allocate ressources of port */
|
||||
/* open layer 3 and init upqueue */
|
||||
protocol = (nt)?L3_PROTOCOL_DSS1_NET:L3_PROTOCOL_DSS1_USER;
|
||||
prop = (1 << MISDN_FLG_L2_CLEAN);
|
||||
if (ptp) // ptp forced
|
||||
|
@ -2318,41 +2363,65 @@ struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt
|
|||
prop |= (1 << MISDN_FLG_L1_HOLD);
|
||||
if (l2hold) // supports layer 2 hold
|
||||
prop |= (1 << MISDN_FLG_L2_HOLD);
|
||||
/* queue must be initializes, because l3-thread may send messages during open_layer3() */
|
||||
mqueue_init(&mISDNport->upqueue);
|
||||
mISDNport->ml3 = open_layer3(port, protocol, prop , do_layer3, mISDNport);
|
||||
if (!mISDNport->ml3)
|
||||
/* open layer 3 and init upqueue */
|
||||
if (gsm)
|
||||
{
|
||||
mqueue_purge(&mISDNport->upqueue);
|
||||
PERROR_RUNTIME("open_layer3() failed for port %d\n", port);
|
||||
start_trace(port,
|
||||
interface,
|
||||
NULL,
|
||||
NULL,
|
||||
DIRECTION_NONE,
|
||||
CATEGORY_CH,
|
||||
0,
|
||||
"PORT (open failed)");
|
||||
end_trace();
|
||||
mISDNport_close(mISDNport);
|
||||
return(NULL);
|
||||
}
|
||||
unsigned long on = 1;
|
||||
struct sockaddr_mISDN addr;
|
||||
|
||||
#if 0
|
||||
/* if ntmode, establish L1 to send the tei removal during start */
|
||||
if (mISDNport->ntmode)
|
||||
if (devinfo.nrbchan < 8)
|
||||
{
|
||||
PERROR_RUNTIME("GSM port %d must have at least 8 b-channels.\n", port);
|
||||
mISDNport_close(mISDNport);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if ((mISDNport->lcr_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_NT_S0)) < 0)
|
||||
{
|
||||
PERROR_RUNTIME("GSM port %d failed to open socket.\n", port);
|
||||
mISDNport_close(mISDNport);
|
||||
return(NULL);
|
||||
}
|
||||
/* set nonblocking io */
|
||||
if (ioctl(mISDNport->lcr_sock, FIONBIO, &on) < 0)
|
||||
{
|
||||
PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", port);
|
||||
mISDNport_close(mISDNport);
|
||||
return(NULL);
|
||||
}
|
||||
/* bind socket to dchannel */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.family = AF_ISDN;
|
||||
addr.dev = port;
|
||||
addr.channel = 0;
|
||||
if (bind(mISDNport->lcr_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
PERROR_RUNTIME("GSM port %d failed to bind socket. (errno %d)\n", port, errno);
|
||||
mISDNport_close(mISDNport);
|
||||
return(NULL);
|
||||
}
|
||||
} else
|
||||
{
|
||||
iframe_t act;
|
||||
/* L1 */
|
||||
act.prim = PH_ACTIVATE | REQUEST;
|
||||
act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
|
||||
printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
|
||||
act.dinfo = 0;
|
||||
act.len = 0;
|
||||
mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
|
||||
usleep(10000); /* to be sure, that l1 is up */
|
||||
/* queue must be initializes, because l3-thread may send messages during open_layer3() */
|
||||
mqueue_init(&mISDNport->upqueue);
|
||||
mISDNport->ml3 = open_layer3(port, protocol, prop , do_layer3, mISDNport);
|
||||
if (!mISDNport->ml3)
|
||||
{
|
||||
mqueue_purge(&mISDNport->upqueue);
|
||||
PERROR_RUNTIME("open_layer3() failed for port %d\n", port);
|
||||
start_trace(port,
|
||||
interface,
|
||||
NULL,
|
||||
NULL,
|
||||
DIRECTION_NONE,
|
||||
CATEGORY_CH,
|
||||
0,
|
||||
"PORT (open failed)");
|
||||
end_trace();
|
||||
mISDNport_close(mISDNport);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SCPY(mISDNport->name, devinfo.name);
|
||||
mISDNport->b_num = devinfo.nrbchan;
|
||||
|
@ -2373,7 +2442,7 @@ struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt
|
|||
}
|
||||
|
||||
/* if ptp, pull up the link */
|
||||
if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
|
||||
if (!mISDNport->gsm && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
|
||||
{
|
||||
mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
|
||||
l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
|
||||
|
@ -2465,13 +2534,22 @@ void mISDNport_close(struct mISDNport *mISDNport)
|
|||
i++;
|
||||
}
|
||||
|
||||
/* close layer 3, if open and purge upqueue */
|
||||
if (mISDNport->ml3)
|
||||
/* close layer 3, if open */
|
||||
if (!mISDNport->gsm && mISDNport->ml3)
|
||||
{
|
||||
close_layer3(mISDNport->ml3);
|
||||
mqueue_purge(&mISDNport->upqueue);
|
||||
}
|
||||
|
||||
/* close gsm socket, if open */
|
||||
if (mISDNport->gsm && mISDNport->lcr_sock > -1)
|
||||
{
|
||||
close(mISDNport->lcr_sock);
|
||||
}
|
||||
|
||||
/* purge upqueue */
|
||||
if (!mISDNport->gsm)
|
||||
mqueue_purge(&mISDNport->upqueue);
|
||||
|
||||
/* remove from list */
|
||||
mISDNportp = &mISDNport_first;
|
||||
while(*mISDNportp)
|
||||
|
|
9
mISDN.h
9
mISDN.h
|
@ -15,6 +15,8 @@
|
|||
extern int entity;
|
||||
extern int mISDNdevice;
|
||||
|
||||
extern int mISDNsocket;
|
||||
|
||||
enum {
|
||||
B_EVENT_USE, /* activate/export bchannel */
|
||||
B_EVENT_EXPORTREQUEST, /* remote app requests bchannel */
|
||||
|
@ -61,6 +63,10 @@ struct mISDNport {
|
|||
unsigned int b_remote_ref[128]; /* the ref currently exported */
|
||||
int locally; /* local causes are sent as local causes not remote */
|
||||
int los, ais, rdi, slip_rx, slip_tx;
|
||||
|
||||
/* gsm */
|
||||
int gsm; /* this is the (only) GSM interface */
|
||||
int lcr_sock; /* socket of loopback on LCR side */
|
||||
};
|
||||
extern mISDNport *mISDNport_first;
|
||||
|
||||
|
@ -82,7 +88,8 @@ calls with no bchannel (call waiting, call on hold).
|
|||
/* mISDN none-object functions */
|
||||
int mISDN_initialize(void);
|
||||
void mISDN_deinitialize(void);
|
||||
struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt, int te_special, int l1hold, int l2hold, struct interface *interface);
|
||||
int mISDN_getportbyname(int sock, int cnt, char *portname);
|
||||
struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt, int te_special, int l1hold, int l2hold, struct interface *interface, int gsm);
|
||||
void mISDNport_close_all(void);
|
||||
void mISDNport_close(struct mISDNport *mISDNport);
|
||||
void mISDN_port_reorder(void);
|
||||
|
|
30
main.c
30
main.c
|
@ -394,6 +394,21 @@ int main(int argc, char *argv[])
|
|||
goto free;
|
||||
}
|
||||
|
||||
#ifdef WITH_GSM
|
||||
/* handle gsm */
|
||||
if (options.gsm && gsm_init())
|
||||
{
|
||||
fprintf(stderr, "GSM initialization failed.\n");
|
||||
goto free;
|
||||
}
|
||||
#else
|
||||
if (options.gsm)
|
||||
{
|
||||
fprintf(stderr, "GSM is enabled, but not compiled. Use --with-gsm while configure!\n");
|
||||
goto free;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* read interfaces and open ports */
|
||||
if (!read_interfaces())
|
||||
{
|
||||
|
@ -614,6 +629,15 @@ BUDETECT
|
|||
all_idle = 0;
|
||||
BUDETECT
|
||||
|
||||
#ifdef WITH_GSM
|
||||
/* handle gsm */
|
||||
if (options.gsm)
|
||||
while(handle_gsm())
|
||||
all_idle = 0;
|
||||
#endif
|
||||
|
||||
BUDETECT
|
||||
|
||||
#if 0
|
||||
/* check for child to exit (eliminate zombies) */
|
||||
if (waitpid(-1, NULL, WNOHANG) > 0)
|
||||
|
@ -746,6 +770,12 @@ free:
|
|||
if (created_misdn)
|
||||
mISDN_deinitialize();
|
||||
|
||||
#ifdef WITH_GSM
|
||||
/* free gsm */
|
||||
if (options.gsm)
|
||||
gsm_exit(0);
|
||||
#endif
|
||||
|
||||
/* display memory leak */
|
||||
#define MEMCHECK(a, b) \
|
||||
if (b) \
|
||||
|
|
5
main.h
5
main.h
|
@ -67,6 +67,7 @@ void debug(const char *function, int line, const char *prefix, char *buffer);
|
|||
#define DEBUG_BCHANNEL 0x0008
|
||||
#define DEBUG_PORT 0x0100
|
||||
#define DEBUG_ISDN 0x0110
|
||||
#define DEBUG_GSM 0x0120
|
||||
//#define DEBUG_KNOCK 0x0140
|
||||
#define DEBUG_VBOX 0x0180
|
||||
#define DEBUG_EPOINT 0x0200
|
||||
|
@ -147,6 +148,9 @@ extern "C" {
|
|||
#include "port.h"
|
||||
#include "mISDN.h"
|
||||
#include "dss1.h"
|
||||
#ifdef WITH_GSM
|
||||
#include "gsm.h"
|
||||
#endif
|
||||
#include "vbox.h"
|
||||
#include "join.h"
|
||||
#include "joinpbx.h"
|
||||
|
@ -158,6 +162,7 @@ extern "C" {
|
|||
#include "socket_server.h"
|
||||
#include "trace.h"
|
||||
|
||||
extern int quit;
|
||||
extern double now_d;
|
||||
extern time_t now;
|
||||
extern struct tm *now_tm;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define ISDN_TRANSMIT 256 // samples
|
||||
|
||||
enum { /* interface types */
|
||||
INFO_ITYPE_ISDN,
|
||||
INFO_ITYPE_ISDN, /* call from external */
|
||||
INFO_ITYPE_ISDN_EXTENSION, /* call from internal extension */
|
||||
INFO_ITYPE_CHAN,
|
||||
INFO_ITYPE_VBOX
|
||||
|
|
|
@ -31,7 +31,8 @@ struct options options = {
|
|||
0, /* by default use priority 0 */
|
||||
"lcr@your.machine", /* source mail adress */
|
||||
"/var/tmp", /* path of lock files */
|
||||
0700 /* rights of lcr admin socket */
|
||||
0700, /* rights of lcr admin socket */
|
||||
0 /* enable gsm */
|
||||
};
|
||||
|
||||
char options_error[256];
|
||||
|
@ -249,6 +250,10 @@ int read_options(void)
|
|||
{
|
||||
options.socketrights = strtol(param, NULL, 0);
|
||||
} else
|
||||
if (!strcmp(option,"gsm"))
|
||||
{
|
||||
options.gsm = 1;
|
||||
} else
|
||||
{
|
||||
SPRINT(options_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option);
|
||||
goto error;
|
||||
|
|
|
@ -28,6 +28,8 @@ struct options {
|
|||
char email[128]; /* source email address */
|
||||
char lock[128]; /* path of lock files */
|
||||
int socketrights; /* rights of lcr admin socket */
|
||||
|
||||
int gsm; /* enable gsm support */
|
||||
};
|
||||
|
||||
extern struct options options;
|
||||
|
|
4
port.h
4
port.h
|
@ -17,6 +17,7 @@
|
|||
#define PORT_CLASS_mISDN 0x0100
|
||||
#define PORT_CLASS_MASK 0xff00
|
||||
#define PORT_CLASS_mISDN_DSS1 0x0110
|
||||
#define PORT_CLASS_mISDN_GSM 0x0120
|
||||
#define PORT_CLASS_mISDN_MASK 0xfff0
|
||||
/* nt-mode */
|
||||
#define PORT_TYPE_DSS1_NT_IN 0x0111
|
||||
|
@ -24,6 +25,9 @@
|
|||
/* te-mode */
|
||||
#define PORT_TYPE_DSS1_TE_IN 0x0113
|
||||
#define PORT_TYPE_DSS1_TE_OUT 0x0114
|
||||
/* gsm */
|
||||
#define PORT_TYPE_GSM_IN 0x0121
|
||||
#define PORT_TYPE_GSM_OUT 0x0122
|
||||
/* answering machine */
|
||||
#define PORT_TYPE_VBOX_OUT 0x0311
|
||||
|
||||
|
|
2
route.c
2
route.c
|
@ -2022,7 +2022,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset)
|
|||
|
||||
case MATCH_PORT:
|
||||
if (ea_endpoint->ep_portlist)
|
||||
if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
|
||||
if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_MASK) != PORT_CLASS_mISDN)
|
||||
break;
|
||||
integer = e_callerinfo.isdn_port;
|
||||
goto match_integer;
|
||||
|
|
Loading…
Reference in New Issue