Added layer1 hold feature. Requires new mISDN and mISDNuser package from git.
[lcr.git] / interface.c
index f7f5a3d..28ad88c 100644 (file)
@@ -9,9 +9,6 @@
 **                                                                           **
 \*****************************************************************************/ 
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
 #include "main.h"
 
 struct interface *interface_first = NULL; /* first interface is current list */
@@ -158,6 +155,7 @@ static int inter_ptp(struct interface *interface, char *filename, int line, char
        ifport->ptp = 1;
        return(0);
 }
+#if 0
 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
        struct interface_port *ifport;
@@ -186,9 +184,9 @@ static int inter_ptmp(struct interface *interface, char *filename, int line, cha
        ifport->ptmp = 1;
        return(0);
 }
+#endif
 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
-#ifdef SOCKET_MISDN
        struct interface_port *ifport;
 
        /* port in chain ? */
@@ -208,7 +206,29 @@ static int inter_nt(struct interface *interface, char *filename, int line, char
                return(-1);
        }
        ifport->nt = 1;
-#endif
+       return(0);
+}
+static int inter_tespecial(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+       struct interface_port *ifport;
+
+       /* port in chain ? */
+       if (!interface->ifport)
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+               return(-1);
+       }
+       /* goto end of chain */
+       ifport = interface->ifport;
+       while(ifport->next)
+               ifport = ifport->next;
+       /* add value */
+       if (value[0])
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
+               return(-1);
+       }
+       ifport->tespecial = 1;
        return(0);
 }
 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
@@ -261,6 +281,11 @@ static int inter_hunt(struct interface *interface, char *filename, int line, cha
 }
 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
+       SPRINT(interface_error, "Error in %s (line %d): parameter '%s' is outdated.\nPlease use 'portnum' and decrease port number by 1! Ports are counted from 0 now.\n", filename, line, parameter);
+       return(-1);
+}
+static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
        struct interface_port *ifport, **ifportp;
        struct interface *searchif;
        int val;
@@ -300,6 +325,97 @@ static int inter_port(struct interface *interface, char *filename, int line, cha
        *ifportp = ifport;
        return(0);
 }
+static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+       struct interface_port *ifport, **ifportp;
+       struct interface *searchif;
+
+       /* check for port already assigned */
+       searchif = interface_newlist;
+       while(searchif)
+       {
+               ifport = searchif->ifport;
+               while(ifport)
+               {
+                       if (!strcasecmp(ifport->portname, value))
+                       {
+                               SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
+                               return(-1);
+                       }
+                       ifport = ifport->next;
+               }
+               searchif = searchif->next;
+       }
+       /* alloc port substructure */
+       ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
+       memuse++;
+       ifport->interface = interface;
+       /* set value */
+       ifport->portnum = -1; // disable until resolved
+       SCPY(ifport->portname, value);
+       /* tail port */
+       ifportp = &interface->ifport;
+       while(*ifportp)
+               ifportp = &((*ifportp)->next);
+       *ifportp = ifport;
+       return(0);
+}
+static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+       struct interface_port *ifport;
+
+       /* port in chain ? */
+       if (!interface->ifport)
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+               return(-1);
+       }
+       /* goto end of chain */
+       ifport = interface->ifport;
+       while(ifport->next)
+               ifport = ifport->next;
+       if (!strcmp(value, "yes"))
+       {
+               ifport->l1hold = 1;
+       } else
+       if (!strcmp(value, "no"))
+       {
+               ifport->l1hold = 0;
+       } else
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
+               return(-1);
+       }
+       return(0);
+}
+static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+       struct interface_port *ifport;
+
+       /* port in chain ? */
+       if (!interface->ifport)
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+               return(-1);
+       }
+       /* goto end of chain */
+       ifport = interface->ifport;
+       while(ifport->next)
+               ifport = ifport->next;
+       if (!strcmp(value, "yes"))
+       {
+               ifport->l2hold = 1;
+       } else
+       if (!strcmp(value, "no"))
+       {
+               ifport->l2hold = -1;
+       } else
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
+               return(-1);
+       }
+       return(0);
+}
 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
        struct interface_port *ifport;
@@ -810,6 +926,23 @@ static int inter_filter(struct interface *interface, char *filename, int line, c
        }
        return(0);
 }
+static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+       struct interface_port *ifport;
+
+       /* port in chain ? */
+       if (!interface->ifport)
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+               return(-1);
+       }
+       /* goto end of chain */
+       ifport = interface->ifport;
+       while(ifport->next)
+               ifport = ifport->next;
+       ifport->dialmax = atoi(value);
+       return(0);
+}
 
 
 /*
@@ -828,7 +961,11 @@ struct interface_param interface_param[] = {
        "Select the algorithm for selecting port with free channel."},
 
        {"port", &inter_port, "<number>",
+       ""},
+       {"portnum", &inter_portnum, "<number>",
        "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
+       {"portname", &inter_portname, "<name>",
+       "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
 
        {"block", &inter_block, "",
        "If keyword is given, calls on this interface are blocked.\n"
@@ -839,17 +976,34 @@ struct interface_param interface_param[] = {
        "This is required on NT-mode ports that are multipoint by default.\n"
        "This parameter must follow a 'port' parameter."},
 
+#if 0
        {"ptmp", &inter_ptmp, "",
        "The given port above is opened as point-to-multipoint.\n"
        "This is required on PRI NT-mode ports that are point-to-point by default.\n"
        "This parameter must follow a 'port' parameter."},
+#endif
+
        {"nt", &inter_nt, "",
        "The given port above is opened in NT-mode.\n"
-#ifdef SOCKET_MISDN
        "This is required on interfaces that support both NT-mode and TE-mode.\n"
-#else
-       "This parameter is only required for socket based mISDN driver.\n"
-#endif
+       "This parameter must follow a 'port' parameter."},
+
+       {"te-special", &inter_tespecial, "",
+       "The given port uses a modified TE-mode.\n"
+       "All information elements that are allowed Network->User will then be\n"
+       "transmitted User->Network also. This is usefull to pass all informations\n"
+       "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
+       "Note that this is not compliant with ISDN protocol.\n"
+       "This parameter must follow a 'port' parameter."},
+
+       {"layer1hold", &inter_l1hold, "yes | no",
+       "The given port will not release layer 1 after layer 2 is down.\n"
+       "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
+       "This parameter must follow a 'port' parameter."},
+
+       {"layer2hold", &inter_l2hold, "yes | no",
+       "The given port will continuously try to establish layer 2 link and hold it.\n"
+       "It is required for PTP links in most cases, therefore it is default.\n"
        "This parameter must follow a 'port' parameter."},
 
        {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
@@ -898,19 +1052,15 @@ struct interface_param interface_param[] = {
        "Disables DTMF detection for this interface.\n"
        "This parameter must follow a 'port' parameter."},
 
-#if 0
-       {"layer2keep", &inter_layer2keep, "yes | no",
-       "By default, layer 2 is establised and kept up on PTP interfaces.\n"
-       ".\n"
-       "This parameter must follow a 'port' parameter."},
-#endif
-
        {"filter", &inter_filter, "<filter> <parameters>",
        "Adds/appends a filter. Filters are ordered in transmit direction.\n"
        "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
        "pipeline <string> - Sets echo cancelation pipeline.\n"
        "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
 
+       {"dialmax", &inter_dialmax, "<digits>",
+       "Limits the number of digits in setup/information message."},
+
        {NULL, NULL, NULL, NULL}
 };
 
@@ -936,7 +1086,7 @@ struct interface *read_interfaces(void)
        if (interface_newlist != NULL)
                FATAL("list is not empty.\n");
        interface_error[0] = '\0';
-       SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
+       SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
 
        if (!(fp = fopen(filename,"r")))
        {
@@ -1204,8 +1354,11 @@ void relink_interfaces(void)
                        mISDNport = mISDNport_first;
                        while(mISDNport)
                        {
+                               if (!strcmp(mISDNport->name, ifport->portname))
+                                       ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
                                if (mISDNport->portnum == ifport->portnum)
                                {
+                                       PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", mISDNport->portnum);
                                        ifport->mISDNport = mISDNport;
                                        mISDNport->ifport = ifport;
                                        set_defaults(ifport);
@@ -1259,12 +1412,16 @@ void load_port(struct interface_port *ifport)
        struct mISDNport *mISDNport;
 
        /* open new port */
-       mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->nt, ifport->interface);
+       mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l1hold, ifport->l2hold, ifport->interface);
        if (mISDNport)
        {
                /* link port */
                ifport->mISDNport = mISDNport;
                mISDNport->ifport = ifport;
+               /* set number and name */
+               ifport->portnum = mISDNport->portnum;
+               SCPY(ifport->portname, mISDNport->name);
+               /* set defaults */
                set_defaults(ifport);
        } else
        {
@@ -1286,15 +1443,19 @@ void doc_interface(void)
        ifparam = interface_param;
        while(ifparam->name)
        {
-               printf("%s %s\n", ifparam->name, ifparam->usage);
+               if (ifparam->name[0])
+                       printf("%s %s\n", ifparam->name, ifparam->usage);
                ifparam++;
        }
 
        ifparam = interface_param;
        while(ifparam->name)
        {
-               printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
-               printf("%s\n", ifparam->help);
+               if (ifparam->name[0])
+               {
+                       printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
+                       printf("%s\n", ifparam->help);
+               }
                ifparam++;
        }
 }
@@ -1328,13 +1489,13 @@ void do_screen(int out, char *id, int idsize, int *type, int *present, struct in
                }
                if (ifmsn)
                {
-                       start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
+                       start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
                        add_trace("msn", NULL, "%s", id);
                        end_trace();
                }
                if (!ifmsn && msn1) // not in list, first msn given
                {
-                       start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
+                       start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
                        add_trace("msn", "given", "%s", id);
                        add_trace("msn", "used", "%s", msn1);
                        end_trace();
@@ -1367,7 +1528,7 @@ void do_screen(int out, char *id, int idsize, int *type, int *present, struct in
        }
        if (ifscreen) // match
        {
-               start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
+               start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
                switch(*type)
                {
                        case INFO_NTYPE_UNKNOWN: