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.

#include "driver.h"

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

VPBConfig::VPBConfig() :
Keydata("/bayonne/vpb")
{
      static Keydata::Define defkeys[] = {
      {"cards", "1"},
      {"first", "300"},
      {"hooktime", "300"},
      {"firmware", "/etc/vpb/vpbmain_pci.out"},
      {"model", "v4pci"},
      {"delay", "10"},
      {"stations", "aann"},
      {"drop", "y"},
      {"pickup", "800"},
      {NULL, NULL}};

      const char *cp;

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

      load(defkeys);

      cp = getLast("steptimer");
      if(cp)
            stepTimer = getMSTimeout(cp);
      else
            stepTimer = keythreads.getStepDelay();

      cp = getLast("synctimer");
      if(cp)
            syncTimer = getMSTimeout(cp);
      else
            syncTimer = keythreads.getResetDelay();

      slog(Slog::levelDebug) << "vpb timers: step=" << stepTimer << ", sync=" << syncTimer << endl;
}

size_t VPBConfig::getStack(void)
{
      const char *cp = getLast("stack");

if(!cp)
            return keythreads.getStack();

      return atoi(cp) * 1024;
}

int   VPBConfig::getModel(void)
{
      const char *cp = getLast("model");
      const char *dn = plugins.getDriverName();

      if(dn)
      {
            if(!strnicmp(dn, "openline", 8))
                  cp = "V4PCI";
#ifdef      VPB_V12PCI
            else if(!strnicmp(dn, "openswitch", 10))
                  cp = "V12PCI";
#endif
      }

      if(!cp)
            cp = getenv("VPB_MODEL");

      if(!cp)
            return VPB_V4PCI;

      if(!stricmp(cp, "VPB4") || !stricmp(cp, "V4ISA"))
            return VPB_VPB4;

      if(!stricmp(cp, "VPB8L"))
            return VPB_VPB8L;

#ifdef      VPB_V12PCI
      if(!stricmp(cp, "V12PCI"))
            return VPB_V12PCI;
#endif

      return VPB_V4PCI;
}

unsigned    VPBConfig::getCardSize(void)
{
      switch(getModel())
      {
      case VPB_VPB8L:
            return 8;
            break;
#ifdef      VPB_V12PCI
      case VPB_V12PCI:
            return 12;
            break;
#endif
      }
      return 4;
}

VPBDriver::VPBDriver() :
Driver(), Thread(keythreads.priService() - 1)
{
        static Script::Define keywords[] = {
                {"join", (Method)&VPBTrunk::scrJoin,
                  &ScriptCommand::chkIgnore},
            {"wait", (Method)&VPBTrunk::scrWait,
                  &ScriptCommand::chkIgnore},
            {"ring", (Method)&VPBTrunk::scrRing,
                  &ScriptCommand::chkIgnore},
            {"pickup", (Method)&VPBTrunk::scrPickup,
                  &ScriptCommand::chkIgnore},
            {"answer", (Method)&VPBTrunk::scrAnswer,
                  &ScriptCommand::chkIgnore},
            {"dial", (Method)&VPBTrunk::scrDial,
                  &ScriptCommand::chkHasArgs},
            {NULL, NULL, NULL}};

      unsigned sizeindex = getCardSize();
      unsigned cardcount = getCards();
      const char *stations = VPBConfig::getLast("stations");

      port_count = cardcount * sizeindex;
      bridge_count = cardcount * sizeindex / 2;
      status = VPBTrunk::status;

      if(sizeindex != 12)
            cardcount = 0;

      while(cardcount--)
      {
            switch(*stations)
            {
            case 'a':
            case 'A':
                  extCount += 8;
                  break;
            case 'b':
            case 'B':
                  extCount += 4;
                  break;
            }
            ++stations;
      }

      trunks = new VPBTrunk *[port_count];
      ports = new VPBTrunk *[port_count];
      groups = new TrunkGroup *[port_count];
      bridges = new bool[bridge_count];
      memset(ports, 0, sizeof(VPBTrunk *) * port_count);
      memset(groups, 0, sizeof(TrunkGroup *) * port_count);
      memset(bridges, 0, sizeof(bool) * bridge_count);

      memset(status, ' ', sizeof(VPBTrunk::status));

//    if(getuid())
//    {
//          slog(Slog::levelCritical) << "vpb driver requires root" << endl;
//          throw((Driver *)this);
//    }
      slog(Slog::levelInfo) << "vpb driver loaded; capacity=" << getCards() << " cards" << endl;

      ScriptCommand::load(keywords);
}

unsigned VPBDriver::getCaps(void)
{
      if(extCount)
            return capDaemon | capSwitch | capJoin | capPSTN;

      return capDaemon | capPSTN | capJoin;
}

unsigned VPBDriver::getBridge(int card)
{
      int bs = getCardSize() / 2;
      int i, first = (card - 1) * bs;

      for(i = 0; i < bs; ++i)
            if(!vpbivr.bridges[first + i])
            {
                  vpbivr.bridges[first + i] = true;
                  return i + 1;
            }

      return 0;
}

void VPBDriver::freeBridge(int card, unsigned src)
{
      if(src && src < 3)
            vpbivr.bridges[(card - 1) * 2 + src - 1] = false;
}

VPBDriver::~VPBDriver()
{

      if(running)
            terminate();

      stop();
      if(ports)
            delete[] ports;

      if(groups)
            delete[] groups;

      if(trunks)
            delete[] trunks;
}

Trunk *VPBDriver::getTrkNumber(const char *trk)
{
      VPBTrunk *trunk;
      unsigned tid;

      if(!trk)
            trk = "9999";

      if(!trunks || *trk == '-')
      {
            trunk = (VPBTrunk *)getTrunkId(trk);
            if(trunk)
                  if(trunk->isStation)
                        trunk = NULL;
            return (Trunk *)trunk;
      }

      tid = atoi(trk);
      if(tid < 0 || tid >= trkCount)
            return NULL;
      return trunks[tid];
}

int VPBDriver::start(void)
{
      VPBTrunk *trunk;
      TrunkGroup *grp;
      unsigned sizeindex = getCardSize();
      unsigned count, ts;
      unsigned cards = getCards();
      int offsets[16];
      int first = getOffset();
      const char *stations = VPBConfig::getLast("stations");
      bool sta;
      char extbuf[3];
      int extnum = 0;
      char *dn = plugins.getDriverName();

      if(!extCount)
            stations = "nnnnnnnn";
      else if(extCount < 9 && !numbering)
            setExtNumbering(1);
      else if(!numbering)
      {
            extnum = 10;
            setExtNumbering(2);
      }

      // assume from port 0x3x0 upward

      for(count = 0; count < cards; ++count)
            offsets[count] = first + 16 * count;

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


      if(getFirmware())
            setenv("VPB_FIRMWARE", getFirmware(), 0);

      if(!strnicmp(dn, "openline", 8))
            setenv("VPB_MODEL", "V4PCI", 0);
      else if(!strnicmp(dn, "openswitch", 10))
            setenv("VPB_MODEL", "V12PCI", 0);
      else if(VPBConfig::getLast("model"))
            setenv("VPB_MODEL", VPBConfig::getLast("model"), 0);

      vpb_seterrormode(VPB_ERROR_CODE);

      for(count = 0; count < cards; ++count)
      {
            for(ts = 0; ts < sizeindex; ++ts)
            {
                  sta = false;
                  switch(*stations)
                  {
                  case 'a':
                  case 'A':
                        if(ts < 8)
                              sta = true;
                        break;
                  case 'b':
                  case 'B':
                        if(ts > 7)
                              sta = true;
                        break;
                  }
                  grp = NULL;
                  if(sta)
                  {
                        if(stacards[count + 1])
                              grp = stacards[count + 1];
                        else
                              grp = stacards[0];
                  }
                  if(grp)
                        groups[count * sizeindex + ts] = grp;

                  ports[count * sizeindex + ts] = trunk = new VPBTrunk(count + 1, ts, sta);
                  if(!sta)
                  {
                        trunks[trkCount++] = trunk;
                        continue;
                  }

                  if(!numbering)
                  {
                        sprintf(extbuf, "%d", extnum++);
                        setExtNumber(count * sizeindex + ts, extbuf);
                  }
            }
            ++stations;
      }

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

      if(extCount)
            slog(Slog::levelInfo) << "vpb: initialized; extensions=" << extCount << ", trunks=" << trkCount << endl;
      else
            slog(Slog::levelInfo) << "vpb: initalized " << cards * sizeindex << " ports successfully..." << endl;
      active = true;
      return cards * sizeindex;
}

void VPBDriver::stop(void)
{
      unsigned port;

      if(!active)
            return;

      if(ports)
            for(port = 0; port < port_count; ++port)
                  if(ports[port])
                        delete ports[port];

      if(ports)
      {
            delete[] ports;
            ports = NULL;
      }
      active = false;
      slog(Slog::levelInfo) << "vpb: stopping..." << endl;
}

void VPBDriver::run(void)
{
        VPB_EVENT vpbevt;
        TrunkEvent event;
        VPBTrunk *trunk;
        unsigned port;
        int cards = vpbivr.getCards();
      const char *cp;
//    char s[VPB_MAX_STR];

      slog(Slog::levelInfo) << "vpb: event thread started..." << endl;
      running = true;
      active = true;
      setCancel(cancelDeferred);

      for(;;)
      {
            if(!active)
            {
                  Thread::sleep(1000);
                  continue;
            }

            if(vpb_get_event_sync(&vpbevt, 0) != VPB_OK)
            {
                  Thread::yield();
                  continue;
            }

            for(port = 0; port < getCardSize() * cards; ++port)
            {
                  if(!vpbivr.ports[port])
                        continue;

                  if(vpbivr.ports[port]->handle == vpbevt.handle)
                        break;
            }

            if(port >= getCardSize() * cards)
                  continue;

            trunk = vpbivr.ports[port];

//                vpb_translate_event(&vpbevt, s);
//                slog(Slog::levelInfo) << s << endl;
                memset(&event, 0, sizeof(event));

                switch(vpbevt.type)
                {
                case VPB_RING:
                  if(trunk->Trunk::flags.offhook)
                  {
                        event.id = TRUNK_STOP_DISCONNECT;
                        break;
                  }
                        event.id = TRUNK_RINGING_ON;
                        trunk->postEvent(&event);
                        event.id = TRUNK_RINGING_OFF;
                        break;
                case VPB_DTMF:
                        event.id = TRUNK_DTMF_KEYUP;
                        event.parm.dtmf.digit = trunk->getDigit(vpbevt.data);
                        event.parm.dtmf.duration = 40;
                        break;
                case VPB_DROP:
                        if(!trunk->isStation)
                        {
                                cp = getLast("drop");
                                switch(*cp)
                                {
                                case 'n':
                                case 'N':
                                case '0':
                                case 'f':
                                case 'F':
                                        break;
                                default:
                                        event.id = TRUNK_STOP_DISCONNECT;
                                }
                        }
                        break;
                case VPB_TIMEREXP:
                        event.id = TRUNK_TIMER_EXPIRED;
                        break;
                case VPB_VOXON:
                        event.id = TRUNK_AUDIO_START;
                        break;
                case VPB_VOXOFF:
                        event.id = TRUNK_AUDIO_STOP;
                        break;
            case VPB_PLAYEND:
                case VPB_RECORDEND:
                        event.id = TRUNK_AUDIO_IDLE;
                        break;
                case VPB_DIALEND:
                        event.id = TRUNK_EXIT_STATE;
                        break;
#ifdef      VPB_V12PCI
            case VPB_STATION_OFFHOOK:
                  event.id = TRUNK_STATION_OFFHOOK;
                  break;
            case VPB_STATION_ONHOOK:
                  event.id = TRUNK_STATION_ONHOOK;
                  break;
#ifdef      VPB_STATION_FLASH
            case VPB_STATION_FLASH:
                  event.id = TRUNK_STATION_FLASH;
                  break;
#endif
#endif
                case VPB_CALLEND:
                  switch(vpbevt.data)
                  {
                  default:
                  case VPB_CALL_CONNECTED:
                        event.id = TRUNK_SERVICE_SUCCESS;
                        break;
                        case VPB_CALL_NO_DIAL_TONE:
                                event.id = TRUNK_CPA_NODIALTONE;
                                break;
                        case VPB_CALL_NO_RING_BACK:
                                event.id = TRUNK_CPA_NORINGBACK;
                                break;
                        case VPB_CALL_BUSY:
                                event.id = TRUNK_CPA_BUSYTONE;
                                break;
                        case VPB_CALL_NO_ANSWER:
                                event.id = TRUNK_CPA_NOANSWER;
                                break;
                        case VPB_CALL_DISCONNECTED:
                                event.id = TRUNK_STOP_DISCONNECT;
                                break;
                  }
                        break;
                case VPB_TONEDETECT:
                        switch(vpbevt.data)
                        {
                  case VPB_GRUNT + 1:
                        event.parm.tone.name = "reorder";
                        event.id = TRUNK_CPA_REORDER;
                        break;
                  case VPB_GRUNT + 2:
                        event.parm.tone.name = "user1";
                        event.id = TRUNK_TONE_START;
                        break;
                  case VPB_GRUNT + 3:
                        event.parm.tone.name = "user2";
                        event.id = TRUNK_TONE_START;
                        break;
                  case VPB_GRUNT + 4:
                        event.parm.tone.name = "user3";
                        event.id = TRUNK_TONE_START;
                        break;
                  case VPB_GRUNT + 5:
                        event.parm.tone.name = "user4";
                        event.id = TRUNK_TONE_START;
                        break;
                  case VPB_GRUNT:
                        event.id = TRUNK_CPA_GRUNT;
                        break;
                        case VPB_DIAL:
                                event.id = TRUNK_CPA_DIALTONE;
                                break;
                        case VPB_RINGBACK:
                                event.id = TRUNK_CPA_RINGING;
                                break;
                        case VPB_BUSY:
                                event.id = TRUNK_CPA_BUSYTONE;
                                break;
                        }
                        break;
                }
                if(event.id)
                        trunk->postEvent(&event);
      }           
}

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

      if(!ports)
            return NULL;

      return (Trunk *)ports[id];
}

VPBDriver vpbivr;

#ifdef      CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index