Add FXS support
[lcr.git] / mISDN.cpp
index 39ccc35..cdc24ef 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -117,12 +117,12 @@ void mISDN_deinitialize(void)
        upqueue_avail = 0;
 }
 
-int load_timer(struct lcr_timer *timer, void *instance, int index);
+static int load_timer(struct lcr_timer *timer, void *instance, int index);
 
 /*
  * constructor
  */
-PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Port(type, portname, settings)
+PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, struct interface *interface, int channel, int exclusive, int mode) : Port(type, portname, settings, interface)
 {
        p_m_mISDNport = mISDNport;
        p_m_portnum = mISDNport->portnum;
@@ -139,6 +139,8 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti
        p_m_txdata = 0;
        p_m_delay = 0;
        p_m_tx_dejitter = 0;
+       p_m_preload = ISDN_LOAD;
+       p_m_disable_dejitter = 0;
        p_m_echo = 0;
        p_m_tone = 0;
        p_m_rxoff = 0;
@@ -649,6 +651,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                                _bchannel_configure(mISDNport, i);
                                state = B_STATE_ACTIVE;
                                b_port->p_m_load = 0;
+                               b_port->update_load();
                        } else {
                                /* bchannel is active, but not used anymore (or has wrong stack config), so we deactivate */
                                _bchannel_activate(mISDNport, i, 0, 0);
@@ -879,31 +882,31 @@ times have no skew.
 
 * levels
 there are two levels:
-ISDN_LOAD will give the load that have to be kept in dsp.
-ISDN_MAXLOAD will give the maximum load before dropping.
+p_m_preload will give the load that have to be kept in dsp.
+ISDN_MAXLOAD (2*p_m_preload) will give the maximum load before dropping.
 
 * procedure for low priority data
 see txfromup() for procedure
 in short: remote data is ignored during high priority tones
 
 * procedure for high priority data
-whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
+whenever load is below p_m_preload, load is filled up to p_m_preload
 if no more data is available, load becomes empty again.
 
 'load' variable:
-0                    ISDN_LOAD           ISDN_MAXLOAD
+0                    p_m_preload           ISDN_MAXLOAD
 +--------------------+----------------------+
 |                    |                      |
 +--------------------+----------------------+
 
-on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
-0                    ISDN_LOAD           ISDN_MAXLOAD
+on empty load or on load below p_m_preload, the load is inceased to p_m_preload:
+0                    p_m_preload           ISDN_MAXLOAD
 +--------------------+----------------------+
 |TTTTTTTTTTTTTTTTTTTT|                      |
 +--------------------+----------------------+
 
-on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
-0                    ISDN_LOAD           ISDN_MAXLOAD
+on empty load, remote-audio causes the load with the remote audio to be increased to p_m_preload.
+0                    p_m_preload           ISDN_MAXLOAD
 +--------------------+----------------------+
 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
 +--------------------+----------------------+
@@ -911,10 +914,6 @@ on empty load, remote-audio causes the load with the remote audio to be increase
  */
 void PmISDN::update_load(void)
 {
-       /* don't trigger load event if: */
-       if (!p_tone_name[0] && !p_m_crypt_msg_loops && !p_m_inband_send_on)
-               return;
-
        /* don't trigger load event if event already active */
        if (p_m_loadtimer.active)
                return;
@@ -922,7 +921,7 @@ void PmISDN::update_load(void)
        schedule_timer(&p_m_loadtimer, 0, 0); /* no delay the first time */
 }
 
-int load_timer(struct lcr_timer *timer, void *instance, int index)
+static int load_timer(struct lcr_timer *timer, void *instance, int index)
 {
        class PmISDN *isdnport = (class PmISDN *)instance;
 
@@ -948,7 +947,10 @@ void PmISDN::load_tx(void)
        p_m_last_tv_msec = current_time.tv_usec/1000;
 
        /* process only if we have samples and we are active */
-       if (elapsed && p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE) {
+       if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE)
+               return;
+
+       if (elapsed) {
                /* update load */
                if (elapsed < p_m_load)
                        p_m_load -= elapsed;
@@ -957,9 +959,9 @@ void PmISDN::load_tx(void)
 
                /* to send data, tone must be on */
                if ((p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on) /* what tones? */
-                && (p_m_load < ISDN_LOAD) /* not too much load? */
+                && (p_m_load < p_m_preload) /* not too much load? */
                 && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones || p_m_inband_send_on)) { /* connected or inband-tones? */
-                       int tosend = ISDN_LOAD - p_m_load, length; 
+                       int tosend = p_m_preload - p_m_load, length; 
                        unsigned char buf[MISDN_HEADER_LEN+tosend];
                        struct mISDNhead *frm = (struct mISDNhead *)buf;
                        unsigned char *p = buf+MISDN_HEADER_LEN;
@@ -1002,20 +1004,18 @@ void PmISDN::load_tx(void)
                        }
 
                        /* send data */
-                       if (ISDN_LOAD - p_m_load - tosend > 0) {
+                       if (p_m_preload - p_m_load - tosend > 0) {
                                frm->prim = PH_DATA_REQ;
                                frm->id = 0;
-                               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
+                               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+p_m_preload-p_m_load-tosend, 0, NULL, 0);
                                if (ret <= 0)
-                                       PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_sock[p_m_b_index].fd, ISDN_LOAD-p_m_load-tosend);
-                               p_m_load += ISDN_LOAD - p_m_load - tosend;
+                                       PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_sock[p_m_b_index].fd, p_m_preload-p_m_load-tosend);
+                               p_m_load += p_m_preload - p_m_load - tosend;
                        }
                }
        }
 
-       if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on || p_m_load) {
-               schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
-       }
+       schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
 }
 
 /* handle timeouts */
@@ -1057,10 +1057,23 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
                        end_trace();
                        if (!p_m_dtmf)
                                return;
-                       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
-                       message->param.dtmf = cont & DTMF_TONE_MASK;
-                       PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
-                       message_put(message);
+                       if (p_type == PORT_TYPE_POTS_FXS_IN && p_state == PORT_STATE_IN_OVERLAP) {
+                               class Pfxs *pfxs = (class Pfxs *)this;
+                               if (!pfxs->p_m_fxs_allow_dtmf) {
+                                       PDEBUG(DEBUG_PORT, "PmISDN(%s) DTMF for FXS not yet allowed\n", p_name);
+                                       return;
+                               }
+                               SCCAT(p_dialinginfo.id, cont & DTMF_TONE_MASK);
+                               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
+                               message->param.information.id[0] = cont & DTMF_TONE_MASK;
+                               PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  INFORMATION digit '%s'\n", p_name, message->param.information.id);
+                               message_put(message);
+                       } else {
+                               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
+                               message->param.dtmf = cont & DTMF_TONE_MASK;
+                               PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
+                               message_put(message);
+                       }
                        return;
                }
                switch(cont) {
@@ -1113,6 +1126,8 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
 //             printf(".");fflush(stdout);return;
                if (p_record)
                        record(data, len, 1); // from up
+               if (p_tap)
+                       tap(data, len, 1); // from up
                return;
        }
        if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND) {
@@ -1153,6 +1168,8 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
        /* record data */
        if (p_record)
                record(data, len, 0); // from down
+       if (p_tap)
+               tap(data, len, 0); // from down
 
        /* randomize and listen to crypt message if enabled */
        if (p_m_crypt_listen) {
@@ -1396,7 +1413,6 @@ void PmISDN::message_crypt(unsigned int epoint_id, int message_id, union paramet
                p_m_crypt_msg_current = 0; /* reset */
                p_m_crypt_msg_loops = 6; /* enable */
                update_rxoff();
-               update_load();
 #if 0
                /* disable txmix, or we get corrupt data due to audio process */
                if (p_m_txmix && p_m_b_index>=0 && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT) {
@@ -1433,6 +1449,13 @@ int PmISDN::message_epoint(unsigned int epoint_id, int message_id, union paramet
                PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
                message_crypt(epoint_id, message_id, param);
                return 1;
+
+               case MESSAGE_DISABLE_DEJITTER:
+               PDEBUG(DEBUG_ISDN, "PmISDN(%s) received de-jitter disable order.\n", p_name);
+               p_m_disable_dejitter = 1;
+               p_m_preload = param->queue;
+               update_rxoff();
+               return 1;
        }
 
        return 0;
@@ -1443,7 +1466,7 @@ void PmISDN::update_rxoff(void)
        int tx_dejitter = 0;
 
        /* call bridges in user space OR crypto OR recording */
-       if (p_bridge || p_m_crypt_msg_loops || p_m_crypt_listen || p_record || p_m_inband_receive_on) {
+       if (p_bridge || p_m_crypt_msg_loops || p_m_crypt_listen || p_record || p_tap || p_m_inband_receive_on) {
                /* rx IS required */
                if (p_m_rxoff) {
                        /* turn on RX */
@@ -1464,8 +1487,8 @@ void PmISDN::update_rxoff(void)
                                        ph_control(p_m_mISDNport, this, p_m_mISDNport->b_sock[p_m_b_index].fd, DSP_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
                }
        }
-       /* recording */
-       if (p_record) {
+       /* recording / tapping */
+       if (p_record || p_tap) {
                /* txdata IS required */
                if (!p_m_txdata) {
                        /* turn on RX */
@@ -1487,11 +1510,11 @@ void PmISDN::update_rxoff(void)
                }
        }
        /* dejitter on bridge */
-       if (p_bridge)
+       if (p_bridge && !p_m_disable_dejitter)
                tx_dejitter = 1;
        if (p_m_tx_dejitter != tx_dejitter) {
                p_m_tx_dejitter = tx_dejitter;
-               PDEBUG(DEBUG_BCHANNEL, "we change dejitter mode to delay=%d.\n", p_m_tx_dejitter);
+               PDEBUG(DEBUG_BCHANNEL, "we change dejitter mode to %s.\n", (p_m_tx_dejitter) ? "on" : "off");
                if (p_m_b_index > -1)
                        if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
                                ph_control(p_m_mISDNport, this, p_m_mISDNport->b_sock[p_m_b_index].fd, DSP_TX_DEJITTER, p_m_tx_dejitter, "DSP-TX_DEJITTER", p_m_tx_dejitter);
@@ -1767,6 +1790,43 @@ int mISDN_getportbyname(int sock, int cnt, char *portname)
        return (port);
 }
 
+/* handle frames from pots */
+static int pots_sock_callback(struct lcr_fd *fd, unsigned int what, void *instance, int i)
+{
+       struct mISDNport *mISDNport = (struct mISDNport *)instance;
+       unsigned char buffer[2048+MISDN_HEADER_LEN];
+       struct mISDNhead *hh = (struct mISDNhead *)buffer;
+       unsigned int cont;
+       int ret;
+
+       ret = recv(fd->fd, buffer, sizeof(buffer), 0);
+       if (ret < 0) {
+               PERROR("read error frame, errno %d\n", errno);
+               return 0;
+       }
+       if (ret < (int)MISDN_HEADER_LEN) {
+               PERROR("read short frame, got %d, expected %d\n", ret, (int)MISDN_HEADER_LEN);
+               return 0;
+       }
+       switch(hh->prim) {
+       case PH_CONTROL_IND:
+               cont = *((unsigned int *)(buffer + MISDN_HEADER_LEN));
+               /* l1-control is sent to LCR */
+               if (mISDNport->ntmode)
+                       stack2manager_fxs(mISDNport, cont);
+               else
+                       PERROR("FXO not supported!\n");
+               break;
+       case PH_ACTIVATE_REQ:
+               break;
+
+       default:
+               PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, fd->fd, ret-MISDN_HEADER_LEN);
+       }
+
+       return 0;
+}
+
 /*
  * global function to add a new card (port)
  */
@@ -1835,32 +1895,29 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
                pri = 1;
                nt = 1;
        }
-#ifdef ISDN_P_FXS
-       if (devinfo.Dprotocols & (1 << ISDN_P_FXS)) {
+#ifdef ISDN_P_FXS_POTS
+       if (devinfo.Dprotocols & (1 << ISDN_P_FXO_POTS)) {
                pots = 1;
                te = 1;
        }
-#endif
-#ifdef ISDN_P_FXO
-       if (devinfo.Dprotocols & (1 << ISDN_P_FXO)) {
+       if (devinfo.Dprotocols & (1 << ISDN_P_FXS_POTS)) {
                pots = 1;
                nt = 1;
        }
 #endif
        if (force_nt && !nt) {
-               PERROR_RUNTIME("Port %d does not support NT-mode\n", port);
+               if (!pots)
+                       PERROR_RUNTIME("Port %d does not support NT-mode\n", port);
+               else
+                       PERROR_RUNTIME("Port %d does not support FXS-mode\n", port);
                return(NULL);
        }
        if (bri && pri) {
                PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
                return(NULL);
        }
-       if (pots && !bri && !pri) {
-               PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
-               return(NULL);
-       }
-       if (!bri && !pri) {
-               PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
+       if (!bri && !pri && !pots) {
+               PERROR_RUNTIME("Port %d does not support BRI nor PRI nor POTS!\n", port);
                return(NULL);
        }
        if (!nt && !te) {
@@ -1873,6 +1930,10 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        /* if TE an NT is supported (and not forced to NT), turn off NT */
        if (te && nt)
                nt = 0;
+       if (pots && te) {
+               PERROR_RUNTIME("Port %d uses FXO-mode, but not supported by LCR!\n", port);
+               return(NULL);
+       }
 
        /* check for double use of port */
        if (nt) {
@@ -1953,40 +2014,85 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        }
                
        /* allocate ressources of port */
-       protocol = (nt)?L3_PROTOCOL_DSS1_NET:L3_PROTOCOL_DSS1_USER;
-       prop = (1 << MISDN_FLG_L2_CLEAN);
-       if (ptp) // ptp forced
-              prop |= (1 << MISDN_FLG_PTP);
-       if (nt) // supports hold/retrieve on nt-mode
-              prop |= (1 << MISDN_FLG_NET_HOLD);
-       if (l1hold) // supports layer 1 hold
-              prop |= (1 << MISDN_FLG_L1_HOLD);
-       if (l2hold) // supports layer 2 hold
-              prop |= (1 << MISDN_FLG_L2_HOLD);
-       /* open layer 3 and init upqueue */
-       /* 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,
-                       ifport->interface,
-                       NULL,
-                       NULL,
-                       DIRECTION_NONE,
-                       CATEGORY_CH,
-                       0,
-                       "PORT (open failed)");
-               end_trace();
-               mISDNport_close(mISDNport);
-               return(NULL);
+       if (!pots) {
+               /* ISDN */
+               protocol = (nt)?L3_PROTOCOL_DSS1_NET:L3_PROTOCOL_DSS1_USER;
+               prop = (1 << MISDN_FLG_L2_CLEAN);
+               if (ptp) // ptp forced
+                      prop |= (1 << MISDN_FLG_PTP);
+               if (nt) // supports hold/retrieve on nt-mode
+                      prop |= (1 << MISDN_FLG_NET_HOLD);
+               if (l1hold) // supports layer 1 hold
+                      prop |= (1 << MISDN_FLG_L1_HOLD);
+               if (l2hold) // supports layer 2 hold
+                      prop |= (1 << MISDN_FLG_L2_HOLD);
+               /* open layer 3 and init upqueue */
+               /* 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,
+                               ifport->interface,
+                               NULL,
+                               NULL,
+                               DIRECTION_NONE,
+                               CATEGORY_CH,
+                               0,
+                               "PORT (open failed)");
+                       end_trace();
+                       mISDNport_close(mISDNport);
+                       return(NULL);
+               }
+       } else {
+#ifdef ISDN_P_FXS_POTS
+               /* POTS */
+               int sock, ret;
+               struct sockaddr_mISDN addr;
+               struct mISDNhead act;
+
+               /* open socket */
+               /* queue must be initializes, because even pots interfaces are checked at mISDN_upqueue loop */
+               mqueue_init(&mISDNport->upqueue);
+               sock = socket(PF_ISDN, SOCK_DGRAM, (nt) ? ISDN_P_FXS_POTS : ISDN_P_FXO_POTS);
+               if (sock < 0) {
+                       PERROR_RUNTIME("Cannot open mISDN due to '%s'.\n", strerror(errno));
+                       return NULL;
+               }
+               /* bind socket to dchannel */
+               addr.family = AF_ISDN;
+               addr.dev = port;
+               addr.channel = 0;
+               ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+               if (ret < 0) {
+                       PERROR_RUNTIME("Error: Failed to bind pots control channel\n");
+                       start_trace(port,
+                               ifport->interface,
+                               NULL,
+                               NULL,
+                               DIRECTION_NONE,
+                               CATEGORY_CH,
+                               0,
+                               "PORT (open failed)");
+                       end_trace();
+                       return(NULL);
+               }
+               act.prim = PH_ACTIVATE_REQ; 
+               act.id = 0;
+               ret = sendto(sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
+               if (ret <= 0)
+                       PERROR("Failed to send to socket %d\n", sock);
+               mISDNport->pots_sock.fd = sock;
+               register_fd(&mISDNport->pots_sock, LCR_FD_READ, pots_sock_callback, mISDNport, i);
+#endif
        }
 
        SCPY(mISDNport->name, devinfo.name);
        mISDNport->b_num = devinfo.nrbchan;
        mISDNport->portnum = port;
        mISDNport->ntmode = nt;
+       mISDNport->pots = pots;
        mISDNport->tespecial = ifport->tespecial;
        mISDNport->pri = pri;
        mISDNport->ptp = ptp;
@@ -2002,7 +2108,7 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        }
 
        /* if ptp, pull up the link */
-       if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) {
+       if (!pots && 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);
                add_trace("tei", NULL, "%d", 0);
@@ -2010,8 +2116,8 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
                schedule_timer(&mISDNport->l2establish, 5, 0); /* 5 seconds */
        }
 
-       /* for nt-mode ptmp the link is always up */
-       if (mISDNport->ntmode && !mISDNport->ptp)
+       /* for POTS or nt-mode ptmp the link is always up */
+       if (pots || (mISDNport->ntmode && !mISDNport->ptp))
                mISDNport->l2link = 1;
 
        PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
@@ -2024,7 +2130,10 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
                    CATEGORY_CH,
                    0,
                    "PORT (open)");
-       add_trace("mode", NULL, (mISDNport->ntmode)?"network":"terminal");
+       if (!pots)
+               add_trace("mode", NULL, (mISDNport->ntmode)?"network":"terminal");
+       else
+               add_trace("mode", NULL, (mISDNport->ntmode)?"FXS":"FXO");
        add_trace("channels", NULL, "%d", mISDNport->b_num);
        if (mISDNport->ss5)
                add_trace("ccitt#5", NULL, "enabled");
@@ -2119,6 +2228,12 @@ void mISDNport_close(struct mISDNport *mISDNport)
                close_layer3(mISDNport->ml3);
        }
 
+       /* close layer 1, if open */
+       if (mISDNport->pots_sock.fd) {
+               unregister_fd(&mISDNport->pots_sock);
+               close(mISDNport->pots_sock.fd);
+       }
+
        /* purge upqueue */
        mqueue_purge(&mISDNport->upqueue);
 
@@ -2143,11 +2258,11 @@ void mISDNport_close(struct mISDNport *mISDNport)
 
 
 /*
- * enque data from upper buffer
+ * enque data from remote port
  */
 int PmISDN::bridge_rx(unsigned char *data, int length)
 {
-       unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
+       unsigned char buf[MISDN_HEADER_LEN+((length>p_m_preload)?length:p_m_preload)];
        struct mISDNhead *hh = (struct mISDNhead *)buf;
        int ret;
 
@@ -2165,22 +2280,26 @@ int PmISDN::bridge_rx(unsigned char *data, int length)
        /* preload procedure
         * if transmit buffer in DSP module is empty,
         * preload it to DSP_LOAD to prevent jitter gaps.
+        * 
+        * if load runs empty, preload again.
         */
-       if (p_m_load == 0 && ISDN_LOAD > 0) {
+       if (p_m_disable_dejitter && p_m_load == 0 && p_m_preload > 0) {
+//printf("preload=%d\n", p_m_preload);
                hh->prim = PH_DATA_REQ; 
                hh->id = 0;
-               memset(buf+MISDN_HEADER_LEN, (options.law=='a')?0x2a:0xff, ISDN_LOAD);
-               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+ISDN_LOAD, 0, NULL, 0);
+               memset(buf+MISDN_HEADER_LEN, silence, p_m_preload);
+               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+p_m_preload, 0, NULL, 0);
                if (ret <= 0)
                        PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
-               p_m_load += ISDN_LOAD;
+               p_m_load += p_m_preload;
                schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
        }
 
        /* drop if load would exceed ISDN_MAXLOAD
         * this keeps the delay not too high
         */
-       if (p_m_load+length > ISDN_MAXLOAD)
+//printf("load=%d len=%d 2*preload=%d\n", p_m_load, length, p_m_preload << 1);
+       if (p_m_disable_dejitter && p_m_preload > 0 && p_m_load+length > (p_m_preload << 1))
                return -EINVAL;
 
        /* make and send frame */
@@ -2205,8 +2324,6 @@ void PmISDN::inband_send_on(void)
 {
        PDEBUG(DEBUG_PORT, "turning inband signalling send on.\n");
        p_m_inband_send_on = 1;
-       /* trigger inband transmit */
-       update_load();
 }
 
 void PmISDN::inband_send_off(void)