Ports can now be specified by number or by name.
[lcr.git] / mISDN.cpp
index 4bc679b..98e2c6c 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -13,6 +13,8 @@
 #include "myisdn.h"
 
 extern "C" {
+#define MISDN_OLD_AF_COMPATIBILITY 1
+#include <compat_af_isdn.h>
 }
 #include <q931.h>
 
@@ -46,6 +48,8 @@ int mISDN_initialize(void)
 {
        char filename[256];
 
+       init_af_isdn();
+
        /* try to open raw socket to check kernel */
        mISDNsocket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
        if (mISDNsocket < 0)
@@ -192,10 +196,10 @@ PmISDN::~PmISDN()
 /*
  * trace
  */
-void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
+void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, const char *msgtext, int direction)
 {
        /* init trace with given values */
-       start_trace(mISDNport?mISDNport->portnum:0,
+       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,
@@ -210,7 +214,7 @@ void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *ms
  * layer trace header
  */
 static struct isdn_message {
-       char *name;
+       const char *name;
        unsigned int value;
 } isdn_message[] = {
        {"PH_ACTIVATE", L1_ACTIVATE_REQ},
@@ -250,7 +254,7 @@ static struct isdn_message {
        {"MT_RELEASE_L3ID", L3_RELEASE_L3ID_REQ},
        {NULL, 0},
 };
-static char *isdn_prim[4] = {
+static const char *isdn_prim[4] = {
        " REQUEST",
        " CONFIRM",
        " INDICATION",
@@ -259,8 +263,9 @@ static char *isdn_prim[4] = {
 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg, int direction)
 {
        int i;
-       char msgtext[64] = "<<UNKNOWN MESSAGE>>";
+       char msgtext[64];
 
+       SCPY(msgtext, "<<UNKNOWN MESSAGE>>");
        /* select message and primitive text */
        i = 0;
        while(isdn_message[i].name)
@@ -296,7 +301,7 @@ void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsign
        }
 
        /* init trace with given values */
-       start_trace(mISDNport?mISDNport->portnum:0,
+       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,
@@ -310,7 +315,7 @@ void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsign
 /*
  * send control information to the channel (dsp-module)
  */
-void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, unsigned int c1, unsigned int c2, char *trace_name, int trace_value)
+void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, unsigned int c1, unsigned int c2, const char *trace_name, int trace_value)
 {
        unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
        struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
@@ -335,7 +340,7 @@ void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, u
        end_trace();
 }
 
-void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, unsigned int c1, void *c2, int c2_len, char *trace_name, int trace_value)
+void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, unsigned int c1, void *c2, int c2_len, const char *trace_name, int trace_value)
 {
        unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
        struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
@@ -396,7 +401,7 @@ static int _bchannel_create(struct mISDNport *mISDNport, int i)
 
        /* bind socket to bchannel */
        addr.family = AF_ISDN;
-       addr.dev = mISDNport->portnum-1;
+       addr.dev = mISDNport->portnum;
        addr.channel = i+1+(i>=15);
        ret = bind(mISDNport->b_socket[i], (struct sockaddr *)&addr, sizeof(addr));
        if (ret < 0)
@@ -434,7 +439,7 @@ static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
                PERROR("Failed to send to socket %d\n", mISDNport->b_socket[i]);
 
        /* trace */
-       chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
+       chan_trace_header(mISDNport, mISDNport->b_port[i], activate ? "BCHANNEL activate" : "BCHANNEL deactivate", DIRECTION_OUT);
        add_trace("channel", NULL, "%d", i+1+(i>=15));
        if (mISDNport->b_timer[i])
                add_trace("event", NULL, "timeout recovery");
@@ -774,6 +779,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                                /* bchannel is active and used by Port class, so we configure bchannel */
                                _bchannel_configure(mISDNport, i);
                                state = B_STATE_ACTIVE;
+                               b_port->p_m_load = 0;
                        } else
                        {
                                /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
@@ -1263,7 +1269,8 @@ int PmISDN::handler(void)
                p_m_last_tv_msec = now_tv.tv_usec/1000;
        }
        /* process only if we have a minimum of samples, to make packets not too small */
-       if (elapsed >= ISDN_TRANSMIT)
+       if (elapsed >= ISDN_TRANSMIT
+        && p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
        {
                /* set clock of last process! */
                p_m_last_tv_sec = now_tv.tv_sec;
@@ -1319,15 +1326,15 @@ int PmISDN::handler(void)
                        }
 
                        /* send data */
-                       if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && ISDN_LOAD-p_m_load-tosend > 0)
+                       if (ISDN_LOAD - p_m_load - tosend > 0)
                        {
                                frm->prim = PH_DATA_REQ;
                                frm->id = 0;
                                ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
                                if (ret <= 0)
                                        PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_socket[p_m_b_index], ISDN_LOAD-p_m_load-tosend);
+                               p_m_load += ISDN_LOAD - p_m_load - tosend;
                        }
-                       p_m_load += ISDN_LOAD - p_m_load - tosend;
                }
        }
 
@@ -1525,7 +1532,7 @@ void PmISDN::set_echotest(int echo)
 /*
  * set tone
  */
-void PmISDN::set_tone(char *dir, char *tone)
+void PmISDN::set_tone(const char *dir, const char *tone)
 {
        int id;
 
@@ -2110,7 +2117,7 @@ int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3
 /*
  * global function to add a new card (port)
  */
-struct mISDNport *mISDNport_open(int port, int ptp, int force_nt, int l2hold, struct interface *interface)
+struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt, int l2hold, struct interface *interface)
 {
        int ret;
        struct mISDNport *mISDNport, **mISDNportp;
@@ -2121,6 +2128,7 @@ struct mISDNport *mISDNport_open(int port, int ptp, int force_nt, int l2hold, st
        struct mISDN_devinfo devinfo;
        unsigned int protocol, prop;
 
+       /* check port counts */
        ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
        if (ret < 0)
        {
@@ -2133,21 +2141,45 @@ struct mISDNport *mISDNport_open(int port, int ptp, int force_nt, int l2hold, st
                PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
                return(NULL);
        }
-       if (port>cnt || port<1)
+       if (port < 0)
+       {
+               /* resolve name */
+               port = 0;
+               while (port < cnt)
+               {
+                       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' no found, use 'isdninfo' tool to list all existing ports.\n", portname);
+                       return(NULL);
+               }
+               // note: 'port' has still the port number
+       }
+       if (port>cnt || port<0)
        {
-               PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
+               PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 0, cnt);
                return(NULL);
        }
 
+       /* get port attributes */
        pri = bri = pots = nt = te = 0;
-       devinfo.id = port - 1;
+       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", i, ret);
+               PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", port, ret);
                return(NULL);
        }
-       /* output the port info */
        if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
        {
                bri = 1;
@@ -2214,6 +2246,24 @@ struct mISDNport *mISDNport_open(int port, int ptp, int force_nt, int l2hold, st
        if (te && nt)
                nt = 0;
 
+       /* check for double use of port */
+       if (nt)
+       {
+               mISDNport = mISDNport_first;
+               while(mISDNport)
+               {
+                       if (mISDNport->portnum == port)
+                               break;
+                       mISDNport = mISDNport->next;
+               }
+               if (mISDNport)
+               {
+                       PERROR_RUNTIME("Port %d already in use by LCR. You can't use a NT port multiple times.\n", port);
+                       return(NULL);
+               }
+       }
+
+
        /* add mISDNport structure */
        mISDNportp = &mISDNport_first;
        while(*mISDNportp)
@@ -2256,7 +2306,7 @@ struct mISDNport *mISDNport_open(int port, int ptp, int force_nt, int l2hold, st
               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-1, protocol, prop , do_layer3, mISDNport);
+       mISDNport->ml3 = open_layer3(port, protocol, prop , do_layer3, mISDNport);
        if (!mISDNport->ml3)
        {
                mqueue_purge(&mISDNport->upqueue);