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

driver.cpp

// Copyright (C) 2000 Open Source Telecom Corporation.
//  
// 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 Dialogic runtime libraries to produce a executable image
// without requiring Dialogic's sources to be supplied so long as each
// each source file so linked contains this exclusion.
//
// 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".

#include "driver.h"
#include <cerrno>

#define     SIGEVTCHK   0x1010
#define SIGBITCHK 0x1111


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

const int HANGUP_TONE_ID=0x0200U;
int hangup_detect=0;

DialogicConfig::DialogicConfig() :
Keydata("/bayonne/dialogic")
{
      static Keydata::Define defkeys[] = {
      {"timeslots", "30"},
      {"voice", "8"},
      {"digital", "1"},
      {"routing", "analog"},
      {"analog", "na_an_io"},
      {"protocol", ""},
      {"buffers", "0"},
      {"interval", "65000"},
      {"delay", "10"},
      {"pri", "1"},
      {"span", "e1"},
      {"spans", "100"},
      {"pickup", "800"},
      {"hangup_detect", "off"},
      {"hangup_freq", "425"},
      {"hangup_freq_dev", "50"},
      {"hangup_on", "30"},
      {"hangup_on_dev", "15"},
      {"hangup_off", "30"},
      {"hangup_off_dev", "15"},
      {"hangup_rep", "2"},
      {NULL, NULL}};

      if(isFHS())
            load("/drivers/dialogic");

      load(defkeys);
}

#include "possibilite.c"

bool DialogicConfig::getRouting(void)
{
      const char *rtflag = getLast("routing");

      if(!stricmp(rtflag, "digital"))
            return false;

      return true;
}

DialogicDriver::DialogicDriver() :
Driver(), Thread(keythreads.priService() - 1)
{
      static Script::Define keywords[] = {
            {"join", (Method)&DialogicTrunk::scrJoin, &ScriptCommand::chkHasArgs},
            {"wait", (Method)&DialogicTrunk::scrWait, &ScriptCommand::chkHasArgs},
            {"reroute", (Method)&DialogicTrunk::scrReroute, &ScriptCommand::chkHasArgs},
            {"conference", (Method)&DialogicTrunk::scrConference, &ScriptCommand::chkHasArgs},
            {NULL, NULL, NULL}};

      char d4xname[32];
      char dtiname[32];
      int spans = 0;
      int isdev = -1;
      int dticards, voxcards, pricards;
      int dticard = 1, voxcard = 1, pricard = 0, isdncard = 0;
      int dti = 0;
      int voxcount, vox, dticount = 0;
      int id = 0, queue;
      int chdev, tsdev;
      int maxslots = getTimeslots();
      interface_t iface = NT_E1;
      char *span;
      const char *cp = getLast("queue");
      CT_DEVINFO ctinfo;

      level = 0;
      status = DialogicTrunk::status;
      memset(status, ' ', sizeof(DialogicTrunk::status));

      running = false;

      voxcards = getVoice();
      dticards = getDigital();
      pricards = getPRICount();
      if(pricards > dticards)
            dticards = pricards;

      isdn_count = pricards;

      if(!voxcards)
      {
            slog(Slog::levelError) << "Dialogic driver missing cards; not initialized" << endl;
            maps = NULL;
            ports = NULL;
            groups = NULL;
            port_count = 0;
            port_used = 0;
            return;
      }

      if((dticards * maxslots > voxcards * 4) || isdn_count)
            port_count = dticards * maxslots;
      else
            port_count = voxcards * 8;

      devmap = new devices_t[port_count]; 
      ports = new DialogicTrunk *[port_count];
      groups = new TrunkGroup *[port_count];
      maps = new DialogicTrunk *[port_count * 5 + 16];
      ismaps = new DialogicISDN *[port_count * 5 + 16];
      spanmaps = new DialogicISDN *[getSpanCount()];
      memset(ports, 0, sizeof(DialogicTrunk *) * port_count);
      memset(groups, 0, sizeof(TrunkGroup *) * port_count);
      memset(maps, 0, sizeof(DialogicTrunk *) * port_count * 5 + 16);
      memset(ismaps, 0, sizeof(DialogicISDN *) * port_count * 5 + 16);
      memset(devmap, 0, sizeof(devices_t) * port_count);
      memset(spanmaps, 0, sizeof(DialogicISDN *) * getSpanCount());

      if(isdn_count)
      {
            isdn = new DialogicISDN *[isdn_count];
            memset(isdn, 0, sizeof(DialogicISDN *) * isdn_count);
      }

      if(cp)
      {
            queue = atoi(cp);
            sr_setparm(SRL_DEVICE, SR_QSIZEID, &queue);
            slog(Slog::levelDebug) << "dialogic: event queue depthset to " << queue << endl;
      }

#ifndef     SIGNAL
      slog(Slog::levelDebug) << "dialogic: setting polled mode" << endl;
      mode = SR_POLLMODE;
      if(sr_setparm(SRL_DEVICE, SR_MODEID, &mode) < 0)
      {
            slog(Slog::levelError) << "dialogic: unable to set polled mode" << endl;
            return;
      }
#endif

      while(voxcard <= voxcards && id < port_count)
      {
            sprintf(d4xname, "dxxxB%d", voxcard);
            chdev = dx_open(d4xname, 0);
            if(chdev < 0)
            {
                  ++voxcard;
                  continue;
            }
      
            voxcount = ATDV_SUBDEVS(chdev);
            dx_close(chdev);

            slog(Slog::levelDebug) << "dialogic: vox card " << voxcard << " of " << voxcards << "; ports=" << voxcount << endl;

            for(vox = 1; vox <= voxcount && id < port_count; ++vox) 
            {
                  sprintf(d4xname, "dxxxB%dC%d", voxcard, vox);
                  chdev = dx_open(d4xname, 0);
                  tsdev = 0;
                  if(dx_deltones(chdev))
                        slog(Slog::levelDebug) << ATDV_ERRMSGP(chdev) << endl;
                  if(dx_chgfreq(TID_BUSY1, 400, 100, 0, 0))
                        slog(Slog::levelDebug) << ATDV_ERRMSGP(chdev) << endl;
                  if(dx_chgdur(TID_BUSY1, 37, 10, 37, 10))
                        slog(Slog::levelDebug) << ATDV_ERRMSGP(chdev) << endl;
                  if(dx_chgrepcnt(TID_BUSY1, 2))
                        slog(Slog::levelDebug) << ATDV_ERRMSGP(chdev) << endl;
                  //dx_chgfreq(TID_BUSY2, 450, 50, 35, 50);
                  //dx_chgdur(TID_BUSY2, 25, 5, 25, 5);
                  //dx_chgrepcnt(TID_BUSY2, 3);
                  if(dx_initcallp(chdev))
                        slog(Slog::levelDebug) << "initcallp " << ATDV_ERRMSGP(chdev) << endl;
                  if(0==strcmp(getLast("hangup_detect"),"on"))
                  {
                        hangup_detect=1;
                        if(dx_bldstcad(HANGUP_TONE_ID, atoi(getLast("hangup_freq")),
                          atoi(getLast("hangup_freq_dev")), atoi(getLast("hangup_on")),
                          atoi(getLast("hangup_on_dev")), atoi(getLast("hangup_off")),
                          atoi(getLast("hangup_off_dev")), atoi(getLast("hangup_rep"))))
                            slog(Slog::levelDebug) << ATDV_ERRMSGP(chdev) << endl;
                        else
                        {
                            if(dx_addtone(chdev, 0, 0))
                              slog(Slog::levelDebug) << ATDV_ERRMSGP(chdev) << endl;
                              }
                  }

                  if(!dti && vox == 1)
                  {
                        if(dx_getctinfo(chdev, &ctinfo))
                        {
                              iface = NT_ANALOG;
                              slog(Slog::levelError) << "dialogic: " << ATDV_ERRMSGP(chdev) << endl;
                        }
                        else
                              switch(ctinfo.ct_nettype)
                              {
                              case CT_NTNONE:
                                    span = (char *)DialogicConfig::getLast("span");
                                    if(!stricmp(span, "e1"))
                                    {
                                          iface = NT_E1;
                                          dti = 1;
                                          dticount = 30;
                                          break;
                                    }
                                    if(!stricmp(span, "t1"))
                                    {
                                          iface = NT_T1;
                                          dti = 1;
                                          dticount = 24;
                                          break;
                                    }
                              default:
                                    iface = NT_ANALOG;
                                    break;
                              case CT_NTT1:
                                    iface = NT_T1;
                                    dti = 1;
                                    dticount = 24;
                                    break;
                              case CT_NTE1:
                                    iface = NT_E1;
                                    dti = 1;
                                    dticount = 30;
                                    break;
                              }

                        if(dti)
                              ++spans;
                  }
                  if(!dti)
                  {
                        sprintf(devmap[id].gcname, ":P_%s:V_%s",
                              getAnalog(), d4xname);
                        devmap[id].chdev = chdev;
                        devmap[id].tsdev = -1;
                        devmap[id].isdev = -1;
                        devmap[id].iface = iface;
                        devmap[id].span = 0;
                        ++id;
                        continue;
                  }
                  while(dti == 1 && dticard <= dticards)
                  {
                        sprintf(dtiname, "dtiB%d", dticard);
                        tsdev = dt_open(dtiname, 0);
                        if(tsdev < 0)
                        {
                              ++dticard;
                              continue;
                        }
                        dticount = ATDV_SUBDEVS(tsdev)+1;
                        switch(iface)
                              {
                              case NT_E1:
                              if(dt_setevtmsk(tsdev, DTG_E1ERREVT,
                                             (DEEC_LOS|DEEC_DPM|DEEC_BPVS|DEEC_ECS|DEEC_RRA|
                                            DEEC_FSERR|DEEC_RUA1|DEEC_RLOS|DEEC_MFSERR|
                                            DEEC_RSA1|DEEC_RDMA|DEEC_CECS), DTA_SETMSK) < 0)
                                    slog(Slog::levelError) << "dialogic: " << ATDV_ERRMSGP(tsdev) << endl;
                              break;
                        case NT_T1:
                              --dticount;
                              if(dt_setevtmsk(tsdev, DTG_T1ERREVT,
                                           (DTEC_RLOS|DTEC_LOS|DTEC_DPM|DTEC_RED|DTEC_BPVS|
                                          DTEC_ECS|DTEC_RYEL|DTEC_RCLX|DTEC_FERR|DTEC_B8ZSD|
                                          DTEC_RBL|DTEC_OOF), DTA_SETMSK) < 0)
                                    slog(Slog::levelError) << "dialogic: " << ATDV_ERRMSGP(tsdev) << endl;
                              break;
                        }
                        break;
                  }

                  if(dti == 1)
                        isdev = -1;

                  if(dti == 1 && pricard < pricards)
                  {
                        if(cc_Open(&isdev, dtiname, 0))
                              isdev = -1;
                  }
                  if(isdev > -1 && dti == 1)
                  {
                        --dticount;
                        ++pricard;
                        cc_Restart(isdev, EV_SYNC);
                        isdn[isdncard] = new DialogicISDN(isdev, spans, iface);
                        spanmaps[spans - 1] = isdn[isdncard];
                        ismaps[isdev] = isdn[isdncard++];
                  }

                  if(dti == 1)
                  {
                        if(isdev < 0)
                              slog(Slog::levelDebug) << "dialogic: dti card " << dticard << "; timeslots=" << dticount << endl;
                        else
                              slog(Slog::levelDebug) << "dialogic: pri card " << pricard << "; timeslots =" << dticount << endl;
                  }
 
                  if(dti)
                  {
                        if(dticards)
                              if(dticard > dticards+1)
                                    break;                              
                        
                        sprintf(dtiname, "dtiB%dT%d", dticard, dti);

                        if(isdev > -1)
                        {
                              if(cc_Open(&tsdev, dtiname, 0))
                                    tsdev = -1;
                        }
                        else
                              tsdev = dt_open(dtiname, 0);  

                        if(tsdev > -1)
                        {
                              sprintf(devmap[id].gcname, ":N_%s:P_%s:V_%s",
                                    dtiname, getProtocol(), d4xname);
                              devmap[id].chdev = chdev;
                              devmap[id].tsdev = tsdev;
                              devmap[id].iface = iface;
                              devmap[id].isdev = isdev;
                              devmap[id].span = spans;
                              ++id;
                        }
                        ++dti;
                                switch(iface)
                                {
                                        case NT_E1:
                                                if(dti > dticount)
                                    {
                                          ++dticard;
                                                        dti = 0;
                                    }
                                                break;
                                        case NT_T1:
                                                if(dti > dticount)
                                    {
                                          ++dticard;
                                                        dti = 0;
                                    }
                                                break;
                                }


                  }
            }
            ++voxcard;
      }

      uio.u_seek = uio_seek;
      uio.u_read = uio_read;
      uio.u_write = uio_write;

      tpt[0].tp_type = IO_CONT;
      tpt[0].tp_termno = DX_LCOFF;
      tpt[0].tp_length = 3;
      tpt[0].tp_flags = TF_LCOFF | TF_10MS;
      tpt[1].tp_type = IO_EOT;
      tpt[1].tp_termno = DX_MAXSIL;
      tpt[1].tp_length = 0;
      tpt[1].tp_flags = TF_MAXSIL;

      if(dx_setuio(uio))
      {
            slog(Slog::levelCritical) << "dialogic: cannot set uio" << endl;
            id = 0;
      }
      
      ScriptCommand::load(keywords);
                        
      slog(Slog::levelInfo) << "Dialogic driver loaded; capacity=" << id << 
            "; maxconference=" << DialogicDCB::detect() << endl;
      port_used = id;
}

DialogicDriver::~DialogicDriver()
{
      if(running)
            stop();

      if(ports)
            delete[] ports;

      if(isdn)
            delete[] isdn;

      if(maps)
            delete[] maps;

      if(ismaps)
            delete[] ismaps;

      if(spanmaps)
            delete[] spanmaps;

      if(groups)
            delete[] groups;

      if(devmap)
            delete[] devmap;
}

int DialogicDriver::start(void)
{
      int count = 0;
      int port, tsdev, chdev, isdev;

      if(active)
      {
            slog(Slog::levelError) << "driver already started" << endl;
            return 0;
      }

      slog(Slog::levelDebug) << "allocating trunks..." << endl;
      for(port = 0; port < port_used; ++port)
      {
            chdev = devmap[port].chdev;
            tsdev = devmap[port].tsdev;
            isdev = devmap[port].isdev;
            if(!chdev && !tsdev)
                  continue;
            ++count;
            ports[port] = new DialogicTrunk(port, &devmap[port]);
            maps[chdev] = ports[port];
            if(tsdev > -1)
                  maps[tsdev] = ports[port];
      }

      slog(Slog::levelDebug) << "starting trunks....." << endl;
      for(port = 0; port < port_used; ++port)
            ports[port]->start();

      slog(Slog::levelInfo) << "driver starting..." << endl;

      if(!running)
            Thread::start();

      active = true;
      return count;
}

void DialogicDriver::stop(void)
{
      int port, is;
      if(!active)
            return;

      for(port = 0; port < port_used; ++port)
      {
            if(!ports[port])
                  continue;
            delete ports[port];
      }

        if(isdn_count && isdn)
                for(is = 0; is < isdn_count; ++is)
                {
                        if(isdn[is])
                                delete isdn[is];
                }

      if(ports)
            memset(ports, 0, sizeof(DialogicTrunk *) * port_count);

      terminate();

      active = false;
      slog(Slog::levelInfo) << "driver stopping..." << endl;
}

void DialogicDriver::run(void)
{
      int evdev;
      DialogicTrunk *trunk;
      DialogicISDN *isdn;
      TrunkEvent event;
      DX_CST *cst;
      DV_DIGIT *digbuf;
      CRN tmpcrn;
      IE_BLK ie_blk;
      int statebuf, i, param;

      unsigned short sig;
      short ind;
      int evtype;
      int digcnt, diglen;
      unsigned long tmask;
      unsigned delay = dialogicivr.getDelay();
      void *datap = NULL;
      unsigned char *alarmp;
      interface_t iface;


      Thread::sleep(2000);
      running = true;
      slog(Slog::levelDebug) << "dialogic: service thread started" << endl;

      setCancel(cancelImmediate);
      for(;;)
      {
            HOLD(NULL)
            if(sr_waitevt(EVT_TIMER) == -1)
            {
                  RELEASE
                  Thread::sleep(delay);
                  continue;
            }
            evtype = sr_getevttype();

            switch(evtype)
            {
            case CCEV_ANSWERED:
            case CCEV_ACCEPT:
            case CCEV_OFFERED:
            case CCEV_CONNECTED:
            case CCEV_DROPCALL:
            case CCEV_HOLDACK:
            case CCEV_HOLDREJ:
            case CCEV_MOREDIGITS:
            case CCEV_RELEASECALL:
            case CCEV_RELEASECALLFAIL:
            case CCEV_REQANI:
            case CCEV_RETRIEVEACK:
            case CCEV_RETRIEVEREJ:
            case CCEV_RETRIEVECALL:
            case CCEV_SETBILLING:
            case CCEV_RESTART:
            case CCEV_RESTARTFAIL:
            case CCEV_TASKFAIL:
            case CCEV_ALERTING:
            case CCEV_CALLINFO:
            case CCEV_CONGESTION:
            case CCEV_DISCONNECTED:
            case CCEV_DIVERTED:
                  datap = sr_getevtdatap();
                  cc_GetLineDev(&evdev, datap);
                  break;
            case CCEV_FACILITY:
                  datap = sr_getevtdatap();
                  cc_GetLineDev(&evdev, datap);
                  break;
            case CCEV_FACILITY_ACK:
                  datap = sr_getevtdatap();
                  cc_GetLineDev(&evdev, datap);
                  break;
            case CCEV_FACILITY_REJ:
                  datap = sr_getevtdatap();
                  cc_GetLineDev(&evdev, datap);
                  break;

            case CCEV_HOLDCALL:
            case CCEV_L2FRAME:
            case CCEV_L2NOBFFR:
            case CCEV_NOTIFY:
            case CCEV_NSI:
            case CCEV_ISDNMSG:
            case CCEV_PROCEEDING:
            case CCEV_PROGRESSING:
            case CCEV_SETUP_ACK:
#ifdef      CCEV_TERM_REGISTGER
            case CCEV_TERM_REGISTER:
#endif
            case CCEV_TRANSFERACK:
            case CCEV_TRANSFERREJ:
            case CCEV_TRANSIT:
#ifdef      CCEV_USERINFO
            case CCEV_USERINFO:
#endif
            case CCEV_SETCHANSTATE:
            case CCEV_D_CHAN_STATUS:
                  datap = sr_getevtdatap();
                  cc_GetLineDev(&evdev, datap);
                  break;
            default:
                  evdev = sr_getevtdev();
            }                       
            if(evdev < 0)
            {
                  CONTINUE
            }

            trunk = maps[evdev];
            if(!trunk && !(evtype & DT_DTI))
            {
                  CONTINUE
            }

            memset(&event, 0, sizeof(event));

            switch(evtype)
            {
            case CCEV_RESTART:
                  event.id = TRUNK_CALL_RESTART;
                  event.parm.ok = true;
                  trunk->postEvent(&event);
                  break;
            case CCEV_RESTARTFAIL:
                  event.id = TRUNK_CALL_RESTART;
                  event.parm.ok = false;
                  trunk->postEvent(&event);
                  break;
            case CCEV_RELEASECALL:
                  event.id = TRUNK_CALL_RELEASE;
                  event.parm.ok = true;
                  trunk->postEvent(&event);
                  break;
            case CCEV_RELEASECALLFAIL:
                  event.id = TRUNK_CALL_RELEASE;
                  event.parm.ok = false;
                  trunk->postEvent(&event);
                  break;
            case CCEV_DISCONNECTED:
                  if(!trunk->_disconnecting)
                  {
                        event.id = TRUNK_STOP_DISCONNECT;
                        trunk->postEvent(&event);
                  }
                  break;
            case CCEV_CONNECTED:
                  event.id = TRUNK_TONE_IDLE;
                  trunk->putEvent(&event);
                  break;
            case CCEV_PROCEEDING:
            case CCEV_ALERTING:
            case CCEV_PROGRESSING:
                  cc_CallState(trunk->crn, &statebuf);
                  switch(statebuf)
                  {
                        case CCST_DISCONNECTED:
                        case CCST_IDLE:
                        case CCST_NULL:
                              event.id = TRUNK_TIMER_EXPIRED;
                              break;
                        case CCST_ALERTING:
                        //case CCST_DIALING:
                        case CCST_ACCEPTED:
                        case CCST_CONNECTED:
                              event.id = TRUNK_LINE_WINK;
                              break;
                  }
                  
                        trunk->putEvent(&event);
                  break;
            case CCEV_OFFERED:
                  // Modification to extract Commande Possibilite
                  datap = sr_getevtdatap();
                  IE_BLK ie_blk;
                  char bufPos[64 + 1];
                  char NAS[20 + 1];
                  char CTX[20 + 1];
                  char APPELANT[20 + 1];
                  char RETOUR[20 + 1];
                  int i, lenPos;

                  strcpy(trunk->callednasposs, "UNKNOWN");
                  strcpy(trunk->callingnasposs, "UNKNOWN");
                  strcpy(trunk->contextposs, "NONE");
                  strcpy(trunk->retourposs, "NONE");
                  if (cc_GetSigInfo((char *) &ie_blk, U_IES, datap) < 0) {
                        slog(Slog::levelError) << "Error on GetSigInfo" << endl;
                  } else {
                        slog(Slog::levelDebug) << "SigInfo length= " << ie_blk.length << endl;
                        for (i = 0 ; i < ie_blk.length; i++)
                              slog(Slog::levelDebug) << hex << (int) ie_blk.data[i] << endl;

                        /* Extract "Command Possibilité" from the ie block data */
                        if ((lenPos = extraitPossibilite(ie_blk.data, bufPos, ie_blk.length)) > 0) {
                              if (extraitInfosPossibilite(bufPos, NAS, APPELANT, CTX, RETOUR, lenPos) >= 0)  {
                                    strcpy(trunk->callednasposs, NAS);
                                    strcpy(trunk->callingnasposs, APPELANT);
                                    strcpy(trunk->contextposs, CTX);
                                    strcpy(trunk->retourposs, RETOUR);
                              }
                        } else slog(Slog::levelDebug) << "No commande Possibilite" << endl;
                  }

                  // End of modification

                  if(cc_GetCRN(&tmpcrn, datap) < 0)
                        trunk->putISDNError("cc_GetCRN");
                  else
                        trunk->crn = tmpcrn;

                  event.id = TRUNK_CALLER_ID;
                  trunk->putEvent(&event);
                  event.id = TRUNK_RINGING_ON;
                  trunk->putEvent(&event);
                  event.id = TRUNK_RINGING_OFF;
                  trunk->putEvent(&event);
                  break;
            case CCEV_ANSWERED:
                  event.id = TRUNK_OFF_HOOK;
                  trunk->putEvent(&event);
                  break;
            case CCEV_ACCEPT:
                  break;
            case CCEV_NOTIFY:
                  if(cc_GetInfoElem(evdev, &ie_blk) < 0)
                        trunk->putISDNError("cc_GetSignInfo ");
                  slog(Slog::levelDebug) << "IE recv: ";
                  break;
            case CCEV_DROPCALL:
                  trunk->releaseISDN();
                  event.id = TRUNK_CALL_RELEASE;
                  trunk->putEvent(&event);
                  break;
            case CCEV_TASKFAIL:
                  trunk->putISDNError("TaskFail");
                  if(cc_Restart(trunk->tsdev, EV_ASYNC) < 0)
                        trunk->putISDNError("cc_Restart");
                  break;

            case TDX_CALLP:
                  switch(ATDX_CPTERM(trunk->chdev))
                  {
                  case CR_BUSY:
                        switch(ATDX_CRTNID(trunk->chdev))
                        {
                        case TID_BUSY1:
                              event.parm.tone.name = "busy";
                        case TID_BUSY2:
                              event.parm.tone.name = "busy2";
                        default:
                              event.parm.tone.name = "unknown";
                        }
                        event.id = TRUNK_CPA_BUSYTONE;
                        break;
                  case CR_CEPT:
                        event.id = TRUNK_CPA_INTERCEPT;
                        break;
                  case CR_CNCT:
                        event.id = TRUNK_CPA_CONNECT;
                        break;
                  case CR_FAXTONE:
                        event.id = TRUNK_TONE_START;
                        event.parm.tone.name = "fax";
                        break;
                  case CR_NOANS:
                        event.id = TRUNK_CPA_NOANSWER;
                        break;
                  case CR_NODIALTONE:
                        event.id = TRUNK_CPA_NODIALTONE;
                        break;
                  case CR_NORB:
                        event.id = TRUNK_CPA_NORINGBACK;
                        break;
                  case CR_STOPD:
                        event.id = TRUNK_CPA_FAILURE;
                        break;
                  case CR_ERROR:
                        switch(ATDX_CPERROR(trunk->chdev))
                        {
                        case CR_LGTUERR:
                        case CR_MEMERR:
                        case CR_MXFRQERR:
                        case CR_OVRLPERR:
                        case CR_TMOUTOFF:
                        case CR_TMOUTON:
                        case CR_UNEXPTN:
                        case CR_UPFRQERR:
                        default:
                              event.id = TRUNK_CPA_FAILURE;
                              break;
                        }
                  }
                  if(event.id)
                        trunk->putEvent(&event);
                  event.id = TRUNK_TONE_IDLE;
                  trunk->putEvent(&event);
                  break;
            case TDX_WINK:
                  event.id = TRUNK_LINE_WINK;
                  trunk->putEvent(&event);
                  break;
            case TDX_GETDIG:
                  digbuf = trunk->digbuf;
                  diglen = strlen(digbuf->dg_value);
                  digcnt = 0;
                  while(digcnt < diglen)
                  {
                        event.id = TRUNK_DTMF_KEYUP;
                        event.parm.dtmf.duration = 40;
                        event.parm.dtmf.digit = trunk->getDigit(digbuf->dg_value[digcnt++]);
                        trunk->putEvent(&event);
                  }
            case TDX_PLAY:
            case TDX_RECORD:
            case TDX_DIAL:                
            case TDX_PLAYTONE:
            case TDX_ERROR:
                  tmask = ATDX_TERMMSK(trunk->chdev);
                  switch(trunk->interface)
                  {
                  case NT_ANALOG:
                        if(tmask & TM_LCOFF)
                        {
                              event.id = TRUNK_LINE_WINK; 
                              trunk->putEvent(&event);
                        }
                        break;
                  case NT_T1:
                        if((ATDT_TSSGBIT(trunk->tsdev) & DTSG_RCVA) == 0)
                        {
                              if(trunk->Trunk::flags.offhook)
                                    event.id = TRUNK_CALL_DISCONNECT;
                              else
                                    event.id = TRUNK_CALL_RINGING;
                              trunk->putEvent(&event);
                        }
                        break;
                  case NT_E1:
                        if((ATDT_TSSGBIT(trunk->tsdev) & DTSG_RCVA) != 0)
                        {
                              if(trunk->Trunk::flags.offhook)
                                    event.id = TRUNK_CALL_DISCONNECT;
                              else
                                    event.id = TRUNK_CALL_RINGING;
                              trunk->putEvent(&event);
                        }
                        break;
                  }

                  if((tmask & TM_IDDTIME) || (tmask & TM_MAXTIME))
                  {
                        event.id = TRUNK_TIMER_EXPIRED;
                        trunk->putEvent(&event);
                  }

                  if(tmask & TM_TONE)
                  {
                        event.id = TRUNK_CPA_DIALTONE;
                        trunk->putEvent(&event);
                  }

                  if((tmask & TM_MAXSIL) || (tmask & TM_MAXNOSIL))
                  {
                        event.id = TRUNK_AUDIO_IDLE;
                        trunk->putEvent(&event);
                  }

                  if(tmask & TM_ERROR)
                  {
                        event.id = TRUNK_TIMER_EXPIRED;
                        trunk->putEvent(&event);
                  }

                  if(tmask & TM_DIGIT)
                  {
                  }
      
                  switch(evtype)
                  {
                  case TDX_PLAYTONE:
                  case TDX_DIAL:
                  case TDX_CALLP:
                        event.id = TRUNK_TONE_IDLE;
                        break;
                  case TDX_PLAY:
                  case TDX_RECORD:
                        event.id = TRUNK_AUDIO_IDLE;
                  }
                  if(event.id)
                        trunk->putEvent(&event);
                        
                  break;
            case TDX_SETHOOK:
                  cst = (DX_CST *)sr_getevtdatap();
                  switch(cst->cst_event)
                  {
                  case DX_ONHOOK:
                        event.id = TRUNK_ON_HOOK;
                        trunk->putEvent(&event);
                        break;
                  case DX_OFFHOOK:
                        event.id = TRUNK_OFF_HOOK;
                        trunk->putEvent(&event);
                  }
                  break;
            case TDX_CST:
                  cst = (DX_CST *)sr_getevtdatap();
                  switch(cst->cst_event)
                  {
// DE_RNGOFF is hangup in ring - ??
                  case DE_RINGS:
                        if(cst->cst_data & 0x0001)
                        {
                              event.id = TRUNK_CALLER_ID;
                              trunk->putEvent(&event);
                        }
                        event.id = TRUNK_RINGING_ON;
                        trunk->putEvent(&event);
                        event.id = TRUNK_RINGING_OFF;
                        trunk->putEvent(&event);
                        break;
                  case DE_RNGOFF:
                        event.id = TRUNK_TIMER_EXPIRED;
                        trunk->putEvent(&event);
                        break;
                  case DE_LCOF:
                  case DE_WINK:
                        event.id = TRUNK_LINE_WINK;
                        trunk->putEvent(&event);
                        break;
                  case DE_DIGITS:
                        event.id = TRUNK_DTMF_KEYUP;
                        event.parm.dtmf.duration = 40;
                        event.parm.dtmf.digit = trunk->getDigit(cst->cst_data);
                        trunk->putEvent(&event);
                        break;
                  case DE_TONEON:
                        if(hangup_detect == 1 && cst->cst_data == HANGUP_TONE_ID)
                        {
                              event.id = TRUNK_STOP_DISCONNECT;
                              trunk->putEvent(&event);
                        }
                        break;
                  }
                  break;
            case SR_TMOUTEVT:
                  event.id = TRUNK_TIMER_EXPIRED;
                  trunk->putEvent(&event);
                  break;
            case DTEV_SIG:
                  cst = (DX_CST *)sr_getevtdatap();
                  if(!cst)
                  {
                        slog(Slog::levelError) << "DTEV_SIG: no data" << endl;
                        break;
                  }
                  sig = (unsigned short)(cst->cst_event);
                  for(ind = 0; ind < 4; ++ind)
                  {
                        if(!(sig & (SIGEVTCHK << ind)))
                              continue;
                        switch(sig & (SIGBITCHK << ind))
                        {
                        case DTMM_AON:
                              if(trunk->interface == NT_T1)
                                    event.id = TRUNK_CALL_RINGING;
                              else
                                    event.id = TRUNK_CALL_DISCONNECT;
                              trunk->putEvent(&event);
                              break;
                        case DTMM_AOFF:
                              if(trunk->interface == NT_E1)
                                    event.id = TRUNK_CALL_RINGING;
                              else
                                    event.id = TRUNK_CALL_DISCONNECT;
                              trunk->putEvent(&event);
                              break;
                        }
                  }
                  break;
            case DTEV_T1ERRC:

                  slog(Slog::levelError) << "dialogic: DTEV_T1ERRC"  << endl;
                  // this needs fixing, we should find the right span involved
                  if(isdn_count)
                  {
                        /* Etoile Diese : is it always the first span ? */
                        isdn = getSpan(1);

                        /* Etoile Diese : don't know why, but here, iface = isdn->getInterface();  crashes. */
                        /* Let's hard-set iface to NT_E1 */
                        iface = NT_E1; 
                  }
                  else {
                        iface = trunk->interface;
                  }

                  alarmp = (unsigned char *)sr_getevtdatap();

                  /* In case of sr_getevtdatap would not provide anything, let's test it */
                  if (alarmp) {
                        switch(iface)
                        {
                        case NT_T1:
                              switch(*alarmp)
                              {
                              case DTT1_RLOS:
                                    slog(Slog::levelError) << "dialogic: remote loss of sync alarm" << endl;
                                    break;
                              case DTT1_LOS:
                                    slog(Slog::levelError) << "dialogic: local loss of sync alarm" << endl;
                                    break;
                              case DTT1_DPM:
                                    slog(Slog::levelError) << "dialogic: performance monitor alarm" << endl;
                                    break;
                              case DTT1_RED:
                                    slog(Slog::levelError) << "dialogic: T1 red alarm" << endl;
                                    break;
                              case DTT1_BPVS:
                                    slog(Slog::levelError) << "dialogic: bipolar violation alarm" << endl;
                                    break;
                              case DTT1_ECS:
                                    slog(Slog::levelError) << "dialogic: error count saturation alarm" << endl;
                                    break;
                              case DTT1_RYEL:
                                    slog(Slog::levelError) << "dialogic: T1 yellow alarm" << endl;
                                    break;
                              case DTT1_RCL:
                                    slog(Slog::levelError) << "dialogic: carrier lost alarm" << endl;
                                    break;
                              case DTT1_FERR:
                                    slog(Slog::levelError) << "dialogic: frame bit error alarm" << endl;
                                    break;
                              case DTT1_B8ZSD:
                                    slog(Slog::levelError) << "dialogic: bipolar eight zero substitution alarm" << endl;
                                    break;
                              case DTT1_RBL:
                                    slog(Slog::levelError) << "dialogic: T1 blue alarm" << endl;
                                    break;
                              case DTT1_OOF:
                                    slog(Slog::levelError) << "dialogic: out of frame error alarm" << endl;
                                    break;
                              case DTT1_B8ZSDOK:
                                    // sample alarm handling code from Intel suggests we should
                                    // disable this alarm once we receive it once...
                                    param = DTSP_B8ZS;
                                    dt_setparm(evdev, DTG_CODESUPR, (void *)&param);
                                    dt_setevtmsk(evdev, DTG_T1ERREVT, DTEC_B8ZSD, DTA_SUBMSK);
                              case DTT1_RLOSOK:
                              case DTT1_LOSOK:
                              case DTT1_REDOK:
                              case DTT1_BPVSOK:
                              case DTT1_ECSOK:
                              case DTT1_RYELOK:
                              case DTT1_RCLOK:
                              case DTT1_FERROK:
                              case DTT1_RBLOK:
                              case DTT1_OOFOK:
                                    slog(Slog::levelError) << "dialogic: alarm recovery" << endl;
                                    break;
                              }
                              break;
                        case NT_E1:
                              switch(*alarmp)
                              {
                              case DTE1_LOS:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_LOS : local loss of sync alarm" << endl;
                                    break;
                              case DTE1_DPM:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_DPM : performance monitor alarm" << endl;
                                    break;
                              case DTE1_BPVS:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_BPVS : bipolar violation alarm" << endl;
                                    break;
                              case DTE1_ECS:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_ECS : error count saturation alarm" << endl;
                                    break;
                              case DTE1_RRA:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RRA : received remote alarm" << endl;
                                    break;
                              case DTE1_FSERR:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_FSERR : frame sync alarm" << endl;
                                    break;
                              case DTE1_RUA1:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RUA1 : unframed all 1's alarm" << endl;
                                    break;
                              case DTE1_RLOS:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RLOS : remote loss of sync alarm" << endl;
                                    break;
                              case DTE1_MFSERR:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_MFSERR : multiframe sync alarm" << endl;
                                    break;
                              case DTE1_RSA1:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RSA1 : signalling all 1's alarm" << endl;
                                    break;
                              case DTE1_RDMA:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RDMA : distant multiframe alarm" << endl;
                                    break;
                              case DTE1_CECS:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_CECS : CRC4 error count alarm" << endl;
                                    break;

                              case DTE1_LOSOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_LOSOK : Received loss of signal recovered" << endl;
                                    break;
                              case DTE1_DPMOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_DPMOK : Driver perf. monitor failure recovered" << endl;
                                    break;
                              case DTE1_BPVSOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_BPVSOK : Bipolar violation cnt saturation recovered" << endl;
                                    break;
                              case DTE1_ECSOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_ECSOK : Error count saturation recovered" << endl;
                                    break;
                              case DTE1_RRAOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RRAOK : Received remote alarm recovered" << endl;
                                    break;
                              case DTE1_FSERROK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_FSERROK : Received frame sync error recovered" << endl;
                                    break;
                              case DTE1_RUA1OK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RUA1OK : Received unframed all 1's recovered" << endl;
                                    break;
                              case DTE1_RLOSOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RLOSOK : Received loss of sync recovered" << endl;
                                    break;
                              case DTE1_MFSERROK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_MFSERROK : Received multi frame sync error recovered" << endl;
                                    break;
                              case DTE1_RSA1OK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RSA1OK : Received signalling all 1's recovered" << endl;
                                    break;
                              case DTE1_RDMAOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_RDMAOK : Recved. dist. multi-frame alarm recovered" << endl;
                                    break;
                              case DTE1_CECSOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_CECSOK : CRC4 error count saturation recovered" << endl;
                                    break;
                              case DTE1_REDOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_REDOK : Red alarm recovered" << endl;
                                    break;
                              case DTE1_LOOPBACK_CFAOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_LOOPBACK_CFAOK : Diagnostic mode on line trunk recovered" << endl;
                                    break;
                              case DTE1_DCHAN_CFAOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_DCHAN_CFAOK :  D channel out of service recovered" << endl;
                                    break;
                              case DTE1_CRC_CFAOK:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - DTE1_CRC_CFAOK : Timeslot 16 CRC failure recovered" << endl;
                                    break;
                              default:
                                    slog(Slog::levelError) << "dialogic: DTEV_T1ERRC - default : " << endl;
                                    break;
                              }
                        }
                  } else {
                        slog(Slog::levelError) <<  "DTEV_T1ERRC : alarmp : no data." << endl;
                  }
                  break;
            case DX_ATOMIC_ERR:
                  trunk->postError(trunk->chdev, "atomic error ");
                  break;
            case CCEV_FACILITY:
                  event.id = TRUNK_CALL_FACILITY;
                  trunk->putEvent(&event);
                  break;
            default:
                  slog(Slog::levelError) << "UNHANDLED EVENT: " << evtype << endl;
            }
            CONTINUE
      }
}

DialogicISDN *DialogicDriver::getISDN(int fd)
{
      if(fd < 0 || fd >= port_count * 5 + 16)
            return NULL;

      if(!ismaps)
            return NULL;

      return ismaps[fd];
}

DialogicISDN *DialogicDriver::getSpan(int span)
{
      if(span < 1 || span >= getSpanCount())
            return NULL;

      if(!spanmaps)
            return NULL;

      return spanmaps[span - 1];
}

bool DialogicDriver::spanEvent(unsigned span, TrunkEvent *evt)
{
      bool rtn = Driver::spanEvent(span, evt);
      DialogicISDN *isdn = getSpan(span);
      
      if(isdn)
            isdn->spanEvent(evt);
      return rtn;
}

Trunk *DialogicDriver::getTrunkPort(int id)
{
      if(id < 0 || id >= port_count)
            return NULL;

      if(!ports)
            return NULL;

      return (Trunk *)ports[id];
}

void DialogicDriver::Hold(const char *id)
{
      enterMutex();
#ifdef      DIALOGIC_DEBUG
      slog(Slog::levelDebug) << "hold " << id << endl;
#endif
      if(!level)
            sr_hold();
      ++level;
}

void DialogicDriver::Release(void)
{
      if(level > 0)
            --level;
      if(!level)
            sr_release();
#ifdef      DIALOGIC_DEBUG
      slog(Slog::levelDebug) << "release" << endl;
#endif
      leaveMutex();
}

DialogicDriver dialogicivr;

#ifdef CCXX_NAMESPACES
};
#endif


Generated by  Doxygen 1.6.0   Back to index