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

driver.h

// 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 Aculab telephony libraries to produce a executable image
// without requiring Aculab's libraries to be supplied in a free software
// license as long as each source file so linked contains this exclusion
// and the unalrtered Aculab source files are made available.
//
// This exception does not however invalidate any other reasons why
// the resulting executable file might be covered by the GNU General
// public license or invalidate the licensing requirements of any
// other component or library.
//
// This exception applies only to the code released by OST under the
// name Bayonne.  If you copy code from other releases into a copy of
// Bayonne, as the General Public License permits, the exception does not
// apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own to Bayonne, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice, at which
// point the terms of your modification would be covered under the GPL
// as explicitly stated in "COPYING".

#include <ivrconfig.h>
#include <server.h>
#include <cc++/audio.h>

extern "C" {

#include <mvcldrvr.h>
#include <mvswdrvr.h>
#include <smport.h>
#include <smbesp.h>
#include <smhlib.h>
#include <smclib.h>
#include <smwavlib.h>
#include <smosintf.h>
#include <smdrvr.h>

};

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

#define     MAXTIMESLOTS      32
#define MAXCHANNELS     30

/* Maximum number of channel identifiers (see sm_get_channel_ix() api
 * call in Aculab API docs).  Range is 0 <= index <= (2*x64*N) where
 * N is maximum number of Prosody modules installable in the system.
 */
#define     MAX_CH_IDX  (2*64*10)

/*
 * MVIP bus definitions
 *
 * The MVIP bus is defined as 16 streams, each capable of
 * carrying 32 unidirectional 64kbit speech paths (timeslots).
 *
 * Streams DSi0->DSi7 are input (network to DSP)
 * Streams DSo0->DSo7 are output (DSP to network)
 *
 * A full-duplex call would thus require timeslots two timelots
 * (one in, one out).  The total number of full-duplex streams is
 * thus half, for a total of 8.
 */
#ifdef MVIP_BASED
      #define     MVIP_FD_STREAMS         8
      #define     MVIP_TIMESLOTS          32
#else
      #define MVIP_FD_STREAMS       16
      #define MVIP_TIMESLOTS        128
#endif
/*
 * Number of worker threads to process the event queue
 */
#define     WORKER_THREADS    4

typedef enum
{
      INVALID_PORT,
      FAILED_PORT,
      PRI_PORT,
      BRI_PORT
}     interface_t;


class AculabTrunk;
class AculabQueueThread;

typedef struct AculabTrunkEvent_s {
      AculabTrunkEvent_s *prev;
      AculabTrunkEvent_s *next;
      AculabTrunk *trunk;
      TrunkEvent  event;
} AculabTrunkEvent;

/*
 * A simple BLOCKING fifo to feed events through to worker
 * threads processing per-port request.
 *
 * TODO:  Make this FIFO more than one item deep!
 */
class AculabFifo : public Mutex
{
private:
      AculabTrunkEvent *head;
      AculabTrunkEvent *tail;
      Conditional *cond;
      bool active;
      
public:
      AculabFifo();
      void push(AculabTrunkEvent *evt);
      AculabTrunkEvent *pullBlock();
      AculabTrunkEvent *pull();
      void disable();
      void enable();
};


typedef bool (AculabTrunk::*trunkhandler_t)(TrunkEvent *event);

/*
 * Some general notes about the Aculab world:
 *
 * Channel numbers and handles are ephemeral - they may change between
 * invocations of call_release()/call_openin().  Timeslots (ts)
 * however are fixed and can be used as a point of reference.
 */
class AculabTrunk : private Trunk, private TimerPort, private AudioService, private URLAudio
{
private:
      friend class AculabDriver;
      friend class AculabQueueThread;
      friend class AculabDSPEventThread;
      friend class AculabAudioThread;
      friend class AculabTimer;

      static char status[MAXPORT * MAXTIMESLOTS];

      AculabTrunk *join; /* For joining 2 channels together */
      AculabTrunk *joinees[MAXPORT * MAXTIMESLOTS]; /* For conferences */
      char name[32];
      trunkhandler_t handler;
      unsigned frames;
      time_t lastring;
      int evbuf[2];
      int port, ts, nettype;
      int channel;
      int handle;
      int hold_handle;
      tSMChannelId dspChannel; /* Prosody DSP channel */
      tSMConference tSMConf;
      int mvip_stream;
      int mvip_slot;
      struct detail_xparms detail_xparms;
      char playaudiobuffer[kSMMaxReplayDataBufferSize];
      char recordaudiobuffer[kSMMaxRecordDataBufferSize];
      unsigned int playaudiobufsize;
      unsigned int recordaudiobufsize;
      char *filename;
      bool _call_setup;

      void initSyms(void);
      void setHandle(int handle); /* Aculab driver handle */
      void setChannel(int c);
      bool postEvent(TrunkEvent *evt);
      void exit(void);
      void getName(char *);
      unsigned long getIdleTime(void);
      void setTimer(timeout_t timeout = 0);
      long getMaxTime(void);

      bool Join(AculabTrunk *trunk);
      void Part(void);

      bool allocateDSP(int type);
      bool freeDSP(void);
      bool connectToDSP(void);
      void disconnectFromDSP(void);
      void setDTMFDetect(bool enable);
      void resetDSPChannel(void);

      AculabTrunk(int port, int ts);
      ~AculabTrunk();
      void trunkStep(trunkstep_t step);

      bool stepHandler(TrunkEvent *event);
      bool idleHandler(TrunkEvent *event);
      bool dialHandler(TrunkEvent *event);
      bool flashHandler(TrunkEvent *event);
      bool joinHandler(TrunkEvent *event);
      bool hangupHandler(TrunkEvent *event);
      bool ringHandler(TrunkEvent *event);
      bool loadHandler(TrunkEvent *event);
      bool answerHandler(TrunkEvent *event);
      bool sleepHandler(TrunkEvent *event);
      bool threadHandler(TrunkEvent *event);
      bool collectHandler(TrunkEvent *event);
      bool playHandler(TrunkEvent *event);
      bool playwaitHandler(TrunkEvent *event);
      bool recordHandler(TrunkEvent *event);

      bool scrJoin(void);
      bool scrWait(void);
      bool scrMaxTime(void);

      /* Play file */
      bool StartPlayFile();
      bool PlayNext();
      timeout_t StopPlayFile();
      char *getContinuation();
      bool isActive()
            { return Trunk::flags.script; };


      /* Record file */
      bool StartRecordFile();
      bool RecordNext();
      timeout_t StopRecordFile();
};

/*
 * This is the consumer thread
 */
class AculabQueueThread : public Mutex, public Thread
{
private:
      friend class AculabDriver;
      friend class AculabTrunk;

      AculabFifo *queue;
      static int count;
      volatile bool active;

      int id;

      void run(void);

public:
      AculabQueueThread(AculabFifo *fifo);
      ~AculabQueueThread();
};


/*
 * This is the DSP event monitoring thread
 */
class AculabDSPEventThread : public Mutex, public Thread
{
private:
      friend class AculabDriver;
      friend class AculabTrunk;

      AculabFifo *queue;
      AculabTrunk **ixmaps;
      volatile bool active;
      SM_CHANNEL_SET_EVENT_PARMS recogEventParms;

      void run(void);

public:
      AculabDSPEventThread(AculabFifo *fifo, AculabTrunk **ix);
      ~AculabDSPEventThread();
};


/*
 * This is the audio processing thread.  This one thread
 * is responsible for pumping audio in/out to/from all trunks/channels
 * in the system.  At some point, this may have to be expanded
 * to more threads (one per port (24/30 channels)?) if it can't keep up.
 */
class AculabAudioThread : public Mutex, public Thread
{
private:
      friend class AculabDriver;
      friend class AculabTrunk;

      SM_CHANNEL_SET_EVENT_PARMS writeEventParms;
      SM_CHANNEL_SET_EVENT_PARMS readEventParms;
      Conditional *cond;
      AculabFifo *queue;
      AculabTrunk **ixmaps;
      volatile bool active;
      int streamCount;

      void run(void);

public:
      AculabAudioThread(AculabFifo *fifo, AculabTrunk **ix);
      ~AculabAudioThread();
};

/*
 * This is the ISDN Layer 1/link monitoring thread
 */
class AculabMonitorThread : public Mutex, public Thread
{
private:
      friend class AculabDriver;
      friend class AculabTrunk;

      volatile bool active;

      void run(void);

public:
      AculabMonitorThread();
      ~AculabMonitorThread();
};

/*
 * This is the trunk timer thread
 */
class AculabTimer : public Thread, public Mutex
{
public:
      /*
       * Notify timer thread that a timer has been set.
       * This servers to knock the thread out of a prolonged
       * wait if a trunk becomes active.
       */
      void notify();
      AculabTimer();
      ~AculabTimer();
      void run(void);

private:
      friend class AculabDriver;
      bool bypass;

      Conditional *cond;
      AculabFifo *queue;
      volatile bool active;

};


class AculabConfig : public Keydata
{
public:
      AculabConfig();

      unsigned getMaxPorts(void);

      inline const char *getPriFirmware(void)
            {return getLast("prifirmware");};

      inline const char *getPriFirmware(int port)
            {     char buf[32];
                  sprintf(buf,"prifirmware_%d",port);
                  return getLast(buf);
            };

      inline const char *getPriConfig(void)
            {return getLast("priconfig");};

      inline const char *getBriFirmware(void)
            {return getLast("brifirmware");};

      inline const char *getBriConfig(void)
            {return getLast("briconfig");};

      inline const char *getProsody(void)
            {return getLast("prosody");};

      inline const char *getNetFormat(void)
            {return getLast("netformat");};

      inline unsigned int getAudioBufferSize(void)
            {return atoi(getLast("buffersize"));};
};

class AculabDriver : public Driver, public AculabConfig, public Thread
{
private:
      friend class AculabTrunk;
      friend class AculabTimer;

      interface_t interfaces[MAXPORT];
      struct siginfo_xparms siginfo[MAXPORT];
      int MVIP[MVIP_FD_STREAMS * MVIP_TIMESLOTS];

      Mutex *mvipMutex;
      AculabTimer *timer;
      AculabMonitorThread *l1thread;
      AculabAudioThread *audiothread;
      AculabDSPEventThread *dspthread;
      AculabQueueThread **qthreads;
      AculabTrunk **trunks;
      AculabTrunk **imaps;
      AculabTrunk **omaps;
      AculabTrunk **ixmaps;
      AculabFifo *queue;
      char *tsmap;
      unsigned port_count, pri_count, bri_count;
      bool running;

      bool callConnected;

      bool InitNetworks(void);
      bool InitProsody(void);

      void postEvent(AculabTrunk *trunk, trunkevent_t id);
      void setChannel(AculabTrunk *trunk);
      void clrChannel(AculabTrunk *trunk);
      bool getMVIPslot(int *stream, int *slot);
      void freeMVIPslot(int stream, int slot);
      void secTick(void)
            {return;};

public:
      AculabDriver();
      ~AculabDriver();

      int start(void);
      void stop(void);
      void run(void);

      unsigned getCaps(void)
            {return capDaemon | capPSTN | capJoin | capSpans;};

      unsigned getTrunkCount(void)
            {return port_count * MAXTIMESLOTS;};

      Trunk *getTrunkPort(int id);
      aaScript *getScript(void);

      unsigned getPort(int id)
            {return id / MAXTIMESLOTS;};

      interface_t getInterface(unsigned port);

private:
      void dumpCallDetail(struct detail_xparms *);

};


extern AculabDriver aculabivr;

#ifdef    CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index