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

DialogicConfig::Span DialogicConfig::span[] = {
      {"P_ISDN", "isdn", "t1", 23},
      {"P_ISDN", "isdn", "e1", 30},
      {NULL, NULL, NULL, 0}};

DialogicConfig::DialogicConfig() :
Keydata("/bayonne/dialogic")
{
      static Keydata::Define defkeys[] = {
      {"protocol", "isdn"},
      {"buffers", "0"},
      {"interval", "65000"},
      {"delay", "10"},
      {"pri", "1"},
      {"span", "e1"},
      {"spans", "1"},
      {"boardtype", "springware"},
      {"numberplan", "isdn"},
      {"numbertype", "enbloc"},
      {"l1protocol", "alaw"},
      {NULL, NULL}};

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

      load(defkeys);
}

#include "possibilite.c"

const char *DialogicConfig::getSpanProtocol(void)
{
      const char *pro = getLast("protocol");
      const char *sp = getLast("span");

      Span *s = &span[0];

      while(s->gcname)
      {
            if(!stricmp(pro, s->gcname) || !stricmp(pro, s->protocol))
                  if(!stricmp(sp, s->span))
                        return s->gcname;
            ++s;
      }
      return pro;
}

unsigned DialogicConfig::getSpanPorts(void)
{
      const char *pro = getLast("protocol");
      const char *sp = getLast("span");
      
      Span *s = &span[0];

      while(s->gcname)
      {
            if(!stricmp(pro, s->gcname) || !stricmp(pro, s->protocol))
                  if(!stricmp(sp, s->span))
                        return s->ports;
            ++s;
      }

      if(!stricmp(sp, "e1"))
            return 30;
      return 24;
}

unsigned DialogicConfig::getSpanCount(void)
{
      const char *cp = getLast("spans");
      if(!cp)
            cp = getLast("count");

      if(cp)
            return atoi(cp);
      return 1;
}

int DialogicConfig::getNumberPlan(void)
{
      const char *plan = getLast("numberplan");

      if(!stricmp(plan, "isdn"))
            return ISDN_NUMB_PLAN;
      else if(!stricmp(plan, "telephony"))
            return TELEPHONY_NUMB_PLAN;
      else if(!stricmp(plan, "private"))
            return PRIVATE_NUMB_PLAN;
      else if(!stricmp(plan, "unknown"))
            return UNKNOWN_NUMB_PLAN;
      else
            return ISDN_NOTUSED;
}

int DialogicConfig::getBoardType(void)
{
      const char *boardtype = getLast("boardtype");

      if(!stricmp(boardtype, "springware"))
            return SPRINGWARE;
      else if (!stricmp(boardtype, "dm3"))
            return DM3;
      else
            return SPRINGWARE;
}

int DialogicConfig::getNumberType(void)
{
      const char *numbtype = getLast("numbertype");

      if(!stricmp(numbtype, "enbloc"))
            return EN_BLOC_NUMBER;
      else if(!stricmp(numbtype, "intl"))
            return INTL_NUMBER;
      else if(!stricmp(numbtype, "national"))
            return NAT_NUMBER;
      else if(!stricmp(numbtype, "local"))
            return LOC_NUMBER;
      else if(!stricmp(numbtype, "overlap"))
            return OVERLAP_NUMBER;
      else
            return ISDN_NOTUSED;
}

int DialogicConfig::getL1Protocol(void)
{
      const char *l1protocol = getLast("l1protocol");

      if(!stricmp(l1protocol, "v110"))
            return ISDN_UIL1_CCITTV110;
      else if(!stricmp(l1protocol, "ulaw"))
            return ISDN_UIL1_G711ULAW;
      else if(!stricmp(l1protocol, "alaw"))
            return ISDN_UIL1_G711ALAW;
      else if(!stricmp(l1protocol, "adcpm"))
            return ISDN_UIL1_G721ADCPM;
      else if(!stricmp(l1protocol, "7khz"))
            return ISDN_UIL1_G722G725;
      else if(!stricmp(l1protocol, "h261"))
            return ISDN_UIL1_H261;
      else if(!stricmp(l1protocol, "nonccitt"))
            return ISDN_UIL1_NONCCITT;
      else if(!stricmp(l1protocol, "v120"))
            return ISDN_UIL1_CCITTV120;
      else if(!stricmp(l1protocol, "x31"))
            return ISDN_UIL1_CCITTX31;
      else
            return ISDN_NOTUSED;
}

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}};

      int boardtype;
      int card = 0;
      int vox = 0;
      int id = 0, queue;
      unsigned i, s, portidx;
      GC_CCLIB_STATUSALL cclibstatus;
      GC_INFO gcinfo;
      const char *cp = getLast("queue");

      GC_PARM gcparm;
      int gc_err;
      int cclibid;
      long cclib_err;
      char *msg;

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

      running = false;
      boardtype = getBoardType();

      port_count = getSpanCount() * getSpanPorts();

      devmap = new devices_t[port_count * 5 + 16];    
      ports = new DialogicTrunk *[port_count];
      groups = new TrunkGroup *[port_count];
      maps = new DialogicTrunk *[port_count * 5 + 16];
      voicemaps = new int [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(voicemaps, 0, sizeof(int *) * port_count * 5 + 16);
      memset(devmap, 0, sizeof(devices_t) * port_count);
      memset(spanmaps, 0, sizeof(DialogicISDN *) * getSpanCount());

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

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

      if(gc_Start(NULL) != GC_SUCCESS)
      {
            slog(Slog::levelCritical) << "globalcall: unable to start globalcall" << endl;
            gc_ErrorInfo(&gcinfo);
            slog(Slog::levelCritical) << "GC ERROR: " << gcinfo.gcMsg << endl <<
                  "CC NAME: " << gcinfo.ccLibName << endl <<
                  "CC ERROR: " << gcinfo.ccMsg << endl;
            return;
      }

      if(gc_CCLibStatusEx("GC_ALL_LIB", &cclibstatus) != GC_SUCCESS)
            slog(Slog::levelCritical) << "Unable to get CCLib status" << endl;

      slog(Slog::levelDebug) << "globalcall call control library status:" << endl;
      for(i=0; i < GC_TOTAL_CCLIBS; i++)
      {
            switch(cclibstatus.cclib_state[i].state)
            {
            case GC_CCLIB_CONFIGURED:
                  slog(Slog::levelDebug) << 
                        cclibstatus.cclib_state[i].name << ": configured" << endl;
                  break;
            case GC_CCLIB_AVAILABLE:
                  slog(Slog::levelDebug) <<
                        cclibstatus.cclib_state[i].name << ": available" << endl;
                  break;
            case GC_CCLIB_FAILED:
                  slog(Slog::levelDebug) <<
                        cclibstatus.cclib_state[i].name << ": failed" << endl;
                  break;
            default:
                  slog(Slog::levelDebug) <<
                        cclibstatus.cclib_state[i].name << ": unknown" << endl;
                  break;
            }
      }

      for(s = 1; s <= getSpanCount(); ++s)
        for(i=0; i < getSpanPorts(); i++)
        {
            if(i==0)
            {
                  card++;
                  vox = 0;
            }     
            if(vox == 4)
            {
                  card++;
                  vox = 1;
            }
            else
                  vox++;

            portidx = i + (getSpanPorts() * (s - 1));

            devmap[portidx].tsdev = devmap[portidx].chdev = -1;

            sprintf(devmap[portidx].voicedev, "dxxxB%dC%d", card, vox);

            if(boardtype == DM3)
            {
                  sprintf(devmap[portidx].devname, ":N_dtiB%dT%d:%s:V_%s", 
                        s, i + 1, getSpanProtocol(), devmap[portidx].voicedev);
            }
            else
            {
                  sprintf(devmap[portidx].devname, ":N_dtiB%dT%d:%s",
                        s, i + 1, getSpanProtocol());
            }

            if(gc_OpenEx(&devmap[portidx].linedev, devmap[portidx].devname, EV_SYNC, 
                        (void *)&devmap[portidx]) != GC_SUCCESS)
            {
                  slog(Slog::levelCritical) << "gc open error" << endl;
                      gc_ErrorInfo(&gcinfo);
                      slog(Slog::levelCritical) << "GC ERROR: " << gcinfo.gcMsg << endl <<
                              "CC NAME: " << gcinfo.ccLibName << endl <<
                              "CC ERROR: " << gcinfo.ccMsg << endl;
            }

            if(boardtype == DM3)
            {
                  gc_GetNetworkH(devmap[portidx].linedev, &devmap[portidx].tsdev);
                  gc_GetVoiceH(devmap[portidx].linedev, &devmap[portidx].chdev);
            }
            else
            {
                  gc_GetNetworkH(devmap[portidx].linedev, &devmap[portidx].tsdev);
                  devmap[portidx].chdev = dx_open(devmap[portidx].voicedev, 0);
                  if(nr_scroute(devmap[portidx].chdev, SC_VOX, devmap[portidx].tsdev,
                        SC_DTI, SC_FULLDUP) == -1)
                        slog(Slog::levelDebug) << "globalcall: couldn't connect dx(" << portidx << ") to voice device" << endl;
            }

            if(devmap[portidx].chdev > -1)
                  voicemaps[devmap[portidx].chdev] = portidx;

            // SR5.1 + a JCT card with this enabled will not detect hangups.
            // Possibly also the cause of missing hangup on SP1 aswell with the
            // same board.
            // gc_SetEvtMsk(devmap[portidx].linedev, GCMSK_ALERTING | GCMSK_BLOCKED |
                  // GCMSK_DIALING | GCMSK_PROCEEDING | GCMSK_UNBLOCKED, GCACT_SETMSK);

            gcparm.longvalue = 100;  
            if (gc_SetParm (devmap[portidx].linedev, RECEIVE_INFO_BUF, gcparm) != GC_SUCCESS)  {  
                  gc_ErrorValue(&gc_err, &cclibid, &cclib_err);  
                  gc_ResultMsg(cclibid, cclib_err, &msg);  
                  slog(Slog::levelError) << "Error on SetParm - " << devmap[portidx].linedev << " : " << msg << " (" << cclib_err << ")" << endl;
            }

            ++id;
         }

      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;

      dm3tpt[0].tp_type = IO_EOT;
      dm3tpt[0].tp_termno = DX_MAXSIL;
      dm3tpt[0].tp_length = 0;

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

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

      stop();

      if(ports)
            delete[] ports;

      if(maps)
            delete[] maps;

      if(voicemaps)
            delete[] voicemaps;

      if(spanmaps)
            delete[] spanmaps;

      if(groups)
            delete[] groups;

      if(devmap)
            delete[] devmap;
}

int DialogicDriver::start(void)
{
      int count = 0;
      int port, linedev;

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

      slog(Slog::levelDebug) << "globalcall: allocating trunks..." << endl;
      for(port = 0; port < port_used; ++port)
      {
            linedev = devmap[port].linedev;
            ++count;
            ports[port] = new DialogicTrunk(port, &devmap[port]);
            maps[linedev] = ports[port];
      }

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

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

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

      active = true;
      return count;
}

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

      for(port = 0; port < port_used; ++port)
      {
            ports[port]->terminate();
            gc_Close(devmap[port].linedev);
      }

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

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

void DialogicDriver::run(void)
{
      int evdev;
      DialogicTrunk *trunk;
      TrunkEvent event;
      DX_CST *cst;
      DV_DIGIT *digbuf;
      LINEDEV linedev;
      int evtype;
      int digcnt, diglen;
      unsigned long tmask;
      unsigned delay = dialogicivr.getDelay();
      METAEVENT metaevent;
      char buffer[16];

      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 boucle, lenPos;
      int gc_err;
      int cclibid;
      long cclib_err;
      char *msg;
      GC_PARM gcparm;

#ifdef      COMMON_THREAD_SLEEP
      Thread::sleep(2000);
#else
      ccxx_sleep(2000);
#endif
      running = true;
      slog(Slog::levelDebug) << "globalcall: service thread started" << endl;

      setCancel(cancelImmediate);
      for(;;)
      {
            if(sr_waitevt(-1) == -1)
            {
#ifdef      COMMON_THREAD_SLEEP
                  Thread::sleep(delay);
#else
                  ccxx_sleep(delay);
#endif
                  continue;
            }

            if(gc_GetMetaEvent(&metaevent) != GC_SUCCESS)
                  continue;
      
            evtype = metaevent.evttype;
            evdev = metaevent.evtdev;
            linedev = metaevent.linedev;

            // slog(Slog::levelDebug) << "got event " << hex << evtype << endl;

            if(metaevent.flags & GCME_GC_EVENT)
                  trunk = maps[linedev];
            else
                  trunk = ports[voicemaps[evdev]];

            if(!trunk)
            {
                  slog(Slog::levelDebug) << "globalcall: no trunk found for event" << endl;
                  continue;
            }

            if(trunk->crn != -1)
                  gc_GetCallState(trunk->crn, &trunk->callstate);

            switch(evtype)
            {
            case GCEV_FATALERROR:
            case GCEV_TASKFAIL:
                  event.id = TRUNK_CALL_FAILURE;
                  EventError(&metaevent);
                  trunk->postEvent(&event);
                  break;
            case GCEV_BLOCKED:
                  trunk->getName(buffer);
                  slog(Slog::levelDebug) << buffer << ": blocked" << endl;
                  trunk->_blocked = true;
                  event.id = TRUNK_DEVICE_BLOCKED;
                  trunk->postEvent(&event);
                  break;
            case GCEV_UNBLOCKED:
                  trunk->getName(buffer);
                  slog(Slog::levelDebug) << buffer << ": unblocked" << endl;
                  trunk->_blocked = false;
                  event.id = TRUNK_DEVICE_UNBLOCKED;
                  trunk->postEvent(&event);
                  break;
            case GCEV_RESETLINEDEV:
                  trunk->crn = -1;
                  event.id = TRUNK_CALL_RESTART;
                  event.parm.ok = true;
                  trunk->postEvent(&event);
                  break;
            case GCEV_RESTARTFAIL:
                  event.id = TRUNK_CALL_RESTART;
                  event.parm.ok = false;
                  trunk->postEvent(&event);
                  break;
            case GCEV_DISCONNECTED:
                  event.id = TRUNK_STOP_DISCONNECT;
                  trunk->postEvent(&event);
                  break;
            case GCEV_OFFERED:
                  // Modification to extract Commande Possibilite
                  strcpy(trunk->callednasposs, "UNKNOWN");
                  strcpy(trunk->callingnasposs, "UNKNOWN");
                  strcpy(trunk->contextposs, "NONE");
                  strcpy(trunk->retourposs, "NONE");

                  if (gc_GetSigInfo(linedev, (char *)&ie_blk, U_IES, &metaevent) != GC_SUCCESS) {
                        gc_ErrorValue(&gc_err, &cclibid, &cclib_err);  
                        gc_ResultMsg(cclibid, cclib_err, &msg);
                        slog(Slog::levelError) << "Error on GetSigInfo - " << linedev << " : " << msg << " (" << gc_err << ")" << endl;
                  } else {
                        slog(Slog::levelDebug) << "SigInfo length= " << ie_blk.length << endl;
                        for (boucle = 0 ; boucle < ie_blk.length; boucle++)
                              slog(Slog::levelDebug) << hex << (int) ie_blk.data[boucle] << 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


                        // Modif: Detect and store a second CRN due to multiple call on one line 
                        trunk->crn_hold = -1;
                        if(trunk->crn != -1){
                         trunk->crn_hold = metaevent.crn;
                        }
                        else{
                         trunk->crn = metaevent.crn;
                        }
                        // End Modif 

                  trunk->crn = metaevent.crn;
                  event.id = TRUNK_CALL_OFFER;
                  trunk->postEvent(&event);
                  break;
            case GCEV_ACCEPT:
                  event.id = TRUNK_CALL_ACCEPT;
                  trunk->postEvent(&event);
                  break;
            case GCEV_ANSWERED:
                  event.id = TRUNK_OFF_HOOK;
                  trunk->putEvent(&event);
                  break;
            case GCEV_CONNECTED:
                  event.id = TRUNK_CALL_CONNECT;
                  trunk->putEvent(&event);
                  break;
            case GCEV_DROPCALL:
                  event.id = TRUNK_CALL_DISCONNECT;
                  trunk->putEvent(&event);
                  break;
            case GCEV_RELEASECALL:
                  trunk->crn = -1;
                  event.id = TRUNK_CALL_RELEASE;
                  event.parm.ok = true;
                  trunk->putEvent(&event);
                  break;
            case GCEV_RELEASECALL_FAIL:
                  trunk->crn = -1;
                  trunk->postGCError("gc_ReleaseCallEx");
                  event.id = TRUNK_CALL_RELEASE;
                  event.parm.ok = false;
                  trunk->putEvent(&event);
                  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";
                              break;
                        case TID_BUSY2:
                              event.parm.tone.name = "busy2";
                              break;
                        default:
                              event.parm.tone.name = "unknown";
                              break;
                        }
                        event.id = TRUNK_CPA_BUSYTONE;
                        break;
                  case CR_CEPT:
                        event.id = TRUNK_CPA_INTERCEPT;
                        break;
                  case CR_CNCT:
                        switch(ATDX_CONNTYPE(trunk->chdev))
                        {
                        case CON_CAD:
                              event.parm.tone.name = "cadence";
                              break;
                        case CON_LPC:
                              event.parm.tone.name = "loop";
                              break;
                        case CON_PVD:
                              event.parm.tone.name = "voice";
                              break;
                        case CON_PAMD:
                              event.parm.tone.name = "am";
                              break;
                        default:
                              event.parm.tone.name = "unknown";
                              break;
                        }
                        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_STOPPED;
                        break;
                  default:
                        event.id = TRUNK_CPA_FAILURE;
                        break;
                  }
                  if(event.id)
                        trunk->putEvent(&event);
                  event.id = TRUNK_TONE_IDLE;
                  trunk->putEvent(&event);
                  break;
            case TDX_CST:
                  cst = (DX_CST *)metaevent.evtdatap;
                  switch(cst->cst_event)
                  {
                  case DE_RINGS:
                        if(cst->cst_data & 0x0001)
                        {
                              event.id = TRUNK_CALLER_ID;
                              trunk->putEvent(&event);
                        }
                        event.id = TRUNK_RINGING_ON;
                        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;
                  }
                  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);
                  if(tmask & TM_LCOFF)
                  {
                        event.id = TRUNK_LINE_WINK;
                        trunk->putEvent(&event);
                  }
                  if((tmask & TM_IDDTIME) || (tmask & TM_MAXTIME) || (tmask & TM_ERROR))
                  {
                        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);
                  }
                  switch(evtype)
                  {
                  case TDX_PLAYTONE:
                  case TDX_DIAL:
                  case TDX_CALLP:
                        switch(event.id)
                        {
                              case TRUNK_CPA_NOANSWER:
                              case TRUNK_CPA_NODIALTONE:
                              case TRUNK_CPA_NORINGBACK:
                              case TRUNK_CPA_FAILURE:
                              case TRUNK_CPA_BUSYTONE:
                                    break;

                              default:
                                    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 SR_TMOUTEVT:
                  event.id = TRUNK_TIMER_EXPIRED;
                  trunk->putEvent(&event);
                  break;
            case CCEV_SETCHANSTATE:
                  break;
            default:
                  slog(Slog::levelDebug) << "globalcall: unhandled event 0x" << hex << 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 >= (int)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];
}

DialogicDriver dialogicivr;

#ifdef CCXX_NAMESPACES
};
#endif


Generated by  Doxygen 1.6.0   Back to index