Asterisk.org: Developer Documentation (28 Oct 2009)

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_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 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_channel * | vpb_new (struct vpb_pvt *i, int state, char *context)
static struct ast_frame * | vpb_read (struct ast_channel *ast)
static struct ast_channel * | vpb_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_t * | bridges
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_pvt * | iflist
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

enum vpb_model_t

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().

struct ast_channel_tech vpb_tech_indicate`[static]`

Definition at line 378 of file chan_vpb.c.

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