Logo Search packages:      
Sourcecode: bayonne version File versions  Download package

dsp.cpp

// Copyright (C) 2002 David Kerry.
//
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Bayonne as noted here.
//
// This exception is that permission is hereby granted to link Bayonne
// with the Aculab telephony libraries to produce a executable image
// without requiring Aculab's libraries to be supplied in a free software
// license as long as each source file so linked contains this exclusion
// and the unalrtered Aculab source files are made available.
//
// This exception does not however invalidate any other reasons why
// the resulting executable file might be covered by the GNU General
// public license or invalidate the licensing requirements of any
// other component or library.
//
// This exception applies only to the code released by OST under the
// name Bayonne.  If you copy code from other releases into a copy of
// Bayonne, as the General Public License permits, the exception does not
// apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own to Bayonne, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice, at which
// point the terms of your modification would be covered under the GPL
// as explicitly stated in "COPYING".

//
// $Id: dsp.cpp,v 1.6 2003/04/02 23:23:14 dyfet Exp $
//

#include "driver.h"

#ifdef    CCXX_NAMESPACES
using namespace std;
namespace ost {
#endif

/*
 * Join/route two calls together using the switching API.
 *
 * Note: To join more than two calls, one should use the conferencing
 *       API!
 */
bool AculabTrunk::Join(AculabTrunk *trunk)
{
      OUTPUT_PARMS      connection;
      int switch_driver0;
      int switch_driver1;
      int rc;

      freeDSP();
      trunk->freeDSP();

      memset(&detail_xparms, 0, sizeof(detail_xparms));
      memset(&connection, 0, sizeof(connection));
      memset(&trunk->detail_xparms, 0, sizeof(trunk->detail_xparms));

      detail_xparms.valid=0;
      detail_xparms.handle=handle;
      detail_xparms.timeout=500;
      if (call_details(&detail_xparms)) {
            slog(Slog::levelError) <<name<<": error retrieving call details"
                        << endl;
            return false;
      }
      slog(Slog::levelDebug)<<name<<": JOIN: ts/call1="<<detail_xparms.ts<<endl;

      trunk->detail_xparms.valid=0;
      trunk->detail_xparms.handle=trunk->handle;
      trunk->detail_xparms.timeout=500;
      if (call_details(&trunk->detail_xparms)) {
            slog(Slog::levelError) <<name<<": error retrieving call details"
                        << endl;
            return false;
      }
      slog(Slog::levelDebug)<<name<<": JOIN: ts/call2="<<trunk->detail_xparms.ts<<endl;

      switch_driver0=call_port_2_swdrvr(port);
      switch_driver1=call_port_2_swdrvr(trunk->port);
      if (switch_driver0 != switch_driver1) {
            /*
             * Calls are terminated on different cards.
             * Use MVIP bus to connect them.
             */
            if (!aculabivr.getMVIPslot(&mvip_stream, &mvip_slot)) {
                  slog(Slog::levelError) <<name<<": no free MVIP slots!"<<endl;
                  return false;
            }


            /* Do network port ---> MVIP connection */
            /*
             * Make conn. from card 0 net port timeslot to DSiX
             * (MVIP bus timeslot chosen by this application to route
             *  data from card 0 to card 1).
             */
            connection.ist=detail_xparms.stream;
            connection.its=detail_xparms.ts;
            connection.mode=CONNECT_MODE;
            connection.ost=mvip_stream;
            connection.ots=mvip_slot;
            rc=sw_set_output(switch_driver0,&connection);
            slog(Slog::levelDebug)<<name<<": join: connect card 0->mvip, rc="<<rc<<endl;

            /*
             * Make conn. from DSoX timeslot 0 (MVIP bus timeslot
             * chosen by this application to route data from card 1
             * to card 0) to network port timeslot.
             */
#ifdef MVIP_BASED
            connection.ist=mvip_stream;
#else
            connection.ist = mvip_stream + MVIP_FD_STREAMS;
#endif
            connection.its=mvip_slot;
            connection.mode=CONNECT_MODE;
            connection.ost=detail_xparms.stream;
            connection.ots=detail_xparms.ts;
            rc=sw_set_output(switch_driver0,&connection);
            slog(Slog::levelDebug)<<name<<": join: connect mvip->card0, rc="<<rc<<endl;

            /* Do MVIP ---> network port connection */
            /*
             * Make conn. from card 1 net port timeslot to DSiX
             * (MVIP bus timeslot chosen by this application to route
             *  data from card 1 to card 0).
             */
            connection.ist=trunk->detail_xparms.stream;
            connection.its=trunk->detail_xparms.ts;
            connection.mode=CONNECT_MODE;
#ifdef MVIP_BASED
            connection.ost=mvip_stream+8;
#else
            connection.ost = mvip_stream + MVIP_FD_STREAMS;
#endif
            connection.ots=mvip_slot;
            rc=sw_set_output(switch_driver1,&connection);
            slog(Slog::levelDebug)<<name<<": join: connect card 1->mvip, rc="<<rc<<endl;

            /*
             * Make conn. from DSoX timeslot 0 (MVIP bus timeslot
             * chosen by this application to route data from card 0
             * to card 1) to network port timeslot.
             */
#ifdef MVIP_BASED
            connection.ist=mvip_stream+8;
#else
            connection.ist = mvip_stream;
#endif
            connection.its=mvip_slot;
            connection.mode=CONNECT_MODE;
            connection.ost=trunk->detail_xparms.stream;
            connection.ots=trunk->detail_xparms.ts;
            rc=sw_set_output(switch_driver1,&connection);
            slog(Slog::levelDebug)<<name<<": join: connect mvip->card1, rc="<<rc<<endl;
      }
      else {
            /*
             * Don't need to use external bus, we can use internal
             * Prosody bus.
             */
            connection.ist=detail_xparms.stream;
            connection.its=detail_xparms.ts;
            connection.mode=CONNECT_MODE;
            connection.ost=trunk->detail_xparms.stream;
            connection.ots=trunk->detail_xparms.ts;
            rc=sw_set_output(switch_driver0,&connection);
            slog(Slog::levelDebug)<<name<<": join: connect call0->call1, rc="<<rc<<endl;

            connection.ist=trunk->detail_xparms.stream;
            connection.its=trunk->detail_xparms.ts;
            connection.mode=CONNECT_MODE;
            connection.ost=detail_xparms.stream;
            connection.ots=detail_xparms.ts;
            rc=sw_set_output(switch_driver0,&connection);
            slog(Slog::levelDebug)<<name<<": join: connect call1->call0, rc="<<rc<<endl;
      }

      join=trunk;
      join->join = this;

      return true;
}

/*
 * Part a channel from a 'join'ed conference.
 *
 * If someone Part's the channel that is the primary
 * channel for the conference, we need to turf all the
 * channels joined to us as well.
 */
void AculabTrunk::Part(void)
{
      OUTPUT_PARMS      connection;
      TrunkEvent event;
      int switch_driver0;
      int switch_driver1;
      int rc;

      if (!join) {
            return;
      }

slog(Slog::levelDebug) <<name<<": parting trunks"<<endl;

      switch_driver0=call_port_2_swdrvr(port);
      switch_driver1=call_port_2_swdrvr(join->port);
      if (switch_driver0 != switch_driver1) {
            /*
             * Disconnect network port from mvip bus using switch
             * API.
             */
            connection.ost=mvip_stream;
            connection.ots=mvip_slot;
            connection.mode=DISABLE_MODE;
            rc=sw_set_output(switch_driver0,&connection);
slog(Slog::levelDebug) <<name<<":disable mvip stream on card 0, rc="<<rc<<endl;

#ifdef MVIP_BASED
            connection.ost=mvip_stream+8;
#else
            connection.ost = mvip_stream + MVIP_FD_STREAMS;
#endif
            connection.ots=mvip_slot;
            connection.mode=DISABLE_MODE;
            rc=sw_set_output(switch_driver1,&connection);
slog(Slog::levelDebug) <<name<<":disable mvip stream on card 1,rc="<<rc<<endl;

            aculabivr.freeMVIPslot(mvip_stream,mvip_slot);
      }
      
//    else {
            connection.ost=detail_xparms.stream;
            connection.ots=detail_xparms.ts;
            connection.mode=DISABLE_MODE;
            rc=sw_set_output(switch_driver0,&connection);
slog(Slog::levelDebug) <<name<<":disable mvip stream on call 0,rc="<<rc<<endl;

            connection.ost=join->detail_xparms.stream;
            connection.ots=join->detail_xparms.ts;
            connection.mode=DISABLE_MODE;
            rc=sw_set_output(switch_driver1,&connection);
slog(Slog::levelDebug) <<name<<":disable mvip stream on call 1,rc="<<rc<<endl;
//    }

        join->join = NULL;
        event.id = TRUNK_PART_TRUNKS;
        join->postEvent(&event);
        join = NULL;
}

/*
 * Allocate dsp resources of a given type and connect
 * to a channel.
 */
bool AculabTrunk::allocateDSP(int type)
{
      int attempt=0;
      int rc;
      SM_CHANNEL_ALLOC_PARMS sm_chan_parms;
      SM_CHANNEL_SET_EVENT_PARMS chRgEvParms;
      SM_CHANNEL_SET_EVENT_PARMS chWrEvParms;
      SM_CHANNEL_SET_EVENT_PARMS chRdEvParms;
      tSMChannelId newChannel=-1;
      struct timespec tspec;

      /*
       * Allocate DSP resources for this timeslot
       */
      sm_chan_parms.type= type;
      sm_chan_parms.group= 0;
      sm_chan_parms.firmware_id= 0;
      sm_chan_parms.caps_mask= 0;

      slog(Slog::levelDebug)<<name<<": in allocate DSP channel"<<endl;

      /*
       * Attempt for a few tries to grab a dsp channel.
       * Some other process may have given one up that we can
       * use.
       */
      while(attempt-- < 4) {
            rc=sm_channel_alloc(&sm_chan_parms);
            if (rc != 0) {
                  slog(Slog::levelCritical) <<name<<": allocate dsp channel attempt "<<attempt<<" failed: " <<rc << endl;
                  tspec.tv_sec=0;
                  tspec.tv_nsec=250000000; /* 250ms */
                  nanosleep(&tspec,NULL);
            }
            newChannel=sm_chan_parms.channel;
      slog(Slog::levelDebug)<<name<<": new DSP channel allocated:"<<newChannel<<endl;
            break;
      }
      if (newChannel == -1) {
                  slog(Slog::levelCritical) <<name<<": allocate dsp channel failure - no resources available"<< endl;
                  return false;
      }

      /* Release old channel */
      freeDSP();

      dspChannel=newChannel;
slog(Slog::levelDebug)<<name<<": connecting DSP channel to prosody"<<endl;
      rc=connectToDSP();
      if (!rc) {
            slog(Slog::levelCritical) <<name<<": failed connecting dsp resources to bus! rc="<<rc<<endl;
            return false;
      }

      /*
       * Indicate to driver that any event that occurs on this
       * channel should fire an 'any channel recognition' event
       * that the AculabDSPEventThread will then pick up and queue
       * to the appropriate trunk.
       */
      chRgEvParms.channel      = dspChannel;
      chRgEvParms.event_type   = kSMEventTypeRecog;
      chRgEvParms.issue_events = kSMAnyChannelEvent;
      sm_channel_set_event(&chRgEvParms);

      /*
       * Also have driver notify fire off a 'any channel write' event
       * if we need to write data (playing audio).
       */
      chWrEvParms.channel      = dspChannel;
      chWrEvParms.event_type   = kSMEventTypeWriteData;
      chWrEvParms.issue_events = kSMAnyChannelEvent;
      sm_channel_set_event(&chWrEvParms);

      /*
       * Also have driver notify fire off a 'any channel read' event
       * if we need to read data (recording audio).
       */
      chRdEvParms.channel      = dspChannel;
      chRdEvParms.event_type   = kSMEventTypeReadData;
      chRdEvParms.issue_events = kSMAnyChannelEvent;
      sm_channel_set_event(&chRdEvParms);

      return true;
}

/*
 * Free DSP resources that we've allocated previously
 */
bool AculabTrunk::freeDSP()
{
      int rc;

      if (dspChannel != -1) {
slog(Slog::levelDebug)<<name<<": freeing DSP channel: "<<dspChannel<<endl;
            disconnectFromDSP();
            rc=sm_channel_release(dspChannel);
            if (rc != 0) {
                  slog(Slog::levelCritical) <<name<<": failed releasing old dsp channel... uh oh!"<<endl;
                  dspChannel=-1;
                  return false;
            }
            dspChannel=-1;
      }

      return true;
}


/*
 * Connect an incoming network port/timeslot with a DSP channel
 * so we can do things like play audio, detect DTMF, etc...
 *
 * This was mostly lifted from the Aculab SDK examples...
 *
 * This function handles connecting the network port and timeslot to the
 * Prosody channel.
 *
 * There are several possibilities to deal with:
 *
 *    1. Prosody channel and network port are on the same card
 *    2. Prosody channel is on a BR card and net port on a E1/T1 card
 *    3. Prosody channel is on a S2 card and net port on a E1/T1 card
 *
 * When the Prosody channel is on a different card to the net port, the
 * MVIP bus is used to connect the two together.
 * A global record is kept of which MVIP bus streams and timeslots are
 * used so that no two call threads can attempt to access the same bus
 * resources at the same time.  In order to prevent multiple threads
 * from corrupting this data it is protected by a mutex.
 */
bool AculabTrunk::connectToDSP()
{
      struct sm_channel_info_parms sm_channel_info_parms;
      struct output_parms sw_output_parms;
      int    rc;
      mvip_stream = -1;
      mvip_slot = -1;


      /* Aculab's API may get extended in the future - if we do
       * not set the structures to zero before use, then spurious
       * values may be interpreted as meaning something at a later
       * date.
       */
      memset(&sm_channel_info_parms, 0, sizeof(sm_channel_info_parms));
      memset(&sw_output_parms, 0, sizeof(sw_output_parms));

      sm_channel_info_parms.channel=dspChannel;
      sm_channel_info(&sm_channel_info_parms);

      if(call_port_2_swdrvr(port) < 0) {
            slog(Slog::levelError) <<name<<": failed to locate switch for port!"<<endl;
            return false;
      }

      if ((sm_channel_info_parms.card == -1) ||
          (sm_channel_info_parms.card == call_port_2_swdrvr(port))) {

            /*
             * Channel is hosted on card whose channels are terminated on
             * MVIP bus (ISA S2) and MVIP stream and timeslot have been
             * chosen by driver (according to scheme set up at driver
             * installation time or by sm_config_module_switching)
             *
             * OR
             *
             * Channel is hosted on card whose channels are terminated
             * on Digital Switch Matrix (BR4/BR8) and channel is to be
             * switched to network port on same card.
             *
             * Most systems are now based on PCI cards.  If PCI cards
             * are used, then the speech processing DSP is usually located
             * on the same card as the network termination (Prosody PCI & cPCI)
             * so this path is actually the most likely...
             */
            sw_output_parms.ist  = sm_channel_info_parms.ost;
            sw_output_parms.its  = sm_channel_info_parms.ots;
            sw_output_parms.ost  = call_port_2_stream(port);
            sw_output_parms.ots  = ts;
            sw_output_parms.mode = CONNECT_MODE;

            if (sw_set_output(call_port_2_swdrvr(port),&sw_output_parms) != 0) {
                  slog(Slog::levelError) <<name<<": driver not installed to assign chan ts to expansion bus!"<<endl;
                  return false;
            }

            sw_output_parms.ist  = call_port_2_stream(port);
            sw_output_parms.its  = ts;
            sw_output_parms.ost  = sm_channel_info_parms.ist;
            sw_output_parms.ots  = sm_channel_info_parms.its;
            sw_output_parms.mode = CONNECT_MODE;

            if (sw_set_output(call_port_2_swdrvr(port),&sw_output_parms) != 0) {
                  slog(Slog::levelError) <<name<<": driver not installed to assign chan ts to expansion bus!"<<endl;
                  return false;
            }
      }
      else {
#ifdef MIVP_BASED
            /*
             * Channel is hosted on card whose channels are terminated on
             * Digital Switch Matrix (BR4/BR8) and channel is to be
             * switched to network port on a different card, thus need
             * to make connections between two cards on MVIP bus.
             */

            /*
             * Get the first available full-duplex MVIP stream and timeslot
             * Note
             */

            mvip_stream=0;
            mvip_slot=0;
            if (!aculabivr.getMVIPslot(&mvip_stream, &mvip_slot)) {
                  slog(Slog::levelError) <<name<<": no free MVIP slots!"<<endl;
                  return false;
            }

            /*Set network port connection to MVIP*/
            sw_output_parms.ist=mvip_stream;
            sw_output_parms.its=mvip_slot;
            sw_output_parms.ost=call_port_2_stream(port);
            sw_output_parms.ots=ts;
            sw_output_parms.mode=CONNECT_MODE;
            sw_set_output(call_port_2_swdrvr(port), &sw_output_parms);

            sw_output_parms.ist=call_port_2_stream(port);
            sw_output_parms.its=ts;
            sw_output_parms.ost=mvip_stream;
            sw_output_parms.ots=mvip_slot;
            sw_output_parms.mode=CONNECT_MODE;
            sw_set_output(call_port_2_swdrvr(port), &sw_output_parms);

            /*
             * This case is used if Prosody is on a BR card but the call
             * is on an E1 card.
             *
             * We have to add 8 to mvip_stream since we are using the BR
             * card as a resource rather than a network card.
             */
            sw_output_parms.ist=sm_channel_info_parms.ost;
            sw_output_parms.its=sm_channel_info_parms.ots;
            sw_output_parms.ost=mvip_stream+8;
            sw_output_parms.ots=mvip_slot;
            sw_output_parms.mode=CONNECT_MODE;
            sw_set_output(sm_channel_info_parms.card,&sw_output_parms);

            sw_output_parms.ist=mvip_stream+8;
            sw_output_parms.its=mvip_slot;
            sw_output_parms.ost=sm_channel_info_parms.ist;
            sw_output_parms.ots=sm_channel_info_parms.its;
            sw_output_parms.mode=CONNECT_MODE;
            sw_set_output(sm_channel_info_parms.card,&sw_output_parms);
#else
      /* MVIP is usually associated with ISA cards.
       * PCI (cPCI) cards support the ECTF H.100 (H.110) CT Bus.
       * H.100 is significantly wider than MVIP, so is less likely
       * to become the limiting factor in how many resources can
       * be hosted in a chassis.
       */

            mvip_stream = mvip_slot = 0;
            if(!aculabivr.getMVIPslot(&mvip_stream, &mvip_slot))
            {
                  slog(Slog::levelError) << name << ": no free H.100 slots!" << endl;
                  return false;
            }

      /* H.100 does not have the same concept of direction as MVIP.
       * It is just a set of connections...
       */

      /* connect from call -> H.100 */
            /* NOTE: we should find the stream associated with the call
             * using the call_details function.  It is possible (VoIP)
             * that the port may have multiple streams associated with it!
             */
            sw_output_parms.ist = call_port_2_stream(port);
            sw_output_parms.its = ts;
            sw_output_parms.ost = mvip_stream;
            sw_output_parms.ots = mvip_slot;

            sw_output_parms.mode = CONNECT_MODE;

            rc = sw_set_output(call_port_2_swdrvr(port), &sw_output_parms);
            if(rc)
            {
                  slog(Slog::levelError) << name << ": sw_set_output failed (" << rc << ")" << endl;
                  /* probably free up the MVIP slot, but we're pretty dead at this point! */
                  return false;
            }

      /* connect from H.100 to the call */
            sw_output_parms.ist = mvip_stream + MVIP_FD_STREAMS;
            sw_output_parms.its = mvip_slot;
            sw_output_parms.ost = call_port_2_stream(port);
            sw_output_parms.ots = ts;

            sw_output_parms.mode = CONNECT_MODE;
            rc = sw_set_output(call_port_2_swdrvr(port), &sw_output_parms);
            if(rc)
            {
                  slog(Slog::levelError) << name << ": sw_set_output failed (" << rc << ")" << endl;
                  return false;
            }

      /* connect from the DSP resource to H.100 */
            sw_output_parms.ist = sm_channel_info_parms.ost;
            sw_output_parms.its = sm_channel_info_parms.ots;
            sw_output_parms.ost = mvip_stream + MVIP_FD_STREAMS;
            sw_output_parms.ots = mvip_slot;

            sw_output_parms.mode = CONNECT_MODE;
            rc = sw_set_output(sm_channel_info_parms.card, &sw_output_parms);
            if(rc)
            {
                  slog(Slog::levelError) << name << " : sw_set_output failed (" << rc << ")" << endl;
                  return false;
            }

      /* connect from H.100 to the DSP resource */
            sw_output_parms.ist = mvip_stream;
            sw_output_parms.its = mvip_slot;
            sw_output_parms.ost = sm_channel_info_parms.ist;
            sw_output_parms.ots = sm_channel_info_parms.its;

            sw_output_parms.mode = CONNECT_MODE;
            rc = sw_set_output(sm_channel_info_parms.card, &sw_output_parms);
            if(rc)
            {
                  slog(Slog::levelError) << name << ": sw_set_output failed (" << rc << ")" << endl;
                  return false;
            }
#endif
      }
      /*
       * Set the MVIP stream and slot being used (if MVIP is not used,
       * -1 is passed back), so that the thread which called this function
       * can disconnect them later on.
       */
      mvip_stream=mvip_stream;
      mvip_slot=mvip_slot;

      return true;
}

/*
 * Disconnect the network/timeslot resource from the Prosody
 * DSP channel.
 */
void AculabTrunk::disconnectFromDSP()
{
      struct output_parms sw_output_parms;
      struct sm_channel_info_parms sm_channel_info_parms;

      sm_channel_info_parms.channel=dspChannel;
      sm_channel_info(&sm_channel_info_parms);
      port=port;

      /*
       * Check if prosody channel and network port are on the
       * same card.
       *
       * If not, disconnect MVIP bus both on the prosody card
       * and the network card.
       */
      if(sm_channel_info_parms.card != call_port_2_swdrvr(port)) {
            if(sm_channel_info_parms.card == -1) {
                  /*
                   * Disconnect connection from net card to MVIP bus
                   * If we didn't do this and application handled
                   * multiple DAC cards there would be danger of
                   * MVIP bus contention.
                   */
                  sw_output_parms.ost  = sm_channel_info_parms.ist;
                  sw_output_parms.ots  = sm_channel_info_parms.its;
                  sw_output_parms.mode = DISABLE_MODE;
                  sw_set_output(call_port_2_swdrvr(port),&sw_output_parms);
            }
            else {
                  /* if prosody channel is on a BR card, use switch API calls */
#ifdef MVIP_BASED
                  sw_output_parms.ost=mvip_stream+8;
#else
                  sw_output_parms.ost = mvip_stream + MVIP_FD_STREAMS;
#endif
                  sw_output_parms.ots=mvip_slot;
                  sw_output_parms.mode=DISABLE_MODE;
                  sw_set_output(sm_channel_info_parms.card,&sw_output_parms);

                  sw_output_parms.ost=sm_channel_info_parms.ist;
                  sw_output_parms.ots=sm_channel_info_parms.its;
                  sw_output_parms.mode=DISABLE_MODE;
                  sw_set_output(sm_channel_info_parms.card,&sw_output_parms);

                  /*
                   * Disconnect network port from mvip bus using switch
                   * API.
                   */
                  sw_output_parms.ost=mvip_stream;
                  sw_output_parms.ots=mvip_slot;
                  sw_output_parms.mode=DISABLE_MODE;
                  sw_set_output(call_port_2_swdrvr(port),&sw_output_parms);

                  aculabivr.freeMVIPslot(mvip_stream,mvip_slot);
            }
      }
      else {
            /*
             * Prosody is on same card as network port,
             * therefore we do not need to worry about the MVIP bus
             *
             * Disable network output to Prosody.
             */
            sw_output_parms.ost=sm_channel_info_parms.ist;
            sw_output_parms.ots=sm_channel_info_parms.its;
            sw_output_parms.mode=DISABLE_MODE;
            sw_set_output(call_port_2_swdrvr(port),&sw_output_parms);
      }
}

/*
 * Set up listening for DTMF tones via DSP channel/event
 */
void AculabTrunk::setDTMFDetect(bool enable)
{
      SM_LISTEN_FOR_PARMS sm_listen_for_parms;

      sm_listen_for_parms.channel = dspChannel;
      if (enable) {
            Trunk::flags.dtmf=true;
            sm_listen_for_parms.tone_detection_mode = kSMToneEndDetectionMinDuration64;
      }
      else {
            Trunk::flags.dtmf=false;
            sm_listen_for_parms.tone_detection_mode = kSMToneDetectionNone;
      }

        sm_listen_for_parms.enable_pulse_digit_recognition = 0;
        sm_listen_for_parms.active_tone_set_id = 0;
        sm_listen_for_parms.enable_cptone_recognition = 0;
        sm_listen_for_parms.map_tones_to_digits = kSMDTMFToneSetDigitMapping;
        sm_listen_for_parms.enable_grunt_detection = 0;

        sm_listen_for(&sm_listen_for_parms);
}

/*
 * Set up listening for DTMF tones via DSP channel/event
 */
void AculabTrunk::resetDSPChannel()
{
      sm_reset_channel(dspChannel);
}


#ifdef    CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index