Added GSM network support.
authorAndreas Eversberg <andreas@eversberg.eu>
Mon, 11 May 2009 09:07:58 +0000 (11:07 +0200)
committerAndreas Eversberg <andreas@eversberg.eu>
Mon, 11 May 2009 09:07:58 +0000 (11:07 +0200)
This turns LCR into a GSM mobile switching center.
More infos will follow.

30 files changed:
Makefile.am
Makefile.in
README
apppbx.cpp
bootstrap.c [new file with mode: 0644]
bootstrap.h [new file with mode: 0644]
configure
configure.ac
default/gsm.conf [new file with mode: 0644]
default/interface.conf
default/options.conf
dss1.cpp
endpoint.cpp
gsm.cpp [new file with mode: 0644]
gsm.h [new file with mode: 0644]
gsm_audio.c [new file with mode: 0644]
gsm_audio.h [new file with mode: 0644]
gsm_conf.c [new file with mode: 0644]
interface.c
interface.h
lcradmin.c
mISDN.cpp
mISDN.h
main.c
main.h
message.h
options.c
options.h
port.h
route.c

index 7f1b577..61d8a86 100644 (file)
@@ -43,8 +43,18 @@ INSTALLATION_DEFINES = \
  -DLOG_DIR="\"$(LOGdir)\"" \
  -DEXTENSION_DATA="\"$(EXTENSIONdir)\""
 
  -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
 
 
 bin_PROGRAMS = lcradmin gentones genwave
 
@@ -74,7 +84,9 @@ install-exec-hook:
        $(INSTALL) chan_lcr.so $(astmoddir)
 endif
 
        $(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 \
        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
 
        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
 
 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)/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 \
        @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 \
index 9a94335..36fafce 100644 (file)
@@ -75,18 +75,30 @@ gentones_LDADD = $(LDADD)
 genwave_SOURCES = genwave.c
 genwave_OBJECTS = genwave.$(OBJEXT)
 genwave_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_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)
 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 \
 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)
 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@
 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@
 EXEEXT = @EXEEXT@
 GREP = @GREP@
 INSTALL_DATA = @INSTALL_DATA@
@@ -224,11 +239,14 @@ INSTALLATION_DEFINES = \
  -DLOG_DIR="\"$(LOGdir)\"" \
  -DEXTENSION_DATA="\"$(EXTENSIONdir)\""
 
  -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
 @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 \
        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
 
        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
 
 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)/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@
 @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)/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@
 @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)/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 \
        @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 \
diff --git a/README b/README
index 75a8913..a5b5945 100644 (file)
--- a/README
+++ b/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.
 
   -> 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.
+
index 88694e0..16da68b 100644 (file)
@@ -827,7 +827,6 @@ void EndpointAppPBX::out_setup(void)
 {
        struct dialing_info     dialinginfo;
        class Port              *port;
 {
        struct dialing_info     dialinginfo;
        class Port              *port;
-//     class pdss1             *pdss1;
        struct port_list        *portlist;
        struct lcr_msg          *message;
        int                     anycall = 0;
        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);
                        }
                        /* 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)
                        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);
                        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);
                                {
                                        /* 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
                                {
                                        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);
                        }
                        /* 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));
                        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;
                        }
                                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));
 //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 ((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)
                {
                        port = find_port_id(portlist->port_id);
                        if (port)
@@ -3626,7 +3640,7 @@ void EndpointAppPBX::pick_join(char *extensions)
                                                        break;
                                                }
                                        }
                                                        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))
                                                {
                                         && port->p_state==PORT_STATE_OUT_ALERTING)
                                                if (match_list(extensions, eapp->e_ext.number))
                                                {
diff --git a/bootstrap.c b/bootstrap.c
new file mode 100644 (file)
index 0000000..0c309a3
--- /dev/null
@@ -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
diff --git a/bootstrap.h b/bootstrap.h
new file mode 100644 (file)
index 0000000..515774b
--- /dev/null
@@ -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);
+
index bc2f8b2..beb24a9 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
 #! /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>.
 #
 #
 # 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'
 # 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"
 PACKAGE_BUGREPORT='andreas@eversberg.eu'
 
 ac_unique_file="main.c"
@@ -640,6 +640,8 @@ ac_includes_default="\
 ac_subst_vars='LTLIBOBJS
 POW_LIB
 LIBOBJS
 ac_subst_vars='LTLIBOBJS
 POW_LIB
 LIBOBJS
+ENABLE_GSM_FALSE
+ENABLE_GSM_TRUE
 LIBCRYPTO
 ENABLE_ASTERISK_CHANNEL_DRIVER_FALSE
 ENABLE_ASTERISK_CHANNEL_DRIVER_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
 enable_dependency_tracking
 with_asterisk
 with_ssl
+with_gsm
 '
       ac_precious_vars='build_alias
 host_alias
 '
       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
   # 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]...
 
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1363,7 +1366,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
 
 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
 
    esac
   cat <<\_ACEOF
 
@@ -1382,6 +1385,8 @@ Optional Packages:
 
   --with-ssl              compile with ssl support (libcrypto) [default=check]
 
 
   --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
 
 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
 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,
 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.
 
 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 $@
 generated by GNU Autoconf 2.63.  Invocation command line was
 
   $ $0 $@
@@ -4033,7 +4038,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=lcr
 
 # Define the identity of the package.
  PACKAGE=lcr
- VERSION=1.4
+ VERSION=1.5
 
 
 cat >>confdefs.h <<_ACEOF
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6253,6 +6258,27 @@ fi
 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
 # 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
 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
 
 : ${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="
 # 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
 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="\\
 _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'`\\"
 
 configured by $0, generated by GNU Autoconf 2.63,
   with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
index e1d3db6..bbd770f 100644 (file)
@@ -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
 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)
 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
 # 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])
 # Checks for libraries.
 AC_CHECK_LIB([m], [main])
 AC_CHECK_LIB([ncurses], [main])
diff --git a/default/gsm.conf b/default/gsm.conf
new file mode 100644 (file)
index 0000000..b7d7bac
--- /dev/null
@@ -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
+
index 51cc036..8f1dc6b 100644 (file)
 #portnum 0
 #dialmax 20
 
 #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.
 
 
 # Hint: Enter "lcr interface" for quick help on interface options.
 
 
index dfa3b34..a020f62 100644 (file)
@@ -11,6 +11,7 @@
 #define DEBUG_BCHANNEL         0x0008
 #define DEBUG_PORT     0x0100
 #define DEBUG_ISDN     0x0110
 #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
 #define DEBUG_VBOX     0x0180
 #define DEBUG_EPOINT   0x0200
 #define DEBUG_JOIN     0x0400
 # Rights must have 0 in front, if octal values above are used.
 #socketrights 0700
 
 # 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
+
index b7ff80c..c8adb27 100644 (file)
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -1,6 +1,6 @@
 /*****************************************************************************\
 **                                                                           **
 /*****************************************************************************\
 **                                                                           **
-** PBX4Linux                                                                 **
+** LCR                                                                       **
 **                                                                           **
 **---------------------------------------------------------------------------**
 ** Copyright: Andreas Eversberg                                              **
 **                                                                           **
 **---------------------------------------------------------------------------**
 ** Copyright: Andreas Eversberg                                              **
@@ -12,7 +12,7 @@
 #include "main.h"
 #include "myisdn.h"
 // socket mISDN
 #include "main.h"
 #include "myisdn.h"
 // socket mISDN
-#include <sys/socket.h>
+//#include <sys/socket.h>
 extern "C" {
 }
 #include <q931.h>
 extern "C" {
 }
 #include <q931.h>
@@ -81,8 +81,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                exclusive = 0;
        
        /* select scenario */
                exclusive = 0;
        
        /* select scenario */
-       if (p_m_b_channel && p_m_b_exclusive)
-       {
+       if (p_m_b_channel && p_m_b_exclusive) {
                /*** we gave an exclusive channel (or if we are done) ***/
 
                /* if not first reply, we are done */
                /*** we gave an exclusive channel (or if we are done) ***/
 
                /* if not first reply, we are done */
@@ -94,8 +93,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
 
                /* if give channel not accepted or not equal */
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
 
                /* if give channel not accepted or not equal */
-               if (channel!=-1 && p_m_b_channel!=channel)
-               {
+               if (channel!=-1 && p_m_b_channel!=channel) {
                        add_trace("conclusion", NULL, "forced channel not accepted");
                        end_trace();
                        ret = -44;
                        add_trace("conclusion", NULL, "forced channel not accepted");
                        end_trace();
                        ret = -44;
@@ -109,8 +107,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                /* activate our exclusive channel */
                bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
        } else
                /* activate our exclusive channel */
                bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
        } else
-       if (p_m_b_channel)
-       {
+       if (p_m_b_channel) {
                /*** we gave a non-exclusive channel ***/
 
                /* if not first reply, we are done */
                /*** we gave a non-exclusive channel ***/
 
                /* if not first reply, we are done */
@@ -122,8 +119,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
 
                /* if channel was accepted as given */
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
 
                /* if channel was accepted as given */
-               if (channel==-1 || p_m_b_channel==channel)
-               {
+               if (channel==-1 || p_m_b_channel==channel) {
                        add_trace("conclusion", NULL, "channel was accepted as given");
                        add_trace("connect", "channel", "%d", p_m_b_channel);
                        end_trace();
                        add_trace("conclusion", NULL, "channel was accepted as given");
                        add_trace("connect", "channel", "%d", p_m_b_channel);
                        end_trace();
@@ -133,8 +129,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                }
 
                /* if channel value is faulty */
                }
 
                /* if channel value is faulty */
-               if (channel <= 0)
-               {
+               if (channel <= 0) {
                        add_trace("conclusion", NULL, "illegal reply");
                        end_trace();
                        ret = -111; // protocol error
                        add_trace("conclusion", NULL, "illegal reply");
                        end_trace();
                        ret = -111; // protocol error
@@ -144,8 +139,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                /* if channel was not accepted, try to get it */
                ret = seize_bchannel(channel, 1); // exclusively
                add_trace("channel", "available", ret<0?"no":"yes");
                /* if channel was not accepted, try to get it */
                ret = seize_bchannel(channel, 1); // exclusively
                add_trace("channel", "available", ret<0?"no":"yes");
-               if (ret < 0)
-               {
+               if (ret < 0) {
                        add_trace("conclusion", NULL, "replied channel not available");
                        end_trace();
                        goto channelerror;
                        add_trace("conclusion", NULL, "replied channel not available");
                        end_trace();
                        goto channelerror;
@@ -157,8 +151,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                /* activate channel given by remote */
                bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
        } else
                /* activate channel given by remote */
                bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
        } else
-       if (p_m_b_reserve)
-       {
+       if (p_m_b_reserve) {
                /*** we sent 'any channel acceptable' ***/
 
                /* if not first reply, we are done */
                /*** we sent 'any channel acceptable' ***/
 
                /* if not first reply, we are done */
@@ -169,8 +162,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                add_trace("channel", "request", "any");
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
                /* if no channel was replied */
                add_trace("channel", "request", "any");
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
                /* if no channel was replied */
-               if (channel <= 0)
-               {
+               if (channel <= 0) {
                        add_trace("conclusion", NULL, "no channel, protocol error");
                        end_trace();
                        ret = -111; // protocol error
                        add_trace("conclusion", NULL, "no channel, protocol error");
                        end_trace();
                        ret = -111; // protocol error
@@ -180,8 +172,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                /* we will see, if our received channel is available */
                ret = seize_bchannel(channel, 1); // exclusively
                add_trace("channel", "available", ret<0?"no":"yes");
                /* we will see, if our received channel is available */
                ret = seize_bchannel(channel, 1); // exclusively
                add_trace("channel", "available", ret<0?"no":"yes");
-               if (ret < 0)
-               {
+               if (ret < 0) {
                        add_trace("conclusion", NULL, "replied channel not available");
                        end_trace();
                        goto channelerror;
                        add_trace("conclusion", NULL, "replied channel not available");
                        end_trace();
                        goto channelerror;
@@ -192,24 +183,20 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
 
                /* activate channel given by remote */
                bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
 
                /* activate channel given by remote */
                bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-       } else
-       {
+       } else {
                /*** we sent 'no channel available' ***/
 
                /* if not the first reply, but a connect, we are forced */
                /*** we sent 'no channel available' ***/
 
                /* if not the first reply, but a connect, we are forced */
-               if (cmd==MT_CONNECT && p_state!=PORT_STATE_OUT_SETUP)
-               {
+               if (cmd==MT_CONNECT && p_state!=PORT_STATE_OUT_SETUP) {
                        chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (connect)", DIRECTION_NONE);
                        add_trace("channel", "request", "no-channel");
                        add_trace("channel", "reply", (channel>=0)?"%d%s":"(none)", channel, exclusive?" (forced)":"");
                        chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (connect)", DIRECTION_NONE);
                        add_trace("channel", "request", "no-channel");
                        add_trace("channel", "reply", (channel>=0)?"%d%s":"(none)", channel, exclusive?" (forced)":"");
-                       if (channel > 0)
-                       {
+                       if (channel > 0) {
                                goto use_from_connect;
                        }
                        ret = seize_bchannel(CHANNEL_ANY, 0); // any channel
                        add_trace("channel", "available", ret<0?"no":"yes");
                                goto use_from_connect;
                        }
                        ret = seize_bchannel(CHANNEL_ANY, 0); // any channel
                        add_trace("channel", "available", ret<0?"no":"yes");
-                       if (ret < 0)
-                       {
+                       if (ret < 0) {
                                add_trace("conclusion", NULL, "no channel available during call-waiting");
                                end_trace();
                                goto channelerror;
                                add_trace("conclusion", NULL, "no channel available during call-waiting");
                                end_trace();
                                goto channelerror;
@@ -232,8 +219,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                add_trace("channel", "request", "no-channel");
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
                /* if first reply has no channel, we are done */
                add_trace("channel", "request", "no-channel");
                add_trace("channel", "reply", (channel>=0)?"%d":"(none)", channel);
                /* if first reply has no channel, we are done */
-               if (channel <= 0)
-               {
+               if (channel <= 0) {
                        add_trace("conclusion", NULL, "no channel until connect");
                        end_trace();
                        return(0);
                        add_trace("conclusion", NULL, "no channel until connect");
                        end_trace();
                        return(0);
@@ -243,8 +229,7 @@ int Pdss1::received_first_reply_to_setup(unsigned int cmd, int channel, int excl
                use_from_connect:
                ret = seize_bchannel(channel, exclusive);
                add_trace("channel", "available", ret<0?"no":"yes");
                use_from_connect:
                ret = seize_bchannel(channel, exclusive);
                add_trace("channel", "available", ret<0?"no":"yes");
-               if (ret < 0)
-               {
+               if (ret < 0) {
                        add_trace("conclusion", NULL, "replied channel not available");
                        end_trace();
                        goto channelerror;
                        add_trace("conclusion", NULL, "replied channel not available");
                        end_trace();
                        goto channelerror;
@@ -291,8 +276,7 @@ int Pdss1::hunt_bchannel(int channel, int exclusive)
                add_trace("channel", "request", "no-channel");
        else
                add_trace("channel", "request", (channel>0)?"%d%s":"any", channel, exclusive?" (forced)":"");
                add_trace("channel", "request", "no-channel");
        else
                add_trace("channel", "request", (channel>0)?"%d%s":"any", channel, exclusive?" (forced)":"");
-       if (channel==CHANNEL_NO && p_type==PORT_TYPE_DSS1_TE_IN)
-       {
+       if (channel==CHANNEL_NO && p_type==PORT_TYPE_DSS1_TE_IN) {
                add_trace("conclusion", NULL, "incoming call-waiting not supported for TE-mode");
                end_trace();
                return(-6); // channel unacceptable
                add_trace("conclusion", NULL, "incoming call-waiting not supported for TE-mode");
                end_trace();
                return(-6); // channel unacceptable
@@ -300,20 +284,17 @@ int Pdss1::hunt_bchannel(int channel, int exclusive)
        if (channel <= 0) /* not given, no channel, whatever.. */
                channel = CHANNEL_ANY; /* any channel */
        add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved);
        if (channel <= 0) /* not given, no channel, whatever.. */
                channel = CHANNEL_ANY; /* any channel */
        add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved);
-       if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) // of out chan..
-       {
+       if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) { // of out chan..
                add_trace("conclusion", NULL, "all channels are reserved");
                end_trace();
                return(-34); // no channel
        }
        if (channel == CHANNEL_ANY)
                goto get_from_list;
                add_trace("conclusion", NULL, "all channels are reserved");
                end_trace();
                return(-34); // no channel
        }
        if (channel == CHANNEL_ANY)
                goto get_from_list;
-       if (channel > 0)
-       {
+       if (channel > 0) {
                /* check for given channel in selection list */
                selchannel = ifport->in_channel;
                /* check for given channel in selection list */
                selchannel = ifport->in_channel;
-               while(selchannel)
-               {
+               while(selchannel) {
                        if (selchannel->channel == channel || selchannel->channel == CHANNEL_FREE)
                                break;
                        selchannel = selchannel->next;
                        if (selchannel->channel == channel || selchannel->channel == CHANNEL_FREE)
                                break;
                        selchannel = selchannel->next;
@@ -322,19 +303,16 @@ int Pdss1::hunt_bchannel(int channel, int exclusive)
                        channel = 0;
 
                /* exclusive channel requests must be in the list */
                        channel = 0;
 
                /* exclusive channel requests must be in the list */
-               if (exclusive)
-               {
+               if (exclusive) {
                        /* no exclusive channel */
                        /* no exclusive channel */
-                       if (!channel)
-                       {
+                       if (!channel) {
                                add_trace("conclusion", NULL, "exclusively requested channel not in list");
                                end_trace();
                                return(-6); // channel unacceptable
                        }
                        /* get index for channel */
                        i = channel-1-(channel>=17);
                                add_trace("conclusion", NULL, "exclusively requested channel not in list");
                                end_trace();
                                return(-6); // channel unacceptable
                        }
                        /* get index for channel */
                        i = channel-1-(channel>=17);
-                       if (i < 0 || i >= p_m_mISDNport->b_num || channel == 16)
-                       {
+                       if (i < 0 || i >= p_m_mISDNport->b_num || channel == 16) {
                                add_trace("conclusion", NULL, "exclusively requested channel outside interface range");
                                end_trace();
                                return(-6); // channel unacceptable
                                add_trace("conclusion", NULL, "exclusively requested channel outside interface range");
                                end_trace();
                                return(-6); // channel unacceptable
@@ -348,12 +326,10 @@ int Pdss1::hunt_bchannel(int channel, int exclusive)
                }
 
                /* requested channels in list will be used */
                }
 
                /* requested channels in list will be used */
-               if (channel)
-               {
+               if (channel) {
                        /* get index for channel */
                        i = channel-1-(channel>=17);
                        /* get index for channel */
                        i = channel-1-(channel>=17);
-                       if (i < 0 || i >= p_m_mISDNport->b_num || channel == 16)
-                       {
+                       if (i < 0 || i >= p_m_mISDNport->b_num || channel == 16) {
                                add_trace("info", NULL, "requested channel %d outside interface range", channel);
                        } else /* if inside range (else) check if available */
                        if (p_m_mISDNport->b_port[i] == NULL)
                                add_trace("info", NULL, "requested channel %d outside interface range", channel);
                        } else /* if inside range (else) check if available */
                        if (p_m_mISDNport->b_port[i] == NULL)
@@ -365,20 +341,16 @@ int Pdss1::hunt_bchannel(int channel, int exclusive)
                /* check for first free channel in list */
                channel = 0;
                selchannel = ifport->in_channel;
                /* check for first free channel in list */
                channel = 0;
                selchannel = ifport->in_channel;
-               while(selchannel)
-               {
-                       switch(selchannel->channel)
-                       {
+               while(selchannel) {
+                       switch(selchannel->channel) {
                                case CHANNEL_FREE: /* free channel */
                                add_trace("hunting", "channel", "free");
                                if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num)
                                        break; /* all channel in use or reserverd */
                                /* find channel */
                                i = 0;
                                case CHANNEL_FREE: /* free channel */
                                add_trace("hunting", "channel", "free");
                                if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num)
                                        break; /* all channel in use or reserverd */
                                /* find channel */
                                i = 0;
-                               while(i < p_m_mISDNport->b_num)
-                               {
-                                       if (p_m_mISDNport->b_port[i] == NULL)
-                                       {
+                               while(i < p_m_mISDNport->b_num) {
+                                       if (p_m_mISDNport->b_port[i] == NULL) {
                                                channel = i+1+(i>=15);
                                                break;
                                        }
                                                channel = i+1+(i>=15);
                                                break;
                                        }
@@ -393,8 +365,7 @@ int Pdss1::hunt_bchannel(int channel, int exclusive)
                                i = selchannel->channel-1-(selchannel->channel>=17);
                                if (i >= p_m_mISDNport->b_num)
                                        break; /* channel not in port */
                                i = selchannel->channel-1-(selchannel->channel>=17);
                                if (i >= p_m_mISDNport->b_num)
                                        break; /* channel not in port */
-                               if (p_m_mISDNport->b_port[i] == NULL)
-                               {
+                               if (p_m_mISDNport->b_port[i] == NULL) {
                                        channel = selchannel->channel;
                                        break;
                                }
                                        channel = selchannel->channel;
                                        break;
                                }
@@ -404,8 +375,7 @@ int Pdss1::hunt_bchannel(int channel, int exclusive)
                                break; /* found channel */
                        selchannel = selchannel->next;
                }
                                break; /* found channel */
                        selchannel = selchannel->next;
                }
-               if (!channel)
-               {
+               if (!channel) {
                        add_trace("conclusion", NULL, "no channel available");
                        end_trace();
                        return(-6); // channel unacceptable
                        add_trace("conclusion", NULL, "no channel available");
                        end_trace();
                        return(-6); // channel unacceptable
@@ -441,8 +411,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        /* process given callref */
        l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
        add_trace("callref", "new", "0x%x", pid);
        /* process given callref */
        l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
        add_trace("callref", "new", "0x%x", pid);
-       if (p_m_d_l3id)
-       {
+       if (p_m_d_l3id) {
                /* release in case the ID is already in use */
                add_trace("error", NULL, "callref already in use");
                end_trace();
                /* release in case the ID is already in use */
                add_trace("error", NULL, "callref already in use");
                end_trace();
@@ -476,8 +445,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        end_trace();
 
        /* if blocked, release call with MT_RELEASE_COMPLETE */
        end_trace();
 
        /* if blocked, release call with MT_RELEASE_COMPLETE */
-       if (p_m_mISDNport->ifport->block)
-       {
+       if (p_m_mISDNport->ifport->block) {
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_REQ, DIRECTION_OUT);
                enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 27); /* temporary unavailable */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_REQ, DIRECTION_OUT);
                enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 27); /* temporary unavailable */
@@ -490,8 +458,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        }
 
        /* caller info */
        }
 
        /* caller info */
-       switch (calling_present)
-       {
+       switch (calling_present) {
                case 1:
                p_callerinfo.present = INFO_PRESENT_RESTRICTED;
                break;
                case 1:
                p_callerinfo.present = INFO_PRESENT_RESTRICTED;
                break;
@@ -502,8 +469,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_callerinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
                p_callerinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
-       switch (calling_screen)
-       {
+       switch (calling_screen) {
                case 0:
                p_callerinfo.screen = INFO_SCREEN_USER;
                break;
                case 0:
                p_callerinfo.screen = INFO_SCREEN_USER;
                break;
@@ -511,8 +477,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_callerinfo.screen = INFO_SCREEN_NETWORK;
                break;
        }
                p_callerinfo.screen = INFO_SCREEN_NETWORK;
                break;
        }
-       switch (calling_type)
-       {
+       switch (calling_type) {
                case -1:
                p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
                case -1:
                p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
@@ -536,8 +501,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
 
        /* caller info2 */
        SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
 
        /* caller info2 */
-       switch (calling_present2)
-       {
+       switch (calling_present2) {
                case 1:
                p_callerinfo.present2 = INFO_PRESENT_RESTRICTED;
                break;
                case 1:
                p_callerinfo.present2 = INFO_PRESENT_RESTRICTED;
                break;
@@ -548,8 +512,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_callerinfo.present2 = INFO_PRESENT_ALLOWED;
                break;
        }
                p_callerinfo.present2 = INFO_PRESENT_ALLOWED;
                break;
        }
-       switch (calling_screen2)
-       {
+       switch (calling_screen2) {
                case 0:
                p_callerinfo.screen2 = INFO_SCREEN_USER;
                break;
                case 0:
                p_callerinfo.screen2 = INFO_SCREEN_USER;
                break;
@@ -557,8 +520,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_callerinfo.screen2 = INFO_SCREEN_NETWORK;
                break;
        }
                p_callerinfo.screen2 = INFO_SCREEN_NETWORK;
                break;
        }
-       switch (calling_type2)
-       {
+       switch (calling_type2) {
                case -1:
                p_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
                break;
                case -1:
                p_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
                break;
@@ -581,8 +543,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 
        /* dialing information */
        SCAT(p_dialinginfo.id, (char *)keypad);
 
        /* dialing information */
        SCAT(p_dialinginfo.id, (char *)keypad);
-       switch (called_type)
-       {
+       switch (called_type) {
                case 0x1:
                p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
                break;
                case 0x1:
                p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
                break;
@@ -598,8 +559,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        }
 
        /* redir info */
        }
 
        /* redir info */
-       switch (redir_present)
-       {
+       switch (redir_present) {
                case 1:
                p_redirinfo.present = INFO_PRESENT_RESTRICTED;
                break;
                case 1:
                p_redirinfo.present = INFO_PRESENT_RESTRICTED;
                break;
@@ -610,8 +570,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_redirinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
                p_redirinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
-       switch (redir_screen)
-       {
+       switch (redir_screen) {
                case 0:
                p_redirinfo.screen = INFO_SCREEN_USER;
                break;
                case 0:
                p_redirinfo.screen = INFO_SCREEN_USER;
                break;
@@ -619,8 +578,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_redirinfo.screen = INFO_SCREEN_NETWORK;
                break;
        }
                p_redirinfo.screen = INFO_SCREEN_NETWORK;
                break;
        }
-       switch (redir_reason)
-       {
+       switch (redir_reason) {
                case 1:
                p_redirinfo.reason = INFO_REDIR_BUSY;
                break;
                case 1:
                p_redirinfo.reason = INFO_REDIR_BUSY;
                break;
@@ -640,8 +598,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_redirinfo.reason = INFO_REDIR_UNKNOWN;
                break;
        }
                p_redirinfo.reason = INFO_REDIR_UNKNOWN;
                break;
        }
-       switch (redir_type)
-       {
+       switch (redir_type) {
                case -1:
                p_redirinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
                case -1:
                p_redirinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
@@ -664,8 +621,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        p_redirinfo.isdn_port = p_m_portnum;
 
        /* bearer capability */
        p_redirinfo.isdn_port = p_m_portnum;
 
        /* bearer capability */
-       switch (bearer_capability)
-       {
+       switch (bearer_capability) {
                case -1:
                p_capainfo.bearer_capa = INFO_BC_AUDIO;
                bearer_user = (options.law=='a')?3:2;
                case -1:
                p_capainfo.bearer_capa = INFO_BC_AUDIO;
                bearer_user = (options.law=='a')?3:2;
@@ -674,8 +630,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_capainfo.bearer_capa = bearer_capability;
                break;
        }
                p_capainfo.bearer_capa = bearer_capability;
                break;
        }
-       switch (bearer_mode)
-       {
+       switch (bearer_mode) {
                case 2:
                p_capainfo.bearer_mode = INFO_BMODE_PACKET;
                break;
                case 2:
                p_capainfo.bearer_mode = INFO_BMODE_PACKET;
                break;
@@ -683,8 +638,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
                break;
        }
                p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
                break;
        }
-       switch (bearer_user)
-       {
+       switch (bearer_user) {
                case -1:
                p_capainfo.bearer_info1 = INFO_INFO1_NONE;
                break;
                case -1:
                p_capainfo.bearer_info1 = INFO_INFO1_NONE;
                break;
@@ -694,8 +648,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        }
 
        /* hlc */
        }
 
        /* hlc */
-       switch (hlc_hlc)
-       {
+       switch (hlc_hlc) {
                case -1:
                p_capainfo.hlc = INFO_HLC_NONE;
                break;
                case -1:
                p_capainfo.hlc = INFO_HLC_NONE;
                break;
@@ -703,8 +656,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_capainfo.hlc = hlc_hlc + 0x80;
                break;
        }
                p_capainfo.hlc = hlc_hlc + 0x80;
                break;
        }
-       switch (hlc_exthlc)
-       {
+       switch (hlc_exthlc) {
                case -1:
                p_capainfo.exthlc = INFO_HLC_NONE;
                break;
                case -1:
                p_capainfo.exthlc = INFO_HLC_NONE;
                break;
@@ -729,8 +681,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 
        /* open channel */
        ret = seize_bchannel(channel, 1);
 
        /* open channel */
        ret = seize_bchannel(channel, 1);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                no_channel:
                /*
                 * NOTE: we send MT_RELEASE_COMPLETE to "REJECT" the channel
                no_channel:
                /*
                 * NOTE: we send MT_RELEASE_COMPLETE to "REJECT" the channel
@@ -788,8 +739,7 @@ void Pdss1::information_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l
        end_trace();
 
        SCAT(p_dialinginfo.id, (char *)keypad);
        end_trace();
 
        SCAT(p_dialinginfo.id, (char *)keypad);
-       switch (type)
-       {
+       switch (type) {
                case 0x1:
                p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
                break;
                case 0x1:
                p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
                break;
@@ -829,8 +779,7 @@ void Pdss1::setup_acknowledge_ind(unsigned int cmd, unsigned int pid, struct l3_
 
        /* process channel */
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
 
        /* process channel */
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -846,10 +795,9 @@ void Pdss1::setup_acknowledge_ind(unsigned int cmd, unsigned int pid, struct l3_
        new_state(PORT_STATE_OUT_OVERLAP);
 
        number = p_m_d_queue;
        new_state(PORT_STATE_OUT_OVERLAP);
 
        number = p_m_d_queue;
-       while (number[0]) /* as long we have something to dial */
-       {
-               if (max > strlen(number) || max == 0)
-                       max = strlen(number);
+       while (number[0]) { /* as long we have something to dial */
+               if (max > (int)strlen(number) || max == 0)
+                       max = (int)strlen(number);
       
                nl3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
       
                nl3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
@@ -879,8 +827,7 @@ void Pdss1::proceeding_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3
        end_trace();
 
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
        end_trace();
 
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -898,16 +845,14 @@ void Pdss1::proceeding_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3
                notify |= 0x80;
        else
                notify = 0;
                notify |= 0x80;
        else
                notify = 0;
-       if (type >= 0 || notify)
-       {
+       if (type >= 0 || notify) {
                if (!notify && type >= 0)
                        notify = 251;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
                message->param.notifyinfo.notify = notify;
                SCPY(message->param.notifyinfo.id, redir);
                /* redirection number */
                if (!notify && type >= 0)
                        notify = 251;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
                message->param.notifyinfo.notify = notify;
                SCPY(message->param.notifyinfo.id, redir);
                /* redirection number */
-               switch (present)
-               {
+               switch (present) {
                        case 1:
                        message->param.notifyinfo.present = INFO_PRESENT_RESTRICTED;
                        break;
                        case 1:
                        message->param.notifyinfo.present = INFO_PRESENT_RESTRICTED;
                        break;
@@ -918,8 +863,7 @@ void Pdss1::proceeding_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3
                        message->param.notifyinfo.present = INFO_PRESENT_ALLOWED;
                        break;
                }
                        message->param.notifyinfo.present = INFO_PRESENT_ALLOWED;
                        break;
                }
-               switch (type)
-               {
+               switch (type) {
                        case -1:
                        message->param.notifyinfo.ntype = INFO_NTYPE_NOTPRESENT;
                        break;
                        case -1:
                        message->param.notifyinfo.ntype = INFO_NTYPE_NOTPRESENT;
                        break;
@@ -960,8 +904,7 @@ void Pdss1::alerting_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 
        /* process channel */
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
 
        /* process channel */
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -979,15 +922,13 @@ void Pdss1::alerting_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                notify |= 0x80;
        else
                notify = 0;
                notify |= 0x80;
        else
                notify = 0;
-       if (type >= 0 || notify)
-       {
+       if (type >= 0 || notify) {
                if (!notify && type >= 0)
                        notify = 251;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
                message->param.notifyinfo.notify = notify;
                SCPY(message->param.notifyinfo.id, redir);
                if (!notify && type >= 0)
                        notify = 251;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
                message->param.notifyinfo.notify = notify;
                SCPY(message->param.notifyinfo.id, redir);
-               switch (present)
-               {
+               switch (present) {
                        case 1:
                        message->param.notifyinfo.present = INFO_PRESENT_RESTRICTED;
                        break;
                        case 1:
                        message->param.notifyinfo.present = INFO_PRESENT_RESTRICTED;
                        break;
@@ -998,8 +939,7 @@ void Pdss1::alerting_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                        message->param.notifyinfo.present = INFO_PRESENT_ALLOWED;
                        break;
                }
                        message->param.notifyinfo.present = INFO_PRESENT_ALLOWED;
                        break;
                }
-               switch (type)
-               {
+               switch (type) {
                        case -1:
                        message->param.notifyinfo.ntype = INFO_NTYPE_NOTPRESENT;
                        break;
                        case -1:
                        message->param.notifyinfo.ntype = INFO_NTYPE_NOTPRESENT;
                        break;
@@ -1041,8 +981,7 @@ void Pdss1::connect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        /* select channel */
        bchannel_before = p_m_b_channel;
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
        /* select channel */
        bchannel_before = p_m_b_channel;
        ret = received_first_reply_to_setup(cmd, channel, exclusive);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = -ret;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -1053,8 +992,7 @@ void Pdss1::connect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        }
 
        /* connect information */
        }
 
        /* connect information */
-       switch (present)
-       {
+       switch (present) {
                case 1:
                p_connectinfo.present = INFO_PRESENT_RESTRICTED;
                break;
                case 1:
                p_connectinfo.present = INFO_PRESENT_RESTRICTED;
                break;
@@ -1065,8 +1003,7 @@ void Pdss1::connect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_connectinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
                p_connectinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
-       switch (screen)
-       {
+       switch (screen) {
                case 0:
                p_connectinfo.screen = INFO_SCREEN_USER;
                break;
                case 0:
                p_connectinfo.screen = INFO_SCREEN_USER;
                break;
@@ -1074,8 +1011,7 @@ void Pdss1::connect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                p_connectinfo.screen = INFO_SCREEN_NETWORK;
                break;
        }
                p_connectinfo.screen = INFO_SCREEN_NETWORK;
                break;
        }
-       switch (type)
-       {
+       switch (type) {
                case -1:
                p_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
                case -1:
                p_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
@@ -1096,8 +1032,7 @@ void Pdss1::connect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
 
        /* only in nt-mode we send connect ack. in te-mode it is done by stack itself or optional */
        SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
 
        /* only in nt-mode we send connect ack. in te-mode it is done by stack itself or optional */
-       if (p_m_d_ntmode)
-       {
+       if (p_m_d_ntmode) {
                /* send connect acknowledge */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_CONNECT_RES, DIRECTION_OUT);
                /* send connect acknowledge */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_CONNECT_RES, DIRECTION_OUT);
@@ -1133,8 +1068,7 @@ void Pdss1::disconnect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3
                cause = 16;
 
        /* release if remote sends us no tones */
                cause = 16;
 
        /* release if remote sends us no tones */
-       if (!p_m_mISDNport->earlyb)
-       {
+       if (!p_m_mISDNport->earlyb) {
                l3_msg *l3m;
 
                l3m = create_l3msg();
                l3_msg *l3m;
 
                l3m = create_l3msg();
@@ -1147,8 +1081,7 @@ void Pdss1::disconnect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3
                /* sending release to endpoint */
                if (location == LOCATION_PRIVATE_LOCAL)
                        location = LOCATION_PRIVATE_REMOTE;
                /* sending release to endpoint */
                if (location == LOCATION_PRIVATE_LOCAL)
                        location = LOCATION_PRIVATE_REMOTE;
-               while(p_epointlist)
-               {
+               while(p_epointlist) {
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                        message->param.disconnectinfo.cause = cause;
                        message->param.disconnectinfo.location = location;
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                        message->param.disconnectinfo.cause = cause;
                        message->param.disconnectinfo.location = location;
@@ -1165,16 +1098,14 @@ void Pdss1::disconnect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3
        /* sending disconnect to active endpoint and release to inactive endpoints */
        if (location == LOCATION_PRIVATE_LOCAL)
                location = LOCATION_PRIVATE_REMOTE;
        /* sending disconnect to active endpoint and release to inactive endpoints */
        if (location == LOCATION_PRIVATE_LOCAL)
                location = LOCATION_PRIVATE_REMOTE;
-       if (ACTIVE_EPOINT(p_epointlist))
-       {
+       if (ACTIVE_EPOINT(p_epointlist)) {
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
                message->param.disconnectinfo.location = location;
                message->param.disconnectinfo.cause = cause;
                SCAT(message->param.disconnectinfo.display, (char *)display);
                message_put(message);
        }
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
                message->param.disconnectinfo.location = location;
                message->param.disconnectinfo.cause = cause;
                SCAT(message->param.disconnectinfo.display, (char *)display);
                message_put(message);
        }
-       while(INACTIVE_EPOINT(p_epointlist))
-       {
+       while(INACTIVE_EPOINT(p_epointlist)) {
                message = message_create(p_serial, INACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.location = location;
                message->param.disconnectinfo.cause = cause;
                message = message_create(p_serial, INACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.location = location;
                message->param.disconnectinfo.cause = cause;
@@ -1193,8 +1124,7 @@ void Pdss1::disconnect_ind_i(unsigned int cmd, unsigned int pid, struct l3_msg *
 
        /* cause */
        l1l2l3_trace_header(p_m_mISDNport, this, L3_DISCONNECT_IND, DIRECTION_IN);
 
        /* cause */
        l1l2l3_trace_header(p_m_mISDNport, this, L3_DISCONNECT_IND, DIRECTION_IN);
-       if (p_m_d_collect_cause > 0)
-       {
+       if (p_m_d_collect_cause > 0) {
                add_trace("old-cause", "location", "%d", p_m_d_collect_location);
                add_trace("old-cause", "value", "%d", p_m_d_collect_cause);
        }
                add_trace("old-cause", "location", "%d", p_m_d_collect_location);
                add_trace("old-cause", "value", "%d", p_m_d_collect_cause);
        }
@@ -1228,8 +1158,7 @@ void Pdss1::release_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        /* sending release to endpoint */
        if (location == LOCATION_PRIVATE_LOCAL)
                location = LOCATION_PRIVATE_REMOTE;
        /* sending release to endpoint */
        if (location == LOCATION_PRIVATE_LOCAL)
                location = LOCATION_PRIVATE_REMOTE;
-       while(p_epointlist)
-       {
+       while(p_epointlist) {
                message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = cause;
                message->param.disconnectinfo.location = location;
                message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = cause;
                message->param.disconnectinfo.location = location;
@@ -1260,12 +1189,10 @@ void Pdss1::release_complete_ind(unsigned int cmd, unsigned int pid, struct l3_m
        
        l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_IND, DIRECTION_IN);
        /* in case layer 2 is down during setup, we send cause 27 loc 5 */
        
        l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_IND, DIRECTION_IN);
        /* in case layer 2 is down during setup, we send cause 27 loc 5 */
-       if (p_state == PORT_STATE_OUT_SETUP && p_m_mISDNport->l1link == 0)
-       {
+       if (p_state == PORT_STATE_OUT_SETUP && p_m_mISDNport->l1link == 0) {
                cause = 27;
                location = 5;
                cause = 27;
                location = 5;
-       } else
-       {
+       } else {
                dec_ie_cause(l3m, &location, &cause);
                if (p_m_mISDNport->l1link < 0)
                        add_trace("layer 1", NULL, "unknown");
                dec_ie_cause(l3m, &location, &cause);
                if (p_m_mISDNport->l1link < 0)
                        add_trace("layer 1", NULL, "unknown");
@@ -1280,8 +1207,7 @@ void Pdss1::release_complete_ind(unsigned int cmd, unsigned int pid, struct l3_m
                cause = 16;
 
        /* sending release to endpoint */
                cause = 16;
 
        /* sending release to endpoint */
-       while(p_epointlist)
-       {
+       while(p_epointlist) {
                message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = cause;
                message->param.disconnectinfo.location = location;
                message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = cause;
                message->param.disconnectinfo.location = location;
@@ -1324,8 +1250,7 @@ void Pdss1::notify_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        message->param.notifyinfo.notify = notify;
        SCPY(message->param.notifyinfo.id, (char *)notifyid);
        /* redirection number */
        message->param.notifyinfo.notify = notify;
        SCPY(message->param.notifyinfo.id, (char *)notifyid);
        /* redirection number */
-       switch (present)
-       {
+       switch (present) {
                case 1:
                message->param.notifyinfo.present = INFO_PRESENT_RESTRICTED;
                break;
                case 1:
                message->param.notifyinfo.present = INFO_PRESENT_RESTRICTED;
                break;
@@ -1336,8 +1261,7 @@ void Pdss1::notify_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                message->param.notifyinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
                message->param.notifyinfo.present = INFO_PRESENT_ALLOWED;
                break;
        }
-       switch (type)
-       {
+       switch (type) {
                case -1:
                message->param.notifyinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
                case -1:
                message->param.notifyinfo.ntype = INFO_NTYPE_NOTPRESENT;
                break;
@@ -1369,8 +1293,7 @@ void Pdss1::hold_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        l1l2l3_trace_header(p_m_mISDNport, this, L3_HOLD_IND, DIRECTION_IN);
        end_trace();
 
        l1l2l3_trace_header(p_m_mISDNport, this, L3_HOLD_IND, DIRECTION_IN);
        end_trace();
 
-       if (!ACTIVE_EPOINT(p_epointlist) || p_m_hold)
-       {
+       if (!ACTIVE_EPOINT(p_epointlist) || p_m_hold) {
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_HOLD_REJECT_REQ, DIRECTION_OUT);
                enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, p_m_hold?101:31); /* normal unspecified / incompatible state */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_HOLD_REJECT_REQ, DIRECTION_OUT);
                enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, p_m_hold?101:31); /* normal unspecified / incompatible state */
@@ -1397,8 +1320,7 @@ void Pdss1::hold_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        p_m_hold = 1;
 #if 0
        epoint = find_epoint_id(ACTIVE_EPOINT(p_epointlist));
        p_m_hold = 1;
 #if 0
        epoint = find_epoint_id(ACTIVE_EPOINT(p_epointlist));
-       if (epoint && p_m_d_ntmode)
-       {
+       if (epoint && p_m_d_ntmode) {
                p_m_timeout = p_settings.tout_hold;
                time(&p_m_timer);
        }
                p_m_timeout = p_settings.tout_hold;
                time(&p_m_timer);
        }
@@ -1423,8 +1345,7 @@ void Pdss1::retrieve_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        dec_ie_channel_id(l3m, &exclusive, &channel);
        end_trace();
 
        dec_ie_channel_id(l3m, &exclusive, &channel);
        end_trace();
 
-       if (!p_m_hold)
-       {
+       if (!p_m_hold) {
                cause = 101; /* incompatible state */
                reject:
 
                cause = 101; /* incompatible state */
                reject:
 
@@ -1450,8 +1371,7 @@ void Pdss1::retrieve_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 
        /* open channel */
        ret = seize_bchannel(channel, 1);
 
        /* open channel */
        ret = seize_bchannel(channel, 1);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                no_channel:
                cause = -ret;
                goto reject;
                no_channel:
                cause = -ret;
                goto reject;
@@ -1483,8 +1403,7 @@ void Pdss1::suspend_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        dec_ie_call_id(l3m, callid, &len);
        end_trace();
 
        dec_ie_call_id(l3m, callid, &len);
        end_trace();
 
-       if (!ACTIVE_EPOINT(p_epointlist))
-       {
+       if (!ACTIVE_EPOINT(p_epointlist)) {
                reject:
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_SUSPEND_REJECT_REQ, DIRECTION_OUT);
                reject:
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_SUSPEND_REJECT_REQ, DIRECTION_OUT);
@@ -1499,13 +1418,10 @@ void Pdss1::suspend_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 
        /* check if call id is in use */
        epoint = epoint_first;
 
        /* check if call id is in use */
        epoint = epoint_first;
-       while(epoint)
-       {
-               if (epoint->ep_park)
-               {
+       while(epoint) {
+               if (epoint->ep_park) {
                        if (epoint->ep_park_len == len)
                        if (epoint->ep_park_len == len)
-                       if (!memcmp(epoint->ep_park_callid, callid, len))
-                       {
+                       if (!memcmp(epoint->ep_park_callid, callid, len)) {
                                ret = -84; /* call id in use */
                                goto reject;
                        }
                                ret = -84; /* call id in use */
                                goto reject;
                        }
@@ -1526,8 +1442,7 @@ void Pdss1::suspend_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        drop_bchannel();
 
        /* sending suspend to endpoint */
        drop_bchannel();
 
        /* sending suspend to endpoint */
-       while (p_epointlist)
-       {
+       while (p_epointlist) {
                message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_SUSPEND);
                memcpy(message->param.parkinfo.callid, callid, sizeof(message->param.parkinfo.callid));
                message->param.parkinfo.len = len;
                message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_SUSPEND);
                memcpy(message->param.parkinfo.callid, callid, sizeof(message->param.parkinfo.callid));
                message->param.parkinfo.len = len;
@@ -1559,8 +1474,7 @@ void Pdss1::resume_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        /* process given callref */
        l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
        add_trace("callref", "new", "0x%x", pid);
        /* process given callref */
        l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
        add_trace("callref", "new", "0x%x", pid);
-       if (p_m_d_l3id)
-       {
+       if (p_m_d_l3id) {
                /* release is case the ID is already in use */
                add_trace("error", NULL, "callref already in use");
                end_trace();
                /* release is case the ID is already in use */
                add_trace("error", NULL, "callref already in use");
                end_trace();
@@ -1583,8 +1497,7 @@ void Pdss1::resume_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        end_trace();
 
        /* if blocked, release call */
        end_trace();
 
        /* if blocked, release call */
-       if (p_m_mISDNport->ifport->block)
-       {
+       if (p_m_mISDNport->ifport->block) {
                ret = -27;
                goto reject;
        }
                ret = -27;
                goto reject;
        }
@@ -1604,8 +1517,7 @@ void Pdss1::resume_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 // mode (if hdlc parked) to be done. never mind, this is almost never requested
        /* open channel */
        ret = seize_bchannel(channel, 1);
 // mode (if hdlc parked) to be done. never mind, this is almost never requested
        /* open channel */
        ret = seize_bchannel(channel, 1);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                no_channel:
                reject:
                l3m = create_l3msg();
                no_channel:
                reject:
                l3m = create_l3msg();
@@ -1626,10 +1538,8 @@ void Pdss1::resume_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                FATAL("Incoming resume but already got an endpoint.\n");
        ret = -85; /* no call suspended */
        epoint = epoint_first;
                FATAL("Incoming resume but already got an endpoint.\n");
        ret = -85; /* no call suspended */
        epoint = epoint_first;
-       while(epoint)
-       {
-               if (epoint->ep_park)
-               {
+       while(epoint) {
+               if (epoint->ep_park) {
                        ret = -83; /* suspended call exists, but this not */
                        if (epoint->ep_park_len == len)
                        if (!memcmp(epoint->ep_park_callid, callid, len))
                        ret = -83; /* suspended call exists, but this not */
                        if (epoint->ep_park_len == len)
                        if (!memcmp(epoint->ep_park_callid, callid, len))
@@ -1688,9 +1598,6 @@ void Pdss1::facility_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 /* CC_PROGRESS INDICATION */
 void Pdss1::progress_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 {
 /* CC_PROGRESS INDICATION */
 void Pdss1::progress_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 {
-       unsigned char facil[256];
-       int facil_len;
-       struct lcr_msg *message;
        int coding, location, progress;
 
        l1l2l3_trace_header(p_m_mISDNport, this, L3_PROGRESS_IND, DIRECTION_IN);
        int coding, location, progress;
 
        l1l2l3_trace_header(p_m_mISDNport, this, L3_PROGRESS_IND, DIRECTION_IN);
@@ -1707,16 +1614,13 @@ void Pdss1::message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 {
        int timer = 0;
 
 {
        int timer = 0;
 
-       switch (cmd)
-       {
+       switch (cmd) {
                case MT_TIMEOUT:
                case MT_TIMEOUT:
-               if (!l3m->cause)
-               {
+               if (!l3m->cause) {
                        PERROR("Pdss1(%s) timeout without cause.\n", p_name);
                        break;
                }
                        PERROR("Pdss1(%s) timeout without cause.\n", p_name);
                        break;
                }
-               if (l3m->cause[0] != 5)
-               {
+               if (l3m->cause[0] != 5) {
                        PERROR("Pdss1(%s) expecting timeout with timer diagnostic. (got len=%d)\n", p_name, l3m->cause[0]);
                        break;
                }
                        PERROR("Pdss1(%s) expecting timeout with timer diagnostic. (got len=%d)\n", p_name, l3m->cause[0]);
                        break;
                }
@@ -1741,8 +1645,7 @@ void Pdss1::message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                break;
 
                case MT_SETUP_ACKNOWLEDGE:
                break;
 
                case MT_SETUP_ACKNOWLEDGE:
-               if (p_state != PORT_STATE_OUT_SETUP)
-               {
+               if (p_state != PORT_STATE_OUT_SETUP) {
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received setup_acknowledge, but we are not in outgoing setup state, IGNORING.\n", p_name);
                        break;
                }
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received setup_acknowledge, but we are not in outgoing setup state, IGNORING.\n", p_name);
                        break;
                }
@@ -1751,8 +1654,7 @@ void Pdss1::message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 
                case MT_CALL_PROCEEDING:
                if (p_state != PORT_STATE_OUT_SETUP
 
                case MT_CALL_PROCEEDING:
                if (p_state != PORT_STATE_OUT_SETUP
-                && p_state != PORT_STATE_OUT_OVERLAP)
-               {
+                && p_state != PORT_STATE_OUT_OVERLAP) {
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received proceeding, but we are not in outgoing setup OR overlap state, IGNORING.\n", p_name);
                        break;
                }
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received proceeding, but we are not in outgoing setup OR overlap state, IGNORING.\n", p_name);
                        break;
                }
@@ -1762,8 +1664,7 @@ void Pdss1::message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                case MT_ALERTING:
                if (p_state != PORT_STATE_OUT_SETUP
                 && p_state != PORT_STATE_OUT_OVERLAP
                case MT_ALERTING:
                if (p_state != PORT_STATE_OUT_SETUP
                 && p_state != PORT_STATE_OUT_OVERLAP
-                && p_state != PORT_STATE_OUT_PROCEEDING)
-               {
+                && p_state != PORT_STATE_OUT_PROCEEDING) {
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received alerting, but we are not in outgoing setup OR overlap OR proceeding state, IGNORING.\n", p_name);
                        break;
                }
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received alerting, but we are not in outgoing setup OR overlap OR proceeding state, IGNORING.\n", p_name);
                        break;
                }
@@ -1774,14 +1675,12 @@ void Pdss1::message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                if (p_state != PORT_STATE_OUT_SETUP
                 && p_state != PORT_STATE_OUT_OVERLAP
                 && p_state != PORT_STATE_OUT_PROCEEDING
                if (p_state != PORT_STATE_OUT_SETUP
                 && p_state != PORT_STATE_OUT_OVERLAP
                 && p_state != PORT_STATE_OUT_PROCEEDING
-                && p_state != PORT_STATE_OUT_ALERTING)
-               {
+                && p_state != PORT_STATE_OUT_ALERTING) {
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received alerting, but we are not in outgoing setup OR overlap OR proceeding OR ALERTING state, IGNORING.\n", p_name);
                        break;
                }
                connect_ind(cmd, pid, l3m);
                        PDEBUG(DEBUG_ISDN, "Pdss1(%s) received alerting, but we are not in outgoing setup OR overlap OR proceeding OR ALERTING state, IGNORING.\n", p_name);
                        break;
                }
                connect_ind(cmd, pid, l3m);
-               if (p_m_d_notify_pending)
-               {
+               if (p_m_d_notify_pending) {
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
@@ -1792,8 +1691,7 @@ void Pdss1::message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                case MT_CONNECT_ACKNOWLEDGE:
                if (p_state == PORT_STATE_CONNECT_WAITING)
                        new_state(PORT_STATE_CONNECT);
                case MT_CONNECT_ACKNOWLEDGE:
                if (p_state == PORT_STATE_CONNECT_WAITING)
                        new_state(PORT_STATE_CONNECT);
-               if (p_m_d_notify_pending)
-               {
+               if (p_m_d_notify_pending) {
                        /* send pending notify message during connect-ack */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
                        /* send pending notify message during connect-ack */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
@@ -1855,16 +1753,13 @@ void Pdss1::message_isdn(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
                /* sending release to endpoint in case we still have an endpoint
                 * this is because we don't get any response if a release_complete is received (or a release in release state)
                 */
                /* sending release to endpoint in case we still have an endpoint
                 * this is because we don't get any response if a release_complete is received (or a release in release state)
                 */
-               while(p_epointlist) // only if not already released
-               {
+               while(p_epointlist) { // only if not already released
                        struct lcr_msg *message;
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                        struct lcr_msg *message;
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-                       if (p_m_d_collect_cause)
-                       {
+                       if (p_m_d_collect_cause) {
                                message->param.disconnectinfo.cause = p_m_d_collect_cause;
                                message->param.disconnectinfo.location = p_m_d_collect_location;
                                message->param.disconnectinfo.cause = p_m_d_collect_cause;
                                message->param.disconnectinfo.location = p_m_d_collect_location;
-                       } else
-                       {
+                       } else {
                                message->param.disconnectinfo.cause = CAUSE_NOUSER;
                                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                        }
                                message->param.disconnectinfo.cause = CAUSE_NOUSER;
                                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                        }
@@ -1888,41 +1783,34 @@ void Pdss1::new_state(int state)
 //     class Endpoint *epoint;
 
        /* set timeout */
 //     class Endpoint *epoint;
 
        /* set timeout */
-       if (state == PORT_STATE_IN_OVERLAP)
-       {
+       if (state == PORT_STATE_IN_OVERLAP) {
                p_m_timeout = p_m_mISDNport->ifport->tout_dialing;
                time(&p_m_timer);
        }
                p_m_timeout = p_m_mISDNport->ifport->tout_dialing;
                time(&p_m_timer);
        }
-       if (state != p_state)
-       {
+       if (state != p_state) {
                if (state == PORT_STATE_IN_SETUP
                 || state == PORT_STATE_OUT_SETUP
                 || state == PORT_STATE_IN_OVERLAP
                if (state == PORT_STATE_IN_SETUP
                 || state == PORT_STATE_OUT_SETUP
                 || state == PORT_STATE_IN_OVERLAP
-                || state == PORT_STATE_OUT_OVERLAP)
-               {
+                || state == PORT_STATE_OUT_OVERLAP) {
                        p_m_timeout = p_m_mISDNport->ifport->tout_setup;
                        time(&p_m_timer);
                }
                if (state == PORT_STATE_IN_PROCEEDING
                        p_m_timeout = p_m_mISDNport->ifport->tout_setup;
                        time(&p_m_timer);
                }
                if (state == PORT_STATE_IN_PROCEEDING
-                || state == PORT_STATE_OUT_PROCEEDING)
-               {
+                || state == PORT_STATE_OUT_PROCEEDING) {
                        p_m_timeout = p_m_mISDNport->ifport->tout_proceeding;
                        time(&p_m_timer);
                }
                if (state == PORT_STATE_IN_ALERTING
                        p_m_timeout = p_m_mISDNport->ifport->tout_proceeding;
                        time(&p_m_timer);
                }
                if (state == PORT_STATE_IN_ALERTING
-                || state == PORT_STATE_OUT_ALERTING)
-               {
+                || state == PORT_STATE_OUT_ALERTING) {
                        p_m_timeout = p_m_mISDNport->ifport->tout_alerting;
                        time(&p_m_timer);
                }
                if (state == PORT_STATE_CONNECT
                        p_m_timeout = p_m_mISDNport->ifport->tout_alerting;
                        time(&p_m_timer);
                }
                if (state == PORT_STATE_CONNECT
-                || state == PORT_STATE_CONNECT_WAITING)
-               {
+                || state == PORT_STATE_CONNECT_WAITING) {
                        p_m_timeout = 0;
                }
                if (state == PORT_STATE_IN_DISCONNECT
                        p_m_timeout = 0;
                }
                if (state == PORT_STATE_IN_DISCONNECT
-                || state == PORT_STATE_OUT_DISCONNECT)
-               {
+                || state == PORT_STATE_OUT_DISCONNECT) {
                        p_m_timeout = p_m_mISDNport->ifport->tout_disconnect;
                        time(&p_m_timer);
                }
                        p_m_timeout = p_m_mISDNport->ifport->tout_disconnect;
                        time(&p_m_timer);
                }
@@ -1943,8 +1831,7 @@ int Pdss1::handler(void)
                return(ret);
 
        /* handle destruction */
                return(ret);
 
        /* handle destruction */
-       if (p_m_delete && p_m_d_l3id==0)
-       {
+       if (p_m_delete && p_m_d_l3id==0) {
                delete this;
                return(-1);
        }
                delete this;
                return(-1);
        }
@@ -1964,10 +1851,9 @@ void Pdss1::message_information(unsigned int epoint_id, int message_id, union pa
        char *number = param->information.id;
        int max = p_m_mISDNport->ifport->dialmax;
 
        char *number = param->information.id;
        int max = p_m_mISDNport->ifport->dialmax;
 
-       while (number[0]) /* as long we have something to dial */
-       {
-               if (max > strlen(number) || max == 0)
-                       max = strlen(number);
+       while (number[0]) { /* as long we have something to dial */
+               if (max > (int)strlen(number) || max == 0)
+                       max = (int)strlen(number);
       
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
       
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
@@ -1999,8 +1885,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        int max = p_m_mISDNport->ifport->dialmax;
 
        /* release if port is blocked */
        int max = p_m_mISDNport->ifport->dialmax;
 
        /* release if port is blocked */
-       if (p_m_mISDNport->ifport->block)
-       {
+       if (p_m_mISDNport->ifport->block) {
                struct lcr_msg *message;
 
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                struct lcr_msg *message;
 
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -2023,13 +1908,11 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
 
        /* only display at connect state: this case happens if endpoint is in connected mode */
        do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
 
        /* only display at connect state: this case happens if endpoint is in connected mode */
-       if (p_state==PORT_STATE_CONNECT)
-       {
+       if (p_state==PORT_STATE_CONNECT) {
                if (p_type!=PORT_TYPE_DSS1_NT_OUT
                 && p_type!=PORT_TYPE_DSS1_NT_IN)
                        return;
                if (p_type!=PORT_TYPE_DSS1_NT_OUT
                 && p_type!=PORT_TYPE_DSS1_NT_IN)
                        return;
-               if (p_callerinfo.display[0])
-               {
+               if (p_callerinfo.display[0]) {
                        /* sending information */
                        l3m = create_l3msg();
                        l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
                        /* sending information */
                        l3m = create_l3msg();
                        l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
@@ -2043,8 +1926,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
 
        /* attach only if not already */
        epointlist = p_epointlist;
 
        /* attach only if not already */
        epointlist = p_epointlist;
-       while(epointlist)
-       {
+       while(epointlist) {
                if (epointlist->epoint_id == epoint_id)
                        break;
                epointlist = epointlist->next;
                if (epointlist->epoint_id == epoint_id)
                        break;
                epointlist = epointlist->next;
@@ -2054,8 +1936,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
 
        /* get channel */
        exclusive = 0;
 
        /* get channel */
        exclusive = 0;
-       if (p_m_b_channel)
-       {
+       if (p_m_b_channel) {
                channel = p_m_b_channel;
                exclusive = p_m_b_exclusive;
        } else
                channel = p_m_b_channel;
                exclusive = p_m_b_exclusive;
        } else
@@ -2069,8 +1950,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        /* see MT_ASSIGN notes at do_layer3() */
        mt_assign_pid = 0;
        ret = p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_ASSIGN, 0, NULL);
        /* see MT_ASSIGN notes at do_layer3() */
        mt_assign_pid = 0;
        ret = p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_ASSIGN, 0, NULL);
-       if (mt_assign_pid == 0 || ret < 0)
-       {
+       if (mt_assign_pid == 0 || ret < 0) {
                struct lcr_msg *message;
 
                add_trace("callref", NULL, "no free id");
                struct lcr_msg *message;
 
                add_trace("callref", NULL, "no free id");
@@ -2093,13 +1973,10 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        l1l2l3_trace_header(p_m_mISDNport, this, L3_SETUP_REQ, DIRECTION_OUT);
        /* channel information */
        if (channel >= 0) /* it should */
        l1l2l3_trace_header(p_m_mISDNport, this, L3_SETUP_REQ, DIRECTION_OUT);
        /* channel information */
        if (channel >= 0) /* it should */
-       {
                enc_ie_channel_id(l3m, exclusive, channel);
                enc_ie_channel_id(l3m, exclusive, channel);
-       }
        /* caller information */
        plan = 1;
        /* caller information */
        plan = 1;
-       switch (p_callerinfo.ntype)
-       {
+       switch (p_callerinfo.ntype) {
                case INFO_NTYPE_UNKNOWN:
                type = 0x0;
                break;
                case INFO_NTYPE_UNKNOWN:
                type = 0x0;
                break;
@@ -2116,8 +1993,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
                type = -1;
                break;
        }
                type = -1;
                break;
        }
-       switch (p_callerinfo.screen)
-       {
+       switch (p_callerinfo.screen) {
                case INFO_SCREEN_USER:
                screen = 0;
                break;
                case INFO_SCREEN_USER:
                screen = 0;
                break;
@@ -2125,8 +2001,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
                screen = 3;
                break;
        }
                screen = 3;
                break;
        }
-       switch (p_callerinfo.present)
-       {
+       switch (p_callerinfo.present) {
                case INFO_PRESENT_ALLOWED:
                present = 0;
                break;
                case INFO_PRESENT_ALLOWED:
                present = 0;
                break;
@@ -2139,8 +2014,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        }
        /* caller information 2 */
        plan2 = 1;
        }
        /* caller information 2 */
        plan2 = 1;
-       switch (p_callerinfo.ntype2)
-       {
+       switch (p_callerinfo.ntype2) {
                case INFO_NTYPE_UNKNOWN:
                type2 = 0x0;
                break;
                case INFO_NTYPE_UNKNOWN:
                type2 = 0x0;
                break;
@@ -2157,8 +2031,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
                type2 = -1;
                break;
        }
                type2 = -1;
                break;
        }
-       switch (p_callerinfo.screen2)
-       {
+       switch (p_callerinfo.screen2) {
                case INFO_SCREEN_USER:
                screen2 = 0;
                break;
                case INFO_SCREEN_USER:
                screen2 = 0;
                break;
@@ -2166,8 +2039,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
                screen2 = 3;
                break;
        }
                screen2 = 3;
                break;
        }
-       switch (p_callerinfo.present2)
-       {
+       switch (p_callerinfo.present2) {
                case INFO_PRESENT_ALLOWED:
                present2 = 0;
                break;
                case INFO_PRESENT_ALLOWED:
                present2 = 0;
                break;
@@ -2181,10 +2053,9 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        if (type >= 0)
                enc_ie_calling_pn(l3m, type, plan, present, screen, (unsigned char *)p_callerinfo.id, type2, plan2, present2, screen2, (unsigned char *)p_callerinfo.id2);
        /* dialing information */
        if (type >= 0)
                enc_ie_calling_pn(l3m, type, plan, present, screen, (unsigned char *)p_callerinfo.id, type2, plan2, present2, screen2, (unsigned char *)p_callerinfo.id2);
        /* dialing information */
-       if (p_dialinginfo.id[0]) /* only if we have something to dial */
-       {
-               if (max > strlen(p_dialinginfo.id) || max == 0)
-                       max = strlen(p_dialinginfo.id);
+       if (p_dialinginfo.id[0]) { /* only if we have something to dial */
+               if (max > (int)strlen(p_dialinginfo.id) || max == 0)
+                       max = (int)strlen(p_dialinginfo.id);
                enc_ie_called_pn(l3m, 0, 1, (unsigned char *)p_dialinginfo.id, max);
                SCPY(p_m_d_queue, p_dialinginfo.id + max);
        }
                enc_ie_called_pn(l3m, 0, 1, (unsigned char *)p_dialinginfo.id, max);
                SCPY(p_m_d_queue, p_dialinginfo.id + max);
        }
@@ -2192,14 +2063,12 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        if (p_dialinginfo.sending_complete)
                enc_ie_complete(l3m, 1);
        /* sending user-user */
        if (p_dialinginfo.sending_complete)
                enc_ie_complete(l3m, 1);
        /* sending user-user */
-       if (param->setup.useruser.len)
-       {
+       if (param->setup.useruser.len) {
                enc_ie_useruser(l3m, param->setup.useruser.protocol, param->setup.useruser.data, param->setup.useruser.len);
        }
        /* redirecting number */
        plan = 1;
                enc_ie_useruser(l3m, param->setup.useruser.protocol, param->setup.useruser.data, param->setup.useruser.len);
        }
        /* redirecting number */
        plan = 1;
-       switch (p_redirinfo.ntype)
-       {
+       switch (p_redirinfo.ntype) {
                case INFO_NTYPE_UNKNOWN:
                type = 0x0;
                break;
                case INFO_NTYPE_UNKNOWN:
                type = 0x0;
                break;
@@ -2216,8 +2085,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
                type = -1;
                break;
        }
                type = -1;
                break;
        }
-       switch (p_redirinfo.screen)
-       {
+       switch (p_redirinfo.screen) {
                case INFO_SCREEN_USER:
                screen = 0;
                break;
                case INFO_SCREEN_USER:
                screen = 0;
                break;
@@ -2225,8 +2093,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
                screen = 3;
                break;
        }
                screen = 3;
                break;
        }
-       switch (p_redirinfo.reason)
-       {
+       switch (p_redirinfo.reason) {
                case INFO_REDIR_BUSY:
                reason = 1;
                break;
                case INFO_REDIR_BUSY:
                reason = 1;
                break;
@@ -2246,8 +2113,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
                reason = 0;
                break;
        }
                reason = 0;
                break;
        }
-       switch (p_redirinfo.present)
-       {
+       switch (p_redirinfo.present) {
                case INFO_PRESENT_ALLOWED:
                present = 0;
                break;
                case INFO_PRESENT_ALLOWED:
                present = 0;
                break;
@@ -2267,8 +2133,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        capability = p_capainfo.bearer_capa;
        mode = p_capainfo.bearer_mode;
        rate = (mode==INFO_BMODE_CIRCUIT)?0x10:0x00;
        capability = p_capainfo.bearer_capa;
        mode = p_capainfo.bearer_mode;
        rate = (mode==INFO_BMODE_CIRCUIT)?0x10:0x00;
-       switch (p_capainfo.bearer_info1)
-       {
+       switch (p_capainfo.bearer_info1) {
                case INFO_INFO1_NONE:
                user = -1;
                break;
                case INFO_INFO1_NONE:
                user = -1;
                break;
@@ -2278,8 +2143,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        }
        enc_ie_bearer(l3m, coding, capability, mode, rate, -1, user);
        /* hlc */
        }
        enc_ie_bearer(l3m, coding, capability, mode, rate, -1, user);
        /* hlc */
-       if (p_capainfo.hlc)
-       {
+       if (p_capainfo.hlc) {
                coding = 0;
                interpretation = 4;
                presentation = 1;
                coding = 0;
                interpretation = 4;
                presentation = 1;
@@ -2333,11 +2197,9 @@ void Pdss1::message_notify(unsigned int epoint_id, int message_id, union paramet
                notify = param->notifyinfo.notify & 0x7f;
        else
                notify = -1;
                notify = param->notifyinfo.notify & 0x7f;
        else
                notify = -1;
-       if (notify >= 0)
-       {
+       if (notify >= 0) {
                plan = 1;
                plan = 1;
-               switch (param->notifyinfo.ntype)
-               {
+               switch (param->notifyinfo.ntype) {
                        case INFO_NTYPE_UNKNOWN:
                        type = 0;
                        break;
                        case INFO_NTYPE_UNKNOWN:
                        type = 0;
                        break;
@@ -2354,8 +2216,7 @@ void Pdss1::message_notify(unsigned int epoint_id, int message_id, union paramet
                        type = -1;
                        break;
                }
                        type = -1;
                        break;
                }
-               switch (param->notifyinfo.present)
-               {
+               switch (param->notifyinfo.present) {
                        case INFO_PRESENT_ALLOWED:
                        present = 0;
                        break;
                        case INFO_PRESENT_ALLOWED:
                        present = 0;
                        break;
@@ -2368,23 +2229,19 @@ void Pdss1::message_notify(unsigned int epoint_id, int message_id, union paramet
                }
        }
 
                }
        }
 
-       if (notify<0 && !param->notifyinfo.display[0])
-       {
+       if (notify<0 && !param->notifyinfo.display[0]) {
                /* nothing to notify, nothing to display */
                return;
        }
 
                /* nothing to notify, nothing to display */
                return;
        }
 
-       if (notify >= 0)
-       {
-               if (p_state!=PORT_STATE_CONNECT && p_state!=PORT_STATE_IN_PROCEEDING && p_state!=PORT_STATE_IN_ALERTING)
-               {
+       if (notify >= 0) {
+               if (p_state!=PORT_STATE_CONNECT && p_state!=PORT_STATE_IN_PROCEEDING && p_state!=PORT_STATE_IN_ALERTING) {
                        /* queue notification */
                        if (p_m_d_notify_pending)
                                message_free(p_m_d_notify_pending);
                        p_m_d_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
                        memcpy(&p_m_d_notify_pending->param, param, sizeof(union parameter));
                        /* queue notification */
                        if (p_m_d_notify_pending)
                                message_free(p_m_d_notify_pending);
                        p_m_d_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
                        memcpy(&p_m_d_notify_pending->param, param, sizeof(union parameter));
-               } else
-               {
+               } else {
                        /* sending notification */
                        l3m = create_l3msg();
                        l1l2l3_trace_header(p_m_mISDNport, this, L3_NOTIFY_REQ, DIRECTION_OUT);
                        /* sending notification */
                        l3m = create_l3msg();
                        l1l2l3_trace_header(p_m_mISDNport, this, L3_NOTIFY_REQ, DIRECTION_OUT);
@@ -2397,8 +2254,7 @@ void Pdss1::message_notify(unsigned int epoint_id, int message_id, union paramet
                        end_trace();
                        p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_NOTIFY, p_m_d_l3id, l3m);
                }
                        end_trace();
                        p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_NOTIFY, p_m_d_l3id, l3m);
                }
-       } else if (p_m_d_ntmode || p_m_d_tespecial)
-       {
+       } else if (p_m_d_ntmode || p_m_d_tespecial) {
                /* sending information */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
                /* sending information */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
@@ -2414,8 +2270,7 @@ void Pdss1::message_overlap(unsigned int epoint_id, int message_id, union parame
        l3_msg *l3m;
 
        /* in case of sending complete, we proceed */
        l3_msg *l3m;
 
        /* in case of sending complete, we proceed */
-       if (p_dialinginfo.sending_complete)
-       {
+       if (p_dialinginfo.sending_complete) {
                PDEBUG(DEBUG_ISDN, "sending proceeding instead of setup_acknowledge, because address is complete.\n");
                message_proceeding(epoint_id, message_id, param);
                return;
                PDEBUG(DEBUG_ISDN, "sending proceeding instead of setup_acknowledge, because address is complete.\n");
                message_proceeding(epoint_id, message_id, param);
                return;
@@ -2468,8 +2323,7 @@ void Pdss1::message_alerting(unsigned int epoint_id, int message_id, union param
        l3_msg *l3m;
 
        /* NT-MODE in setup state we must send PROCEEDING first */
        l3_msg *l3m;
 
        /* NT-MODE in setup state we must send PROCEEDING first */
-       if (p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP)
-       {
+       if (p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP) {
                /* sending proceeding */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_PROCEEDING_REQ, DIRECTION_OUT);
                /* sending proceeding */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_PROCEEDING_REQ, DIRECTION_OUT);
@@ -2512,8 +2366,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
        class Endpoint *epoint;
 
        /* NT-MODE in setup state we must send PROCEEDING first */
        class Endpoint *epoint;
 
        /* NT-MODE in setup state we must send PROCEEDING first */
-       if (p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP)
-       {
+       if (p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP) {
                /* sending proceeding */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_PROCEEDING_REQ, DIRECTION_OUT);
                /* sending proceeding */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_PROCEEDING_REQ, DIRECTION_OUT);
@@ -2531,8 +2384,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
 
        /* only display at connect state */
        if (p_state == PORT_STATE_CONNECT)
 
        /* only display at connect state */
        if (p_state == PORT_STATE_CONNECT)
-       if (p_connectinfo.display[0])
-       {
+       if (p_connectinfo.display[0]) {
                /* sending information */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
                /* sending information */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
@@ -2543,8 +2395,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
                return;
        }
 
                return;
        }
 
-       if (p_state!=PORT_STATE_IN_SETUP && p_state!=PORT_STATE_IN_OVERLAP && p_state!=PORT_STATE_IN_PROCEEDING && p_state!=PORT_STATE_IN_ALERTING)
-       {
+       if (p_state!=PORT_STATE_IN_SETUP && p_state!=PORT_STATE_IN_OVERLAP && p_state!=PORT_STATE_IN_PROCEEDING && p_state!=PORT_STATE_IN_ALERTING) {
                /* connect command only possible in setup, proceeding or alerting state */
                return;
        }
                /* connect command only possible in setup, proceeding or alerting state */
                return;
        }
@@ -2554,8 +2405,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
        l1l2l3_trace_header(p_m_mISDNport, this, L3_CONNECT_REQ, DIRECTION_OUT);
        /* connect information */
        plan = 1;
        l1l2l3_trace_header(p_m_mISDNport, this, L3_CONNECT_REQ, DIRECTION_OUT);
        /* connect information */
        plan = 1;
-       switch (p_connectinfo.ntype)
-       {
+       switch (p_connectinfo.ntype) {
                case INFO_NTYPE_UNKNOWN:
                type = 0x0;
                break;
                case INFO_NTYPE_UNKNOWN:
                type = 0x0;
                break;
@@ -2572,8 +2422,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
                type = -1;
                break;
        }
                type = -1;
                break;
        }
-       switch (param->connectinfo.screen)
-       {
+       switch (param->connectinfo.screen) {
                case INFO_SCREEN_USER:
                screen = 0;
                break;
                case INFO_SCREEN_USER:
                screen = 0;
                break;
@@ -2581,8 +2430,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
                screen = 3;
                break;
        }
                screen = 3;
                break;
        }
-       switch (p_connectinfo.present)
-       {
+       switch (p_connectinfo.present) {
                case INFO_PRESENT_ALLOWED:
                present = 0;
                break;
                case INFO_PRESENT_ALLOWED:
                present = 0;
                break;
@@ -2602,8 +2450,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
 //     if (p_connectinfo.name[0] && (p_m_d_ntmode || p_m_d_tespecial))
 //             enc_facility_centrex(&connect->FACILITY, dmsg, (unsigned char *)p_connectinfo.name, 0);
        /* date & time */
 //     if (p_connectinfo.name[0] && (p_m_d_ntmode || p_m_d_tespecial))
 //             enc_facility_centrex(&connect->FACILITY, dmsg, (unsigned char *)p_connectinfo.name, 0);
        /* date & time */
-       if (p_m_d_ntmode || p_m_d_tespecial)
-       {
+       if (p_m_d_ntmode || p_m_d_tespecial) {
                epoint = find_epoint_id(epoint_id);
                enc_ie_date(l3m, now, p_settings.no_seconds);
        }
                epoint = find_epoint_id(epoint_id);
                enc_ie_date(l3m, now, p_settings.no_seconds);
        }
@@ -2627,11 +2474,9 @@ void Pdss1::message_disconnect(unsigned int epoint_id, int message_id, union par
 
        /* we reject during incoming setup when we have no tones. also if we are in outgoing setup state */
 //     if ((p_state==PORT_STATE_IN_SETUP && !p_m_mISDNport->tones)
 
        /* we reject during incoming setup when we have no tones. also if we are in outgoing setup state */
 //     if ((p_state==PORT_STATE_IN_SETUP && !p_m_mISDNport->tones)
-if (/*  ||*/ p_state==PORT_STATE_OUT_SETUP)
-       {
+if (/*  ||*/ p_state==PORT_STATE_OUT_SETUP) {
                /* sending release to endpoint */
                /* sending release to endpoint */
-               while(p_epointlist)
-               {
+               while(p_epointlist) {
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                        memcpy(&message->param, param, sizeof(union parameter));
                        message_put(message);
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                        memcpy(&message->param, param, sizeof(union parameter));
                        message_put(message);
@@ -2651,8 +2496,7 @@ if (/*     ||*/ p_state==PORT_STATE_OUT_SETUP)
        }
 
        /* workarround: NT-MODE in setup state we must send PROCEEDING first to make it work */
        }
 
        /* workarround: NT-MODE in setup state we must send PROCEEDING first to make it work */
-       if (p_state==PORT_STATE_IN_SETUP)
-       {
+       if (p_state==PORT_STATE_IN_SETUP) {
                /* sending proceeding */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_PROCEEDING_REQ, DIRECTION_OUT);
                /* sending proceeding */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_PROCEEDING_REQ, DIRECTION_OUT);
@@ -2702,8 +2546,7 @@ void Pdss1::message_release(unsigned int epoint_id, int message_id, union parame
         * this means that the endpoint doesnt require audio anymore
         */
        if (p_state == PORT_STATE_IN_DISCONNECT
         * this means that the endpoint doesnt require audio anymore
         */
        if (p_state == PORT_STATE_IN_DISCONNECT
-        || p_state == PORT_STATE_OUT_DISCONNECT)
-       {
+        || p_state == PORT_STATE_OUT_DISCONNECT) {
                /* sending release */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_REQ, DIRECTION_OUT);
                /* sending release */
                l3m = create_l3msg();
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_REQ, DIRECTION_OUT);
@@ -2723,8 +2566,7 @@ void Pdss1::message_release(unsigned int epoint_id, int message_id, union parame
         * also on outgoing call setup, we send a release complete, BUT this is not conform. (i don't know any other way)
         */
        if (p_state==PORT_STATE_IN_SETUP
         * also on outgoing call setup, we send a release complete, BUT this is not conform. (i don't know any other way)
         */
        if (p_state==PORT_STATE_IN_SETUP
-        || p_state==PORT_STATE_OUT_SETUP)
-       {
+        || p_state==PORT_STATE_OUT_SETUP) {
 //#warning remove me
 //PDEBUG(DEBUG_LOG, "JOLLY sending release complete %d\n", p_serial);
                /* sending release complete */
 //#warning remove me
 //PDEBUG(DEBUG_LOG, "JOLLY sending release complete %d\n", p_serial);
                /* sending release complete */
@@ -2744,8 +2586,7 @@ void Pdss1::message_release(unsigned int epoint_id, int message_id, union parame
 #if 0
 wirklich erst proceeding?:
        /* NT-MODE in setup state we must send PROCEEDING first */
 #if 0
 wirklich erst proceeding?:
        /* NT-MODE in setup state we must send PROCEEDING first */
-       if (p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP)
-       {
+       if (p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP) {
                CALL_PROCEEDING_t *proceeding;
 
                /* sending proceeding */
                CALL_PROCEEDING_t *proceeding;
 
                /* sending proceeding */
@@ -2800,15 +2641,13 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
        if (PmISDN::message_epoint(epoint_id, message_id, param))
                return(1);
 
        if (PmISDN::message_epoint(epoint_id, message_id, param))
                return(1);
 
-       switch(message_id)
-       {
+       switch(message_id) {
                case MESSAGE_INFORMATION: /* overlap dialing */
                if (p_type==PORT_TYPE_DSS1_NT_OUT
                 && p_state!=PORT_STATE_OUT_OVERLAP
                 && p_state!=PORT_STATE_CONNECT
                 && p_state!=PORT_STATE_OUT_DISCONNECT
                case MESSAGE_INFORMATION: /* overlap dialing */
                if (p_type==PORT_TYPE_DSS1_NT_OUT
                 && p_state!=PORT_STATE_OUT_OVERLAP
                 && p_state!=PORT_STATE_CONNECT
                 && p_state!=PORT_STATE_OUT_DISCONNECT
-                && p_state!=PORT_STATE_IN_DISCONNECT)
-               {
+                && p_state!=PORT_STATE_IN_DISCONNECT) {
                        break;
                }
                if (p_type==PORT_TYPE_DSS1_TE_OUT
                        break;
                }
                if (p_type==PORT_TYPE_DSS1_TE_OUT
@@ -2817,8 +2656,7 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                 && p_state!=PORT_STATE_OUT_ALERTING
                 && p_state!=PORT_STATE_CONNECT
                 && p_state!=PORT_STATE_OUT_DISCONNECT
                 && p_state!=PORT_STATE_OUT_ALERTING
                 && p_state!=PORT_STATE_CONNECT
                 && p_state!=PORT_STATE_OUT_DISCONNECT
-                && p_state!=PORT_STATE_IN_DISCONNECT)
-               {
+                && p_state!=PORT_STATE_IN_DISCONNECT) {
                        break;
                }
                if ((p_type==PORT_TYPE_DSS1_NT_IN || p_type==PORT_TYPE_DSS1_TE_IN)
                        break;
                }
                if ((p_type==PORT_TYPE_DSS1_NT_IN || p_type==PORT_TYPE_DSS1_TE_IN)
@@ -2828,8 +2666,7 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                 && p_state!=PORT_STATE_CONNECT
                 && p_state!=PORT_STATE_CONNECT_WAITING
                 && p_state!=PORT_STATE_OUT_DISCONNECT
                 && p_state!=PORT_STATE_CONNECT
                 && p_state!=PORT_STATE_CONNECT_WAITING
                 && p_state!=PORT_STATE_OUT_DISCONNECT
-                && p_state!=PORT_STATE_IN_DISCONNECT)
-               {
+                && p_state!=PORT_STATE_IN_DISCONNECT) {
                        break;
                }
                message_information(epoint_id, message_id, param);
                        break;
                }
                message_information(epoint_id, message_id, param);
@@ -2837,8 +2674,7 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
 
                case MESSAGE_SETUP: /* dial-out command received from epoint */
                if (p_state!=PORT_STATE_IDLE
 
                case MESSAGE_SETUP: /* dial-out command received from epoint */
                if (p_state!=PORT_STATE_IDLE
-                && p_state!=PORT_STATE_CONNECT)
-               {
+                && p_state!=PORT_STATE_CONNECT) {
                        PERROR("Pdss1(%s) ignoring setup because isdn port is not in idle state (or connected for sending display info).\n", p_name);
                        break;
                }
                        PERROR("Pdss1(%s) ignoring setup because isdn port is not in idle state (or connected for sending display info).\n", p_name);
                        break;
                }
@@ -2856,8 +2692,7 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                break;
 
                case MESSAGE_OVERLAP: /* more information is needed */
                break;
 
                case MESSAGE_OVERLAP: /* more information is needed */
-               if (p_state!=PORT_STATE_IN_SETUP)
-               {
+               if (p_state!=PORT_STATE_IN_SETUP) {
                        break;
                }
                message_overlap(epoint_id, message_id, param);
                        break;
                }
                message_overlap(epoint_id, message_id, param);
@@ -2865,13 +2700,11 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
 
                case MESSAGE_PROCEEDING: /* call of endpoint is proceeding */
                if (p_state!=PORT_STATE_IN_SETUP
 
                case MESSAGE_PROCEEDING: /* call of endpoint is proceeding */
                if (p_state!=PORT_STATE_IN_SETUP
-                && p_state!=PORT_STATE_IN_OVERLAP)
-               {
+                && p_state!=PORT_STATE_IN_OVERLAP) {
                        break;
                }
                message_proceeding(epoint_id, message_id, param);
                        break;
                }
                message_proceeding(epoint_id, message_id, param);
-               if (p_m_d_notify_pending)
-               {
+               if (p_m_d_notify_pending) {
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
@@ -2882,13 +2715,11 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                case MESSAGE_ALERTING: /* call of endpoint is ringing */
                if (p_state!=PORT_STATE_IN_SETUP
                 && p_state!=PORT_STATE_IN_OVERLAP
                case MESSAGE_ALERTING: /* call of endpoint is ringing */
                if (p_state!=PORT_STATE_IN_SETUP
                 && p_state!=PORT_STATE_IN_OVERLAP
-                && p_state!=PORT_STATE_IN_PROCEEDING)
-               {
+                && p_state!=PORT_STATE_IN_PROCEEDING) {
                        break;
                }
                message_alerting(epoint_id, message_id, param);
                        break;
                }
                message_alerting(epoint_id, message_id, param);
-               if (p_m_d_notify_pending)
-               {
+               if (p_m_d_notify_pending) {
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
@@ -2901,13 +2732,11 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                 && p_state!=PORT_STATE_IN_OVERLAP
                 && p_state!=PORT_STATE_IN_PROCEEDING
                 && p_state!=PORT_STATE_IN_ALERTING
                 && p_state!=PORT_STATE_IN_OVERLAP
                 && p_state!=PORT_STATE_IN_PROCEEDING
                 && p_state!=PORT_STATE_IN_ALERTING
-                && !(p_state==PORT_STATE_CONNECT && p_m_d_ntmode))
-               {
+                && !(p_state==PORT_STATE_CONNECT && p_m_d_ntmode)) {
                        break;
                }
                message_connect(epoint_id, message_id, param);
                        break;
                }
                message_connect(epoint_id, message_id, param);
-               if (p_m_d_notify_pending)
-               {
+               if (p_m_d_notify_pending) {
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
                        /* send pending notify message during connect */
                        message_notify(ACTIVE_EPOINT(p_epointlist), p_m_d_notify_pending->type, &p_m_d_notify_pending->param);
                        message_free(p_m_d_notify_pending);
@@ -2925,16 +2754,14 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                 && p_state!=PORT_STATE_OUT_PROCEEDING
                 && p_state!=PORT_STATE_OUT_ALERTING
                 && p_state!=PORT_STATE_CONNECT
                 && p_state!=PORT_STATE_OUT_PROCEEDING
                 && p_state!=PORT_STATE_OUT_ALERTING
                 && p_state!=PORT_STATE_CONNECT
-                && p_state!=PORT_STATE_CONNECT_WAITING)
-               {
+                && p_state!=PORT_STATE_CONNECT_WAITING) {
                        break;
                }
                message_disconnect(epoint_id, message_id, param);
                break;
 
                case MESSAGE_RELEASE: /* release isdn port */
                        break;
                }
                message_disconnect(epoint_id, message_id, param);
                break;
 
                case MESSAGE_RELEASE: /* release isdn port */
-               if (p_state==PORT_STATE_RELEASE)
-               {
+               if (p_state==PORT_STATE_RELEASE) {
                        break;
                }
                message_release(epoint_id, message_id, param);
                        break;
                }
                message_release(epoint_id, message_id, param);
@@ -2960,30 +2787,24 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
 
        PDEBUG(DEBUG_ISDN, "cmd(0x%x) pid(0x%x)\n", cmd, pid);
 
 
        PDEBUG(DEBUG_ISDN, "cmd(0x%x) pid(0x%x)\n", cmd, pid);
 
-       if (pid == 0)
-       {
+       if (pid == 0) {
                PDEBUG(DEBUG_ISDN, "ignoring dummy process from phone.\n");
                return(0);
        }
 
        /* find Port object of type ISDN */
        port = port_first;
                PDEBUG(DEBUG_ISDN, "ignoring dummy process from phone.\n");
                return(0);
        }
 
        /* find Port object of type ISDN */
        port = port_first;
-       while(port)
-       {
+       while(port) {
                /* are we ISDN ? */
                /* are we ISDN ? */
-               if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1)
-               {
+               if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1) {
                        pdss1 = (class Pdss1 *)port;
                        /* check out correct stack and id */
                        pdss1 = (class Pdss1 *)port;
                        /* check out correct stack and id */
-                       if (pdss1->p_m_mISDNport == mISDNport)
-                       {
-                               if (pdss1->p_m_d_l3id & MISDN_PID_CR_FLAG)
-                               {
+                       if (pdss1->p_m_mISDNport == mISDNport) {
+                               if (pdss1->p_m_d_l3id & MISDN_PID_CR_FLAG) {
                                        /* local callref, so match value only */
                                        if ((pdss1->p_m_d_l3id & MISDN_PID_CRVAL_MASK) == (pid & MISDN_PID_CRVAL_MASK))
                                                break; // found
                                        /* local callref, so match value only */
                                        if ((pdss1->p_m_d_l3id & MISDN_PID_CRVAL_MASK) == (pid & MISDN_PID_CRVAL_MASK))
                                                break; // found
-                               } else
-                               {
+                               } else {
                                        /* remote callref, ref + channel id */
                                        if (pdss1->p_m_d_l3id == pid)
                                                break; // found
                                        /* remote callref, ref + channel id */
                                        if (pdss1->p_m_d_l3id == pid)
                                                break; // found
@@ -2994,10 +2815,8 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
        }
 
        /* aktueller prozess */
        }
 
        /* aktueller prozess */
-       if (port)
-       {
-               if (cmd == MT_ASSIGN)
-               {
+       if (port) {
+               if (cmd == MT_ASSIGN) {
                        /* stack gives us new layer 3 id (during connect) */
                        l1l2l3_trace_header(mISDNport, pdss1, L3_NEW_L3ID_IND, DIRECTION_IN);
                        add_trace("callref", "old", "0x%x", pdss1->p_m_d_l3id);
                        /* stack gives us new layer 3 id (during connect) */
                        l1l2l3_trace_header(mISDNport, pdss1, L3_NEW_L3ID_IND, DIRECTION_IN);
                        add_trace("callref", "old", "0x%x", pdss1->p_m_d_l3id);
@@ -3014,11 +2833,9 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
                /* if process id is master process, but a child disconnects */
                if (mISDNport->ntmode
                 && (pid & MISDN_PID_CRTYPE_MASK) != MISDN_PID_MASTER
                /* if process id is master process, but a child disconnects */
                if (mISDNport->ntmode
                 && (pid & MISDN_PID_CRTYPE_MASK) != MISDN_PID_MASTER
-                && (pdss1->p_m_d_l3id & MISDN_PID_CRTYPE_MASK) == MISDN_PID_MASTER)
-               {
+                && (pdss1->p_m_d_l3id & MISDN_PID_CRTYPE_MASK) == MISDN_PID_MASTER) {
                        if (cmd == MT_DISCONNECT
                        if (cmd == MT_DISCONNECT
-                        || cmd == MT_RELEASE)
-                       {
+                        || cmd == MT_RELEASE) {
                                /* send special indication for child disconnect */
                                pdss1->disconnect_ind_i(cmd, pid, l3m);
                                return(0);
                                /* send special indication for child disconnect */
                                pdss1->disconnect_ind_i(cmd, pid, l3m);
                                return(0);
@@ -3039,8 +2856,7 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
        }
 
        /* d-message */
        }
 
        /* d-message */
-       switch(cmd)
-       {
+       switch(cmd) {
                case MT_SETUP:
                /* creating port object, transparent until setup with hdlc */
                SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
                case MT_SETUP:
                /* creating port object, transparent until setup with hdlc */
                SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
@@ -3073,10 +2889,8 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
                default:
                PERROR("unhandled message: cmd(0x%x) pid(0x%x)\n", cmd, pid);
                port = port_first;
                default:
                PERROR("unhandled message: cmd(0x%x) pid(0x%x)\n", cmd, pid);
                port = port_first;
-               while(port)
-               {
-                       if (port->p_type == PORT_TYPE_DSS1_NT_IN || port->p_type == PORT_TYPE_DSS1_NT_OUT)
-                       {
+               while(port) {
+                       if (port->p_type == PORT_TYPE_DSS1_NT_IN || port->p_type == PORT_TYPE_DSS1_NT_OUT) {
                                pdss1 = (class Pdss1 *)port;
                                /* check out correct stack */
                                if (pdss1->p_m_mISDNport == mISDNport)
                                pdss1 = (class Pdss1 *)port;
                                /* check out correct stack */
                                if (pdss1->p_m_mISDNport == mISDNport)
index 1dce9f1..e9c680f 100644 (file)
@@ -67,7 +67,7 @@ Endpoint::Endpoint(unsigned int port_id, unsigned int join_id)
                port = find_port_id(port_id);
                if (port)
                {
                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");
                                earlyb = ((class PmISDN *)port)->p_m_mISDNport->earlyb;
                        if (!portlist_new(port_id, port->p_type, earlyb))
                                FATAL("No memory for portlist.\n");
diff --git a/gsm.cpp b/gsm.cpp
new file mode 100644 (file)
index 0000000..f2519f5
--- /dev/null
+++ b/gsm.cpp
@@ -0,0 +1,1614 @@
+/*****************************************************************************\
+**                                                                           **
+** LCR                                                                       **
+**                                                                           **
+**---------------------------------------------------------------------------**
+** Copyright: Andreas Eversberg                                              **
+**                                                                           **
+** mISDN gsm                                                                 **
+**                                                                           **
+\*****************************************************************************/ 
+
+#include "main.h"
+extern "C" {
+#include "openbsc/openbsc.h"
+#include "openbsc/mncc.h"
+#include "openbsc/trau_frame.h"
+#include "bootstrap.h"
+#include "gsm_audio.h"
+
+#undef AF_ISDN
+#undef PF_ISDN
+extern  int     AF_ISDN;
+#define PF_ISDN AF_ISDN
+}
+
+struct lcr_gsm *gsm = NULL;
+
+static unsigned int new_callref = 1;
+
+
+/*
+ * create and send mncc message
+ */
+static struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
+{
+       struct gsm_mncc *mncc;
+
+       mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
+       mncc->msg_type = msg_type;
+       mncc->callref = callref;
+       return (mncc);
+}
+static int send_and_free_mncc(void *net, unsigned int msg_type, void *data)
+{
+       int ret;
+
+       ret = mncc_send(net, msg_type, data);
+       free(data);
+
+       return ret;
+}
+
+
+/*
+ * constructor
+ */
+Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+{
+       p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
+       p_m_g_callref = 0;
+       p_m_g_mode = 0;
+       p_m_g_gsm_b_sock = -1;
+       p_m_g_gsm_b_index = -1;
+       p_m_g_gsm_b_active = 0;
+       p_m_g_notify_pending = NULL;
+       p_m_g_decoder = gsm_audio_create();
+       p_m_g_encoder = gsm_audio_create();
+       if (!p_m_g_encoder || !p_m_g_decoder) {
+               PERROR("Failed to create GSM audio codec instance\n");
+               p_m_delete = 1;
+       }
+       p_m_g_rxpos = 0;
+       p_m_g_tch_connected = 0;
+
+       PDEBUG(DEBUG_GSM, "Created new mISDNPort(%s).\n", portname);
+}
+
+/*
+ * destructor
+ */
+Pgsm::~Pgsm()
+{
+       PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
+
+       /* remove queued message */
+       if (p_m_g_notify_pending)
+               message_free(p_m_g_notify_pending);
+
+       /* close audio transfer socket */
+       if (p_m_g_gsm_b_sock > -1)
+               bchannel_close();
+
+       /* close codec */
+       if (p_m_g_encoder)
+               gsm_audio_destroy(p_m_g_encoder);
+       if (p_m_g_decoder)
+               gsm_audio_destroy(p_m_g_decoder);
+}
+
+
+/* close bsc side bchannel */
+void Pgsm::bchannel_close(void)
+{
+       if (p_m_g_gsm_b_sock > -1)
+               close(p_m_g_gsm_b_sock);
+       p_m_g_gsm_b_sock = -1;
+       p_m_g_gsm_b_index = -1;
+       p_m_g_gsm_b_active = 0;
+}
+
+/* open bsc side bchannel */
+int Pgsm::bchannel_open(int index)
+{
+       int ret;
+       unsigned int on = 1;
+       struct sockaddr_mISDN addr;
+       struct mISDNhead act;
+
+       if (p_m_g_gsm_b_sock > -1) {
+               PERROR("Socket already created for index %d\n", index);
+               return(-EIO);
+       }
+
+       /* open socket */
+       ret = p_m_g_gsm_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
+       if (ret < 0) {
+               PERROR("Failed to open bchannel-socket for index %d\n", index);
+               bchannel_close();
+               return(ret);
+       }
+       
+       /* set nonblocking io */
+       ret = ioctl(p_m_g_gsm_b_sock, FIONBIO, &on);
+       if (ret < 0) {
+               PERROR("Failed to set bchannel-socket index %d into nonblocking IO\n", index);
+               bchannel_close();
+               return(ret);
+       }
+
+       /* bind socket to bchannel */
+       addr.family = AF_ISDN;
+       addr.dev = gsm->gsm_port;
+       addr.channel = index+1+(index>15);
+       ret = bind(p_m_g_gsm_b_sock, (struct sockaddr *)&addr, sizeof(addr));
+       if (ret < 0) {
+               PERROR("Failed to bind bchannel-socket for index %d\n", index);
+               bchannel_close();
+               return(ret);
+       }
+       /* activate bchannel */
+       PDEBUG(DEBUG_GSM, "Activating GSM side channel index %i.\n", index);
+       act.prim = PH_ACTIVATE_REQ; 
+       act.id = 0;
+       ret = sendto(p_m_g_gsm_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
+       if (ret < 0) {
+               PERROR("Failed to activate index %d\n", index);
+               bchannel_close();
+               return(ret);
+       }
+
+       p_m_g_gsm_b_index = index;
+
+       return(0);
+}
+
+/* receive from bchannel */
+void Pgsm::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
+{
+       int i, j, k;
+       unsigned char frame[33];
+       struct decoded_trau_frame tf;
+
+       /* encoder init failed */
+       if (!p_m_g_encoder)
+               return;
+
+       /* (currently) not connected, so don't flood tch! */
+       if (!p_m_g_tch_connected)
+               return;
+
+       /* write to rx buffer */
+       while(len--) {
+               p_m_g_rxdata[p_m_g_rxpos++] = audio_law_to_s32[*data++];
+               if (p_m_g_rxpos == 160) {
+                       p_m_g_rxpos = 0;
+
+                       /* encode data */
+                       gsm_audio_encode(p_m_g_encoder, p_m_g_rxdata, frame);
+
+                       /* set c-bits and t-bits */
+                       tf.c_bits[0] = 1;
+                       tf.c_bits[1] = 1;
+                       tf.c_bits[2] = 1;
+                       tf.c_bits[3] = 0;
+                       tf.c_bits[4] = 0;
+                       memset(&tf.c_bits[5], 0, 6);
+                       memset(&tf.c_bits[11], 1, 10);
+                       memset(&tf.t_bits[0], 1, 4);
+
+                       /* reassemble d-bits */
+                       i = 0;
+                       j = 0;
+                       k = 0;
+                       while(i < 260) {
+                               tf.d_bits[i] = (frame[j] >> k) & 1;
+                               if (++k == 8) {
+                                       k = 0;
+                                       j++;
+                               }
+                               i++;
+                       }
+
+                       trau_send(&tf);
+               }
+       }
+}
+
+/* transmit to bchannel */
+void Pgsm::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
+{
+       unsigned char buf[MISDN_HEADER_LEN+len];
+       struct mISDNhead *hh = (struct mISDNhead *)buf;
+       int ret;
+
+       if (!p_m_g_gsm_b_active)
+               return;
+
+       /* make and send frame */
+       hh->prim = PH_DATA_REQ;
+       hh->id = 0;
+       memcpy(buf+MISDN_HEADER_LEN, data, len);
+       ret = sendto(p_m_g_gsm_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
+       if (ret <= 0)
+               PERROR("Failed to send to socket index %d\n", index);
+}
+
+void Pgsm::trau_send(void *_tf)
+{
+       struct decoded_trau_frame *tf = (struct decoded_trau_frame *)_tf;
+       unsigned char data[sizeof(struct gsm_trau_frame) + sizeof(struct decoded_trau_frame)];
+       struct gsm_trau_frame *frame = (struct gsm_trau_frame *)data;
+       
+       frame->msg_type = GSM_TRAU_FRAME;
+       frame->callref = p_m_g_callref;
+       memcpy(frame->data, tf, sizeof(struct decoded_trau_frame));
+       mncc_send(gsm->network, frame->msg_type, frame);
+}
+
+
+void Pgsm::trau_receive(void *_frame)
+{
+       struct gsm_trau_frame *frm = (struct gsm_trau_frame *)_frame;
+       struct decoded_trau_frame *tf = (struct decoded_trau_frame *)frm->data;
+//struct decoded_trau_frame *tf = (struct decoded_trau_frame *)_frame;
+       unsigned char frame[33];
+       signed short samples[160];
+       unsigned char data[160];
+       int i, j, k;
+
+       if (!p_m_g_decoder)
+               return;
+
+//     printf("got trau %d %d %d %d %d\n", tf->c_bits[0], tf->c_bits[1], tf->c_bits[2], tf->c_bits[3], tf->c_bits[4]);
+       if (tf->c_bits[0]!=0 || tf->c_bits[1]!=0 || tf->c_bits[2]!=0 || tf->c_bits[3]!=1 || tf->c_bits[4]!=0)
+               PERROR("illegal trau (C1-C5) %d %d %d %d %d\n", tf->c_bits[0], tf->c_bits[1], tf->c_bits[2], tf->c_bits[3], tf->c_bits[4]);
+
+       /* set GSM_MAGIC */
+       memset(&frame, 0, sizeof(frame));
+//     frame[0] = 0xd << 4;
+
+       /* reassemble bits */
+       i = 0;
+       j = 0;
+       k = 0;
+       while(i < 260) {
+               if (tf->d_bits[i] > 1)
+                       PERROR("fix!\n");
+               frame[j] |= (tf->d_bits[i] << k);
+               if (++k == 8) {
+                       k = 0;
+                       j++;
+               }
+               i++;
+       }
+       
+       /* decode */
+       gsm_audio_decode(p_m_g_decoder, frame, samples);
+       for (i = 0; i < 160; i++) {
+               data[i] = audio_s16_to_law[samples[i] & 0xffff];
+       }
+
+       /* send */
+       bchannel_send(PH_DATA_REQ, 0, data, 160);
+}
+
+
+/*
+ * create trace
+ **/
+static void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction)
+{
+       char msgtext[64];
+
+       /* select message and primitive text */
+       SCPY(msgtext, get_mncc_name(msg_type));
+
+       /* add direction */
+       if (direction == DIRECTION_OUT)
+               SCAT(msgtext, " MSC->BSC");
+       else
+               SCAT(msgtext, " MSC<-BSC");
+
+       /* init trace with given values */
+       start_trace(mISDNport?mISDNport->portnum:-1,
+                   mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
+                   port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
+                   port?port->p_dialinginfo.id:NULL,
+                   direction,
+                   CATEGORY_CH,
+                   port?port->p_serial:0,
+                   msgtext);
+}
+
+
+
+/* select bchannel */
+int Pgsm::hunt_bchannel(void)
+{
+       int channel;
+       int i;
+
+       chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (setup)", DIRECTION_NONE);
+       add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved);
+       if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) { // of out chan..
+               add_trace("conclusion", NULL, "all channels are reserved");
+               end_trace();
+               return(-34); // no channel
+       }
+       /* find channel */
+       i = 0;
+       channel = 0;
+       while(i < p_m_mISDNport->b_num) {
+               if (p_m_mISDNport->b_port[i] == NULL) {
+                       channel = i+1+(i>=15);
+                       break;
+               }
+               i++;
+       }
+       if (!channel) {
+               add_trace("conclusion", NULL, "no channel available");
+               end_trace();
+               return(-6); // channel unacceptable
+       }
+       add_trace("conclusion", NULL, "channel available");
+       add_trace("connect", "channel", "%d", channel);
+       end_trace();
+       return(channel);
+}
+
+
+/*
+ * handles all indications
+ */
+/* SETUP INDICATION */
+void Pgsm::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       int ret;
+       class Endpoint *epoint;
+       struct lcr_msg *message;
+       int channel;
+       struct gsm_mncc *mode, *proceeding, *frame;
+
+       /* emergency shutdown */
+       printf("%d %d\n", mncc->emergency, !gsm->conf.noemergshut);
+       if (mncc->emergency && !gsm->conf.noemergshut) {
+               start_trace(p_m_mISDNport->portnum,
+                       p_m_mISDNport->ifport->interface,
+                       NULL,
+                       NULL,
+                       DIRECTION_NONE,
+                       CATEGORY_CH,
+                       0,
+                       "EMERGENCY SHUTDOWN (due to received emergency call)");
+               end_trace();
+               quit = 1;
+       }
+       /* process given callref */
+       l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
+       add_trace("callref", "new", "0x%x", callref);
+       if (p_m_g_callref) {
+               /* release in case the ID is already in use */
+               add_trace("error", NULL, "callref already in use");
+               end_trace();
+               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
+               add_trace("cause", "location", "1");
+               add_trace("cause", "value", "47");
+               add_trace("reason", NULL, "callref already in use");
+               end_trace();
+               mncc = create_mncc(MNCC_REJ_REQ, callref);
+               mncc->cause = 1;
+               mncc->cause_location = 1;
+               mncc->cause_value = 47;
+               send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+               new_state(PORT_STATE_RELEASE);
+               p_m_delete = 1;
+               return;
+       }
+       p_m_g_callref = callref;
+       end_trace();
+
+       /* if blocked, release call with MT_RELEASE_COMPLETE */
+       if (p_m_mISDNport->ifport->block) {
+               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
+               add_trace("cause", "location", "1");
+               add_trace("cause", "value", "27");
+               add_trace("reason", NULL, "port blocked");
+               end_trace();
+               mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
+               mncc->cause = 1;
+               mncc->cause_location = 1;
+               mncc->cause_value = 27;
+               send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+               new_state(PORT_STATE_RELEASE);
+               p_m_delete = 1;
+               return;
+       }
+
+       /* caller info */
+       if (mncc->clir_inv)
+               p_callerinfo.present = INFO_PRESENT_RESTRICTED;
+       else
+               p_callerinfo.present = INFO_PRESENT_ALLOWED;
+       if (mncc->calling_number[0])
+               SCPY(p_callerinfo.id, mncc->calling_number);
+       else
+               p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
+       p_callerinfo.screen = INFO_SCREEN_NETWORK;
+       p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
+       p_callerinfo.isdn_port = p_m_portnum;
+       SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+
+       /* dialing information */
+       SCAT(p_dialinginfo.id, mncc->called_number);
+       switch (mncc->called_type) {
+               case 0x1:
+               p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
+               break;
+               case 0x2:
+               p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
+               break;
+               case 0x4:
+               p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
+               break;
+               default:
+               p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
+               break;
+       }
+       if (mncc->emergency) {
+               SCPY(p_dialinginfo.id, "emergency");
+       }
+       p_dialinginfo.sending_complete = 1;
+
+       /* bearer capability */
+       // todo
+       p_capainfo.bearer_capa = INFO_BC_SPEECH;
+       p_capainfo.bearer_info1 = (options.law=='a')?3:2;
+       p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
+       p_capainfo.source_mode = B_MODE_TRANSPARENT;
+       p_m_g_mode = p_capainfo.source_mode;
+
+       /* useruser */
+
+       /* hunt channel */
+       ret = channel = hunt_bchannel();
+       if (ret < 0)
+               goto no_channel;
+
+       /* open channel */
+       ret = seize_bchannel(channel, 1);
+       if (ret < 0) {
+               no_channel:
+               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
+               add_trace("cause", "location", "1");
+               add_trace("cause", "value", "34");
+               add_trace("reason", NULL, "no channel");
+               end_trace();
+               mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
+               mncc->cause = 1;
+               mncc->cause_location = 1;
+               mncc->cause_value = 34;
+               send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+               new_state(PORT_STATE_RELEASE);
+               p_m_delete = 1;
+               return;
+       }
+       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
+       if (bchannel_open(p_m_b_index))
+               goto no_channel;
+
+       /* what infos did we got ... */
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       add_trace("subscr", "number", "%s", p_callerinfo.id);
+       add_trace("dialing", "number", "%s", p_dialinginfo.id);
+       end_trace();
+
+       /* create endpoint */
+       if (p_epointlist)
+               FATAL("Incoming call but already got an endpoint.\n");
+       if (!(epoint = new Endpoint(p_serial, 0)))
+               FATAL("No memory for Endpoint instance\n");
+       if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
+               FATAL("No memory for Endpoint Application instance\n");
+       epointlist_new(epoint->ep_serial);
+
+       /* modify lchan to GSM codec V1 */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+       end_trace();
+       mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+       mode->lchan_mode = 0x01; /* GSM V1 */
+       add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
+       send_and_free_mncc(gsm->network, mode->msg_type, mode);
+
+       /* send call proceeding */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
+       proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
+       if (p_m_mISDNport->tones) {
+               proceeding->progress = 1;
+               proceeding->progress_coding = 3; /* GSM */
+               proceeding->progress_location = 1;
+               proceeding->progress_descr = 8;
+               add_trace("progress", "coding", "%d", proceeding->progress_coding);
+               add_trace("progress", "location", "%d", proceeding->progress_location);
+               add_trace("progress", "descr", "%d", proceeding->progress_descr);
+       }
+       send_and_free_mncc(gsm->network, proceeding->msg_type, proceeding);
+       end_trace();
+
+       new_state(PORT_STATE_IN_PROCEEDING);
+
+       if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+               end_trace();
+               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
+               send_and_free_mncc(gsm->network, frame->msg_type, frame);
+               p_m_g_tch_connected = 1;
+       }
+
+       /* send setup message to endpoit */
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
+       message->param.setup.isdn_port = p_m_portnum;
+       message->param.setup.port_type = p_type;
+//     message->param.setup.dtmf = 0;
+       memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
+       memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
+       memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
+       SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser_info);
+       message->param.setup.useruser.len = strlen(mncc->useruser_info);
+       message->param.setup.useruser.protocol = mncc->useruser_proto;
+       message_put(message);
+}
+
+/* DTMF INDICATION */
+void Pgsm::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct lcr_msg *message;
+       struct gsm_mncc *resp;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       add_trace("keypad", NULL, "%c", mncc->keypad);
+       end_trace();
+       SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
+       p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
+
+       /* send resp */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
+       add_trace("keypad", NULL, "%c", mncc->keypad);
+       end_trace();
+       resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
+       resp->keypad = mncc->keypad;
+       send_and_free_mncc(gsm->network, resp->msg_type, resp);
+
+       /* send dialing information */
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
+       memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
+       message_put(message);
+}
+void Pgsm::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct gsm_mncc *resp;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       add_trace("keypad", NULL, "%c", mncc->keypad);
+       end_trace();
+
+       /* send resp */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
+       add_trace("keypad", NULL, "%c", mncc->keypad);
+       end_trace();
+       resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
+       resp->keypad = mncc->keypad;
+       send_and_free_mncc(gsm->network, resp->msg_type, resp);
+}
+
+/* PROCEEDING INDICATION */
+void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct gsm_mncc *mode;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       if (mncc->cause) {
+               add_trace("cause", "location", "%", mncc->cause_location);
+               add_trace("cause", "value", "%", mncc->cause_value);
+       }
+       end_trace();
+
+       /* modify lchan to GSM codec V1 */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+       end_trace();
+       mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+       mode->lchan_mode = 0x01; /* GSM V1 */
+       add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
+       send_and_free_mncc(gsm->network, mode->msg_type, mode);
+
+}
+
+/* ALERTING INDICATION */
+void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct lcr_msg *message;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       end_trace();
+
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
+       message_put(message);
+
+       new_state(PORT_STATE_OUT_ALERTING);
+
+}
+
+/* CONNECT INDICATION */
+void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct gsm_mncc *resp, *frame;
+       struct lcr_msg *message;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       end_trace();
+
+       /* send resp */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
+       resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
+       end_trace();
+       send_and_free_mncc(gsm->network, resp->msg_type, resp);
+
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
+       message_put(message);
+
+       new_state(PORT_STATE_CONNECT);
+
+       if (!p_m_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+               end_trace();
+               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
+               send_and_free_mncc(gsm->network, frame->msg_type, frame);
+               p_m_g_tch_connected = 1;
+       }
+}
+
+/* CONNECT ACK INDICATION */
+void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct gsm_mncc *frame;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       end_trace();
+
+       new_state(PORT_STATE_CONNECT);
+
+       if (!p_m_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+               end_trace();
+               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
+               send_and_free_mncc(gsm->network, frame->msg_type, frame);
+               p_m_g_tch_connected = 1;
+       }
+}
+
+/* DISCONNECT INDICATION */
+void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct lcr_msg *message;
+       int cause = 16, location = 0;
+       struct gsm_mncc *resp;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       if (mncc->cause) {
+               location = mncc->cause_location;
+               cause = mncc->cause_value;
+               add_trace("cause", "location", "%d", location);
+               add_trace("cause", "value", "%d", cause);
+       }
+       end_trace();
+
+       /* send release */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
+       add_trace("cause", "location", "%d", 1);
+       add_trace("cause", "value", "%d", cause);
+       end_trace();
+       resp = create_mncc(MNCC_REL_REQ, p_m_g_callref);
+       resp->cause = 1;
+       resp->cause_location = 1;
+       resp->cause_value = cause;
+       send_and_free_mncc(gsm->network, resp->msg_type, resp);
+
+       /* sending release to endpoint */
+       while(p_epointlist) {
+               message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = cause;
+               message->param.disconnectinfo.location = location;
+               message_put(message);
+               /* remove epoint */
+               free_epointlist(p_epointlist);
+       }
+       new_state(PORT_STATE_RELEASE);
+       p_m_delete = 1;
+}
+
+/* CC_RELEASE INDICATION */
+void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       int location = 0, cause = 16;
+       struct lcr_msg *message;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       if (mncc->cause) {
+               location = mncc->cause_location;
+               cause = mncc->cause_value;
+               add_trace("cause", "location", "%d", location);
+               add_trace("cause", "value", "%d", cause);
+       }
+       end_trace();
+
+       /* sending release to endpoint */
+       while(p_epointlist) {
+               message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = cause;
+               message->param.disconnectinfo.location = location;
+               message_put(message);
+               /* remove epoint */
+               free_epointlist(p_epointlist);
+       }
+       new_state(PORT_STATE_RELEASE);
+       p_m_delete = 1;
+}
+
+/* NOTIFY INDICATION */
+void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       end_trace();
+}
+
+
+/* HOLD INDICATION */
+void Pgsm::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct lcr_msg *message;
+       struct gsm_mncc *resp, *frame;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       end_trace();
+
+       /* notify the hold of call */
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
+       message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
+       message->param.notifyinfo.local = 1; /* call is held by supplementary service */
+       message_put(message);
+
+       /* acknowledge hold */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
+       end_trace();
+       resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
+       send_and_free_mncc(gsm->network, resp->msg_type, resp);
+
+       /* disable audio */
+       if (p_m_g_tch_connected) { /* it should be true */
+               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
+               end_trace();
+               frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
+               send_and_free_mncc(gsm->network, frame->msg_type, frame);
+               p_m_g_tch_connected = 0;
+       }
+}
+
+
+/* RETRIEVE INDICATION */
+void Pgsm::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct lcr_msg *message;
+       struct gsm_mncc *resp, *frame;
+
+       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       end_trace();
+
+       /* notify the retrieve of call */
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
+       message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
+       message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
+       message_put(message);
+
+       /* acknowledge retr */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
+       end_trace();
+       resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
+       send_and_free_mncc(gsm->network, resp->msg_type, resp);
+
+       /* enable audio */
+       if (!p_m_g_tch_connected) { /* it should be true */
+               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+               end_trace();
+               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
+               send_and_free_mncc(gsm->network, frame->msg_type, frame);
+               p_m_g_tch_connected = 1;
+       }
+}
+
+/*
+ * BSC sends message to port
+ */
+static int message_bcs(void *net, int msg_type, void *arg)
+{
+       struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
+       unsigned int callref = mncc->callref;
+       class Port *port;
+       class Pgsm *pgsm = NULL;
+       char name[64];
+       struct mISDNport *mISDNport;
+
+       /* Special messages */
+       switch(msg_type) {
+       }
+
+       /* find callref */
+       callref = mncc->callref;
+       port = port_first;
+       while(port) {
+               if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_GSM) {
+                       pgsm = (class Pgsm *)port;
+                       if (pgsm->p_m_g_callref == callref) {
+                               break;
+                       }
+               }
+               port = port->next;
+       }
+
+       if (msg_type == GSM_TRAU_FRAME) {
+               if (port)
+                       pgsm->trau_receive((struct gsm_trau_frame *)arg);
+               return 0;
+       }
+
+       if (!port) {
+               if (msg_type != MNCC_SETUP_IND)
+                       return(0);
+               /* find gsm port */
+               mISDNport = mISDNport_first;
+               while(mISDNport) {
+                       if (mISDNport->gsm)
+                               break;
+                       mISDNport = mISDNport->next;
+               }
+               if (!mISDNport) {
+                       struct gsm_mncc *rej;
+
+                       gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
+                       add_trace("cause", "location", "1");
+                       add_trace("cause", "value", "27");
+                       add_trace("reason", NULL, "GSM port not loaded");
+                       end_trace();
+                       rej = create_mncc(MNCC_REJ_REQ, callref);
+                       rej->cause = 1;
+                       rej->cause_location = 1;
+                       rej->cause_value = 27;
+                       send_and_free_mncc(gsm->network, rej->msg_type, rej);
+                       return 0;
+               }
+               /* creating port object, transparent until setup with hdlc */
+               SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
+               if (!(pgsm = new Pgsm(PORT_TYPE_GSM_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
+
+                       FATAL("Cannot create Port instance.\n");
+       }
+
+       switch(msg_type) {
+               case MNCC_SETUP_IND:
+               pgsm->setup_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_START_DTMF_IND:
+               pgsm->start_dtmf_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_STOP_DTMF_IND:
+               pgsm->stop_dtmf_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_CALL_CONF_IND:
+               pgsm->call_conf_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_ALERT_IND:
+               pgsm->alert_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_SETUP_CNF:
+               pgsm->setup_cnf(msg_type, callref, mncc);
+               break;
+
+               case MNCC_SETUP_COMPL_IND:
+               pgsm->setup_compl_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_DISC_IND:
+               pgsm->disc_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_REL_IND:
+               case MNCC_REL_CNF:
+               pgsm->rel_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_NOTIFY_IND:
+               pgsm->notify_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_HOLD_IND:
+               pgsm->hold_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_RETRIEVE_IND:
+               pgsm->retr_ind(msg_type, callref, mncc);
+               break;
+
+               default:
+               PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm->p_name, pgsm->p_callerinfo.id, msg_type);
+       }
+       return(0);
+}
+
+/* MESSAGE_SETUP */
+void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       struct lcr_msg *message;
+       int ret;
+       struct epoint_list *epointlist;
+       struct gsm_mncc *mncc;
+       int channel;
+
+       /* copy setup infos to port */
+       memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
+       memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
+       memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
+       memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
+
+       /* no number */
+       if (!p_dialinginfo.id[0]) {
+               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+               add_trace("failure", NULL, "No dialed subscriber given.");
+               end_trace();
+               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = 28;
+               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+               message_put(message);
+               new_state(PORT_STATE_RELEASE);
+               p_m_delete = 1;
+               return;
+       }
+       
+       /* release if port is blocked */
+       if (p_m_mISDNport->ifport->block) {
+               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+               add_trace("failure", NULL, "Port blocked.");
+               end_trace();
+               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = 27; // temp. unavail.
+               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+               message_put(message);
+               new_state(PORT_STATE_RELEASE);
+               p_m_delete = 1;
+               return;
+       }
+
+       /* hunt channel */
+       ret = channel = hunt_bchannel();
+       if (ret < 0)
+               goto no_channel;
+       /* open channel */
+       ret = seize_bchannel(channel, 1);
+       if (ret < 0) {
+               no_channel:
+               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+               add_trace("failure", NULL, "No internal audio channel available.");
+               end_trace();
+               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = 34;
+               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+               message_put(message);
+               new_state(PORT_STATE_RELEASE);
+               p_m_delete = 1;
+               return;
+       }
+       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
+       if (bchannel_open(p_m_b_index))
+               goto no_channel;
+
+//             SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
+       /* screen outgoing caller id */
+       do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
+       do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
+
+       /* attach only if not already */
+       epointlist = p_epointlist;
+       while(epointlist) {
+               if (epointlist->epoint_id == epoint_id)
+                       break;
+               epointlist = epointlist->next;
+       }
+       if (!epointlist)
+               epointlist_new(epoint_id);
+
+       /* creating l3id */
+       l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
+       p_m_g_callref = new_callref++;
+       add_trace("callref", "new", "0x%x", p_m_g_callref);
+       end_trace();
+
+       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+       mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
+       /* caller information */
+       mncc->calling = 1;
+       mncc->calling_plan = 1;
+       switch (p_callerinfo.ntype) {
+               case INFO_NTYPE_UNKNOWN:
+               mncc->calling_type = 0x0;
+               break;
+               case INFO_NTYPE_INTERNATIONAL:
+               mncc->calling_type = 0x1;
+               break;
+               case INFO_NTYPE_NATIONAL:
+               mncc->calling_type = 0x2;
+               break;
+               case INFO_NTYPE_SUBSCRIBER:
+               mncc->calling_type = 0x4;
+               break;
+               default: /* INFO_NTYPE_NOTPRESENT */
+               mncc->calling = 0;
+               break;
+       }
+       switch (p_callerinfo.screen) {
+               case INFO_SCREEN_USER:
+               mncc->calling_screen = 0;
+               break;
+               default: /* INFO_SCREEN_NETWORK */
+               mncc->calling_screen = 3;
+               break;
+       }
+       switch (p_callerinfo.present) {
+               case INFO_PRESENT_ALLOWED:
+               mncc->calling_present = 0;
+               break;
+               case INFO_PRESENT_RESTRICTED:
+               mncc->calling_present = 1;
+               break;
+               default: /* INFO_PRESENT_NOTAVAIL */
+               mncc->calling_present = 2;
+               break;
+       }
+       if (mncc->calling) {
+               SCPY(mncc->calling_number, p_callerinfo.id);
+               add_trace("calling", "type", "%d", mncc->calling_type);
+               add_trace("calling", "plan", "%d", mncc->calling_plan);
+               add_trace("calling", "present", "%d", mncc->calling_present);
+               add_trace("calling", "screen", "%d", mncc->calling_screen);
+               add_trace("calling", "number", "%s", mncc->calling_number);
+       }
+       /* dialing information */
+       mncc->called = 1;
+       SCPY(mncc->called_number, p_dialinginfo.id);
+       add_trace("dialing", "number", "%s", mncc->calling_number);
+       
+       /* sending user-user */
+
+       /* redirecting number */
+       mncc->redirecting = 1;
+       mncc->redirecting_plan = 1;
+       switch (p_redirinfo.ntype) {
+               case INFO_NTYPE_UNKNOWN:
+               mncc->redirecting_type = 0x0;
+               break;
+               case INFO_NTYPE_INTERNATIONAL:
+               mncc->redirecting_type = 0x1;
+               break;
+               case INFO_NTYPE_NATIONAL:
+               mncc->redirecting_type = 0x2;
+               break;
+               case INFO_NTYPE_SUBSCRIBER:
+               mncc->redirecting_type = 0x4;
+               break;
+               default: /* INFO_NTYPE_NOTPRESENT */
+               mncc->redirecting = 0;
+               break;
+       }
+       switch (p_redirinfo.screen) {
+               case INFO_SCREEN_USER:
+               mncc->redirecting_screen = 0;
+               break;
+               default: /* INFO_SCREE_NETWORK */
+               mncc->redirecting_screen = 3;
+               break;
+       }
+       switch (p_redirinfo.present) {
+               case INFO_PRESENT_ALLOWED:
+               mncc->redirecting_present = 0;
+               break;
+               case INFO_PRESENT_RESTRICTED:
+               mncc->redirecting_present = 1;
+               break;
+               default: /* INFO_PRESENT_NOTAVAIL */
+               mncc->redirecting_present = 2;
+               break;
+       }
+       /* sending redirecting number only in ntmode */
+       if (mncc->redirecting) {
+               SCPY(mncc->redirecting_number, p_redirinfo.id);
+               add_trace("redir", "type", "%d", mncc->redirecting_type);
+               add_trace("redir", "plan", "%d", mncc->redirecting_plan);
+               add_trace("redir", "present", "%d", mncc->redirecting_present);
+               add_trace("redir", "screen", "%d", mncc->redirecting_screen);
+               add_trace("redir", "number", "%s", mncc->redirecting_number);
+       }
+       /* bearer capability */
+       //todo
+
+       send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+       end_trace();
+
+       new_state(PORT_STATE_OUT_SETUP);
+
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
+       message_put(message);
+
+       new_state(PORT_STATE_OUT_PROCEEDING);
+}
+
+/* MESSAGE_NOTIFY */
+void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       struct gsm_mncc *mncc;
+       int notify;
+
+       printf("if = %d\n", param->notifyinfo.notify);
+       if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
+               notify = param->notifyinfo.notify & 0x7f;
+               if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
+                       /* queue notification */
+                       if (p_m_g_notify_pending)
+                               message_free(p_m_g_notify_pending);
+                       p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
+                       memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
+               } else {
+                       /* sending notification */
+                       gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
+                       add_trace("notify", NULL, "%d", notify);
+                       end_trace();
+                       mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
+                       mncc->notify = notify;
+                       send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+               }
+       }
+}
+
+/* MESSAGE_ALERTING */
+void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       struct gsm_mncc *mncc;
+
+       /* send alert */
+       gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
+       mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
+       if (p_m_mISDNport->tones) {
+               mncc->progress = 1;
+               mncc->progress_coding = 3; /* GSM */
+               mncc->progress_location = 1;
+               mncc->progress_descr = 8;
+               add_trace("progress", "coding", "%d", mncc->progress_coding);
+               add_trace("progress", "location", "%d", mncc->progress_location);
+               add_trace("progress", "descr", "%d", mncc->progress_descr);
+       }
+       send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+       end_trace();
+
+       new_state(PORT_STATE_IN_ALERTING);
+
+       if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+               end_trace();
+               mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
+               send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+               p_m_g_tch_connected = 1;
+       }
+}
+
+/* MESSAGE_CONNECT */
+void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       struct gsm_mncc *mncc;
+
+       /* copy connected information */
+       memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
+       /* screen outgoing caller id */
+       do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
+
+       /* send connect */
+       mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
+       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
+       /* caller information */
+       mncc->connected = 1;
+       mncc->connected_plan = 1;
+       switch (p_callerinfo.ntype) {
+               case INFO_NTYPE_UNKNOWN:
+               mncc->connected_type = 0x0;
+               break;
+               case INFO_NTYPE_INTERNATIONAL:
+               mncc->connected_type = 0x1;
+               break;
+               case INFO_NTYPE_NATIONAL:
+               mncc->connected_type = 0x2;
+               break;
+               case INFO_NTYPE_SUBSCRIBER:
+               mncc->connected_type = 0x4;
+               break;
+               default: /* INFO_NTYPE_NOTPRESENT */
+               mncc->connected = 0;
+               break;
+       }
+       switch (p_callerinfo.screen) {
+               case INFO_SCREEN_USER:
+               mncc->connected_screen = 0;
+               break;
+               default: /* INFO_SCREEN_NETWORK */
+               mncc->connected_screen = 3;
+               break;
+       }
+       switch (p_callerinfo.present) {
+               case INFO_PRESENT_ALLOWED:
+               mncc->connected_present = 0;
+               break;
+               case INFO_PRESENT_RESTRICTED:
+               mncc->connected_present = 1;
+               break;
+               default: /* INFO_PRESENT_NOTAVAIL */
+               mncc->connected_present = 2;
+               break;
+       }
+       if (mncc->connected) {
+               SCPY(mncc->connected_number, p_connectinfo.id);
+               add_trace("connected", "type", "%d", mncc->connected_type);
+               add_trace("connected", "plan", "%d", mncc->connected_plan);
+               add_trace("connected", "present", "%d", mncc->connected_present);
+               add_trace("connected", "screen", "%d", mncc->connected_screen);
+               add_trace("connected", "number", "%s", mncc->connected_number);
+       }
+       end_trace();
+       send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+
+       new_state(PORT_STATE_CONNECT_WAITING);
+}
+
+/* MESSAGE_DISCONNECT */
+void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       struct gsm_mncc *mncc;
+
+       /* send disconnect */
+       mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
+       gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
+       if (p_m_mISDNport->tones) {
+               mncc->progress = 1;
+               mncc->progress_coding = 3; /* GSM */
+               mncc->progress_location = 1;
+               mncc->progress_descr = 8;
+               add_trace("progress", "coding", "%d", mncc->progress_coding);
+               add_trace("progress", "location", "%d", mncc->progress_location);
+               add_trace("progress", "descr", "%d", mncc->progress_descr);
+       }
+       mncc->cause = 1;
+       mncc->cause_location = param->disconnectinfo.location;
+       mncc->cause_value = param->disconnectinfo.cause;
+       add_trace("cause", "location", "%d", mncc->cause_location);
+       add_trace("cause", "value", "%d", mncc->cause_value);
+       end_trace();
+       send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+
+       new_state(PORT_STATE_OUT_DISCONNECT);
+
+       if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+               end_trace();
+               mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
+               send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+               p_m_g_tch_connected = 1;
+       }
+}
+
+
+/* MESSAGE_RELEASE */
+void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       struct gsm_mncc *mncc;
+
+       /* send release */
+       mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
+       gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
+       mncc->cause = 1;
+       mncc->cause_location = param->disconnectinfo.location;
+       mncc->cause_value = param->disconnectinfo.cause;
+       add_trace("cause", "location", "%d", mncc->cause_location);
+       add_trace("cause", "value", "%d", mncc->cause_value);
+       end_trace();
+       send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
+
+       new_state(PORT_STATE_RELEASE);
+       p_m_delete = 1;
+       return;
+}
+
+
+/*
+ * endpoint sends messages to the port
+ */
+int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       if (PmISDN::message_epoint(epoint_id, message_id, param))
+               return(1);
+
+       switch(message_id) {
+               case MESSAGE_SETUP: /* dial-out command received from epoint */
+               if (p_state!=PORT_STATE_IDLE)
+                       break;
+               message_setup(epoint_id, message_id, param);
+               break;
+
+               case MESSAGE_NOTIFY: /* display and notifications */
+               message_notify(epoint_id, message_id, param);
+               break;
+
+//             case MESSAGE_FACILITY: /* facility message */
+//             message_facility(epoint_id, message_id, param);
+//             break;
+
+               case MESSAGE_PROCEEDING: /* message not handles */
+               break;
+
+               case MESSAGE_ALERTING: /* call of endpoint is ringing */
+               if (p_state!=PORT_STATE_IN_PROCEEDING)
+                       break;
+               message_alerting(epoint_id, message_id, param);
+               if (p_m_g_notify_pending) {
+                       /* send pending notify message during connect */
+                       message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
+                       message_free(p_m_g_notify_pending);
+                       p_m_g_notify_pending = NULL;
+               }
+               break;
+
+               case MESSAGE_CONNECT: /* call of endpoint is connected */
+               if (p_state!=PORT_STATE_IN_PROCEEDING
+                && p_state!=PORT_STATE_IN_ALERTING)
+                       break;
+               message_connect(epoint_id, message_id, param);
+               if (p_m_g_notify_pending) {
+                       /* send pending notify message during connect */
+                       message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
+                       message_free(p_m_g_notify_pending);
+                       p_m_g_notify_pending = NULL;
+               }
+               break;
+
+               case MESSAGE_DISCONNECT: /* call has been disconnected */
+               if (p_state!=PORT_STATE_IN_PROCEEDING
+                && p_state!=PORT_STATE_IN_ALERTING
+                && p_state!=PORT_STATE_OUT_SETUP
+                && p_state!=PORT_STATE_OUT_OVERLAP
+                && p_state!=PORT_STATE_OUT_PROCEEDING
+                && p_state!=PORT_STATE_OUT_ALERTING
+                && p_state!=PORT_STATE_CONNECT
+                && p_state!=PORT_STATE_CONNECT_WAITING)
+                       break;
+               message_disconnect(epoint_id, message_id, param);
+               break;
+
+               case MESSAGE_RELEASE: /* release isdn port */
+               if (p_state==PORT_STATE_RELEASE)
+                       break;
+               message_release(epoint_id, message_id, param);
+               break;
+
+               default:
+               PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
+       }
+
+       return(1);
+}
+
+
+/*
+ * handler
+ */
+int Pgsm::handler(void)
+{
+       int ret;
+       int work = 0;
+       unsigned char buffer[2048+MISDN_HEADER_LEN];
+       struct mISDNhead *hh = (struct mISDNhead *)buffer;
+
+       if ((ret = PmISDN::handler()))
+               return(ret);
+
+       /* handle destruction */
+       if (p_m_delete) {
+               delete this;
+               return(-1);
+       }
+
+       /* handle message from bchannel */
+       if (p_m_g_gsm_b_sock > -1) {
+               ret = recv(p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
+               if (ret >= (int)MISDN_HEADER_LEN) {
+                       switch(hh->prim) {
+                               /* we don't care about confirms, we use rx data to sync tx */
+                               case PH_DATA_CNF:
+                               break;
+                               /* we receive audio data, we respond to it AND we send tones */
+                               case PH_DATA_IND:
+                               bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
+                               break;
+                               case PH_ACTIVATE_IND:
+                               p_m_g_gsm_b_active = 1;
+                               break;
+                               case PH_DEACTIVATE_IND:
+                               p_m_g_gsm_b_active = 0;
+                               break;
+                       }
+                       work = 1;
+               } else {
+                       if (ret < 0 && errno != EWOULDBLOCK)
+                               PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
+               }
+       }
+
+       return(work);
+}
+
+
+/*
+ * handles bsc select function within LCR's main loop
+ */
+int handle_gsm(void)
+{
+       int ret1, ret2;
+
+       ret1 = bsc_upqueue(gsm->network);
+       ret2 = bsc_select_main(1); /* polling */
+       if (ret1 || ret2)
+               return 1;
+       return 0;
+}
+
+static void gsm_sock_close(void)
+{
+       if (gsm->gsm_sock > -1)
+               close(gsm->gsm_sock);
+       gsm->gsm_sock = -1;
+}
+
+static int gsm_sock_open(char *portname)
+{
+       int ret;
+       int cnt;
+       unsigned long on = 1;
+       struct sockaddr_mISDN addr;
+       struct mISDN_devinfo devinfo;
+       int pri, bri;
+
+       /* check port counts */
+       ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
+       if (ret < 0) {
+               fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
+               return(ret);
+       }
+
+       if (cnt <= 0) {
+               PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
+               return -EIO;
+       }
+       gsm->gsm_port = mISDN_getportbyname(mISDNsocket, cnt, portname);
+       if (gsm->gsm_port < 0) {
+               PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname);
+               return gsm->gsm_port;
+       }
+       /* get protocol */
+       bri = pri = 0;
+       devinfo.id = gsm->gsm_port;
+       ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
+       if (ret < 0) {
+               PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", gsm->gsm_port, ret);
+               return ret;
+       }
+       if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
+               bri = 1;
+       }
+       if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
+               pri = 1;
+       }
+       if (!pri && !pri) {
+               PERROR_RUNTIME("GSM port %d does not support TE PRI or TE BRI.\n", gsm->gsm_port);
+       }
+       /* open socket */
+       if ((gsm->gsm_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_TE_S0)) < 0) {
+               PERROR_RUNTIME("GSM port %d failed to open socket.\n", gsm->gsm_port);
+               gsm_sock_close();
+               return gsm->gsm_sock;
+       }
+       /* set nonblocking io */
+       if ((ret = ioctl(gsm->gsm_sock, FIONBIO, &on)) < 0) {
+               PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", gsm->gsm_port);
+               gsm_sock_close();
+               return ret;
+       }
+       /* bind socket to dchannel */
+       memset(&addr, 0, sizeof(addr));
+       addr.family = AF_ISDN;
+       addr.dev = gsm->gsm_port;
+       addr.channel = 0;
+       if ((ret = bind(gsm->gsm_sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
+               PERROR_RUNTIME("GSM port %d failed to bind socket. (name = %s errno=%d)\n", gsm->gsm_port, portname, errno);
+               gsm_sock_close();
+               return (ret);
+       }
+
+       return 0;
+}
+
+
+int gsm_exit(int rc)
+{
+       /* free gsm instance */
+       if (gsm) {
+               if (gsm->gsm_sock > -1)
+                       gsm_sock_close();
+               /* shutdown network */
+               if (gsm->network)
+                       shutdown_net(gsm->network);
+               /* free network */
+               if (gsm->network) {
+                       free(gsm->network); /* TBD */
+               }
+               free(gsm);
+               gsm = NULL;
+       }
+
+       return(rc);
+}
+
+int gsm_init(void)
+{
+       char hlr[128];
+
+       /* create gsm instance */
+       gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
+       gsm->gsm_sock = -1;
+
+       /* parse options */
+       if (!gsm_conf(&gsm->conf)) {
+               PERROR("%s", gsm_conf_error);
+               return gsm_exit(-EINVAL);
+       }
+
+       /* init database */
+       if (gsm->conf.hlr[0] == '/')
+               SCPY(hlr, gsm->conf.hlr);
+       else
+               SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
+
+       // TODO multiple base stations
+       if (gsm->conf.numbts < 1 || gsm->conf.numbts > 1) {
+               PERROR("Expecting exactly one BTS. You defined %d.\n", gsm->conf.numbts);
+               return gsm_exit(-1);
+       }
+       /* bootstrap network */
+       gsm->network = bootstrap_network(&message_bcs, gsm->conf.bts[0].type, gsm->conf.mcc, gsm->conf.mnc, gsm->conf.lac, gsm->conf.bts[0].frequency[0], gsm->conf.bts[0].card, !gsm->conf.keep_l2, gsm->conf.short_name, gsm->conf.long_name, hlr, gsm->conf.allow_all);
+       if (!gsm->network) {
+               PERROR("Failed to bootstrap GSM network.\n");
+               return gsm_exit(-1);
+       }
+       /* open gsm loop interface */
+       if (gsm_sock_open(gsm->conf.interface_bsc)) {
+               return gsm_exit(-1);
+       }
+
+       return 0;
+}
+
diff --git a/gsm.h b/gsm.h
new file mode 100644 (file)
index 0000000..61676de
--- /dev/null
+++ b/gsm.h
@@ -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);
+
diff --git a/gsm_audio.c b/gsm_audio.c
new file mode 100644 (file)
index 0000000..751f354
--- /dev/null
@@ -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);
+}
+
+}
+
diff --git a/gsm_audio.h b/gsm_audio.h
new file mode 100644 (file)
index 0000000..04a6d77
--- /dev/null
@@ -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);
+
diff --git a/gsm_conf.c b/gsm_conf.c
new file mode 100644 (file)
index 0000000..8898cf2
--- /dev/null
@@ -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);
+}
+
+
index 28ad88c..613614a 100644 (file)
@@ -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);
                        }
                                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;
                        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);
 }
        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."},
 
        {"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}
 };
 
        {NULL, NULL, NULL, NULL}
 };
 
@@ -1412,7 +1465,7 @@ void load_port(struct interface_port *ifport)
        struct mISDNport *mISDNport;
 
        /* open new port */
        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 */
        if (mISDNport)
        {
                /* link port */
index a467a71..e459b5b 100644 (file)
@@ -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                     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 */
        int                     channel_force; /* forces channel by protocol */
        int                     nodtmf; /* disables DTMF */
        struct select_channel   *out_channel; /* list of channels to select */
index b8b9ac3..12bfa74 100644 (file)
@@ -1836,7 +1836,7 @@ int main(int argc, char *argv[])
        int mode;
        int sock, conn;
        struct sockaddr_un sock_address;
        int mode;
        int sock, conn;
        struct sockaddr_un sock_address;
-       const char *ret;
+       const char *ret = "invalid mode";
 
 
        /* show options */
 
 
        /* show options */
index 2cbd39f..57c942e 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -1947,106 +1947,109 @@ int mISDN_handler(void)
                }
 
                /* handle queued up-messages (d-channel) */
                }
 
                /* 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++;
+                                       case MPH_ACTIVATE_IND:
+                                       if (mISDNport->l1link != 1)
+                                       {
+                                               l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
+                                               end_trace();
+                                               mISDNport->l1link = 1;
+                                       }
                                        break;
                                        break;
-                                       case L1_SIGNAL_SLIP_RX:
-                                       mISDNport->slip_rx++;
+               
+                                       case MPH_DEACTIVATE_IND:
+                                       if (mISDNport->l1link != 0)
+                                       {
+                                               l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
+                                               end_trace();
+                                               mISDNport->l1link = 0;
+                                       }
                                        break;
                                        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_INFORMATION_IND:
+                                       PDEBUG(DEBUG_ISDN, "Received MPH_INFORMATION_IND for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
+                                       switch (l3m->pid)
                                        {
                                        {
-                                               mISDNport->l2establish = 0;
-                                               PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
+                                               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;
+                                       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 MT_L2ESTABLISH:
+                                       l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
                                        add_trace("tei", NULL, "%d", l3m->pid);
                                        end_trace();
                                        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
                }
 
 #if 0
@@ -2062,7 +2065,7 @@ int mISDN_handler(void)
                        if (now-mISDNport->l2establish > 5)
                        {
                                mISDNport->l2establish = 0;
                        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);
                                {
 
                                        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);
        }
                mt_assign_pid = pid;
                return(0);
        }
-       
        /* queue message, create, if required */
        if (!l3m)
        {
        /* 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;
 }
 
        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)
  */
 
 /*
  * 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;
 {
        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)
        {
        }
        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
                        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));
 
        /* 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;
 
        pmemuse++;
        *mISDNportp = mISDNport;
 
@@ -2307,7 +2353,6 @@ struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt
        }
                
        /* allocate ressources of port */
        }
                
        /* 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
        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);
               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)
-       {
-               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 */
+               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
+       {
+               /* 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;
 
        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 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);
        {
                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++;
        }
 
                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);
        {
                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)
        /* remove from list */
        mISDNportp = &mISDNport_first;
        while(*mISDNportp)
diff --git a/mISDN.h b/mISDN.h
index 90f686b..4f1e596 100644 (file)
--- a/mISDN.h
+++ b/mISDN.h
@@ -15,6 +15,8 @@
 extern int entity;
 extern int mISDNdevice;
 
 extern int entity;
 extern int mISDNdevice;
 
+extern int mISDNsocket;
+
 enum {
        B_EVENT_USE,            /* activate/export bchannel */
        B_EVENT_EXPORTREQUEST,  /* remote app requests bchannel */
 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;
        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;
 
 };
 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);
 /* 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);
 void mISDNport_close_all(void);
 void mISDNport_close(struct mISDNport *mISDNport);
 void mISDN_port_reorder(void);
diff --git a/main.c b/main.c
index 51da4a1..522b214 100644 (file)
--- a/main.c
+++ b/main.c
@@ -394,6 +394,21 @@ int main(int argc, char *argv[])
                goto free;
        }
 
                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())
        {
        /* read interfaces and open ports */
        if (!read_interfaces())
        {
@@ -614,6 +629,15 @@ BUDETECT
                        all_idle = 0;
 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)
 #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();
 
        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) \
        /* display memory leak */
 #define MEMCHECK(a, b) \
        if (b) \
diff --git a/main.h b/main.h
index 427b39c..0b9f754 100644 (file)
--- a/main.h
+++ b/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_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
 //#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"
 #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"
 #include "vbox.h"
 #include "join.h"
 #include "joinpbx.h"
@@ -158,6 +162,7 @@ extern "C" {
 #include "socket_server.h"
 #include "trace.h"
 
 #include "socket_server.h"
 #include "trace.h"
 
+extern int quit;
 extern double now_d;
 extern time_t now;
 extern struct tm *now_tm;
 extern double now_d;
 extern time_t now;
 extern struct tm *now_tm;
index 7ac4a84..9fc01b2 100644 (file)
--- a/message.h
+++ b/message.h
@@ -12,7 +12,7 @@
 #define ISDN_TRANSMIT  256 // samples
 
 enum { /* interface types */
 #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
        INFO_ITYPE_ISDN_EXTENSION, /* call from internal extension */
        INFO_ITYPE_CHAN,
        INFO_ITYPE_VBOX
index 160a8a8..b76059e 100644 (file)
--- a/options.c
+++ b/options.c
@@ -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 */
        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];
 };
 
 char options_error[256];
@@ -249,6 +250,10 @@ int read_options(void)
                {
                        options.socketrights = strtol(param, NULL, 0);
                } else
                {
                        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;
                {
                        SPRINT(options_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option);
                        goto error;
index 976aaba..872ac7d 100644 (file)
--- a/options.h
+++ b/options.h
@@ -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 */
        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;
 };     
 
 extern struct options options;
diff --git a/port.h b/port.h
index 3a1a930..be2598f 100644 (file)
--- a/port.h
+++ b/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       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
 #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
        /* 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
 
        /* answering machine */
 #define        PORT_TYPE_VBOX_OUT      0x0311
 
diff --git a/route.c b/route.c
index 017a55c..da59e98 100644 (file)
--- a/route.c
+++ b/route.c
@@ -2022,7 +2022,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset)
 
                                case MATCH_PORT:
                                if (ea_endpoint->ep_portlist)
 
                                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;
                                        break;
                                integer = e_callerinfo.isdn_port;
                                goto match_integer;