Wed Oct 28 15:48:38 2009

Asterisk developer's documentation


chan_vpb.c File Reference

VoiceTronix Interface driver. More...

#include <stdio.h>
#include <string.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/callerid.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <ctype.h>
#include <vpbapi.h>
#include <assert.h>

Include dependency graph for chan_vpb.c:

Go to the source code of this file.

Data Structures

struct  vpb_bridge_t
struct  vpb_pvt

Defines

#define BAD_V4PCI_BRIDGE
#define CID_MSECS   2000
#define DEFAULT_ECHO_CANCEL   1
#define DEFAULT_GAIN   0
#define DTMF_CALLERID
#define DTMF_CID_START   'D'
#define DTMF_CID_STOP   'C'
#define MAX_BRIDGES_V12PCI   128
#define MAX_BRIDGES_V4PCI   2
#define MAX_VPB_GAIN   12.0
#define MIN_VPB_GAIN   -12.0
#define MODE_DIALTONE   1
#define MODE_FXO   3
#define MODE_IMMEDIATE   2
#define RING_SKIP   300
#define TIMER_PERIOD_BUSY   700
#define TIMER_PERIOD_NOANSWER   120000
#define TIMER_PERIOD_RING   4000
#define TIMER_PERIOD_RINGBACK   2000
#define TONES_AU
#define VPB_CONNECTED_WAIT   4000
#define VPB_DIALTONE_WAIT   2000
#define VPB_EVENTS_ALL
#define VPB_EVENTS_NODROP
#define VPB_EVENTS_NODTMF
#define VPB_EVENTS_STAT
#define VPB_GOT_RXHWG   1
#define VPB_GOT_RXSWG   4
#define VPB_GOT_TXHWG   2
#define VPB_GOT_TXSWG   8
#define VPB_MAX_BUF   VPB_SAMPLES*4 + AST_FRIENDLY_OFFSET
#define VPB_NULL_EVENT   200
#define VPB_RINGWAIT   4000
#define VPB_SAMPLES   160
#define VPB_STATE_DIALLING   2
#define VPB_STATE_GETDTMF   4
#define VPB_STATE_JOINED   3
#define VPB_STATE_OFFHOOK   1
#define VPB_STATE_ONHOOK   0
#define VPB_STATE_PLAYBUSY   6
#define VPB_STATE_PLAYDIAL   5
#define VPB_STATE_PLAYRING   7
#define VPB_WAIT_TIMEOUT   4000

Enumerations

enum  vpb_model_t { vpb_model_unknown = 0, vpb_model_v4pci, vpb_model_v12pci }

Functions

int a_gain_vector (float g, short *v, int n)
static int ast2vpbformat (int ast_format)
static char * ast2vpbformatname (int ast_format)
 AST_MUTEX_DEFINE_STATIC (bridge_lock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 AST_MUTEX_DEFINE_STATIC (iflock)
 AST_MUTEX_DEFINE_STATIC (usecnt_lock)
static int astformatbits (int ast_format)
char * description ()
 Provides a description of the module.
static void * do_chanreads (void *pvt)
static void * do_monitor (void *unused)
static void get_callerid (struct vpb_pvt *p)
static void get_callerid_ast (struct vpb_pvt *p)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module ()
 Initialize the module.
static void mkbrd (vpb_model_t model, int echo_cancel)
static struct vpb_pvtmkif (int board, int channel, int mode, int gains, float txgain, float rxgain, float txswgain, float rxswgain, int bal1, int bal2, int bal3, char *callerid, int echo_cancel, int group, ast_group_t callgroup, ast_group_t pickupgroup)
static int monitor_handle_notowned (struct vpb_pvt *p, VPB_EVENT *e)
static int monitor_handle_owned (struct vpb_pvt *p, VPB_EVENT *e)
static float parse_gain_value (char *gain_type, char *value)
static int playtone (int handle, VPB_TONE *tone)
static int restart_monitor (void)
static void stoptone (int handle)
int unload_module ()
 Cleanup all module structures, sockets, etc.
int usecount ()
 Provides a usecount.
static int vpb_answer (struct ast_channel *ast)
static enum ast_bridge_result vpb_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int vpb_call (struct ast_channel *ast, char *dest, int timeout)
static int vpb_digit (struct ast_channel *ast, char digit)
static int vpb_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int vpb_hangup (struct ast_channel *ast)
static int vpb_indicate (struct ast_channel *ast, int condition)
static struct ast_channelvpb_new (struct vpb_pvt *i, int state, char *context)
static struct ast_framevpb_read (struct ast_channel *ast)
static struct ast_channelvpb_request (const char *type, int format, void *data, int *cause)
static int vpb_write (struct ast_channel *ast, struct ast_frame *frame)

Variables

static int break_for_dtmf = 1
static vpb_bridge_tbridges
static VPB_TONE Busytone = {470, 0, 0, -10, -100, -100, 5000, 0 }
static const char config [] = "vpb.conf"
static char context [AST_MAX_EXTENSION] = "default"
static const char desc [] = "VoiceTronix V6PCI/V12PCI/V4PCI API Support"
static VPB_TONE Dialtone = {440, 440, 440, -10, -10, -10, 5000, 0 }
VPB_TONE_MAP DialToneMap []
static int dtmf_idd = 3000
static int ec_supp_threshold = -1
static int gruntdetect_timeout = 3600000
static struct vpb_pvtiflist
static char language [MAX_LANGUAGE] = ""
static int max_bridges = MAX_BRIDGES_V4PCI
static pthread_t monitor_thread
static int mthreadactive = -1
static const int prefformat = AST_FORMAT_SLINEAR
static int relaxdtmf = 0
static VPB_TONE Ringbacktone = {400, 50, 440, -10, -10, -10, 1400, 800 }
static const char tdesc [] = "Standard VoiceTronix API Driver"
static int timer_period_ring = TIMER_PERIOD_RING
static VPB_DETECT toned_grunt = { 3, VPB_GRUNT, 1, 2000, 3000, 0, 0, -40, 0, 0, 0, 40, { { VPB_DELAY, 1000, 0, 0 }, { VPB_RISING, 0, 40, 0 }, { 0, 100, 0, 0 } } }
static VPB_DETECT toned_ungrunt = { 2, VPB_GRUNT, 1, 2000, 1, 0, 0, -40, 0, 0, 30, 40, { { 0, 0, 0, 0 } } }
static const char type [] = "vpb"
static int use_ast_dtmf = 0
static int use_ast_dtmfdet = 0
static int use_ast_ind = 0
static int usecnt = 0
static int UseLoopDrop = 1
static int UseNativeBridge = 1
static int UsePolarityCID = 0
static struct ast_channel_tech vpb_tech
static struct ast_channel_tech vpb_tech_indicate


Detailed Description

VoiceTronix Interface driver.

Definition in file chan_vpb.c.


Define Documentation

#define BAD_V4PCI_BRIDGE

Definition at line 409 of file chan_vpb.c.

#define CID_MSECS   2000

Definition at line 614 of file chan_vpb.c.

Referenced by get_callerid().

#define DEFAULT_ECHO_CANCEL   1

Definition at line 73 of file chan_vpb.c.

Referenced by load_module().

#define DEFAULT_GAIN   0

Definition at line 72 of file chan_vpb.c.

#define DTMF_CALLERID

Definition at line 85 of file chan_vpb.c.

#define DTMF_CID_START   'D'

Definition at line 86 of file chan_vpb.c.

Referenced by monitor_handle_notowned().

#define DTMF_CID_STOP   'C'

Definition at line 87 of file chan_vpb.c.

Referenced by monitor_handle_notowned().

#define MAX_BRIDGES_V12PCI   128

Definition at line 218 of file chan_vpb.c.

#define MAX_BRIDGES_V4PCI   2

Definition at line 217 of file chan_vpb.c.

Referenced by mkbrd().

#define MAX_VPB_GAIN   12.0

Definition at line 82 of file chan_vpb.c.

Referenced by do_chanreads(), mkif(), and vpb_write().

#define MIN_VPB_GAIN   -12.0

Definition at line 83 of file chan_vpb.c.

Referenced by mkif().

#define MODE_DIALTONE   1

Definition at line 132 of file chan_vpb.c.

#define MODE_FXO   3

Definition at line 134 of file chan_vpb.c.

#define MODE_IMMEDIATE   2

Definition at line 133 of file chan_vpb.c.

#define RING_SKIP   300

Definition at line 613 of file chan_vpb.c.

Referenced by get_callerid().

#define TIMER_PERIOD_BUSY   700

Definition at line 186 of file chan_vpb.c.

Referenced by mkif().

#define TIMER_PERIOD_NOANSWER   120000

Definition at line 215 of file chan_vpb.c.

Referenced by vpb_call().

#define TIMER_PERIOD_RING   4000

Definition at line 187 of file chan_vpb.c.

#define TIMER_PERIOD_RINGBACK   2000

Definition at line 185 of file chan_vpb.c.

Referenced by mkif().

#define TONES_AU

Definition at line 138 of file chan_vpb.c.

#define VPB_CONNECTED_WAIT   4000

Definition at line 214 of file chan_vpb.c.

Referenced by vpb_call().

#define VPB_DIALTONE_WAIT   2000

Definition at line 212 of file chan_vpb.c.

Referenced by vpb_call().

#define VPB_EVENTS_ALL

Value:

(VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
         |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
         |VPB_MRING_OFF|VPB_MDROP|VPB_MSTATION_FLASH)

Definition at line 190 of file chan_vpb.c.

Referenced by do_chanreads(), and mkif().

#define VPB_EVENTS_NODROP

Value:

(VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
         |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
         |VPB_MRING_OFF|VPB_MSTATION_FLASH)

Definition at line 193 of file chan_vpb.c.

#define VPB_EVENTS_NODTMF

Value:

(VPB_MRING|VPB_MDIGIT|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
         |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
         |VPB_MRING_OFF|VPB_MDROP|VPB_MSTATION_FLASH)

Definition at line 196 of file chan_vpb.c.

Referenced by do_chanreads(), and mkif().

#define VPB_EVENTS_STAT

Value:

(VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP|VPB_MPLAY_UNDERFLOW \
         |VPB_MRECORD_OVERFLOW|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \
         |VPB_MRING_OFF|VPB_MSTATION_FLASH)

Definition at line 199 of file chan_vpb.c.

Referenced by mkif().

#define VPB_GOT_RXHWG   1

Definition at line 230 of file chan_vpb.c.

Referenced by load_module(), and mkif().

#define VPB_GOT_RXSWG   4

Definition at line 232 of file chan_vpb.c.

Referenced by load_module(), and mkif().

#define VPB_GOT_TXHWG   2

Definition at line 231 of file chan_vpb.c.

Referenced by load_module(), and mkif().

#define VPB_GOT_TXSWG   8

Definition at line 233 of file chan_vpb.c.

Referenced by load_module(), and mkif().

#define VPB_MAX_BUF   VPB_SAMPLES*4 + AST_FRIENDLY_OFFSET

Definition at line 76 of file chan_vpb.c.

#define VPB_NULL_EVENT   200

Definition at line 78 of file chan_vpb.c.

Referenced by do_monitor(), and restart_monitor().

#define VPB_RINGWAIT   4000

Definition at line 213 of file chan_vpb.c.

Referenced by vpb_call().

#define VPB_SAMPLES   160

Definition at line 75 of file chan_vpb.c.

Referenced by do_chanreads(), vpb_bridge(), and vpb_write().

#define VPB_STATE_DIALLING   2

Definition at line 223 of file chan_vpb.c.

#define VPB_STATE_GETDTMF   4

Definition at line 225 of file chan_vpb.c.

Referenced by monitor_handle_notowned().

#define VPB_STATE_JOINED   3

Definition at line 224 of file chan_vpb.c.

#define VPB_STATE_OFFHOOK   1

Definition at line 222 of file chan_vpb.c.

Referenced by vpb_answer(), and vpb_call().

#define VPB_STATE_ONHOOK   0

Definition at line 221 of file chan_vpb.c.

Referenced by monitor_handle_notowned(), and vpb_hangup().

#define VPB_STATE_PLAYBUSY   6

Definition at line 227 of file chan_vpb.c.

Referenced by monitor_handle_notowned(), monitor_handle_owned(), and vpb_indicate().

#define VPB_STATE_PLAYDIAL   5

Definition at line 226 of file chan_vpb.c.

Referenced by monitor_handle_notowned().

#define VPB_STATE_PLAYRING   7

Definition at line 228 of file chan_vpb.c.

Referenced by vpb_indicate().

#define VPB_WAIT_TIMEOUT   4000

Definition at line 80 of file chan_vpb.c.

Referenced by do_monitor().


Enumeration Type Documentation

Enumerator:
vpb_model_unknown 
vpb_model_v4pci 
vpb_model_v12pci 

Definition at line 250 of file chan_vpb.c.

00250              {
00251    vpb_model_unknown = 0, 
00252    vpb_model_v4pci,
00253    vpb_model_v12pci
00254 } vpb_model_t;


Function Documentation

int a_gain_vector ( float  g,
short *  v,
int  n 
)

Definition at line 2235 of file chan_vpb.c.

Referenced by do_chanreads(), and vpb_write().

02236 {
02237    int i;
02238    float tmp;
02239    for ( i = 0; i<n; i++) {
02240       tmp = g*v[i];
02241       if (tmp > 32767.0)
02242          tmp = 32767.0;
02243       if (tmp < -32768.0)
02244          tmp = -32768.0;
02245       v[i] = (short)tmp;   
02246    }  
02247    return(i);
02248 }

static int ast2vpbformat ( int  ast_format  )  [inline, static]

Definition at line 2188 of file chan_vpb.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, and AST_FORMAT_ULAW.

Referenced by do_chanreads(), and vpb_write().

02189 {
02190    switch(ast_format) {
02191       case AST_FORMAT_ALAW:
02192          return VPB_ALAW;
02193       case AST_FORMAT_SLINEAR:
02194          return VPB_LINEAR;
02195       case AST_FORMAT_ULAW:
02196          return VPB_MULAW;
02197       case AST_FORMAT_ADPCM:
02198          return VPB_OKIADPCM;
02199       default:
02200          return -1;
02201    }
02202 }

static char* ast2vpbformatname ( int  ast_format  )  [inline, static]

Definition at line 2204 of file chan_vpb.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, and AST_FORMAT_ULAW.

Referenced by do_chanreads(), and vpb_write().

02205 {
02206    switch(ast_format) {
02207       case AST_FORMAT_ALAW:
02208          return "AST_FORMAT_ALAW:VPB_ALAW";
02209       case AST_FORMAT_SLINEAR:
02210          return "AST_FORMAT_SLINEAR:VPB_LINEAR";
02211       case AST_FORMAT_ULAW:
02212          return "AST_FORMAT_ULAW:VPB_MULAW";
02213       case AST_FORMAT_ADPCM:
02214          return "AST_FORMAT_ADPCM:VPB_OKIADPCM";
02215       default:
02216          return "UNKN:UNKN";
02217    }
02218 }

AST_MUTEX_DEFINE_STATIC ( bridge_lock   ) 

AST_MUTEX_DEFINE_STATIC ( monlock   ) 

AST_MUTEX_DEFINE_STATIC ( iflock   ) 

AST_MUTEX_DEFINE_STATIC ( usecnt_lock   ) 

static int astformatbits ( int  ast_format  )  [inline, static]

Definition at line 2220 of file chan_vpb.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, and AST_FORMAT_ULAW.

Referenced by do_chanreads().

02221 {
02222    switch(ast_format) {
02223       case AST_FORMAT_ALAW:
02224       case AST_FORMAT_ULAW:
02225          return 8;
02226       case AST_FORMAT_SLINEAR:
02227          return 16;
02228       case AST_FORMAT_ADPCM:
02229          return 4;
02230       default:
02231          return 8;
02232    }   
02233 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 3042 of file chan_vpb.c.

References desc.

03043 {
03044    return (char *) desc;
03045 }

static void * do_chanreads ( void *  pvt  )  [static]

Definition at line 2353 of file chan_vpb.c.

References ast_channel::_bridge, ast_channel::_state, a_gain_vector(), ast2vpbformat(), ast2vpbformatname(), AST_BRIDGE_REC_CHANNEL_0, AST_BRIDGE_REC_CHANNEL_1, ast_dsp_process(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), AST_STATE_UP, ast_verbose(), astformatbits(), vpb_pvt::bridge, vpb_pvt::buf, vpb_bridge_t::c0, vpb_bridge_t::c1, ast_frame::data, ast_frame::datalen, ast_frame::delivery, vpb_pvt::dev, vpb_bridge_t::flags, fmt, vpb_pvt::fr, ast_frame::frametype, vpb_pvt::handle, vpb_pvt::last_ignore_dtmf, vpb_pvt::lastinput, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, MAX_VPB_GAIN, ast_channel::name, ast_frame::offset, option_verbose, vpb_pvt::owner, pbx_builtin_getvar_helper(), vpb_pvt::play_dtmf, vpb_pvt::play_dtmf_lock, ast_channel::rawreadformat, vpb_pvt::read_state, vpb_pvt::record_lock, vpb_pvt::rxswgain, ast_frame::samples, ast_frame::src, vpb_pvt::stopreads, ast_frame::subclass, type, use_ast_dtmfdet, vpb_pvt::vad, VERBOSE_PREFIX_2, VPB_EVENTS_ALL, VPB_EVENTS_NODTMF, and VPB_SAMPLES.

Referenced by vpb_answer(), and vpb_call().

02354 {
02355    struct vpb_pvt *p = (struct vpb_pvt *)pvt;
02356    struct ast_frame *fr = &p->fr;
02357    char *readbuf = ((char *)p->buf) + AST_FRIENDLY_OFFSET;
02358    int bridgerec = 0;
02359    int afmt, readlen, res, fmt, trycnt=0;
02360    int ignore_dtmf;
02361    char * getdtmf_var = NULL;
02362 
02363    fr->frametype = AST_FRAME_VOICE;
02364    fr->src = (char *)type;
02365    fr->mallocd = 0;
02366    fr->delivery.tv_sec = 0;
02367    fr->delivery.tv_usec = 0;
02368    fr->samples = VPB_SAMPLES;
02369    fr->offset = AST_FRIENDLY_OFFSET;
02370    memset(p->buf, 0, sizeof p->buf);
02371 
02372    if (option_verbose > 2) {
02373       ast_verbose("%s: chanreads: starting thread\n", p->dev);
02374    }  
02375    ast_mutex_lock(&p->record_lock);
02376 
02377    p->stopreads = 0; 
02378    p->read_state = 1;
02379    while (!p->stopreads && p->owner) {
02380 
02381       if (option_verbose > 4)
02382          ast_verbose("%s: chanreads: Starting cycle ...\n", p->dev);
02383       if (option_verbose > 4)
02384          ast_verbose("%s: chanreads: Checking bridge \n", p->dev);
02385       if (p->bridge) {
02386          if (p->bridge->c0 == p->owner && (p->bridge->flags & AST_BRIDGE_REC_CHANNEL_0))
02387             bridgerec = 1;
02388          else if (p->bridge->c1 == p->owner && (p->bridge->flags & AST_BRIDGE_REC_CHANNEL_1))
02389             bridgerec = 1;
02390          else 
02391             bridgerec = 0;
02392       } else {
02393          if (option_verbose > 4)
02394             ast_verbose("%s: chanreads: No native bridge.\n", p->dev);
02395          if (p->owner->_bridge){
02396             if (option_verbose > 4){
02397                ast_verbose("%s: chanreads: Got Asterisk bridge with [%s].\n", p->dev,p->owner->_bridge->name);
02398             }
02399             bridgerec = 1;
02400          }
02401          else {
02402             bridgerec = 0;
02403          }
02404       }
02405 
02406 /*    if ( (p->owner->_state != AST_STATE_UP) || !bridgerec) */
02407       if ( (p->owner->_state != AST_STATE_UP) ) 
02408       {
02409          if (option_verbose > 4) {
02410             if (p->owner->_state != AST_STATE_UP)
02411                ast_verbose("%s: chanreads: Im not up[%d]\n", p->dev,p->owner->_state);
02412             else
02413                ast_verbose("%s: chanreads: No bridgerec[%d]\n", p->dev,bridgerec);
02414          }  
02415          vpb_sleep(10);
02416          continue;
02417       }
02418 
02419       /* Voicetronix DTMF detection can be triggered off ordinary speech
02420        * This leads to annoying beeps during the conversation
02421        * Avoid this problem by just setting VPB_GETDTMF when you want to listen for DTMF
02422        */
02423       /* ignore_dtmf = 1; */
02424       ignore_dtmf = 0; /* set this to 1 to turn this feature on */
02425       getdtmf_var = pbx_builtin_getvar_helper(p->owner,"VPB_GETDTMF");
02426       if( getdtmf_var && ( strcasecmp( getdtmf_var, "yes" ) == 0 ) )
02427          ignore_dtmf = 0;
02428 
02429       if(( ignore_dtmf != p->last_ignore_dtmf ) &&(!use_ast_dtmfdet)){
02430          if(option_verbose>1) 
02431             ast_verbose( VERBOSE_PREFIX_2 "%s:Now %s DTMF \n",
02432                p->dev, ignore_dtmf ? "ignoring" : "listening for");
02433          vpb_set_event_mask(p->handle, ignore_dtmf ? VPB_EVENTS_NODTMF : VPB_EVENTS_ALL );
02434       }
02435       p->last_ignore_dtmf = ignore_dtmf;
02436 
02437       /* Play DTMF digits here to avoid problem you get if playing a digit during 
02438        * a record operation
02439        */
02440       if (option_verbose > 5) {
02441          ast_verbose("%s: chanreads: Checking dtmf's \n", p->dev);
02442       }  
02443       ast_mutex_lock(&p->play_dtmf_lock);
02444       if( p->play_dtmf[0] ) {
02445          /* Try to ignore DTMF event we get after playing digit */
02446          /* This DTMF is played by asterisk and leads to an annoying trailing beep on CISCO phones */
02447          if( !ignore_dtmf) 
02448             vpb_set_event_mask(p->handle, VPB_EVENTS_NODTMF );
02449          if (p->bridge == NULL){
02450             vpb_dial_sync(p->handle,p->play_dtmf);
02451             if(option_verbose>1) 
02452                ast_verbose( VERBOSE_PREFIX_2 "%s: chanreads: Played DTMF %s\n",p->dev,p->play_dtmf);
02453          }
02454          else {
02455             if (option_verbose > 1) 
02456                ast_verbose(VERBOSE_PREFIX_2 "%s: chanreads: Not playing DTMF frame on native bridge\n", p->dev);
02457          }
02458          p->play_dtmf[0] = '\0';
02459          ast_mutex_unlock(&p->play_dtmf_lock);
02460          vpb_sleep(700); /* Long enough to miss echo and DTMF event */
02461          if( !ignore_dtmf) 
02462             vpb_set_event_mask(p->handle, VPB_EVENTS_ALL );
02463          continue;
02464       }
02465       ast_mutex_unlock(&p->play_dtmf_lock);
02466 
02467 /*    afmt = (p->owner) ? p->owner->rawreadformat : AST_FORMAT_SLINEAR; */
02468       if (p->owner){
02469          afmt = p->owner->rawreadformat;
02470 /*       ast_log(LOG_DEBUG,"%s: Record using owner format [%s]\n", p->dev, ast2vpbformatname(afmt)); */
02471       }
02472       else {
02473          afmt = AST_FORMAT_SLINEAR;
02474 /*       ast_log(LOG_DEBUG,"%s: Record using default format [%s]\n", p->dev, ast2vpbformatname(afmt)); */
02475       }
02476       fmt = ast2vpbformat(afmt);
02477       if (fmt < 0) {
02478          ast_log(LOG_WARNING,"%s: Record failure (unsupported format %d)\n", p->dev, afmt);
02479          return NULL;
02480       }
02481       readlen = VPB_SAMPLES * astformatbits(afmt) / 8;
02482 
02483       if (p->lastinput == -1) {
02484          vpb_record_buf_start(p->handle, fmt);
02485          vpb_reset_record_fifo_alarm(p->handle);
02486          p->lastinput = fmt;
02487          if(option_verbose>1) 
02488             ast_verbose( VERBOSE_PREFIX_2 "%s: Starting record mode (codec=%d)[%s]\n",p->dev,fmt,ast2vpbformatname(afmt));
02489          continue;
02490       } else if (p->lastinput != fmt) {
02491          vpb_record_buf_finish(p->handle);
02492          vpb_record_buf_start(p->handle, fmt);
02493          p->lastinput = fmt;
02494          if(option_verbose>1) 
02495             ast_verbose( VERBOSE_PREFIX_2 "%s: Changed record format (%d=>%d)\n",p->dev,p->lastinput,fmt);
02496          continue;
02497       }
02498 
02499       /* Read only if up and not bridged, or a bridge for which we can read. */
02500       if (option_verbose > 5) {
02501          ast_verbose("%s: chanreads: getting buffer!\n", p->dev);
02502       }  
02503       if( (res = vpb_record_buf_sync(p->handle, readbuf, readlen) ) == VPB_OK ) {
02504          if (option_verbose > 5) {
02505             ast_verbose("%s: chanreads: got buffer!\n", p->dev);
02506          }  
02507          /* Apply extra gain ! */
02508          if( p->rxswgain > MAX_VPB_GAIN )
02509             a_gain_vector(p->rxswgain - MAX_VPB_GAIN , (short*)readbuf, readlen/sizeof(short));
02510          if (option_verbose > 5) {
02511             ast_verbose("%s: chanreads: applied gain\n", p->dev);
02512          }  
02513 
02514          fr->subclass = afmt;
02515          fr->data = readbuf;
02516          fr->datalen = readlen;
02517          fr->frametype = AST_FRAME_VOICE;
02518 
02519          if ((use_ast_dtmfdet)&&(p->vad)){
02520             fr = ast_dsp_process(p->owner,p->vad,fr);
02521             if (fr && (fr->frametype == AST_FRAME_DTMF))
02522                ast_log(LOG_DEBUG, "%s: chanreads: Detected DTMF '%c'\n",p->dev, fr->subclass);
02523             if (fr->subclass == 'm'){
02524                /* conf mute request */
02525                fr->frametype = AST_FRAME_NULL;
02526                fr->subclass = 0;
02527             }
02528             else if (fr->subclass == 'u'){
02529                /* Unmute */
02530                fr->frametype = AST_FRAME_NULL;
02531                fr->subclass = 0;
02532             }
02533             else if (fr->subclass == 'f'){
02534             }
02535          }
02536          /* Using trylock here to prevent deadlock when channel is hungup
02537           * (ast_hangup() immediately gets lock)
02538           */
02539          if (p->owner && !p->stopreads ) {
02540             if (option_verbose > 5) {
02541                ast_verbose("%s: chanreads: queueing buffer on read frame q (state[%d])\n", p->dev,p->owner->_state);
02542             }  
02543             do {
02544                res = ast_mutex_trylock(&p->owner->lock);
02545                trycnt++;
02546             } while((res !=0)&&(trycnt<300));
02547             if (res==0)  {
02548                ast_queue_frame(p->owner, fr);
02549                ast_mutex_unlock(&p->owner->lock);
02550             } else {
02551                if (option_verbose > 4) 
02552                   ast_verbose("%s: chanreads: Couldnt get lock after %d tries!\n", p->dev,trycnt);
02553             }
02554             trycnt=0;
02555             
02556 /*
02557             res = ast_mutex_trylock(&p->owner->lock);
02558             if (res==0)  {
02559                ast_queue_frame(p->owner, fr);
02560                ast_mutex_unlock(&p->owner->lock);
02561             } else {
02562                if (res == EINVAL )
02563                   if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EINVAL[%d]\n", p->dev,res);
02564                else if (res == EBUSY )
02565                   if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EBUSY[%d]\n", p->dev,res);
02566                while(res !=0){
02567                res = ast_mutex_trylock(&p->owner->lock);
02568                }
02569                if (res==0)  {
02570                   ast_queue_frame(p->owner, fr);
02571                   ast_mutex_unlock(&p->owner->lock);
02572                }
02573                else {
02574                   if (res == EINVAL )
02575                      if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EINVAL[%d]\n", p->dev,res);
02576                   else if (res == EBUSY )
02577                      if (option_verbose > 4) ast_verbose("%s: chanreads: try owner->lock gave me EBUSY[%d]\n", p->dev,res);
02578                   if (option_verbose > 4) ast_verbose("%s: chanreads: Couldnt get lock on owner[%s][%d][%d] channel to send frame!\n", p->dev,p->owner->name,(int)p->owner->lock.__m_owner,(int)p->owner->lock.__m_count);
02579                }
02580             }
02581 */
02582             if (option_verbose > 6) {
02583                short * data = (short*)readbuf;
02584                ast_verbose("%s: Read channel (codec=%d) %d %d\n", p->dev, fmt, data[0], data[1] );
02585             }  
02586          }
02587          else {
02588             if (option_verbose > 4) {
02589                ast_verbose("%s: p->stopreads[%d] p->owner[%p]\n", p->dev, p->stopreads,(void *)p->owner);
02590             }  
02591          }
02592       }
02593       if (option_verbose > 4)
02594          ast_verbose("%s: chanreads: Finished cycle...\n", p->dev);
02595    }
02596    p->read_state=0;
02597 
02598    /* When stopreads seen, go away! */
02599    vpb_record_buf_finish(p->handle);
02600    p->read_state=0;
02601    ast_mutex_unlock(&p->record_lock);
02602 
02603    if (option_verbose > 1)
02604       ast_verbose(VERBOSE_PREFIX_2 "%s: Ending record mode (%d/%s)\n",
02605           p->dev, p->stopreads, p->owner? "yes" : "no");     
02606    return NULL;
02607 }

static void* do_monitor ( void *  unused  )  [static]

Definition at line 1320 of file chan_vpb.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), vpb_pvt::dev, vpb_pvt::golock, vpb_pvt::handle, iflist, LOG_ERROR, LOG_WARNING, monitor_handle_notowned(), monitor_handle_owned(), vpb_pvt::next, option_verbose, vpb_pvt::owner, VERBOSE_PREFIX_2, VERBOSE_PREFIX_4, VPB_NULL_EVENT, and VPB_WAIT_TIMEOUT.

01321 {
01322 
01323    /* Monitor thread, doesn't die until explicitly killed. */
01324 
01325    if (option_verbose > 1) 
01326       ast_verbose(VERBOSE_PREFIX_2 "Starting vpb monitor thread[%ld]\n",
01327    pthread_self());
01328 
01329    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
01330 
01331    for(;;) {
01332       VPB_EVENT e;
01333       VPB_EVENT je;
01334       char str[VPB_MAX_STR];
01335       struct vpb_pvt *p;
01336 
01337       /*
01338       if (option_verbose > 3)
01339            ast_verbose(VERBOSE_PREFIX_4 "Monitor waiting for event\n");
01340       */
01341 
01342       int res = vpb_get_event_sync(&e, VPB_WAIT_TIMEOUT);
01343       if( (res==VPB_NO_EVENTS) || (res==VPB_TIME_OUT) ){
01344          /*
01345          if (option_verbose > 3){
01346             if (res ==  VPB_NO_EVENTS){
01347                ast_verbose(VERBOSE_PREFIX_4 "No events....\n");
01348             } else {
01349                ast_verbose(VERBOSE_PREFIX_4 "No events, timed out....\n");
01350             }
01351          }
01352          */
01353          continue;
01354       }
01355 
01356       if (res != VPB_OK) {
01357          ast_log(LOG_ERROR,"Monitor get event error %s\n", vpb_strerror(res) );
01358          ast_verbose("Monitor get event error %s\n", vpb_strerror(res) );
01359          continue;
01360       }
01361 
01362       str[0] = 0;
01363 
01364       p = NULL;
01365 
01366       ast_mutex_lock(&monlock); {
01367 
01368          if (e.type == VPB_NULL_EVENT) {
01369             if (option_verbose > 3)
01370                ast_verbose(VERBOSE_PREFIX_4 "Monitor got null event\n");
01371          }
01372          else {
01373             vpb_translate_event(&e, str);
01374             if (strlen(str)>1){
01375                str[(strlen(str)-1)]='\0';
01376             }
01377 
01378             ast_mutex_lock(&iflock); {
01379                p = iflist;
01380                while (p && p->handle != e.handle)
01381                   p = p->next;
01382             } ast_mutex_unlock(&iflock);
01383 
01384             if (p && (option_verbose > 3))
01385                ast_verbose(VERBOSE_PREFIX_4 "%s: Event [%d=>%s] \n", 
01386                   p ? p->dev : "null", e.type, str );
01387          }
01388 
01389       } ast_mutex_unlock(&monlock); 
01390 
01391       if (!p) {
01392          if (e.type != VPB_NULL_EVENT){
01393             ast_log(LOG_WARNING, "Got event [%s][%d], no matching iface!\n", str,e.type);    
01394             if (option_verbose > 3){
01395                ast_verbose(VERBOSE_PREFIX_4 "vpb/ERR: No interface for Event [%d=>%s] \n",e.type,str );
01396             }
01397          }
01398          continue;
01399       } 
01400 
01401       /* flush the event from the channel event Q */
01402       vpb_get_event_ch_async(e.handle,&je);
01403       if (option_verbose > 4){
01404          vpb_translate_event(&je, str);
01405          ast_verbose("%s: Flushing event [%d]=>%s\n",p->dev,je.type,str);
01406       }
01407 
01408       /* Check for ownership and locks */
01409       if ((p->owner)&&(!p->golock)){
01410          /* Need to get owner lock */
01411          /* Safely grab both p->lock and p->owner->lock so that there
01412          cannot be a race with something from the other side */
01413          /*
01414          ast_mutex_lock(&p->lock);
01415          while(ast_mutex_trylock(&p->owner->lock)) {
01416             ast_mutex_unlock(&p->lock);
01417             usleep(1);
01418             ast_mutex_lock(&p->lock);
01419             if (!p->owner)
01420                break;
01421          }
01422          if (p->owner)
01423             p->golock=1;
01424          */
01425       }
01426       /* Two scenarios: Are you owned or not. */
01427       if (p->owner) {
01428          monitor_handle_owned(p, &e);
01429       } else {
01430          monitor_handle_notowned(p, &e);
01431       }
01432       /* if ((!p->owner)&&(p->golock)){
01433          ast_mutex_unlock(&p->owner->lock);
01434          ast_mutex_unlock(&p->lock);
01435       }
01436       */
01437 
01438    }
01439 
01440    return NULL;
01441 }

static void get_callerid ( struct vpb_pvt p  )  [static]

Definition at line 616 of file chan_vpb.c.

References ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_verbose(), vpb_pvt::buf, vpb_pvt::callerid, ast_channel::cid, CID_MSECS, ast_callerid::cid_name, vpb_pvt::cid_name, ast_callerid::cid_num, vpb_pvt::cid_num, vpb_pvt::dev, vpb_pvt::handle, LOG_ERROR, option_verbose, vpb_pvt::owner, vpb_pvt::record_lock, RING_SKIP, and VERBOSE_PREFIX_4.

Referenced by monitor_handle_notowned().

00617 {
00618    short buf[CID_MSECS*8]; /* 8kHz sampling rate */
00619    struct timeval cid_record_time;
00620    int rc;
00621    struct ast_channel *owner = p->owner;
00622 /*
00623    char callerid[AST_MAX_EXTENSION] = ""; 
00624 */
00625 #ifdef ANALYSE_CID
00626    void * ws;
00627    char * file="cidsams.wav";
00628 #endif
00629 
00630 
00631    if( ast_mutex_trylock(&p->record_lock) == 0 ) {
00632 
00633       cid_record_time = ast_tvnow();
00634       if (option_verbose>3) 
00635          ast_verbose(VERBOSE_PREFIX_4 "CID record - start\n");
00636 
00637       /* Skip any trailing ringtone */
00638       if (UsePolarityCID != 1){
00639          vpb_sleep(RING_SKIP);
00640       }
00641 
00642       if (option_verbose>3) 
00643          ast_verbose(VERBOSE_PREFIX_4 "CID record - skipped %ldms trailing ring\n",
00644              ast_tvdiff_ms(ast_tvnow(), cid_record_time));
00645       cid_record_time = ast_tvnow();
00646 
00647       /* Record bit between the rings which contains the callerid */
00648       vpb_record_buf_start(p->handle, VPB_LINEAR);
00649       rc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));
00650       vpb_record_buf_finish(p->handle);
00651 #ifdef ANALYSE_CID
00652       vpb_wave_open_write(&ws, file, VPB_LINEAR);
00653       vpb_wave_write(ws,(char*)buf,sizeof(buf));
00654       vpb_wave_close_write(ws);
00655 #endif
00656 
00657       if (option_verbose>3) 
00658          ast_verbose(VERBOSE_PREFIX_4 "CID record - recorded %ldms between rings\n", 
00659              ast_tvdiff_ms(ast_tvnow(), cid_record_time));
00660 
00661       ast_mutex_unlock(&p->record_lock);
00662 
00663       if( rc != VPB_OK ) {
00664          ast_log(LOG_ERROR, "Failed to record caller id sample on %s\n", p->dev );
00665          return;
00666       }
00667 
00668       VPB_CID *cli_struct = new VPB_CID;
00669       cli_struct->ra_cldn[0]=0;
00670       cli_struct->ra_cn[0]=0;
00671       /* This decodes FSK 1200baud type callerid */
00672       if ((rc=vpb_cid_decode2(cli_struct, buf, CID_MSECS*8)) == VPB_OK ) {
00673          /*
00674          if (owner->cid.cid_num)
00675             free(owner->cid.cid_num);
00676          owner->cid.cid_num=NULL;
00677          if (owner->cid.cid_name)
00678             free(owner->cid.cid_name);
00679          owner->cid.cid_name=NULL;
00680          */
00681          
00682          if (cli_struct->ra_cldn[0]=='\0'){
00683             /*
00684             owner->cid.cid_num = strdup(cli_struct->cldn);
00685             owner->cid.cid_name = strdup(cli_struct->cn);
00686             */
00687             if (owner){
00688                ast_set_callerid(owner, cli_struct->cldn, cli_struct->cn, cli_struct->cldn);
00689             } else {
00690                strcpy(p->cid_num, cli_struct->cldn);
00691                strcpy(p->cid_name, cli_struct->cn);
00692 
00693             }
00694             if (option_verbose>3) 
00695                ast_verbose(VERBOSE_PREFIX_4 "CID record - got [%s] [%s]\n",owner->cid.cid_num,owner->cid.cid_name );
00696             snprintf(p->callerid,sizeof(p->callerid)-1,"%s %s",cli_struct->cldn,cli_struct->cn);
00697          }
00698          else {
00699             ast_log(LOG_ERROR,"CID record - No caller id avalable on %s \n", p->dev);
00700          }
00701 
00702       } else {
00703          ast_log(LOG_ERROR, "CID record - Failed to decode caller id on %s - %s\n", p->dev, vpb_strerror(rc) );
00704          strncpy(p->callerid,"unknown", sizeof(p->callerid) - 1);
00705       }
00706       delete cli_struct;
00707 
00708    } else 
00709       ast_log(LOG_ERROR, "CID record - Failed to set record mode for caller id on %s\n", p->dev );
00710 }

static void get_callerid_ast ( struct vpb_pvt p  )  [static]

Definition at line 712 of file chan_vpb.c.

References AST_FORMAT_ULAW, ast_log(), ast_shrink_phone_number(), ast_strlen_zero(), ast_verbose(), vpb_pvt::callerid, callerid_feed(), callerid_free(), callerid_get(), callerid_new(), vpb_pvt::callerid_type, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, CID_SIG_BELL, CID_SIG_V23, vpb_pvt::dev, callerid_state::flags, free, vpb_pvt::handle, LOG_ERROR, name, callerid_state::number, option_verbose, vpb_pvt::owner, strdup, VERBOSE_PREFIX_1, and VERBOSE_PREFIX_4.

Referenced by monitor_handle_notowned().

00713 {
00714    struct callerid_state *cs;
00715    char buf[1024];
00716    char *name=NULL, *number=NULL;
00717    int flags;
00718    int rc=0,vrc;
00719    int sam_count=0;
00720    struct ast_channel *owner = p->owner;
00721    int which_cid;
00722 /*
00723    float old_gain;
00724 */
00725 #ifdef ANALYSE_CID
00726    void * ws;
00727    char * file="cidsams.wav";
00728 #endif
00729 
00730    if(p->callerid_type == 1) {
00731    if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collected caller ID already\n");
00732       return;
00733    }
00734    else if(p->callerid_type == 2 ) {
00735       which_cid=CID_SIG_V23;
00736    if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collecting Caller ID v23...\n");
00737    }
00738    else if(p->callerid_type == 3) {
00739       which_cid=CID_SIG_BELL;
00740    if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collecting Caller ID bell...\n");
00741    }
00742    else {
00743       if (option_verbose>3) 
00744          ast_verbose(VERBOSE_PREFIX_4 "Caller ID disabled\n");
00745       return;
00746    }
00747 /* vpb_sleep(RING_SKIP); */
00748 /* vpb_record_get_gain(p->handle, &old_gain); */
00749    cs = callerid_new(which_cid);
00750    if (cs){
00751 #ifdef ANALYSE_CID
00752       vpb_wave_open_write(&ws, file, VPB_MULAW); 
00753       vpb_record_set_gain(p->handle, 3.0); 
00754       vpb_record_set_hw_gain(p->handle,12.0); 
00755 #endif
00756       vpb_record_buf_start(p->handle, VPB_MULAW);
00757       while((rc == 0)&&(sam_count<8000*3)){
00758          vrc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));
00759          if (vrc != VPB_OK)
00760             ast_log(LOG_ERROR, "%s: Caller ID couldnt read audio buffer!\n",p->dev);
00761          rc = callerid_feed(cs,(unsigned char *)buf,sizeof(buf),AST_FORMAT_ULAW);
00762 #ifdef ANALYSE_CID
00763          vpb_wave_write(ws,(char*)buf,sizeof(buf)); 
00764 #endif
00765          sam_count+=sizeof(buf);
00766          if (option_verbose>3) ast_verbose(VERBOSE_PREFIX_4 "Collecting Caller ID samples [%d][%d]...\n",sam_count,rc);
00767       }
00768       vpb_record_buf_finish(p->handle);
00769 #ifdef ANALYSE_CID
00770       vpb_wave_close_write(ws); 
00771 #endif
00772       if (rc == 1){
00773          callerid_get(cs, &name, &number, &flags);
00774          if (option_verbose>0) 
00775             ast_verbose(VERBOSE_PREFIX_1 "%s: Caller ID name [%s] number [%s] flags [%d]\n",p->dev,name, number,flags);
00776       }
00777       else {
00778          ast_log(LOG_ERROR, "%s: Failed to decode Caller ID \n", p->dev );
00779       }
00780 /*    vpb_record_set_gain(p->handle, old_gain); */
00781 /*    vpb_record_set_hw_gain(p->handle,6.0); */
00782    }
00783    else {
00784       ast_log(LOG_ERROR, "%s: Failed to create Caller ID struct\n", p->dev );
00785    }
00786    if (owner->cid.cid_num) {
00787       free(owner->cid.cid_num);
00788       owner->cid.cid_num = NULL;
00789    }
00790    if (owner->cid.cid_name) {
00791       free(owner->cid.cid_name);
00792       owner->cid.cid_name = NULL;
00793    }
00794    if (number)
00795       ast_shrink_phone_number(number);
00796    if (!ast_strlen_zero(number)) {
00797       owner->cid.cid_num = strdup(number);
00798       owner->cid.cid_ani = strdup(number);
00799       if (!ast_strlen_zero(name)){
00800          owner->cid.cid_name = strdup(name);
00801          snprintf(p->callerid,(sizeof(p->callerid)-1),"%s %s",number,name);
00802       }
00803       else {
00804          snprintf(p->callerid,(sizeof(p->callerid)-1),"%s",number);
00805       }
00806    }
00807                                                
00808    if (cs)
00809       callerid_free(cs);
00810 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 3047 of file chan_vpb.c.

References ASTERISK_GPL_KEY.

03048 {
03049    return ASTERISK_GPL_KEY;
03050 }

int load_module ( void   ) 

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.
TE STUFF END

Definition at line 2775 of file chan_vpb.c.

References ast_channel_register(), ast_config_destroy(), ast_config_load(), ast_get_group(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_variable_browse(), break_for_dtmf, vpb_pvt::callerid, vpb_pvt::callgroup, cfg, config, context, DEFAULT_ECHO_CANCEL, DEFAULT_GAIN, dtmf_idd, ec_supp_threshold, error(), group, gruntdetect_timeout, iflist, language, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mkbrd(), mkif(), vpb_pvt::mode, MODE_DIALTONE, MODE_FXO, MODE_IMMEDIATE, ast_variable::name, vpb_pvt::next, ast_variable::next, parse_gain_value(), vpb_pvt::pickupgroup, relaxdtmf, restart_monitor(), vpb_pvt::rxgain, vpb_pvt::rxswgain, strdup, timer_period_ring, vpb_pvt::txgain, vpb_pvt::txswgain, type, unload_module(), use_ast_dtmf, use_ast_dtmfdet, use_ast_ind, UseLoopDrop, UseNativeBridge, UsePolarityCID, ast_variable::value, VPB_GOT_RXHWG, VPB_GOT_RXSWG, VPB_GOT_TXHWG, VPB_GOT_TXSWG, vpb_pvt::vpb_model, vpb_tech, and vpb_tech_indicate.

02776 {
02777    struct ast_config *cfg;
02778    struct ast_variable *v;
02779    struct vpb_pvt *tmp;
02780    int board = 0, group = 0;
02781    ast_group_t callgroup = 0;
02782    ast_group_t pickupgroup = 0;
02783    int mode = MODE_IMMEDIATE;
02784    float txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; 
02785    float txswgain = 0, rxswgain = 0; 
02786    int got_gain=0;
02787    int first_channel = 1;
02788    int echo_cancel = DEFAULT_ECHO_CANCEL;
02789    int error = 0; /* Error flag */
02790    int bal1 = -1; /* Special value - means do not set */
02791    int bal2 = -1; 
02792    int bal3 = -1;
02793    char * callerid = NULL;
02794 
02795    cfg = ast_config_load(config);
02796 
02797    /* We *must* have a config file otherwise stop immediately */
02798    if (!cfg) {
02799       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
02800       return -1;
02801    }  
02802 
02803    vpb_seterrormode(VPB_ERROR_CODE);
02804 
02805    ast_mutex_lock(&iflock); {
02806       v = ast_variable_browse(cfg, "general");
02807       while (v){
02808          if (strcasecmp(v->name, "cards") == 0) {
02809             ast_log(LOG_NOTICE,"VPB Driver configured to use [%d] cards\n",atoi(v->value));
02810          }
02811          else if (strcasecmp(v->name, "indication") == 0) {
02812             use_ast_ind = 1;
02813             ast_log(LOG_NOTICE,"VPB driver using Asterisk Indication functions!\n");
02814          }
02815          else if (strcasecmp(v->name, "break-for-dtmf") == 0) {
02816             if (ast_true(v->value)){
02817                break_for_dtmf = 1;
02818             }
02819             else {
02820                break_for_dtmf = 0;
02821                ast_log(LOG_NOTICE,"VPB driver not stopping for DTMF's in native bridge\n");
02822             }
02823          }
02824          else if (strcasecmp(v->name, "ast-dtmf") == 0) {
02825             use_ast_dtmf = 1;
02826             ast_log(LOG_NOTICE,"VPB driver using Asterisk DTMF play functions!\n");
02827          }
02828          else if (strcasecmp(v->name, "ast-dtmf-det") == 0) {
02829             use_ast_dtmfdet = 1;
02830             ast_log(LOG_NOTICE,"VPB driver using Asterisk DTMF detection functions!\n");
02831          }
02832          else if (strcasecmp(v->name, "relaxdtmf") == 0) {
02833             relaxdtmf = 1;
02834             ast_log(LOG_NOTICE,"VPB driver using Relaxed DTMF with Asterisk DTMF detections functions!\n");
02835          }
02836          else if (strcasecmp(v->name, "timer_period_ring") ==0) {
02837             timer_period_ring = atoi(v->value);
02838          }
02839          else if (strcasecmp(v->name, "ecsuppthres") ==0) {
02840             ec_supp_threshold = atoi(v->value);
02841          }
02842          else if (strcasecmp(v->name, "dtmfidd") ==0) {
02843             dtmf_idd = atoi(v->value);
02844             ast_log(LOG_NOTICE,"VPB Driver setting DTMF IDD to [%d]ms\n",dtmf_idd);
02845          }
02846          v = v->next;
02847       }
02848    
02849       v = ast_variable_browse(cfg, "interfaces");
02850       while(v) {
02851          /* Create the interface list */
02852          if (strcasecmp(v->name, "board") == 0) {
02853             board = atoi(v->value);
02854          } else  if (strcasecmp(v->name, "group") == 0){
02855             group = atoi(v->value);
02856          } else  if (strcasecmp(v->name, "callgroup") == 0){
02857             callgroup = ast_get_group(v->value);
02858          } else  if (strcasecmp(v->name, "pickupgroup") == 0){
02859             pickupgroup = ast_get_group(v->value);
02860          } else  if (strcasecmp(v->name, "usepolaritycid") == 0){
02861             UsePolarityCID = atoi(v->value);
02862          } else  if (strcasecmp(v->name, "useloopdrop") == 0){
02863             UseLoopDrop = atoi(v->value);
02864          } else  if (strcasecmp(v->name, "usenativebridge") == 0){
02865             UseNativeBridge = atoi(v->value);
02866          } else if (strcasecmp(v->name, "channel") == 0) {
02867             int channel = atoi(v->value);
02868             tmp = mkif(board, channel, mode, got_gain, txgain, rxgain, txswgain, rxswgain, bal1, bal2, bal3, callerid, echo_cancel,group,callgroup,pickupgroup);
02869             if (tmp) {
02870                if(first_channel) {
02871                   mkbrd( tmp->vpb_model, echo_cancel );
02872                   first_channel = 0;
02873                }
02874                tmp->next = iflist;
02875                iflist = tmp;
02876             } else {
02877                ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
02878                error = -1;
02879                goto done;
02880             }
02881          } else if (strcasecmp(v->name, "language") == 0) {
02882             strncpy(language, v->value, sizeof(language)-1);
02883          } else if (strcasecmp(v->name, "callerid") == 0) {
02884             callerid = strdup(v->value);
02885          } else if (strcasecmp(v->name, "mode") == 0) {
02886             if (strncasecmp(v->value, "di", 2) == 0) 
02887                mode = MODE_DIALTONE;
02888             else if (strncasecmp(v->value, "im", 2) == 0)
02889                mode = MODE_IMMEDIATE;
02890             else if (strncasecmp(v->value, "fx", 2) == 0)
02891                mode = MODE_FXO;
02892             else
02893                ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
02894          } else if (!strcasecmp(v->name, "context")) {
02895             strncpy(context, v->value, sizeof(context)-1);
02896          } else if (!strcasecmp(v->name, "echocancel")) {
02897             if (!strcasecmp(v->value, "off")) 
02898                echo_cancel = 0;
02899          } else if (strcasecmp(v->name, "txgain") == 0) {
02900             txswgain = parse_gain_value(v->name, v->value);
02901             got_gain |=VPB_GOT_TXSWG;
02902          } else if (strcasecmp(v->name, "rxgain") == 0) {
02903             rxswgain = parse_gain_value(v->name, v->value);
02904             got_gain |=VPB_GOT_RXSWG;
02905          } else if (strcasecmp(v->name, "txhwgain") == 0) {
02906             txgain = parse_gain_value(v->name, v->value);
02907             got_gain |=VPB_GOT_TXHWG;
02908          } else if (strcasecmp(v->name, "rxhwgain") == 0) {
02909             rxgain = parse_gain_value(v->name, v->value);
02910             got_gain |=VPB_GOT_RXHWG;
02911          } else if (strcasecmp(v->name, "bal1") == 0) {
02912             bal1 = strtol(v->value, NULL, 16);
02913             if(bal1<0 || bal1>255) {
02914                ast_log(LOG_WARNING, "Bad bal1 value: %d\n", bal1);
02915                bal1 = -1;
02916             }
02917          } else if (strcasecmp(v->name, "bal2") == 0) {
02918             bal2 = strtol(v->value, NULL, 16);
02919             if(bal2<0 || bal2>255) {
02920                ast_log(LOG_WARNING, "Bad bal2 value: %d\n", bal2);
02921                bal2 = -1;
02922             }
02923          } else if (strcasecmp(v->name, "bal3") == 0) {
02924             bal3 = strtol(v->value, NULL, 16);
02925             if(bal3<0 || bal3>255) {
02926                ast_log(LOG_WARNING, "Bad bal3 value: %d\n", bal3);
02927                bal3 = -1;
02928             }
02929          } else if (strcasecmp(v->name, "grunttimeout") == 0) {
02930             gruntdetect_timeout = 1000*atoi(v->value);
02931          }
02932          v = v->next;
02933       }
02934 
02935       if (gruntdetect_timeout < 1000)
02936          gruntdetect_timeout = 1000;
02937 
02938       done: (void)0;
02939    } ast_mutex_unlock(&iflock);
02940 
02941    ast_config_destroy(cfg);
02942 
02943    if (use_ast_ind == 1){
02944       if (!error && ast_channel_register(&vpb_tech_indicate) != 0) {
02945          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
02946          error = -1;
02947       }
02948       else {
02949          ast_log(LOG_NOTICE,"VPB driver Registered (w/AstIndication)\n");
02950       }
02951    }
02952    else {
02953       if (!error && ast_channel_register(&vpb_tech) != 0) {
02954          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
02955          error = -1;
02956       }
02957       else {
02958          ast_log(LOG_NOTICE,"VPB driver Registered )\n");
02959       }
02960    }
02961 
02962 
02963    if (error)
02964       unload_module();
02965    else 
02966       restart_monitor(); /* And start the monitor for the first time */
02967 
02968    return error;
02969 }

static void mkbrd ( vpb_model_t  model,
int  echo_cancel 
) [static]

Definition at line 1494 of file chan_vpb.c.

References ast_cond_init(), ast_log(), ast_mutex_init(), lock, LOG_ERROR, LOG_NOTICE, malloc, MAX_BRIDGES_V4PCI, and vpb_model_v4pci.

Referenced by load_module().

01495 {
01496    if(!bridges) {
01497       if(model==vpb_model_v4pci) 
01498          max_bridges = MAX_BRIDGES_V4PCI;
01499       bridges = (vpb_bridge_t *)malloc(max_bridges * sizeof(vpb_bridge_t) );
01500       if(!bridges) 
01501          ast_log(LOG_ERROR, "Failed to initialize bridges\n");
01502       else {
01503          memset(bridges,0,max_bridges * sizeof(vpb_bridge_t));
01504          for(int i = 0; i < max_bridges; i++ ) {
01505             ast_mutex_init(&bridges[i].lock);
01506             ast_cond_init(&bridges[i].cond, NULL);
01507          }
01508       }
01509    }
01510    if(!echo_cancel) {
01511       if (model==vpb_model_v4pci) {
01512          vpb_echo_canc_disable();
01513          ast_log(LOG_NOTICE, "Voicetronix echo cancellation OFF\n");
01514       } 
01515       else {
01516       /* need to it port by port for OpenSwitch*/
01517       }
01518    } else {
01519       if (model==vpb_model_v4pci) {
01520          vpb_echo_canc_enable();
01521          ast_log(LOG_NOTICE, "Voicetronix echo cancellation ON\n");
01522          if (ec_supp_threshold > -1){
01523             #ifdef VPB_PRI
01524             vpb_echo_canc_set_sup_thresh(0,(short *)&ec_supp_threshold);
01525             #else
01526             vpb_echo_canc_set_sup_thresh((short *)&ec_supp_threshold);
01527             #endif
01528             ast_log(LOG_NOTICE, "Voicetronix EC Sup Thres set\n");
01529          }
01530       }
01531       else {
01532       /* need to it port by port for OpenSwitch*/
01533       }
01534    }
01535 }

static struct vpb_pvt* mkif ( int  board,
int  channel,
int  mode,
int  gains,
float  txgain,
float  rxgain,
float  txswgain,
float  rxswgain,
int  bal1,
int  bal2,
int  bal3,
char *  callerid,
int  echo_cancel,
int  group,
ast_group_t  callgroup,
ast_group_t  pickupgroup 
) [static, read]

Definition at line 1537 of file chan_vpb.c.

References ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_features(), ast_log(), ast_mutex_init(), vpb_pvt::buf, vpb_pvt::busy_timer, vpb_pvt::busy_timer_id, vpb_pvt::callerid, vpb_pvt::callerid_type, vpb_pvt::callgroup, calloc, vpb_pvt::context, vpb_pvt::dev, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_DTMF_DETECT, vpb_pvt::dtmf_caller_pos, vpb_pvt::dtmfidd_timer, vpb_pvt::dtmfidd_timer_id, free, vpb_pvt::golock, vpb_pvt::group, vpb_pvt::handle, vpb_pvt::language, vpb_pvt::lock, LOG_NOTICE, LOG_WARNING, MAX_VPB_GAIN, MIN_VPB_GAIN, vpb_pvt::mode, MODE_FXO, vpb_pvt::owner_lock, vpb_pvt::pickupgroup, vpb_pvt::play_dtmf_lock, vpb_pvt::play_lock, vpb_pvt::read_state, vpb_pvt::record_lock, vpb_pvt::ring_timer, vpb_pvt::ring_timer_id, vpb_pvt::ringback_timer, vpb_pvt::ringback_timer_id, vpb_pvt::rxgain, vpb_pvt::rxswgain, TIMER_PERIOD_BUSY, TIMER_PERIOD_RINGBACK, vpb_pvt::txgain, vpb_pvt::txswgain, vpb_pvt::vad, VPB_EVENTS_ALL, VPB_EVENTS_NODTMF, VPB_EVENTS_STAT, VPB_GOT_RXHWG, VPB_GOT_RXSWG, VPB_GOT_TXHWG, VPB_GOT_TXSWG, vpb_pvt::vpb_model, vpb_model_unknown, vpb_model_v12pci, and vpb_model_v4pci.

01540 {
01541    struct vpb_pvt *tmp;
01542    char buf[64];
01543 
01544    tmp = (struct vpb_pvt *)calloc(1, sizeof *tmp);
01545 
01546    if (!tmp)
01547       return NULL;
01548 
01549    tmp->handle = vpb_open(board, channel);
01550 
01551    if (tmp->handle < 0) {    
01552       ast_log(LOG_WARNING, "Unable to create channel vpb/%d-%d: %s\n", 
01553                board, channel, strerror(errno));
01554       free(tmp);
01555       return NULL;
01556    }
01557           
01558    snprintf(tmp->dev, sizeof(tmp->dev), "vpb/%d-%d", board, channel);
01559 
01560    tmp->mode = mode;
01561 
01562    tmp->group = group;
01563    tmp->callgroup = callgroup;
01564    tmp->pickupgroup = pickupgroup;
01565 
01566    /* Initilize dtmf caller ID position variable */
01567    tmp->dtmf_caller_pos=0;
01568 
01569    strncpy(tmp->language, language, sizeof(tmp->language) - 1);
01570    strncpy(tmp->context, context, sizeof(tmp->context) - 1);
01571 
01572    tmp->callerid_type=0;
01573    if(callerid) { 
01574       if (strcasecmp(callerid,"on")==0){
01575          tmp->callerid_type =1;
01576          strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
01577       }
01578       else if (strcasecmp(callerid,"v23")==0){
01579          tmp->callerid_type =2;
01580          strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
01581       }
01582       else if (strcasecmp(callerid,"bell")==0){
01583          tmp->callerid_type =3;
01584          strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
01585       }
01586       else {
01587          strncpy(tmp->callerid, callerid, sizeof(tmp->callerid) - 1);
01588       }
01589    } else {
01590       strncpy(tmp->callerid, "unknown", sizeof(tmp->callerid) - 1);
01591    }
01592 
01593    /* check if codec balances have been set in the config file */
01594    if (bal3>=0) {
01595       if ((bal1>=0) && !(bal1 & 32)) bal1 |= 32;
01596          vpb_set_codec_reg(tmp->handle, 0x42, bal3);
01597    }
01598    if(bal1>=0) vpb_set_codec_reg(tmp->handle, 0x32, bal1);
01599    if(bal2>=0) vpb_set_codec_reg(tmp->handle, 0x3a, bal2);
01600 
01601    if (gains & VPB_GOT_TXHWG){
01602       if (txgain > MAX_VPB_GAIN){
01603          tmp->txgain = MAX_VPB_GAIN;
01604       }
01605       else if (txgain < MIN_VPB_GAIN){
01606          tmp->txgain = MIN_VPB_GAIN;
01607       }
01608       else {
01609          tmp->txgain = txgain;
01610       }
01611       
01612       ast_log(LOG_NOTICE,"VPB setting Tx Hw gain to [%f]\n",tmp->txgain);
01613       vpb_play_set_hw_gain(tmp->handle, tmp->txgain);
01614    }
01615 
01616    if (gains & VPB_GOT_RXHWG){
01617       if (rxgain > MAX_VPB_GAIN){
01618          tmp->rxgain = MAX_VPB_GAIN;
01619       }
01620       else if (rxgain < MIN_VPB_GAIN){
01621          tmp->rxgain = MIN_VPB_GAIN;
01622       }
01623       else {
01624          tmp->rxgain = rxgain;
01625       }
01626       ast_log(LOG_NOTICE,"VPB setting Rx Hw gain to [%f]\n",tmp->rxgain);
01627       vpb_record_set_hw_gain(tmp->handle,tmp->rxgain);
01628    }
01629 
01630    if (gains & VPB_GOT_TXSWG){
01631       tmp->txswgain = txswgain;
01632       ast_log(LOG_NOTICE,"VPB setting Tx Sw gain to [%f]\n",tmp->txswgain);
01633       vpb_play_set_gain(tmp->handle, tmp->txswgain);
01634    }
01635 
01636    if (gains & VPB_GOT_RXSWG){
01637       tmp->rxswgain = rxswgain;
01638       ast_log(LOG_NOTICE,"VPB setting Rx Sw gain to [%f]\n",tmp->rxswgain);
01639       vpb_record_set_gain(tmp->handle, tmp->rxswgain);
01640    }
01641 
01642    tmp->vpb_model = vpb_model_unknown;
01643    if( vpb_get_model(buf) == VPB_OK ) {
01644       if(strcmp(buf,"V12PCI")==0) 
01645          tmp->vpb_model = vpb_model_v12pci;
01646       else if(strcmp(buf,"VPB4")==0) 
01647          tmp->vpb_model = vpb_model_v4pci;
01648    }
01649 
01650    ast_mutex_init(&tmp->owner_lock);
01651    ast_mutex_init(&tmp->lock);
01652    ast_mutex_init(&tmp->record_lock);
01653    ast_mutex_init(&tmp->play_lock);
01654    ast_mutex_init(&tmp->play_dtmf_lock);
01655 
01656    /* set default read state */
01657    tmp->read_state = 0;
01658    
01659    tmp->golock=0;
01660 
01661    tmp->busy_timer_id = vpb_timer_get_unique_timer_id();
01662    vpb_timer_open(&tmp->busy_timer, tmp->handle, tmp->busy_timer_id, TIMER_PERIOD_BUSY);
01663 
01664    tmp->ringback_timer_id = vpb_timer_get_unique_timer_id();
01665    vpb_timer_open(&tmp->ringback_timer, tmp->handle, tmp->ringback_timer_id, TIMER_PERIOD_RINGBACK);
01666 
01667    tmp->ring_timer_id = vpb_timer_get_unique_timer_id();
01668    vpb_timer_open(&tmp->ring_timer, tmp->handle, tmp->ring_timer_id, timer_period_ring);
01669          
01670    tmp->dtmfidd_timer_id = vpb_timer_get_unique_timer_id();
01671    vpb_timer_open(&tmp->dtmfidd_timer, tmp->handle, tmp->dtmfidd_timer_id, dtmf_idd);
01672          
01673    if (mode == MODE_FXO){
01674       if (use_ast_dtmfdet)
01675          vpb_set_event_mask(tmp->handle, VPB_EVENTS_NODTMF );
01676       else
01677          vpb_set_event_mask(tmp->handle, VPB_EVENTS_ALL );
01678    }
01679    else {
01680 /*
01681       if (use_ast_dtmfdet)
01682          vpb_set_event_mask(tmp->handle, VPB_EVENTS_NODTMF );
01683       else
01684 */
01685          vpb_set_event_mask(tmp->handle, VPB_EVENTS_STAT );
01686    }
01687 
01688    if ((tmp->vpb_model == vpb_model_v12pci) && (echo_cancel)){
01689       vpb_hostecho_on(tmp->handle);
01690    }
01691    if (use_ast_dtmfdet) {
01692       tmp->vad = ast_dsp_new();
01693       ast_dsp_set_features(tmp->vad, DSP_FEATURE_DTMF_DETECT);
01694       ast_dsp_digitmode(tmp->vad, DSP_DIGITMODE_DTMF);
01695       if (relaxdtmf)
01696          ast_dsp_digitmode(tmp->vad, DSP_DIGITMODE_DTMF|DSP_DIGITMODE_RELAXDTMF);
01697    }
01698    else {
01699       tmp->vad = NULL;
01700    }
01701 
01702    /* define grunt tone */
01703    vpb_settonedet(tmp->handle,&toned_ungrunt);
01704 
01705    ast_log(LOG_NOTICE,"Voicetronix %s channel %s initialized (rxsg=%f/txsg=%f/rxhg=%f/txhg=%f)(0x%x/0x%x/0x%x)\n",
01706       (tmp->vpb_model==vpb_model_v4pci)?"V4PCI": (tmp->vpb_model==vpb_model_v12pci)?"V12PCI":"[Unknown model]",
01707       tmp->dev, tmp->rxswgain, tmp->txswgain, tmp->rxgain, tmp->txgain, bal1, bal2, bal3 );
01708 
01709    return tmp;
01710 }

static int monitor_handle_notowned ( struct vpb_pvt p,
VPB_EVENT *  e 
) [inline, static]

Definition at line 1103 of file chan_vpb.c.

References ast_channel::_state, ast_callerid_split(), ast_canmatch_extension(), ast_exists_extension(), ast_log(), AST_MAX_EXTENSION, ast_pickup_call(), ast_pickup_ext(), ast_set_callerid(), AST_STATE_RING, AST_STATE_UP, ast_verbose(), vpb_pvt::busy_timer, vpb_pvt::callerid, vpb_pvt::callerid_type, vpb_pvt::cid_name, cid_name, vpb_pvt::cid_num, cid_num, vpb_pvt::context, vpb_pvt::dev, vpb_pvt::dtmf_caller_pos, DTMF_CID_START, DTMF_CID_STOP, vpb_pvt::dtmfidd_timer, vpb_pvt::dtmfidd_timer_id, vpb_pvt::ext, get_callerid(), get_callerid_ast(), vpb_pvt::handle, LOG_ERROR, vpb_pvt::mode, MODE_DIALTONE, MODE_FXO, MODE_IMMEDIATE, option_verbose, vpb_pvt::owner, playtone(), vpb_pvt::ring_timer, vpb_pvt::ring_timer_id, s, vpb_pvt::state, stoptone(), VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, vpb_new(), VPB_STATE_GETDTMF, VPB_STATE_ONHOOK, VPB_STATE_PLAYBUSY, VPB_STATE_PLAYDIAL, and vpb_pvt::wantdtmf.

Referenced by do_monitor().

01104 {
01105    char s[2] = {0};
01106    struct ast_channel *owner = p->owner;
01107    char cid_num[256];
01108    char cid_name[256];
01109 /*
01110    struct ast_channel *c;
01111 */
01112 
01113    if (option_verbose > 3) {
01114       char str[VPB_MAX_STR];
01115       vpb_translate_event(e, str);
01116       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: mode=%d, event[%d][%s]=[%d]\n",
01117          p->dev, p->mode, e->type,str, e->data);
01118    }
01119 
01120    switch(e->type) {
01121       case VPB_LOOP_ONHOOK:
01122       case VPB_LOOP_POLARITY:
01123          if (UsePolarityCID == 1){
01124             if (option_verbose>3)
01125                ast_verbose(VERBOSE_PREFIX_4 "Polarity reversal\n");
01126             if(p->callerid_type == 1) {
01127                if (option_verbose>3)
01128                   ast_verbose(VERBOSE_PREFIX_4 "Using VPB Caller ID\n");
01129                get_callerid(p);        /* UK CID before 1st ring*/
01130             }
01131 /*          get_callerid_ast(p);    /* Caller ID using the ast functions */
01132          }
01133          break;
01134       case VPB_RING:
01135          if (p->mode == MODE_FXO) /* FXO port ring, start * */ {
01136             vpb_new(p, AST_STATE_RING, p->context);
01137             if (UsePolarityCID != 1){
01138                if(p->callerid_type == 1) {
01139                   if (option_verbose>3)
01140                      ast_verbose(VERBOSE_PREFIX_4 "Using VPB Caller ID\n");
01141                   get_callerid(p);        /* Australian CID only between 1st and 2nd ring  */
01142                }
01143                get_callerid_ast(p);    /* Caller ID using the ast functions */
01144             }
01145             else {
01146                ast_log(LOG_ERROR, "Setting caller ID: %s %s\n",p->cid_num, p->cid_name);
01147                ast_set_callerid(p->owner, p->cid_num, p->cid_name, p->cid_num);
01148                p->cid_num[0]=0;
01149                p->cid_name[0]=0;
01150             }
01151 
01152             vpb_timer_stop(p->ring_timer);
01153             vpb_timer_start(p->ring_timer);
01154          }
01155          break;
01156 
01157       case VPB_RING_OFF:
01158          break;
01159 
01160       case VPB_STATION_OFFHOOK:
01161          if (p->mode == MODE_IMMEDIATE) 
01162             vpb_new(p,AST_STATE_RING, p->context);
01163          else {
01164             ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: playing dialtone\n",p->dev);
01165             playtone(p->handle, &Dialtone);
01166             p->state=VPB_STATE_PLAYDIAL;
01167             p->wantdtmf = 1;
01168             p->ext[0] = 0; /* Just to be sure & paranoid.*/
01169          }
01170          break;
01171 
01172       case VPB_DIALEND:
01173          if (p->mode == MODE_DIALTONE){
01174             if (p->state == VPB_STATE_PLAYDIAL) {
01175                playtone(p->handle, &Dialtone);
01176                p->wantdtmf = 1;
01177                p->ext[0] = 0; /* Just to be sure & paranoid. */
01178             }
01179             /* These are not needed as they have timers to restart them
01180             else if (p->state == VPB_STATE_PLAYBUSY) {
01181                playtone(p->handle, &Busytone);
01182                p->wantdtmf = 1;
01183                p->ext[0] = 0; 
01184             }
01185             else if (p->state == VPB_STATE_PLAYRING) {
01186                playtone(p->handle, &Ringbacktone);
01187                p->wantdtmf = 1;
01188                p->ext[0] = 0;
01189             }
01190             */
01191          } else {
01192             ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: Got a DIALEND when not really expected\n",p->dev);
01193          }
01194          break;
01195 
01196       case VPB_STATION_ONHOOK:   /* clear ext */
01197          stoptone(p->handle);
01198          p->wantdtmf = 1 ;
01199          p->ext[0] = 0;
01200          p->state=VPB_STATE_ONHOOK;
01201          break;
01202       case VPB_TIMEREXP:
01203          if (e->data == p->dtmfidd_timer_id) {
01204             if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid)){
01205                if (option_verbose > 3)
01206                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: DTMF IDD timer out, matching on [%s] in [%s]\n", p->dev,p->ext , p->context);
01207 
01208                vpb_new(p,AST_STATE_RING, p->context);
01209             }
01210          } else if (e->data == p->ring_timer_id) {
01211             /* We didnt get another ring in time! */
01212             if (p->owner){
01213                if (p->owner->_state != AST_STATE_UP)  {
01214                    /* Assume caller has hung up */
01215                   vpb_timer_stop(p->ring_timer);
01216                }
01217             } else {
01218                 /* No owner any more, Assume caller has hung up */
01219                vpb_timer_stop(p->ring_timer);
01220             }
01221          } 
01222          break;
01223 
01224       case VPB_DTMF:
01225          if (p->state == VPB_STATE_ONHOOK){
01226             /* DTMF's being passed while on-hook maybe Caller ID */
01227             if ( p->mode == MODE_FXO ) {
01228                if ( e->data == DTMF_CID_START ) { /* CallerID Start signal */
01229                   p->dtmf_caller_pos = 0; /* Leaves the first digit out */
01230                   memset(p->callerid,0,AST_MAX_EXTENSION);
01231                }
01232                else if ( e->data == DTMF_CID_STOP ) { /* CallerID End signal */
01233                   p->callerid[p->dtmf_caller_pos] = '\0';
01234                   if (option_verbose > 2)
01235                      ast_verbose(VERBOSE_PREFIX_3 " %s: DTMF CallerID %s\n",p->dev,p->callerid);
01236                   if (owner){
01237                      /*
01238                      if (owner->cid.cid_num)
01239                         free(owner->cid.cid_num);
01240                      owner->cid.cid_num=NULL;
01241                      if (owner->cid.cid_name)
01242                         free(owner->cid.cid_name);
01243                      owner->cid.cid_name=NULL;
01244                      owner->cid.cid_num = strdup(p->callerid);
01245                      */
01246                      cid_name[0] = '\0';
01247                      cid_num[0] = '\0';
01248                      ast_callerid_split(p->callerid, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
01249                      ast_set_callerid(owner, cid_num, cid_name, cid_num);
01250 
01251                   }
01252                   else {
01253                      if (option_verbose > 2)
01254                         ast_verbose(VERBOSE_PREFIX_3 " %s: DTMF CallerID: no owner to assign CID \n",p->dev);
01255                   }
01256                } else if ( p->dtmf_caller_pos < AST_MAX_EXTENSION ) {
01257                   if ( p->dtmf_caller_pos >= 0 )
01258                      p->callerid[p->dtmf_caller_pos] = e->data;
01259                   p->dtmf_caller_pos++;
01260                }
01261             }
01262             break;
01263          }
01264          if (p->wantdtmf == 1) {
01265             stoptone(p->handle);
01266             p->wantdtmf = 0;
01267          }
01268          p->state=VPB_STATE_GETDTMF;
01269          s[0] = e->data;
01270          strncat(p->ext, s, sizeof(p->ext) - strlen(p->ext) - 1);
01271          #if 0
01272          if (!strcmp(p->ext,ast_pickup_ext())) {
01273             /* Call pickup has been dialled! */
01274             if (ast_pickup_call(c)) {
01275                /* Call pickup wasnt possible */
01276             }
01277          }
01278          else 
01279          #endif
01280          if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid)){
01281             if ( ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid)){
01282                if (option_verbose > 3)
01283                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: Multiple matches on [%s] in [%s]\n", p->dev,p->ext , p->context);
01284                /* Start DTMF IDD timer */
01285                vpb_timer_stop(p->dtmfidd_timer);
01286                vpb_timer_start(p->dtmfidd_timer);
01287             }
01288             else {
01289                if (option_verbose > 3)
01290                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: Matched on [%s] in [%s]\n", p->dev,p->ext , p->context);
01291                vpb_new(p,AST_STATE_UP, p->context);
01292             }
01293          } else if (!ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid)){
01294             if (ast_exists_extension(NULL, "default", p->ext, 1, p->callerid)) {
01295                vpb_new(p,AST_STATE_UP, "default");       
01296             } else if (!ast_canmatch_extension(NULL, "default", p->ext, 1, p->callerid)) {
01297                if (option_verbose > 3) {
01298                   ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: can't match anything in %s or default\n", p->dev, p->context);
01299                }
01300                playtone(p->handle, &Busytone);
01301                vpb_timer_stop(p->busy_timer);
01302                vpb_timer_start(p->busy_timer);
01303                p->state = VPB_STATE_PLAYBUSY;
01304             }
01305          }
01306          break;
01307 
01308       default:
01309          /* Ignore.*/
01310          break;
01311    }
01312 
01313    if (option_verbose > 3) 
01314       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_notowned: mode=%d, [%d=>%d]\n",
01315          p->dev, p->mode, e->type, e->data);
01316 
01317    return 0;
01318 }

static int monitor_handle_owned ( struct vpb_pvt p,
VPB_EVENT *  e 
) [inline, static]

Definition at line 841 of file chan_vpb.c.

References ast_channel::_state, ast_async_goto(), AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, ast_cond_signal(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_RING, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, ast_frisolate(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), AST_STATE_UP, ast_strlen_zero(), ast_verbose(), vpb_pvt::bridge, vpb_pvt::busy_timer, vpb_pvt::busy_timer_id, vpb_bridge_t::c0, vpb_bridge_t::c1, ast_channel::cid, ast_callerid::cid_num, vpb_bridge_t::cond, ast_channel::context, vpb_pvt::dev, vpb_bridge_t::endbridge, ast_channel::exten, vpb_pvt::faxhandled, vpb_bridge_t::flags, vpb_bridge_t::fo, ast_frame::frametype, vpb_pvt::handle, vpb_pvt::lastgrunt, ast_channel::lock, vpb_pvt::lock, vpb_bridge_t::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, vpb_pvt::mode, MODE_FXO, ast_channel::name, option_verbose, vpb_pvt::owner, pbx_builtin_setvar_helper(), playtone(), vpb_bridge_t::rc, vpb_pvt::ring_timer, vpb_pvt::ring_timer_id, vpb_pvt::ringback_timer, vpb_pvt::ringback_timer_id, ast_frame::src, vpb_pvt::state, ast_frame::subclass, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, and VPB_STATE_PLAYBUSY.

Referenced by do_monitor().

00842 {
00843    struct ast_frame f = {AST_FRAME_CONTROL}; /* default is control, Clear rest. */
00844    int endbridge = 0;
00845    int res=0;
00846 
00847    if (option_verbose > 3) 
00848       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: got event: [%d=>%d]\n", p->dev, e->type, e->data);
00849 
00850    f.src = (char *)type;
00851    switch (e->type) {
00852       case VPB_RING:
00853          if (p->mode == MODE_FXO) {
00854             f.subclass = AST_CONTROL_RING;
00855             vpb_timer_stop(p->ring_timer);
00856             vpb_timer_start(p->ring_timer);
00857          } else
00858             f.frametype = -1; /* ignore ring on station port. */
00859          break;
00860 
00861       case VPB_RING_OFF:
00862          f.frametype = -1;
00863          break;
00864 
00865       case VPB_TIMEREXP:
00866          if (e->data == p->busy_timer_id) {
00867             playtone(p->handle,&Busytone);
00868             p->state = VPB_STATE_PLAYBUSY;
00869             vpb_timer_stop(p->busy_timer);
00870             vpb_timer_start(p->busy_timer);
00871             f.frametype = -1;
00872          } else if (e->data == p->ringback_timer_id) {
00873             playtone(p->handle, &Ringbacktone);
00874             vpb_timer_stop(p->ringback_timer);
00875             vpb_timer_start(p->ringback_timer);
00876             f.frametype = -1;
00877          } else if (e->data == p->ring_timer_id) {
00878             /* We didnt get another ring in time! */
00879             if (p->owner->_state != AST_STATE_UP)  {
00880                 /* Assume caller has hung up */
00881                vpb_timer_stop(p->ring_timer);
00882                f.subclass = AST_CONTROL_HANGUP;
00883             } else {
00884                vpb_timer_stop(p->ring_timer);
00885                f.frametype = -1;
00886             }
00887             
00888          } else {
00889             f.frametype = -1; /* Ignore. */
00890          }
00891          break;
00892 
00893       case VPB_DTMF_DOWN:
00894       case VPB_DTMF:
00895          if (use_ast_dtmfdet){
00896             f.frametype = -1;
00897          } else if (p->owner->_state == AST_STATE_UP) {
00898                f.frametype = AST_FRAME_DTMF;
00899                f.subclass = e->data;
00900          } else
00901             f.frametype = -1;
00902          break;
00903 
00904       case VPB_TONEDETECT:
00905          if (e->data == VPB_BUSY || e->data == VPB_BUSY_308 || e->data == VPB_BUSY_AUST ) {
00906             if (option_verbose > 3) 
00907                ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: got event: BUSY\n", p->dev);
00908             if (p->owner->_state == AST_STATE_UP) {
00909                f.subclass = AST_CONTROL_HANGUP;
00910             }
00911             else {
00912                f.subclass = AST_CONTROL_BUSY;
00913             }
00914          } 
00915          else if (e->data == VPB_FAX){
00916             if (!p->faxhandled){
00917                if (strcmp(p->owner->exten, "fax")) {
00918                   const char *target_context = ast_strlen_zero(p->owner->macrocontext) ? p->owner->context : p->owner->macrocontext;
00919                   
00920                   if (ast_exists_extension(p->owner, target_context, "fax", 1, p->owner->cid.cid_num)) {
00921                      if (option_verbose > 2)
00922                         ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", p->owner->name);
00923                      /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
00924                      pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten);
00925                      if (ast_async_goto(p->owner, target_context, "fax", 1))
00926                         ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name, target_context);
00927                   } else
00928                      ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
00929                } else
00930                   ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
00931             } else
00932                ast_log(LOG_DEBUG, "Fax already handled\n");
00933 
00934          } 
00935          else if (e->data == VPB_GRUNT) {
00936             if ( ast_tvdiff_ms(ast_tvnow(), p->lastgrunt) > gruntdetect_timeout ) {
00937                /* Nothing heard on line for a very long time
00938                 * Timeout connection */
00939                if (option_verbose > 2) 
00940                   ast_verbose(VERBOSE_PREFIX_3 "grunt timeout\n");
00941                ast_log(LOG_NOTICE,"%s: Line hangup due of lack of conversation\n",p->dev); 
00942                f.subclass = AST_CONTROL_HANGUP;
00943             } else {
00944                p->lastgrunt = ast_tvnow();
00945                f.frametype = -1;
00946             }
00947          } 
00948          else {
00949             f.frametype = -1;
00950          }
00951          break;
00952 
00953       case VPB_CALLEND:
00954          #ifdef DIAL_WITH_CALL_PROGRESS
00955          if (e->data == VPB_CALL_CONNECTED) 
00956             f.subclass = AST_CONTROL_ANSWER;
00957          else if (e->data == VPB_CALL_NO_DIAL_TONE || e->data == VPB_CALL_NO_RING_BACK)
00958             f.subclass =  AST_CONTROL_CONGESTION;
00959          else if (e->data == VPB_CALL_NO_ANSWER || e->data == VPB_CALL_BUSY)
00960             f.subclass = AST_CONTROL_BUSY;
00961          else if (e->data  == VPB_CALL_DISCONNECTED) 
00962             f.subclass = AST_CONTROL_HANGUP;
00963          #else
00964          ast_log(LOG_NOTICE,"%s: Got call progress callback but blind dialing \n", p->dev); 
00965          f.frametype = -1;
00966          #endif
00967          break;
00968 
00969       case VPB_STATION_OFFHOOK:
00970          f.subclass = AST_CONTROL_ANSWER;
00971          break;
00972 
00973       case VPB_DROP:
00974          if ((p->mode == MODE_FXO)&&(UseLoopDrop)){ /* ignore loop drop on stations */
00975             if (p->owner->_state == AST_STATE_UP) 
00976                f.subclass = AST_CONTROL_HANGUP;
00977             else
00978                f.frametype = -1;
00979          }
00980          break;
00981       case VPB_LOOP_ONHOOK:
00982          if (p->owner->_state == AST_STATE_UP)
00983             f.subclass = AST_CONTROL_HANGUP;
00984          else
00985             f.frametype = -1;
00986          break;
00987       case VPB_STATION_ONHOOK:
00988          f.subclass = AST_CONTROL_HANGUP;
00989          break;
00990 
00991       case VPB_STATION_FLASH:
00992          f.subclass = AST_CONTROL_FLASH;
00993          break;
00994 
00995       /* Called when dialing has finished and ringing starts
00996        * No indication that call has really been answered when using blind dialing
00997        */
00998       case VPB_DIALEND:
00999          if (p->state < 5){
01000             f.subclass = AST_CONTROL_ANSWER;
01001             if (option_verbose > 1) 
01002                ast_verbose(VERBOSE_PREFIX_2 "%s: Dialend\n", p->dev);
01003          } else {
01004             f.frametype = -1;
01005          }
01006          break;
01007 
01008       case VPB_PLAY_UNDERFLOW:
01009          f.frametype = -1;
01010          vpb_reset_play_fifo_alarm(p->handle);
01011          break;
01012 
01013       case VPB_RECORD_OVERFLOW:
01014          f.frametype = -1;
01015          vpb_reset_record_fifo_alarm(p->handle);
01016          break;
01017 
01018       default:
01019          f.frametype = -1;
01020          break;
01021    }
01022 
01023 /*
01024    if (option_verbose > 3) ast_verbose("%s: LOCKING in handle_owned [%d]\n", p->dev,res);
01025    res = ast_mutex_lock(&p->lock); 
01026    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
01027 */
01028    {
01029       if (p->bridge) { /* Check what happened, see if we need to report it. */
01030          switch (f.frametype) {
01031             case AST_FRAME_DTMF:
01032                if (  !(p->bridge->c0 == p->owner && 
01033                      (p->bridge->flags & AST_BRIDGE_DTMF_CHANNEL_0) ) &&
01034                   !(p->bridge->c1 == p->owner && 
01035                      (p->bridge->flags & AST_BRIDGE_DTMF_CHANNEL_1) )) 
01036                   /* Kill bridge, this is interesting. */
01037                   endbridge = 1;
01038                break;
01039 
01040             case AST_FRAME_CONTROL:
01041                if (!(p->bridge->flags & AST_BRIDGE_IGNORE_SIGS)) 
01042                #if 0
01043                if (f.subclass == AST_CONTROL_BUSY ||
01044                f.subclass == AST_CONTROL_CONGESTION ||
01045                f.subclass == AST_CONTROL_HANGUP ||
01046                f.subclass == AST_CONTROL_FLASH)
01047                #endif
01048                   endbridge = 1;
01049                break;
01050 
01051             default:
01052                break;
01053          }
01054          if (endbridge) {
01055             if (p->bridge->fo)
01056                *p->bridge->fo = ast_frisolate(&f);
01057             if (p->bridge->rc)
01058                *p->bridge->rc = p->owner;
01059 
01060             ast_mutex_lock(&p->bridge->lock); {
01061                p->bridge->endbridge = 1;
01062                ast_cond_signal(&p->bridge->cond);
01063             } ast_mutex_unlock(&p->bridge->lock);                 
01064          }    
01065       }
01066    } 
01067 
01068    if (endbridge){
01069       res = ast_mutex_unlock(&p->lock);
01070 /*
01071       if (option_verbose > 3) ast_verbose("%s: unLOCKING in handle_owned [%d]\n", p->dev,res);
01072 */
01073       return 0;
01074    }
01075 
01076    if (option_verbose > 3) 
01077       ast_verbose(VERBOSE_PREFIX_4 "%s: handle_owned: Prepared frame type[%d]subclass[%d], bridge=%p owner=[%s]\n",
01078          p->dev, f.frametype, f.subclass, (void *)p->bridge, p->owner->name);
01079 
01080    /* Trylock used here to avoid deadlock that can occur if we
01081     * happen to be in here handling an event when hangup is called
01082     * Problem is that hangup holds p->owner->lock
01083     */
01084    if ((f.frametype >= 0)&& (f.frametype != AST_FRAME_NULL)&&(p->owner)) {
01085       if (ast_mutex_trylock(&p->owner->lock)==0)  {
01086          ast_queue_frame(p->owner, &f);
01087          ast_mutex_unlock(&p->owner->lock);
01088          if (option_verbose > 3) 
01089             ast_verbose(VERBOSE_PREFIX_4 "%s: handled_owned: Queued Frame to [%s]\n", p->dev,p->owner->name);
01090       } else {
01091          ast_verbose("%s: handled_owned: Missed event %d/%d \n",
01092             p->dev,f.frametype, f.subclass);
01093       }
01094    }
01095    res = ast_mutex_unlock(&p->lock);
01096 /*
01097    if (option_verbose > 3) ast_verbose("%s: unLOCKING in handle_owned [%d]\n", p->dev,res);
01098 */
01099 
01100    return 0;
01101 }

static float parse_gain_value ( char *  gain_type,
char *  value 
) [static]

Definition at line 2756 of file chan_vpb.c.

References ast_log(), config, DEFAULT_GAIN, and LOG_ERROR.

02757 {
02758    float gain;
02759 
02760    /* try to scan number */
02761    if (sscanf(value, "%30f", &gain) != 1)
02762    {
02763       ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n", value, gain_type, config);
02764       return DEFAULT_GAIN;
02765    }
02766 
02767 
02768    /* percentage? */
02769    /*if (value[strlen(value) - 1] == '%') */
02770    /* return gain / (float)100; */
02771 
02772    return gain;
02773 }

static int playtone ( int  handle,
VPB_TONE *  tone 
) [static]

Definition at line 831 of file chan_vpb.c.

References ast_verbose(), option_verbose, stoptone(), and VERBOSE_PREFIX_4.

Referenced by monitor_handle_notowned(), monitor_handle_owned(), and vpb_indicate().

00832 {
00833    int ret=VPB_OK;
00834    stoptone(handle);
00835    if (option_verbose > 3) 
00836       ast_verbose(VERBOSE_PREFIX_4 "[%02d]: Playing tone\n", handle);
00837    ret = vpb_playtone_async(handle, tone);
00838    return ret;
00839 }

static int restart_monitor ( void   )  [static]

Definition at line 1443 of file chan_vpb.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_verbose(), do_monitor(), error(), LOG_ERROR, LOG_WARNING, option_verbose, VERBOSE_PREFIX_4, and VPB_NULL_EVENT.

01444 {
01445    int error = 0;
01446 
01447    /* If we're supposed to be stopped -- stay stopped */
01448    if (mthreadactive == -2)
01449       return 0;
01450 
01451    if (option_verbose > 3)
01452       ast_verbose(VERBOSE_PREFIX_4 "Restarting monitor\n");
01453 
01454    ast_mutex_lock(&monlock); {
01455       if (monitor_thread == pthread_self()) {
01456          ast_log(LOG_WARNING, "Cannot kill myself\n");
01457          error = -1;
01458          if (option_verbose > 3)
01459             ast_verbose(VERBOSE_PREFIX_4 "Monitor trying to kill monitor\n");
01460       }
01461       else {
01462          if (mthreadactive != -1) {
01463             /* Why do other drivers kill the thread? No need says I, simply awake thread with event. */
01464             VPB_EVENT e;
01465             e.handle = 0;
01466             e.type = VPB_NULL_EVENT;
01467             e.data = 0;
01468 
01469             if (option_verbose > 3)
01470                ast_verbose(VERBOSE_PREFIX_4 "Trying to reawake monitor\n");
01471 
01472             vpb_put_event(&e);
01473          } else {
01474             /* Start a new monitor */
01475             int pid = ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL); 
01476             if (option_verbose > 3)
01477                ast_verbose(VERBOSE_PREFIX_4 "Created new monitor thread %d\n",pid);
01478             if (pid < 0) {
01479                ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01480                error = -1;
01481             } else
01482                mthreadactive = 0; /* Started the thread!*/
01483          }
01484       }
01485    } ast_mutex_unlock(&monlock);
01486 
01487    if (option_verbose > 3)
01488       ast_verbose(VERBOSE_PREFIX_4 "Monitor restarted\n");
01489 
01490    return error;
01491 }

static void stoptone ( int  handle  )  [static]

Definition at line 813 of file chan_vpb.c.

References ast_verbose(), option_verbose, and VERBOSE_PREFIX_4.

Referenced by monitor_handle_notowned(), playtone(), vpb_hangup(), and vpb_indicate().

00814 {
00815    int ret;
00816    VPB_EVENT je;
00817    while(vpb_playtone_state(handle)!=VPB_OK){
00818       vpb_tone_terminate(handle);
00819       ret = vpb_get_event_ch_async(handle,&je);
00820       if ((ret == VPB_OK)&&(je.type != VPB_DIALEND)){
00821          if (option_verbose > 3){
00822                ast_verbose(VERBOSE_PREFIX_4 "Stop tone collected a wrong event!![%d]\n",je.type);
00823          }
00824 /*       vpb_put_event(&je); */
00825       }
00826       vpb_sleep(10);
00827    }
00828 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 2972 of file chan_vpb.c.

References ast_channel_unregister(), ast_cond_destroy(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, bridges, free, vpb_pvt::handle, iflist, lock, vpb_pvt::lock, max_bridges, monitor_thread, mthreadactive, oh323_pvt::next, vpb_pvt::next, vpb_pvt::owner, vpb_pvt::owner_lock, vpb_pvt::play_dtmf_lock, vpb_pvt::play_lock, vpb_pvt::readthread, vpb_pvt::record_lock, use_ast_ind, vpb_tech, and vpb_tech_indicate.

02973 {
02974    struct vpb_pvt *p;
02975    /* First, take us out of the channel loop */
02976    if (use_ast_ind == 1){
02977       ast_channel_unregister(&vpb_tech_indicate);
02978    }
02979    else {
02980       ast_channel_unregister(&vpb_tech);
02981    }
02982 
02983    ast_mutex_lock(&iflock); {
02984       /* Hangup all interfaces if they have an owner */
02985       p = iflist;
02986       while(p) {
02987          if (p->owner)
02988             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
02989          p = p->next;
02990       }
02991       iflist = NULL;
02992    } ast_mutex_unlock(&iflock);
02993 
02994    ast_mutex_lock(&monlock); {
02995       if (mthreadactive > -1) {
02996          pthread_cancel(monitor_thread);
02997          pthread_join(monitor_thread, NULL);
02998       }
02999       mthreadactive = -2;
03000    } ast_mutex_unlock(&monlock);
03001 
03002    ast_mutex_lock(&iflock); {
03003       /* Destroy all the interfaces and free their memory */
03004 
03005       while(iflist) {
03006          p = iflist;        
03007          ast_mutex_destroy(&p->lock);
03008          pthread_cancel(p->readthread);
03009          ast_mutex_destroy(&p->owner_lock);
03010          ast_mutex_destroy(&p->record_lock);
03011          ast_mutex_destroy(&p->play_lock);
03012          ast_mutex_destroy(&p->play_dtmf_lock);
03013          p->readthread = 0;
03014 
03015          vpb_close(p->handle);
03016 
03017          iflist = iflist->next;
03018 
03019          free(p);
03020       }
03021       iflist = NULL;
03022    } ast_mutex_unlock(&iflock);
03023 
03024    ast_mutex_lock(&bridge_lock); {
03025       memset(bridges, 0, sizeof bridges);      
03026    } ast_mutex_unlock(&bridge_lock);
03027    ast_mutex_destroy(&bridge_lock);
03028    for(int i = 0; i < max_bridges; i++ ) {
03029       ast_mutex_destroy(&bridges[i].lock);
03030       ast_cond_destroy(&bridges[i].cond);
03031    }
03032    free(bridges);
03033 
03034    return 0;
03035 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 3037 of file chan_vpb.c.

References usecnt.

03038 {
03039    return usecnt;
03040 }

static int vpb_answer ( struct ast_channel ast  )  [static]

Definition at line 2102 of file chan_vpb.c.

References ast_channel::_state, ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_setstate(), AST_STATE_UP, ast_verbose(), vpb_pvt::dev, do_chanreads(), vpb_pvt::handle, vpb_pvt::lock, vpb_pvt::mode, MODE_FXO, ast_channel::name, option_verbose, vpb_pvt::readthread, ast_channel::rings, vpb_pvt::state, ast_channel::tech_pvt, VERBOSE_PREFIX_2, VERBOSE_PREFIX_4, and VPB_STATE_OFFHOOK.

Referenced by vpb_new().

02103 {
02104    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
02105    int res = 0;
02106 /*
02107    VPB_EVENT je;
02108    int ret;
02109    if (option_verbose > 3) ast_verbose("%s: LOCKING in answer \n", p->dev);
02110    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
02111 */
02112    ast_mutex_lock(&p->lock);
02113 
02114    if (option_verbose > 3)
02115          ast_verbose(VERBOSE_PREFIX_4 "%s: Answering channel\n",p->dev);
02116 
02117    if (p->mode == MODE_FXO){
02118       if (option_verbose > 3)
02119             ast_verbose("%s: Disabling Loop Drop detection\n",p->dev);
02120       vpb_disable_event(p->handle, VPB_MDROP);
02121    }
02122 
02123    if (ast->_state != AST_STATE_UP) {
02124       if (p->mode == MODE_FXO){
02125          vpb_sethook_sync(p->handle, VPB_OFFHOOK);
02126          p->state=VPB_STATE_OFFHOOK;
02127 /*       vpb_sleep(500);
02128          ret = vpb_get_event_ch_async(p->handle,&je);
02129          if ((ret == VPB_OK)&&((je.type != VPB_DROP)&&(je.type != VPB_RING))){
02130             if (option_verbose > 3){
02131                   ast_verbose(VERBOSE_PREFIX_4 "%s: Answer collected a wrong event!!\n",p->dev);
02132             }
02133             vpb_put_event(&je);
02134          }
02135 */
02136       }
02137       ast_setstate(ast, AST_STATE_UP);
02138 
02139       if(option_verbose>1) 
02140 /*
02141          ast_verbose( VERBOSE_PREFIX_2 "%s: Answered call from %s on %s [%s]\n", p->dev, 
02142                p->owner->callerid, ast->name,(p->mode == MODE_FXO)?"FXO":"FXS"); 
02143 */
02144          ast_verbose( VERBOSE_PREFIX_2 "%s: Answered call on %s [%s]\n", p->dev,
02145                 ast->name,(p->mode == MODE_FXO)?"FXO":"FXS");
02146 
02147       ast->rings = 0;
02148       if( !p->readthread ){
02149    /*    res = ast_mutex_unlock(&p->lock); */
02150    /*    ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res); */
02151          ast_pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
02152       } else {
02153          if(option_verbose>3) 
02154             ast_verbose(VERBOSE_PREFIX_4 "%s: Record thread already running!!\n",p->dev);
02155       }
02156    } else {
02157       if(option_verbose>3) {
02158          ast_verbose(VERBOSE_PREFIX_4 "%s: Answered state is up\n",p->dev);
02159       }
02160    /* res = ast_mutex_unlock(&p->lock); */
02161    /* ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res); */
02162    }
02163    vpb_sleep(500);
02164    if (p->mode == MODE_FXO){
02165       if (option_verbose > 3)
02166             ast_verbose("%s: Re-enabling Loop Drop detection\n",p->dev);
02167       vpb_enable_event(p->handle,VPB_MDROP);
02168    }
02169    res = ast_mutex_unlock(&p->lock);
02170 /*
02171    if(option_verbose>3) ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res);
02172 */
02173    return 0;
02174 }

static enum ast_bridge_result vpb_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
) [static]

Definition at line 417 of file chan_vpb.c.

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_check_hangup(), AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_verbose(), ast_waitfor_n(), vpb_pvt::bridge, vpb_pvt::buf, vpb_bridge_t::c0, vpb_bridge_t::c1, vpb_pvt::dev, vpb_bridge_t::endbridge, vpb_bridge_t::flags, vpb_bridge_t::fo, ast_frame::frametype, vpb_pvt::handle, vpb_bridge_t::inuse, inuse, vpb_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_verbose, vpb_bridge_t::rc, ast_frame::subclass, ast_channel::tech_pvt, VERBOSE_PREFIX_2, vpb_pvt::vpb_model, vpb_model_v4pci, and VPB_SAMPLES.

00418 {
00419    struct vpb_pvt *p0 = (struct vpb_pvt *)c0->tech_pvt;
00420    struct vpb_pvt *p1 = (struct vpb_pvt *)c1->tech_pvt;
00421    int i;
00422    int res;
00423    struct ast_channel *cs[3];
00424    struct ast_channel *who;
00425    struct ast_frame *f;
00426 
00427    cs[0] = c0;
00428    cs[1] = c1;
00429 
00430    #ifdef BAD_V4PCI_BRIDGE
00431    if(p0->vpb_model==vpb_model_v4pci)
00432       return AST_BRIDGE_FAILED_NOWARN;
00433    #endif
00434    if ( UseNativeBridge != 1){
00435       return AST_BRIDGE_FAILED_NOWARN;
00436    }
00437 
00438 /*
00439    ast_mutex_lock(&p0->lock);
00440    ast_mutex_lock(&p1->lock);
00441 */
00442 
00443    /* Bridge channels, check if we can.  I believe we always can, so find a slot.*/
00444 
00445    ast_mutex_lock(&bridge_lock); {
00446       for (i = 0; i < max_bridges; i++) 
00447          if (!bridges[i].inuse)
00448             break;
00449       if (i < max_bridges) {
00450          bridges[i].inuse = 1;
00451          bridges[i].endbridge = 0;
00452          bridges[i].flags = flags;
00453          bridges[i].rc = rc;
00454          bridges[i].fo = fo;
00455          bridges[i].c0 = c0;
00456          bridges[i].c1 = c1;
00457       }         
00458    } ast_mutex_unlock(&bridge_lock); 
00459 
00460    if (i == max_bridges) {
00461       ast_log(LOG_WARNING, "%s: vpb_bridge: Failed to bridge %s and %s!\n", p0->dev, c0->name, c1->name);
00462       ast_mutex_unlock(&p0->lock);
00463       ast_mutex_unlock(&p1->lock);
00464       return AST_BRIDGE_FAILED_NOWARN;
00465    } else {
00466       /* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/
00467       ast_mutex_lock(&p0->lock); {
00468          p0->bridge = &bridges[i];
00469       } ast_mutex_unlock(&p0->lock);
00470 
00471       ast_mutex_lock(&p1->lock); {
00472          p1->bridge = &bridges[i];
00473       } ast_mutex_unlock(&p1->lock);
00474 
00475       if (option_verbose>1) 
00476          ast_verbose(VERBOSE_PREFIX_2 "%s: vpb_bridge: Bridging call entered with [%s, %s]\n",p0->dev, c0->name, c1->name);
00477    }
00478 
00479    #ifdef HALF_DUPLEX_BRIDGE
00480 
00481    if (option_verbose>1) 
00482       ast_verbose(VERBOSE_PREFIX_2 "%s: vpb_bridge: Starting half-duplex bridge [%s, %s]\n",p0->dev, c0->name, c1->name);
00483 
00484    int dir = 0;
00485 
00486    memset(p0->buf, 0, sizeof p0->buf);
00487    memset(p1->buf, 0, sizeof p1->buf);
00488 
00489    vpb_record_buf_start(p0->handle, VPB_ALAW);
00490    vpb_record_buf_start(p1->handle, VPB_ALAW);
00491 
00492    vpb_play_buf_start(p0->handle, VPB_ALAW);
00493    vpb_play_buf_start(p1->handle, VPB_ALAW);
00494 
00495    while( !bridges[i].endbridge ) {
00496       struct vpb_pvt *from, *to;
00497       if(++dir%2) {
00498          from = p0;
00499          to = p1;
00500       } else {
00501          from = p1;
00502          to = p0;
00503       }
00504       vpb_record_buf_sync(from->handle, from->buf, VPB_SAMPLES);
00505       vpb_play_buf_sync(to->handle, from->buf, VPB_SAMPLES);
00506    }
00507 
00508    vpb_record_buf_finish(p0->handle);
00509    vpb_record_buf_finish(p1->handle);
00510 
00511    vpb_play_buf_finish(p0->handle);
00512    vpb_play_buf_finish(p1->handle);
00513 
00514    if (option_verbose>1) 
00515       ast_verbose(VERBOSE_PREFIX_2 "%s: vpb_bridge: Finished half-duplex bridge [%s, %s]\n",p0->dev, c0->name, c1->name);
00516 
00517    res = VPB_OK;
00518 
00519    #else
00520 
00521    res = vpb_bridge(p0->handle, p1->handle, VPB_BRIDGE_ON, i+1 /* resource 1 & 2 only for V4PCI*/ );
00522    if (res == VPB_OK) {
00523       /* pthread_cond_wait(&bridges[i].cond, &bridges[i].lock);*/ /* Wait for condition signal. */
00524       while( !bridges[i].endbridge ) {
00525          /* Are we really ment to be doing nothing ?!?! */
00526          who = ast_waitfor_n(cs, 2, &timeoutms);
00527          if (!who) {
00528             if (!timeoutms) {
00529                res = AST_BRIDGE_RETRY;
00530                break;
00531             }
00532             ast_log(LOG_DEBUG, "%s: vpb_bridge: Empty frame read...\n",p0->dev);
00533             /* check for hangup / whentohangup */
00534             if (ast_check_hangup(c0) || ast_check_hangup(c1))
00535                break;
00536             continue;
00537          }
00538          f = ast_read(who);
00539          if (!f || ((f->frametype == AST_FRAME_DTMF) &&
00540                   (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 
00541                    ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
00542             *fo = f;
00543             *rc = who;
00544             ast_log(LOG_DEBUG, "%s: vpb_bridge: Got a [%s]\n",p0->dev, f ? "digit" : "hangup");
00545 /*
00546             if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) {
00547                if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 
00548                   ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
00549             }
00550             if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) {
00551                if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 
00552                   ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
00553             }
00554 */
00555             /* That's all we needed */
00556             /*return 0; */
00557             /* Check if we need to break */
00558             if (break_for_dtmf){
00559                break;
00560             }
00561             else if ((f->frametype == AST_FRAME_DTMF) && ((f->subclass == '#')||(f->subclass == '*'))){
00562                break;
00563             }
00564          } else {
00565             if ((f->frametype == AST_FRAME_DTMF) || 
00566                (f->frametype == AST_FRAME_VOICE) || 
00567                (f->frametype == AST_FRAME_VIDEO)) 
00568                {
00569                /* Forward voice or DTMF frames if they happen upon us */
00570                /* Actually I dont think we want to forward on any frames!
00571                if (who == c0) {
00572                   ast_write(c1, f);
00573                } else if (who == c1) {
00574                   ast_write(c0, f);
00575                }
00576                */
00577             }
00578             ast_frfree(f);
00579          }
00580          /* Swap priority not that it's a big deal at this point */
00581          cs[2] = cs[0];
00582          cs[0] = cs[1];
00583          cs[1] = cs[2];
00584       };
00585       vpb_bridge(p0->handle, p1->handle, VPB_BRIDGE_OFF, i+1 /* resource 1 & 2 only for V4PCI*/ ); 
00586    }
00587 
00588    #endif
00589 
00590    ast_mutex_lock(&bridge_lock); {
00591       bridges[i].inuse = 0;
00592    } ast_mutex_unlock(&bridge_lock); 
00593 
00594    p0->bridge = NULL;
00595    p1->bridge = NULL;
00596 
00597 
00598    if (option_verbose>1) 
00599       ast_verbose(VERBOSE_PREFIX_2 "Bridging call done with [%s, %s] => %d\n", c0->name, c1->name, res);
00600 
00601 /*
00602    ast_mutex_unlock(&p0->lock);
00603    ast_mutex_unlock(&p1->lock);
00604 */
00605    return (res==VPB_OK) ? AST_BRIDGE_COMPLETE : AST_BRIDGE_FAILED;
00606 }

static int vpb_call ( struct ast_channel ast,
char *  dest,
int  timeout 
) [static]

Definition at line 1858 of file chan_vpb.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_verbose(), vpb_pvt::dev, do_chanreads(), vpb_pvt::handle, vpb_pvt::lock, LOG_DEBUG, LOG_WARNING, vpb_pvt::mode, MODE_FXO, ast_channel::name, option_verbose, vpb_pvt::readthread, s, vpb_pvt::state, ast_channel::tech_pvt, TIMER_PERIOD_NOANSWER, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, VPB_CONNECTED_WAIT, VPB_DIALTONE_WAIT, VPB_RINGWAIT, and VPB_STATE_OFFHOOK.

01859 {
01860    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
01861    int res = 0,i;
01862    char *s = strrchr(dest, '/');
01863    char dialstring[254] = "";
01864    int tmp = 0;
01865 
01866 /*
01867    if (option_verbose > 3) ast_verbose("%s: LOCKING in call \n", p->dev);
01868    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
01869 */
01870    ast_mutex_lock(&p->lock);
01871    if (option_verbose > 3)
01872       ast_verbose(VERBOSE_PREFIX_4 "%s: starting call to [%s]\n", p->dev,dest);
01873 
01874    if (s)
01875       s = s + 1;
01876    else
01877       s = dest;
01878    strncpy(dialstring, s, sizeof(dialstring) - 1);
01879    for (i=0; dialstring[i] != '\0' ; i++) {
01880       if ((dialstring[i] == 'w') || (dialstring[i] == 'W'))
01881          dialstring[i] = ',';
01882       else if ((dialstring[i] == 'f') || (dialstring[i] == 'F'))
01883          dialstring[i] = '&';
01884    }  
01885 
01886    if (ast->_state != AST_STATE_DOWN && ast->_state != AST_STATE_RESERVED) {
01887       ast_log(LOG_WARNING, "vpb_call on %s neither down nor reserved!\n", ast->name);
01888       tmp = ast_mutex_unlock(&p->lock);
01889 /*
01890       if (option_verbose > 3) ast_verbose("%s: unLOCKING in call [%d]\n", p->dev,tmp);
01891 */
01892       return -1;
01893    }
01894    if (p->mode != MODE_FXO)  /* Station port, ring it. */
01895       res = vpb_ring_station_async(p->handle, VPB_RING_STATION_ON,0);       
01896    else {
01897       VPB_CALL call;
01898 
01899       /* Dial must timeout or it can leave channels unuseable */
01900       if( timeout == 0 )
01901          timeout = TIMER_PERIOD_NOANSWER;
01902       else 
01903          timeout = timeout * 1000; /* convert from secs to ms. */
01904 
01905       /* These timeouts are only used with call progress dialing */
01906       call.dialtones = 1; /* Number of dialtones to get outside line */
01907       call.dialtone_timeout = VPB_DIALTONE_WAIT; /* Wait this long for dialtone (ms) */
01908       call.ringback_timeout = VPB_RINGWAIT; /* Wait this long for ringing after dialing (ms) */
01909       call.inter_ringback_timeout = VPB_CONNECTED_WAIT; /* If ringing stops for this long consider it connected (ms) */
01910       call.answer_timeout = timeout; /* Time to wait for answer after ringing starts (ms) */
01911       memcpy( &call.tone_map,  DialToneMap, sizeof(DialToneMap) );
01912       vpb_set_call(p->handle, &call);
01913 
01914       if (option_verbose > 1)
01915          ast_verbose(VERBOSE_PREFIX_2 "%s: Calling %s on %s \n",p->dev, dialstring, ast->name); 
01916 
01917       if (option_verbose > 2) {
01918          int j;
01919          ast_verbose(VERBOSE_PREFIX_2 "%s: Dial parms for %s %d/%dms/%dms/%dms/%dms\n", p->dev
01920             , ast->name, call.dialtones, call.dialtone_timeout
01921             , call.ringback_timeout, call.inter_ringback_timeout
01922             , call.answer_timeout );
01923          for( j=0; !call.tone_map[j].terminate; j++ )
01924             ast_verbose(VERBOSE_PREFIX_2 "%s: Dial parms for %s tone %d->%d\n", p->dev,
01925                ast->name, call.tone_map[j].tone_id, call.tone_map[j].call_id); 
01926       }
01927 
01928       if (option_verbose > 3)
01929             ast_verbose("%s: Disabling Loop Drop detection\n",p->dev);
01930       vpb_disable_event(p->handle, VPB_MDROP);
01931       vpb_sethook_sync(p->handle,VPB_OFFHOOK);
01932       p->state=VPB_STATE_OFFHOOK;
01933 
01934       #ifndef DIAL_WITH_CALL_PROGRESS
01935       vpb_sleep(300);
01936       if (option_verbose > 3)
01937             ast_verbose("%s: Enabling Loop Drop detection\n",p->dev);
01938       vpb_enable_event(p->handle, VPB_MDROP);
01939       res = vpb_dial_async(p->handle, dialstring);
01940       #else
01941       if (option_verbose > 3)
01942             ast_verbose("%s: Enabling Loop Drop detection\n",p->dev);
01943       vpb_enable_event(p->handle, VPB_MDROP);
01944       res = vpb_call_async(p->handle, dialstring);
01945       #endif
01946 
01947       if (res != VPB_OK) {
01948          ast_log(LOG_DEBUG, "Call on %s to %s failed: %s\n", ast->name, s, vpb_strerror(res));        
01949          res = -1;
01950       } else 
01951          res = 0;
01952    }
01953 
01954    if (option_verbose > 2)
01955       ast_verbose(VERBOSE_PREFIX_3 "%s: VPB Calling %s [t=%d] on %s returned %d\n",p->dev , s, timeout, ast->name, res); 
01956    if (res == 0) {
01957       ast_setstate(ast, AST_STATE_RINGING);
01958       ast_queue_control(ast,AST_CONTROL_RINGING);     
01959    }
01960 
01961    if (!p->readthread){
01962       ast_pthread_create(&p->readthread, NULL, do_chanreads, (void *)p);
01963    }
01964 
01965    tmp = ast_mutex_unlock(&p->lock);
01966 /*
01967    if (option_verbose > 3) ast_verbose("%s: unLOCKING in call [%d]\n", p->dev,tmp);
01968 */
01969    return res;
01970 }

static int vpb_digit ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 1821 of file chan_vpb.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), vpb_pvt::dev, vpb_pvt::lock, option_verbose, vpb_pvt::play_dtmf, vpb_pvt::play_dtmf_lock, s, ast_channel::tech_pvt, and VERBOSE_PREFIX_4.

01822 {
01823    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
01824    char s[2];
01825    int res = 0;
01826 
01827    if (use_ast_dtmf){
01828       if (option_verbose > 3)
01829          ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_digit: asked to play digit[%c] but we are using asterisk dtmf play back?!\n", p->dev, digit);
01830       return 0;
01831    }
01832 
01833 /*
01834    if (option_verbose > 3) ast_verbose("%s: LOCKING in digit \n", p->dev);
01835    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
01836 */
01837    ast_mutex_lock(&p->lock);
01838 
01839 
01840    s[0] = digit;
01841    s[1] = '\0';
01842 
01843    if (option_verbose > 3)
01844       ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_digit: asked to play digit[%s]\n", p->dev, s);
01845 
01846    ast_mutex_lock(&p->play_dtmf_lock);
01847    strncat(p->play_dtmf,s,sizeof(*p->play_dtmf));
01848    ast_mutex_unlock(&p->play_dtmf_lock);
01849 
01850    res = ast_mutex_unlock(&p->lock);
01851 /*
01852    if (option_verbose > 3) ast_verbose("%s: unLOCKING in digit [%d]\n", p->dev,res);
01853 */
01854    return 0;
01855 }

static int vpb_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 1785 of file chan_vpb.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_indicate(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, ast_verbose(), vpb_pvt::dev, vpb_pvt::lock, LOG_DEBUG, ast_channel::name, option_verbose, vpb_pvt::owner, ast_channel::tech_pvt, VERBOSE_PREFIX_4, and vpb_indicate().

01786 {
01787    struct vpb_pvt *p = (struct vpb_pvt *)newchan->tech_pvt;
01788    int res = 0;
01789 
01790 /*
01791    if (option_verbose > 3) ast_verbose("%s: LOCKING in fixup \n", p->dev);
01792    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
01793 */
01794    ast_mutex_lock(&p->lock);
01795    ast_log(LOG_DEBUG, "New owner for channel %s is %s\n", p->dev, newchan->name);
01796 
01797    if (p->owner == oldchan) {
01798       p->owner = newchan;
01799    }
01800 
01801    if (newchan->_state == AST_STATE_RINGING){
01802       if (use_ast_ind == 1) {
01803          if (option_verbose > 3)
01804             ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_fixup Calling ast_indicate\n", p->dev);
01805          ast_indicate(newchan, AST_CONTROL_RINGING);
01806       }
01807       else {
01808          if (option_verbose > 3)
01809             ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_fixup Calling vpb_indicate\n", p->dev);
01810          vpb_indicate(newchan, AST_CONTROL_RINGING);
01811       }
01812    }
01813 
01814    res= ast_mutex_unlock(&p->lock);
01815 /*
01816    if (option_verbose > 3) ast_verbose("%s: unLOCKING in fixup [%d]\n", p->dev,res);
01817 */
01818    return 0;
01819 }

static int vpb_hangup ( struct ast_channel ast  )  [static]

Definition at line 1972 of file chan_vpb.c.

References ast_dsp_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, ast_update_use_count(), ast_verbose(), vpb_pvt::dialtone, vpb_pvt::ext, vpb_pvt::handle, vpb_pvt::last_ignore_dtmf, vpb_pvt::lastinput, vpb_pvt::lastoutput, vpb_pvt::lock, LOG_WARNING, vpb_pvt::mode, MODE_FXO, ast_channel::name, option_verbose, vpb_pvt::owner, vpb_pvt::play_lock, vpb_pvt::readthread, restart_monitor(), vpb_pvt::state, vpb_pvt::stopreads, stoptone(), ast_channel::tech, ast_channel::tech_pvt, usecnt_lock, vpb_pvt::vad, VERBOSE_PREFIX_2, VERBOSE_PREFIX_4, and VPB_STATE_ONHOOK.

01973 {
01974    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
01975    VPB_EVENT je;
01976    char str[VPB_MAX_STR];
01977    int res =0 ;
01978 
01979 /*
01980    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup \n", p->dev);
01981    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
01982    if (option_verbose > 3) ast_verbose("%s: LOCKING pthread_self(%d)\n", p->dev,pthread_self());
01983    ast_mutex_lock(&p->lock);
01984 */
01985    if (option_verbose > 1) 
01986       ast_verbose(VERBOSE_PREFIX_2 "%s: Hangup requested\n", ast->name);
01987 
01988    if (!ast->tech || !ast->tech_pvt) {
01989       ast_log(LOG_WARNING, "%s: channel not connected?\n", ast->name);
01990       res = ast_mutex_unlock(&p->lock);
01991 /*
01992       if (option_verbose > 3) ast_verbose("%s: unLOCKING in hangup [%d]\n", p->dev,res);
01993 */
01994       /* Free up ast dsp if we have one */
01995       if ((use_ast_dtmfdet)&&(p->vad)) {
01996          ast_dsp_free(p->vad);
01997          p->vad = NULL;
01998       }
01999       return 0;
02000    }
02001 
02002 
02003 
02004    /* Stop record */
02005    p->stopreads = 1;
02006    if( p->readthread ){
02007       pthread_join(p->readthread, NULL); 
02008       if(option_verbose>3) 
02009          ast_verbose( VERBOSE_PREFIX_4 "%s: stopped record thread \n",ast->name);
02010    }
02011 
02012    /* Stop play */
02013    if (p->lastoutput != -1) {
02014       if(option_verbose>1) 
02015          ast_verbose( VERBOSE_PREFIX_2 "%s: Ending play mode \n",ast->name);
02016       vpb_play_terminate(p->handle);
02017       ast_mutex_lock(&p->play_lock); {
02018          vpb_play_buf_finish(p->handle);
02019       } ast_mutex_unlock(&p->play_lock);
02020    }
02021 
02022    if(option_verbose>3) 
02023       ast_verbose( VERBOSE_PREFIX_4 "%s: Setting state down\n",ast->name);
02024    ast_setstate(ast,AST_STATE_DOWN);
02025 
02026 
02027 /*
02028    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup \n", p->dev);
02029    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
02030    if (option_verbose > 3) ast_verbose("%s: LOCKING pthread_self(%d)\n", p->dev,pthread_self());
02031 */
02032    ast_mutex_lock(&p->lock);
02033 
02034    if (p->mode != MODE_FXO) {
02035       /* station port. */
02036       vpb_ring_station_async(p->handle, VPB_RING_STATION_OFF,0);  
02037       if(p->state!=VPB_STATE_ONHOOK){
02038          /* This is causing a "dial end" "play tone" loop
02039          playtone(p->handle, &Busytone); 
02040          p->state = VPB_STATE_PLAYBUSY;
02041          if(option_verbose>4) 
02042             ast_verbose( VERBOSE_PREFIX_4 "%s: Station offhook[%d], playing busy tone\n",
02043                         ast->name,p->state);
02044          */
02045       }
02046       else {
02047          stoptone(p->handle);
02048       }
02049       #ifdef VPB_PRI
02050       vpb_setloop_async(p->handle, VPB_OFFHOOK);
02051       vpb_sleep(100);
02052       vpb_setloop_async(p->handle, VPB_ONHOOK);
02053       #endif
02054    } else {
02055       stoptone(p->handle); /* Terminates any dialing */
02056       vpb_sethook_sync(p->handle, VPB_ONHOOK);
02057       p->state=VPB_STATE_ONHOOK;
02058    }
02059    while (VPB_OK==vpb_get_event_ch_async(p->handle,&je)){
02060       if(option_verbose>3) {
02061          vpb_translate_event(&je, str);
02062          ast_verbose( VERBOSE_PREFIX_4 "%s: Flushing event [%d]=>%s\n",ast->name,je.type,str);
02063       }
02064    }
02065 
02066    p->readthread = 0;
02067    p->lastoutput = -1;
02068    p->lastinput = -1;
02069    p->last_ignore_dtmf = 1;
02070    p->ext[0]  = 0;
02071    p->dialtone = 0;
02072 
02073    p->owner = NULL;
02074    ast->tech_pvt=NULL;
02075 
02076    /* Free up ast dsp if we have one */
02077    if ((use_ast_dtmfdet)&&(p->vad)) {
02078       ast_dsp_free(p->vad);
02079       p->vad = NULL;
02080    }
02081 
02082    ast_mutex_lock(&usecnt_lock); {
02083       usecnt--;
02084    } ast_mutex_unlock(&usecnt_lock);
02085    ast_update_use_count();
02086 
02087    if (option_verbose > 1)
02088       ast_verbose(VERBOSE_PREFIX_2 "%s: Hangup complete\n", ast->name);
02089 
02090    restart_monitor();
02091 /*
02092    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
02093 */
02094    res = ast_mutex_unlock(&p->lock);
02095 /*
02096    if (option_verbose > 3) ast_verbose("%s: unLOCKING in hangup [%d]\n", p->dev,res);
02097    if (option_verbose > 3) ast_verbose("%s: LOCKING in hangup count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
02098 */
02099    return 0;
02100 }

static int vpb_indicate ( struct ast_channel ast,
int  condition 
) [static]

Definition at line 1712 of file chan_vpb.c.

References ast_channel::_state, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, ast_verbose(), vpb_pvt::busy_timer, vpb_pvt::dev, vpb_pvt::handle, vpb_pvt::lock, option_verbose, playtone(), vpb_pvt::ringback_timer, vpb_pvt::ringback_timer_id, vpb_pvt::state, stoptone(), ast_channel::tech_pvt, VERBOSE_PREFIX_4, VPB_STATE_PLAYBUSY, and VPB_STATE_PLAYRING.

Referenced by vpb_fixup().

01713 {
01714    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
01715    int res = 0;
01716    int tmp = 0;
01717 
01718    if (use_ast_ind == 1) {
01719       if (option_verbose > 3)
01720          ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_indicate called when using Ast Indications !?!\n", p->dev);
01721       return 0;
01722    }
01723 
01724    if (option_verbose > 3)
01725       ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_indicate [%d] state[%d]\n", p->dev, condition,ast->_state);
01726 /*
01727    if (ast->_state != AST_STATE_UP) {
01728       ast_verbose(VERBOSE_PREFIX_4 "%s: vpb_indicate Not in AST_STATE_UP\n", p->dev, condition,ast->_state);
01729       return res;
01730    }
01731 */
01732 
01733 /*
01734    if (option_verbose > 3) ast_verbose("%s: LOCKING in indicate \n", p->dev);
01735    if (option_verbose > 3) ast_verbose("%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);
01736 */
01737    ast_mutex_lock(&p->lock);
01738    switch(condition) {
01739       case AST_CONTROL_BUSY:
01740       case AST_CONTROL_CONGESTION:
01741          if (ast->_state == AST_STATE_UP) {
01742             playtone(p->handle, &Busytone);
01743             p->state = VPB_STATE_PLAYBUSY;
01744             vpb_timer_stop(p->busy_timer); 
01745             vpb_timer_start(p->busy_timer); 
01746          }
01747          break;
01748       case AST_CONTROL_RINGING:
01749          if (ast->_state == AST_STATE_UP) {
01750             playtone(p->handle, &Ringbacktone);
01751             p->state = VPB_STATE_PLAYRING;
01752             if (option_verbose > 3)
01753                ast_verbose(VERBOSE_PREFIX_4 "%s: vpb indicate: setting ringback timer [%d]\n", p->dev,p->ringback_timer_id);
01754             
01755             vpb_timer_stop(p->ringback_timer);
01756             vpb_timer_start(p->ringback_timer);
01757          }
01758          break;       
01759       case AST_CONTROL_ANSWER:
01760       case -1: /* -1 means stop playing? */
01761          vpb_timer_stop(p->ringback_timer);
01762          vpb_timer_stop(p->busy_timer);
01763          stoptone(p->handle);
01764          break;
01765       case AST_CONTROL_HANGUP:
01766          if (ast->_state == AST_STATE_UP) {
01767             playtone(p->handle, &Busytone);
01768             p->state = VPB_STATE_PLAYBUSY;
01769             vpb_timer_stop(p->busy_timer);
01770             vpb_timer_start(p->busy_timer);
01771          }
01772          break;
01773 
01774       default:
01775          res = 0;
01776          break;
01777    }
01778    tmp = ast_mutex_unlock(&p->lock);
01779 /*
01780    if (option_verbose > 3) ast_verbose("%s: unLOCKING in indicate [%d]\n", p->dev,tmp);
01781 */
01782    return res;
01783 }

static struct ast_channel * vpb_new ( struct vpb_pvt i,
int  state,
char *  context 
) [static, read]

Definition at line 2609 of file chan_vpb.c.

References ast_callerid_split(), ast_channel_alloc(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_update_use_count(), ast_verbose(), vpb_pvt::bridge, vpb_pvt::callerid, vpb_pvt::callgroup, ast_channel::callgroup, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, cid_name, ast_callerid::cid_num, cid_num, ast_channel::context, vpb_pvt::dev, vpb_pvt::ext, ast_channel::exten, vpb_pvt::faxhandled, ast_channel::language, vpb_pvt::language, vpb_pvt::last_ignore_dtmf, vpb_pvt::lastgrunt, vpb_pvt::lastinput, vpb_pvt::lastoutput, vpb_pvt::lastplay, LOG_WARNING, vpb_pvt::mode, MODE_FXO, ast_channel::name, ast_channel::nativeformats, option_verbose, vpb_pvt::owner, vpb_pvt::pickupgroup, ast_channel::pickupgroup, vpb_pvt::play_dtmf, prefformat, ast_channel::rawreadformat, ast_channel::rawwriteformat, vpb_pvt::readthread, ast_channel::rings, strdup, ast_channel::tech, ast_channel::tech_pvt, type, ast_channel::type, use_ast_ind, usecnt, usecnt_lock, vpb_answer(), vpb_tech, and vpb_tech_indicate.

Referenced by monitor_handle_notowned(), and vpb_request().

02610 {
02611    struct ast_channel *tmp; 
02612    char cid_num[256];
02613    char cid_name[256];
02614 
02615    if (me->owner) {
02616        ast_log(LOG_WARNING, "Called vpb_new on owned channel (%s) ?!\n", me->dev);
02617        return NULL;
02618    }
02619    if (option_verbose > 3)
02620       ast_verbose("%s: New call for context [%s]\n",me->dev,context);
02621        
02622    tmp = ast_channel_alloc(1);
02623    if (tmp) {
02624       if (use_ast_ind == 1){
02625          tmp->tech = &vpb_tech_indicate;
02626       }
02627       else {
02628          tmp->tech = &vpb_tech;
02629       }
02630 
02631       strncpy(tmp->name, me->dev, sizeof(tmp->name) - 1);
02632       tmp->type = type;
02633       
02634       tmp->callgroup = me->callgroup;
02635       tmp->pickupgroup = me->pickupgroup;
02636           
02637       /* Linear is the preferred format. Although Voicetronix supports other formats
02638        * they are all converted to/from linear in the vpb code. Best for us to use
02639        * linear since we can then adjust volume in this modules.
02640        */
02641       tmp->nativeformats = prefformat;
02642       tmp->rawreadformat = AST_FORMAT_SLINEAR;
02643       tmp->rawwriteformat =  AST_FORMAT_SLINEAR;
02644       ast_setstate(tmp, state);
02645       if (state == AST_STATE_RING) {
02646          tmp->rings = 1;
02647          cid_name[0] = '\0';
02648          cid_num[0] = '\0';
02649          ast_callerid_split(me->callerid, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
02650          if (!ast_strlen_zero(cid_num)) {
02651             tmp->cid.cid_num = strdup(cid_num);
02652             tmp->cid.cid_ani = strdup(cid_num);
02653          }
02654          if (!ast_strlen_zero(cid_name))
02655             tmp->cid.cid_name = strdup(cid_name);
02656       }
02657       tmp->tech_pvt = me;
02658       
02659       strncpy(tmp->context, context, sizeof(tmp->context)-1);
02660       if (strlen(me->ext))
02661          strncpy(tmp->exten, me->ext, sizeof(tmp->exten)-1);
02662       else
02663          strncpy(tmp->exten, "s",  sizeof(tmp->exten) - 1);
02664       if (strlen(me->language))
02665          strncpy(tmp->language, me->language, sizeof(tmp->language)-1);
02666 
02667       me->owner = tmp;
02668      
02669          me->bridge = NULL;
02670       me->lastoutput = -1;
02671       me->lastinput = -1;
02672       me->last_ignore_dtmf = 1;
02673       me->readthread = 0;
02674       me->play_dtmf[0] = '\0';
02675       me->faxhandled =0;
02676       
02677       me->lastgrunt  = ast_tvnow(); /* Assume at least one grunt tone seen now. */
02678       me->lastplay  = ast_tvnow(); /* Assume at least one grunt tone seen now. */
02679 
02680       ast_mutex_lock(&usecnt_lock);
02681       usecnt++;
02682       ast_mutex_unlock(&usecnt_lock);
02683       ast_update_use_count();
02684       if (state != AST_STATE_DOWN) {
02685          if ((me->mode != MODE_FXO)&&(state != AST_STATE_UP)){
02686             vpb_answer(tmp);
02687          }
02688          if (ast_pbx_start(tmp)) {
02689             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
02690             ast_hangup(tmp);
02691             }
02692       }
02693    } else {
02694       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02695    }
02696    return tmp;
02697 }

static struct ast_frame * vpb_read ( struct ast_channel ast  )  [static, read]

Definition at line 2176 of file chan_vpb.c.

References AST_FRAME_NULL, and ast_channel::tech_pvt.

02177 {
02178    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt; 
02179    static struct ast_frame f = {AST_FRAME_NULL}; 
02180 
02181    f.src = (char *)type;
02182    ast_log(LOG_NOTICE, "%s: vpb_read: should never be called!\n", p->dev);
02183    ast_verbose("%s: vpb_read: should never be called!\n", p->dev);
02184 
02185    return &f;
02186 }

static struct ast_channel * vpb_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static, read]

Definition at line 2699 of file chan_vpb.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, ast_verbose(), vpb_pvt::context, vpb_pvt::dev, free, vpb_pvt::group, group, iflist, LOG_NOTICE, ast_channel::name, name, vpb_pvt::next, option_verbose, vpb_pvt::owner, prefformat, restart_monitor(), s, strdup, strsep(), VERBOSE_PREFIX_2, and vpb_new().

02700 {
02701    int oldformat;
02702    struct vpb_pvt *p;
02703    struct ast_channel *tmp = NULL;
02704    char *name = strdup(data ? (char *)data : "");
02705    char *s, *sepstr;
02706    int group=-1;
02707 
02708    oldformat = format;
02709    format &= prefformat;
02710    if (!format) {
02711       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
02712       return NULL;
02713    }
02714 
02715    sepstr = name;
02716    s = strsep(&sepstr, "/"); /* Handle / issues */
02717    if (!s) 
02718       s = "";
02719    /* Check if we are looking for a group */
02720    if (toupper(name[0]) == 'G' || toupper(name[0])=='R') {
02721       group=atoi(name+1);  
02722    }
02723    /* Search for an unowned channel */
02724    ast_mutex_lock(&iflock); {
02725       p = iflist;
02726       while(p) {
02727          if (group == -1){
02728             if (strncmp(s, p->dev + 4, sizeof p->dev) == 0) {
02729                if (!p->owner) {
02730                   tmp = vpb_new(p, AST_STATE_DOWN, p->context);
02731                   break;
02732                }
02733             }
02734          }
02735          else {
02736             if ((p->group == group) && (!p->owner)) {
02737                tmp = vpb_new(p, AST_STATE_DOWN, p->context);
02738                break;
02739             }
02740          }
02741          p = p->next;
02742       }
02743    } ast_mutex_unlock(&iflock);
02744 
02745 
02746    if (option_verbose > 1) 
02747       ast_verbose(VERBOSE_PREFIX_2 " %s requested, got: [%s]\n",
02748       name, tmp ? tmp->name : "None");
02749 
02750    free(name);
02751 
02752    restart_monitor();
02753    return tmp;
02754 }

static int vpb_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 2251 of file chan_vpb.c.

References ast_channel::_state, a_gain_vector(), ast2vpbformat(), ast2vpbformatname(), AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, ast_verbose(), vpb_pvt::chuck_count, ast_frame::data, ast_frame::datalen, vpb_pvt::dev, fmt, ast_frame::frametype, vpb_pvt::handle, vpb_pvt::lastoutput, vpb_pvt::lastplay, LOG_DEBUG, LOG_WARNING, MAX_VPB_GAIN, ast_channel::name, option_verbose, vpb_pvt::play_buf_time, vpb_pvt::play_lock, vpb_pvt::read_state, ast_frame::subclass, ast_channel::tech_pvt, vpb_pvt::txswgain, and VPB_SAMPLES.

02252 {
02253    struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt; 
02254    int res = 0, fmt = 0;
02255    struct timeval play_buf_time_start;
02256    struct ast_frame *nextf;
02257    int tdiff;
02258 
02259 /* ast_mutex_lock(&p->lock); */
02260    if(option_verbose>5) 
02261       ast_verbose("%s: vpb_write: Writing to channel\n", p->dev);
02262 
02263    if (frame->frametype != AST_FRAME_VOICE) {
02264       if(option_verbose>3) 
02265          ast_verbose("%s: vpb_write: Don't know how to handle from type %d\n", ast->name, frame->frametype);
02266 /*    ast_mutex_unlock(&p->lock); */
02267       return 0;
02268    } else if (ast->_state != AST_STATE_UP) {
02269       if(option_verbose>3) 
02270          ast_verbose("%s: vpb_write: Attempt to Write frame type[%d]subclass[%d] on not up chan(state[%d])\n",ast->name, frame->frametype, frame->subclass,ast->_state);
02271       p->lastoutput = -1;
02272 /*    ast_mutex_unlock(&p->lock); */
02273       return 0;
02274    }
02275 /* ast_log(LOG_DEBUG, "%s: vpb_write: Checked frame type..\n", p->dev); */
02276 
02277 
02278    fmt = ast2vpbformat(frame->subclass);
02279    if (fmt < 0) {
02280       ast_log(LOG_WARNING, "%s: vpb_write: Cannot handle frames of %d format!\n",ast->name, frame->subclass);
02281       return -1;
02282    }
02283 
02284    tdiff = ast_tvdiff_ms(ast_tvnow(), p->lastplay);
02285    ast_log(LOG_DEBUG, "%s: vpb_write: time since last play(%d) \n", p->dev, tdiff); 
02286    if (tdiff < (VPB_SAMPLES/8 - 1)){
02287       ast_log(LOG_DEBUG, "%s: vpb_write: Asked to play too often (%d) (%d)\n", p->dev, tdiff,frame->datalen); 
02288 //    return 0;
02289    }
02290    p->lastplay = ast_tvnow();
02291 /*
02292    ast_log(LOG_DEBUG, "%s: vpb_write: Checked frame format..\n", p->dev); 
02293 */
02294 
02295    ast_mutex_lock(&p->play_lock);
02296 
02297 /*
02298    ast_log(LOG_DEBUG, "%s: vpb_write: Got play lock..\n", p->dev); 
02299 */
02300 
02301    /* Check if we have set up the play_buf */
02302    if (p->lastoutput == -1) {
02303       vpb_play_buf_start(p->handle, fmt);
02304       if(option_verbose>1) {
02305          ast_verbose("%s: vpb_write: Starting play mode (codec=%d)[%s]\n",p->dev,fmt,ast2vpbformatname(frame->subclass));
02306       }
02307       p->lastoutput = fmt;
02308       ast_mutex_unlock(&p->play_lock);
02309       return 0;
02310    } else if (p->lastoutput != fmt) {
02311       vpb_play_buf_finish(p->handle);
02312       vpb_play_buf_start(p->handle, fmt);
02313       if(option_verbose>1) 
02314          ast_verbose("%s: vpb_write: Changed play format (%d=>%d)\n",p->dev,p->lastoutput,fmt);
02315       ast_mutex_unlock(&p->play_lock);
02316       return 0;
02317    }
02318    p->lastoutput = fmt;
02319 
02320 
02321 
02322    /* Apply extra gain ! */
02323    if( p->txswgain > MAX_VPB_GAIN )
02324       a_gain_vector(p->txswgain - MAX_VPB_GAIN , (short*)frame->data, frame->datalen/sizeof(short));
02325 
02326 /* ast_log(LOG_DEBUG, "%s: vpb_write: Applied gain..\n", p->dev); */
02327 /* ast_log(LOG_DEBUG, "%s: vpb_write: play_buf_time %d\n", p->dev, p->play_buf_time); */
02328 
02329    if ((p->read_state == 1)&&(p->play_buf_time<5)){
02330       play_buf_time_start = ast_tvnow();
02331 /*    res = vpb_play_buf_sync(p->handle, (char*)frame->data, tdiff*8*2); */
02332       res = vpb_play_buf_sync(p->handle, (char*)frame->data, frame->datalen);
02333       if( res == VPB_OK && option_verbose > 5 ) {
02334          short * data = (short*)frame->data;
02335          ast_verbose("%s: vpb_write: Wrote chan (codec=%d) %d %d\n", p->dev, fmt, data[0],data[1]);
02336       }
02337       p->play_buf_time = ast_tvdiff_ms(ast_tvnow(), play_buf_time_start);
02338    }
02339    else {
02340       p->chuck_count++;
02341       ast_log(LOG_DEBUG, "%s: vpb_write: Tossed data away, tooooo much data!![%d]\n", p->dev,p->chuck_count);
02342       p->play_buf_time=0;
02343    }
02344 
02345    ast_mutex_unlock(&p->play_lock);
02346 /* ast_mutex_unlock(&p->lock); */
02347    if(option_verbose>5) 
02348       ast_verbose("%s: vpb_write: Done Writing to channel\n", p->dev);
02349    return 0;
02350 }


Variable Documentation

int break_for_dtmf = 1 [static]

Definition at line 177 of file chan_vpb.c.

Referenced by load_module().

vpb_bridge_t* bridges [static]

Definition at line 245 of file chan_vpb.c.

Referenced by unload_module().

VPB_TONE Busytone = {470, 0, 0, -10, -100, -100, 5000, 0 } [static]

Definition at line 143 of file chan_vpb.c.

const char config[] = "vpb.conf" [static]

Definition at line 98 of file chan_vpb.c.

char context[AST_MAX_EXTENSION] = "default" [static]

Definition at line 101 of file chan_vpb.c.

const char desc[] = "VoiceTronix V6PCI/V12PCI/V4PCI API Support" [static]

Definition at line 95 of file chan_vpb.c.

VPB_TONE Dialtone = {440, 440, 440, -10, -10, -10, 5000, 0 } [static]

Definition at line 142 of file chan_vpb.c.

VPB_TONE_MAP DialToneMap[]

Definition at line 206 of file chan_vpb.c.

int dtmf_idd = 3000 [static]

Definition at line 183 of file chan_vpb.c.

Referenced by load_module().

int ec_supp_threshold = -1 [static]

Definition at line 180 of file chan_vpb.c.

Referenced by load_module().

int gruntdetect_timeout = 3600000 [static]

Definition at line 107 of file chan_vpb.c.

Referenced by load_module().

struct vpb_pvt * iflist [static]

char language[MAX_LANGUAGE] = "" [static]

Definition at line 104 of file chan_vpb.c.

int max_bridges = MAX_BRIDGES_V4PCI [static]

Definition at line 246 of file chan_vpb.c.

Referenced by unload_module().

pthread_t monitor_thread [static]

Definition at line 122 of file chan_vpb.c.

int mthreadactive = -1 [static]

Definition at line 124 of file chan_vpb.c.

Referenced by unload_module().

const int prefformat = AST_FORMAT_SLINEAR [static]

Definition at line 109 of file chan_vpb.c.

int relaxdtmf = 0 [static]

Definition at line 171 of file chan_vpb.c.

VPB_TONE Ringbacktone = {400, 50, 440, -10, -10, -10, 1400, 800 } [static]

Definition at line 144 of file chan_vpb.c.

const char tdesc[] = "Standard VoiceTronix API Driver" [static]

Definition at line 97 of file chan_vpb.c.

int timer_period_ring = TIMER_PERIOD_RING [static]

Definition at line 188 of file chan_vpb.c.

Referenced by load_module().

VPB_DETECT toned_grunt = { 3, VPB_GRUNT, 1, 2000, 3000, 0, 0, -40, 0, 0, 0, 40, { { VPB_DELAY, 1000, 0, 0 }, { VPB_RISING, 0, 40, 0 }, { 0, 100, 0, 0 } } } [static]

Definition at line 153 of file chan_vpb.c.

VPB_DETECT toned_ungrunt = { 2, VPB_GRUNT, 1, 2000, 1, 0, 0, -40, 0, 0, 30, 40, { { 0, 0, 0, 0 } } } [static]

Definition at line 154 of file chan_vpb.c.

const char type[] = "vpb" [static]

Definition at line 96 of file chan_vpb.c.

int use_ast_dtmf = 0 [static]

Definition at line 174 of file chan_vpb.c.

Referenced by load_module().

int use_ast_dtmfdet = 0 [static]

Definition at line 169 of file chan_vpb.c.

Referenced by do_chanreads(), and load_module().

int use_ast_ind = 0 [static]

Definition at line 166 of file chan_vpb.c.

Referenced by load_module(), unload_module(), and vpb_new().

int usecnt = 0 [static]

Definition at line 105 of file chan_vpb.c.

int UseLoopDrop = 1 [static]

Definition at line 160 of file chan_vpb.c.

Referenced by load_module().

int UseNativeBridge = 1 [static]

Definition at line 163 of file chan_vpb.c.

Referenced by load_module().

int UsePolarityCID = 0 [static]

Definition at line 157 of file chan_vpb.c.

Referenced by load_module().

struct ast_channel_tech vpb_tech [static]

Definition at line 351 of file chan_vpb.c.

Referenced by load_module(), unload_module(), and vpb_new().

Definition at line 378 of file chan_vpb.c.

Referenced by load_module(), unload_module(), and vpb_new().


Generated on Wed Oct 28 15:48:38 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6