2003-04-15 14:39:06 +00:00
/*
2005-09-14 20:46:50 +00:00
* Asterisk - - An open source telephony toolkit .
2003-04-15 14:39:06 +00:00
*
* Copyright ( C ) 2003 , Paul Bagyenda
* Paul Bagyenda < bagyenda @ dsmagic . com >
2005-01-21 07:06:25 +00:00
* Copyright ( C ) 2004 - 2005 , Ben Kramer
2004-05-26 01:29:29 +00:00
* Ben Kramer < ben @ voicetronix . com . au >
2003-04-15 14:39:06 +00:00
*
2004-09-17 00:14:48 +00:00
* Daniel Bichara < daniel @ bichara . com . br > - Brazilian CallerID detection ( c ) 2004
*
* Welber Silveira - welberms @ magiclink . com . br - ( c ) 2004
* Copying CLID string to propper structure after detection
*
2005-09-14 20:46:50 +00:00
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
* the project provides a web site , mailing lists and IRC
* channels for your use .
*
2003-04-15 14:39:06 +00:00
* This program is free software , distributed under the terms of
2005-09-14 20:46:50 +00:00
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree .
*/
2005-10-24 20:12:06 +00:00
/*! \file
2005-09-14 20:46:50 +00:00
*
2005-10-24 20:12:06 +00:00
* \ brief VoiceTronix Interface driver
2005-09-14 20:46:50 +00:00
*
2005-11-06 15:09:47 +00:00
* \ ingroup channel_drivers
2003-04-15 14:39:06 +00:00
*/
2006-04-24 17:11:45 +00:00
/*** MODULEINFO
< depend > vpbapi < / depend >
* * */
2004-05-14 04:39:16 +00:00
2004-11-29 23:20:16 +00:00
extern " C " {
2005-06-06 21:09:59 +00:00
# include "asterisk.h"
2005-06-06 23:12:05 +00:00
ASTERISK_FILE_VERSION ( __FILE__ , " $Revision$ " )
2005-06-06 21:09:59 +00:00
2006-06-07 18:54:56 +00:00
# include <stdio.h>
# include <string.h>
2005-04-21 06:02:45 +00:00
# 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"
2006-07-19 20:44:39 +00:00
# include "asterisk/musiconhold.h"
2004-11-29 23:20:16 +00:00
}
2003-04-15 14:39:06 +00:00
# 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>
2004-04-05 05:37:01 +00:00
# include <ctype.h>
2003-04-15 14:39:06 +00:00
# include <vpbapi.h>
2004-05-26 01:29:29 +00:00
# include <assert.h>
2003-04-15 14:39:06 +00:00
2004-08-18 05:06:26 +00:00
# ifdef pthread_create
# undef pthread_create
# endif
2004-03-31 04:29:55 +00:00
# define DEFAULT_GAIN 0
# define DEFAULT_ECHO_CANCEL 1
2004-07-15 01:24:15 +00:00
# define VPB_SAMPLES 160
2003-04-18 14:34:46 +00:00
# define VPB_MAX_BUF VPB_SAMPLES*4 + AST_FRIENDLY_OFFSET
2003-04-15 14:39:06 +00:00
# define VPB_NULL_EVENT 200
2004-05-14 04:39:16 +00:00
# define VPB_WAIT_TIMEOUT 4000
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
# define MAX_VPB_GAIN 12.0
2005-02-17 04:58:03 +00:00
# define MIN_VPB_GAIN -12.0
2004-03-31 04:29:55 +00:00
2004-12-15 22:59:47 +00:00
# define DTMF_CALLERID
# define DTMF_CID_START 'D'
# define DTMF_CID_STOP 'C'
2004-11-29 23:20:16 +00:00
/**/
2003-04-15 14:39:06 +00:00
# if defined(__cplusplus) || defined(c_plusplus)
extern " C " {
# endif
2004-11-29 23:20:16 +00:00
/**/
2003-04-15 14:39:06 +00:00
2005-03-04 06:47:24 +00:00
static const char desc [ ] = " VoiceTronix V6PCI/V12PCI/V4PCI API Support " ;
static const char tdesc [ ] = " Standard VoiceTronix API Driver " ;
static const char config [ ] = " vpb.conf " ;
2003-04-15 14:39:06 +00:00
/* Default context for dialtone mode */
static char context [ AST_MAX_EXTENSION ] = " default " ;
/* Default language */
static char language [ MAX_LANGUAGE ] = " " ;
2004-03-31 04:29:55 +00:00
static int gruntdetect_timeout = 3600000 ; /* Grunt detect timeout is 1hr. */
2003-05-04 05:56:50 +00:00
2004-03-31 04:29:55 +00:00
static const int prefformat = AST_FORMAT_SLINEAR ;
2003-04-15 14:39:06 +00:00
/* Protect the interface list (of vpb_pvt's) */
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( iflock ) ;
2003-04-15 14:39:06 +00:00
/* Protect the monitoring thread, so only one process can kill or start it, and not
when it ' s doing something critical . */
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( monlock ) ;
2003-04-15 14:39:06 +00:00
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use . */
2003-08-24 06:27:34 +00:00
static pthread_t monitor_thread ;
2003-04-15 14:39:06 +00:00
static int mthreadactive = - 1 ; /* Flag for monitoring monitorthread.*/
static int restart_monitor ( void ) ;
2004-03-31 04:29:55 +00:00
/* The private structures of the VPB channels are
linked for selecting outgoing channels */
2003-04-15 14:39:06 +00:00
# define MODE_DIALTONE 1
# define MODE_IMMEDIATE 2
# define MODE_FXO 3
2004-03-31 04:29:55 +00:00
/* Pick a country or add your own! */
2004-09-17 00:14:48 +00:00
/* These are the tones that are played to the user */
2004-03-31 04:29:55 +00:00
# define TONES_AU
2004-12-23 01:46:39 +00:00
/* #define TONES_USA */
2004-03-31 04:29:55 +00:00
# ifdef TONES_AU
static VPB_TONE Dialtone = { 440 , 440 , 440 , - 10 , - 10 , - 10 , 5000 , 0 } ;
static VPB_TONE Busytone = { 470 , 0 , 0 , - 10 , - 100 , - 100 , 5000 , 0 } ;
static VPB_TONE Ringbacktone = { 400 , 50 , 440 , - 10 , - 10 , - 10 , 1400 , 800 } ;
# endif
# ifdef TONES_USA
2004-12-23 01:46:39 +00:00
static VPB_TONE Dialtone = { 350 , 440 , 0 , - 16 , - 16 , - 100 , 10000 , 0 } ;
static VPB_TONE Busytone = { 480 , 620 , 0 , - 10 , - 10 , - 100 , 500 , 500 } ;
static VPB_TONE Ringbacktone = { 440 , 480 , 0 , - 20 , - 20 , - 100 , 2000 , 4000 } ;
2004-03-31 04:29:55 +00:00
# endif
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
/* grunt tone defn's */
2006-02-23 17:13:57 +00:00
#if 0
2004-03-31 04:29:55 +00:00
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 } } } ;
2006-02-23 17:13:57 +00:00
# endif
2004-03-31 04:29:55 +00:00
static VPB_DETECT toned_ungrunt = { 2 , VPB_GRUNT , 1 , 2000 , 1 , 0 , 0 , - 40 , 0 , 0 , 30 , 40 , { { 0 , 0 , 0 , 0 } } } ;
2003-04-15 14:39:06 +00:00
2005-11-01 23:20:46 +00:00
/* Use loop polarity detection for CID */
static int UsePolarityCID = 0 ;
2004-05-14 04:39:16 +00:00
/* Use loop drop detection */
static int UseLoopDrop = 1 ;
2004-08-18 05:06:26 +00:00
/* To use or not to use Native bridging */
static int UseNativeBridge = 1 ;
2004-11-30 04:14:27 +00:00
/* Use Asterisk Indication or VPB */
static int use_ast_ind = 0 ;
2005-02-21 00:48:35 +00:00
/* Use Asterisk DTMF detection or VPB */
static int use_ast_dtmfdet = 0 ;
static int relaxdtmf = 0 ;
/* Use Asterisk DTMF play back or VPB */
static int use_ast_dtmf = 0 ;
2005-02-21 04:30:42 +00:00
/* Break for DTMF on native bridge ? */
static int break_for_dtmf = 1 ;
2005-01-31 04:51:41 +00:00
/* Set EC suppression threshold */
static int ec_supp_threshold = - 1 ;
2005-01-31 23:51:19 +00:00
/* Inter Digit Delay for collecting DTMF's */
static int dtmf_idd = 3000 ;
2004-05-24 01:43:05 +00:00
# define TIMER_PERIOD_RINGBACK 2000
2004-03-31 04:29:55 +00:00
# define TIMER_PERIOD_BUSY 700
2005-01-14 04:51:20 +00:00
# define TIMER_PERIOD_RING 4000
2005-06-22 23:54:47 +00:00
static int timer_period_ring = TIMER_PERIOD_RING ;
2004-03-31 04:29:55 +00:00
# define VPB_EVENTS_ALL (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 )
2004-08-18 05:06:26 +00:00
# define VPB_EVENTS_NODROP (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 )
2004-03-31 04:29:55 +00:00
# define VPB_EVENTS_NODTMF (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 )
# define VPB_EVENTS_STAT (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 )
2004-12-18 22:04:07 +00:00
/* Dialing parameters for Australia */
/* #define DIAL_WITH_CALL_PROGRESS */
2004-03-31 04:29:55 +00:00
VPB_TONE_MAP DialToneMap [ ] = { { VPB_BUSY_AUST , VPB_CALL_DISCONNECT , 0 } ,
{ VPB_DIAL , VPB_CALL_DIALTONE , 0 } ,
{ VPB_RINGBACK_308 , VPB_CALL_RINGBACK , 0 } ,
{ VPB_BUSY_AUST , VPB_CALL_BUSY , 0 } ,
{ VPB_GRUNT , VPB_CALL_GRUNT , 0 } ,
{ 0 , 0 , 1 } } ;
# define VPB_DIALTONE_WAIT 2000 /* Wait up to 2s for a dialtone */
# define VPB_RINGWAIT 4000 /* Wait up to 4s for ring tone after dialing */
# define VPB_CONNECTED_WAIT 4000 /* If no ring tone detected for 4s then consider call connected */
# define TIMER_PERIOD_NOANSWER 120000 /* Let it ring for 120s before deciding theres noone there */
# define MAX_BRIDGES_V4PCI 2
# define MAX_BRIDGES_V12PCI 128
/* port states */
# define VPB_STATE_ONHOOK 0
# define VPB_STATE_OFFHOOK 1
# define VPB_STATE_DIALLING 2
# define VPB_STATE_JOINED 3
# define VPB_STATE_GETDTMF 4
# define VPB_STATE_PLAYDIAL 5
# define VPB_STATE_PLAYBUSY 6
# define VPB_STATE_PLAYRING 7
2005-02-17 04:58:03 +00:00
# define VPB_GOT_RXHWG 1
# define VPB_GOT_TXHWG 2
# define VPB_GOT_RXSWG 4
# define VPB_GOT_TXSWG 8
2004-03-31 04:29:55 +00:00
typedef struct {
2004-04-05 05:37:01 +00:00
int inuse ;
struct ast_channel * c0 , * c1 , * * rc ;
struct ast_frame * * fo ;
int flags ;
ast_mutex_t lock ;
2005-11-01 23:20:46 +00:00
ast_cond_t cond ;
2004-04-05 05:37:01 +00:00
int endbridge ;
2004-03-31 04:29:55 +00:00
} vpb_bridge_t ;
2004-05-26 01:29:29 +00:00
2004-03-31 04:29:55 +00:00
static vpb_bridge_t * bridges ;
static int max_bridges = MAX_BRIDGES_V4PCI ;
2003-04-18 14:34:46 +00:00
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( bridge_lock ) ;
2003-04-18 14:34:46 +00:00
2004-03-31 04:29:55 +00:00
typedef enum {
2004-04-05 05:37:01 +00:00
vpb_model_unknown = 0 ,
vpb_model_v4pci ,
vpb_model_v12pci
2004-03-31 04:29:55 +00:00
} vpb_model_t ;
2003-04-15 14:39:06 +00:00
static struct vpb_pvt {
2004-04-05 05:37:01 +00:00
ast_mutex_t owner_lock ; /* Protect blocks that expect ownership to remain the same */
2004-05-21 02:51:05 +00:00
struct ast_channel * owner ; /* Channel who owns us, possibly NULL */
int golock ; /* Got owner lock ? */
2003-04-15 14:39:06 +00:00
2004-04-05 05:37:01 +00:00
int mode ; /* fxo/imediate/dialtone*/
int handle ; /* Handle for vpb interface */
2003-04-15 14:39:06 +00:00
2004-04-05 05:37:01 +00:00
int state ; /* used to keep port state (internal to driver) */
2003-04-15 14:39:06 +00:00
2004-04-05 05:37:01 +00:00
int group ; /* Which group this port belongs to */
2005-03-16 04:53:30 +00:00
ast_group_t callgroup ; /* Call group */
ast_group_t pickupgroup ; /* Pickup group */
2003-04-15 14:39:06 +00:00
2004-05-20 01:59:03 +00:00
char dev [ 256 ] ; /* Device name, eg vpb/1-1 */
vpb_model_t vpb_model ; /* card model */
2003-04-15 14:39:06 +00:00
2004-05-20 01:59:03 +00:00
struct ast_frame f , fr ; /* Asterisk frame interface */
2004-04-05 05:37:01 +00:00
char buf [ VPB_MAX_BUF ] ; /* Static buffer for reading frames */
2003-05-04 05:56:50 +00:00
2004-05-20 01:59:03 +00:00
int dialtone ; /* NOT USED */
2004-04-05 05:37:01 +00:00
float txgain , rxgain ; /* Hardware gain control */
float txswgain , rxswgain ; /* Software gain control */
2004-03-31 04:29:55 +00:00
2004-04-05 05:37:01 +00:00
int wantdtmf ; /* Waiting for DTMF. */
2004-05-20 01:59:03 +00:00
char context [ AST_MAX_EXTENSION ] ; /* The context for this channel */
2003-04-15 14:39:06 +00:00
2004-05-20 01:59:03 +00:00
char ext [ AST_MAX_EXTENSION ] ; /* DTMF buffer for the ext[ens] */
char language [ MAX_LANGUAGE ] ; /* language being used */
2004-04-05 05:37:01 +00:00
char callerid [ AST_MAX_EXTENSION ] ; /* CallerId used for directly connected phone */
2005-01-18 03:24:41 +00:00
int callerid_type ; /* Caller ID type: 0=>none 1=>vpb 2=>AstV23 3=>AstBell */
2005-11-01 23:20:46 +00:00
char cid_num [ AST_MAX_EXTENSION ] ;
char cid_name [ AST_MAX_EXTENSION ] ;
2004-03-31 04:29:55 +00:00
2004-12-15 22:59:47 +00:00
int dtmf_caller_pos ; /* DTMF CallerID detection (Brazil)*/
2004-09-17 00:14:48 +00:00
2004-05-20 01:59:03 +00:00
int lastoutput ; /* Holds the last Audio format output'ed */
int lastinput ; /* Holds the last Audio format input'ed */
2004-04-05 05:37:01 +00:00
int last_ignore_dtmf ;
2004-05-20 01:59:03 +00:00
void * busy_timer ; /* Void pointer for busy vpb_timer */
int busy_timer_id ; /* unique timer ID for busy timer */
2004-04-05 05:37:01 +00:00
2004-05-20 01:59:03 +00:00
void * ringback_timer ; /* Void pointer for ringback vpb_timer */
int ringback_timer_id ; /* unique timer ID for ringback timer */
2004-04-05 05:37:01 +00:00
2005-01-14 04:51:20 +00:00
void * ring_timer ; /* Void pointer for ring vpb_timer */
int ring_timer_id ; /* unique timer ID for ring timer */
2005-01-31 23:51:19 +00:00
void * dtmfidd_timer ; /* Void pointer for DTMF IDD vpb_timer */
int dtmfidd_timer_id ; /* unique timer ID for DTMF IDD timer */
2005-02-21 00:48:35 +00:00
struct ast_dsp * vad ; /* AST Voice Activation Detection dsp */
2005-07-15 23:00:47 +00:00
struct timeval lastgrunt ; /* time stamp of last grunt event */
2004-04-05 05:37:01 +00:00
ast_mutex_t lock ; /* This one just protects bridge ptr below */
vpb_bridge_t * bridge ;
int stopreads ; /* Stop reading...*/
2004-08-18 05:06:26 +00:00
int read_state ; /* Read state */
int chuck_count ; /* a count of packets weve chucked away!*/
2004-04-05 05:37:01 +00:00
pthread_t readthread ; /* For monitoring read channel. One per owned channel. */
ast_mutex_t record_lock ; /* This one prevents reentering a record_buf block */
ast_mutex_t play_lock ; /* This one prevents reentering a play_buf block */
2004-08-18 05:06:26 +00:00
int play_buf_time ; /* How long the last play_buf took */
2005-11-03 00:04:09 +00:00
struct timeval lastplay ; /* Last play time */
2004-04-05 05:37:01 +00:00
ast_mutex_t play_dtmf_lock ;
char play_dtmf [ 16 ] ;
2005-03-04 00:27:52 +00:00
int faxhandled ; /* has a fax tone been handled ? */
2004-04-05 05:37:01 +00:00
struct vpb_pvt * next ; /* Next channel in list */
2003-04-15 14:39:06 +00:00
} * iflist = NULL ;
2006-08-19 00:33:44 +00:00
static struct ast_channel * vpb_new ( struct vpb_pvt * i , enum ast_channel_state state , char * context ) ;
2004-03-31 04:29:55 +00:00
static void * do_chanreads ( void * pvt ) ;
2005-03-04 06:47:24 +00:00
static struct ast_channel * vpb_request ( const char * type , int format , void * data , int * cause ) ;
2006-08-31 01:59:02 +00:00
static int vpb_digit_begin ( struct ast_channel * ast , char digit ) ;
static int vpb_digit_end ( struct ast_channel * ast , char digit ) ;
2005-03-04 06:47:24 +00:00
static int vpb_call ( struct ast_channel * ast , char * dest , int timeout ) ;
static int vpb_hangup ( struct ast_channel * ast ) ;
static int vpb_answer ( struct ast_channel * ast ) ;
static struct ast_frame * vpb_read ( struct ast_channel * ast ) ;
static int vpb_write ( struct ast_channel * ast , struct ast_frame * frame ) ;
2006-02-02 21:49:36 +00:00
static enum ast_bridge_result ast_vpb_bridge ( struct ast_channel * c0 , struct ast_channel * c1 , int flags , struct ast_frame * * fo , struct ast_channel * * rc , int timeoutms ) ;
2006-05-10 12:24:11 +00:00
static int vpb_indicate ( struct ast_channel * ast , int condition , const void * data , size_t datalen ) ;
2005-03-04 06:47:24 +00:00
static int vpb_fixup ( struct ast_channel * oldchan , struct ast_channel * newchan ) ;
2005-04-13 04:15:23 +00:00
static struct ast_channel_tech vpb_tech = {
2006-02-02 21:49:36 +00:00
type : " vpb " ,
2005-03-21 00:05:57 +00:00
description : tdesc ,
capabilities : AST_FORMAT_SLINEAR ,
2006-02-02 21:49:36 +00:00
properties : 0 ,
2005-03-21 00:05:57 +00:00
requester : vpb_request ,
devicestate : NULL ,
2006-08-31 01:59:02 +00:00
send_digit_begin : vpb_digit_begin ,
send_digit_end : vpb_digit_end ,
2005-03-21 00:05:57 +00:00
call : vpb_call ,
hangup : vpb_hangup ,
answer : vpb_answer ,
read : vpb_read ,
write : vpb_write ,
send_text : NULL ,
send_image : NULL ,
send_html : NULL ,
exception : NULL ,
2006-02-02 21:49:36 +00:00
bridge : ast_vpb_bridge ,
2005-03-21 00:05:57 +00:00
indicate : vpb_indicate ,
fixup : vpb_fixup ,
setoption : NULL ,
queryoption : NULL ,
transfer : NULL ,
write_video : NULL ,
bridged_channel : NULL
2005-03-04 06:47:24 +00:00
} ;
2005-04-13 04:15:23 +00:00
static struct ast_channel_tech vpb_tech_indicate = {
2006-02-02 21:49:36 +00:00
type : " vpb " ,
2005-04-13 04:15:23 +00:00
description : tdesc ,
capabilities : AST_FORMAT_SLINEAR ,
2006-02-02 21:49:36 +00:00
properties : 0 ,
2005-04-13 04:15:23 +00:00
requester : vpb_request ,
devicestate : NULL ,
2006-08-31 01:59:02 +00:00
send_digit_begin : vpb_digit_begin ,
send_digit_end : vpb_digit_end ,
2005-04-13 04:15:23 +00:00
call : vpb_call ,
hangup : vpb_hangup ,
answer : vpb_answer ,
read : vpb_read ,
write : vpb_write ,
send_text : NULL ,
send_image : NULL ,
send_html : NULL ,
exception : NULL ,
2006-02-02 21:49:36 +00:00
bridge : ast_vpb_bridge ,
2005-04-13 04:15:23 +00:00
indicate : NULL ,
fixup : vpb_fixup ,
setoption : NULL ,
queryoption : NULL ,
transfer : NULL ,
write_video : NULL ,
bridged_channel : NULL
} ;
2006-02-02 21:49:36 +00:00
/* Can't get ast_vpb_bridge() working on v4pci without either a horrible
2004-12-18 22:04:07 +00:00
* high pitched feedback noise or bad hiss noise depending on gain settings
* Get asterisk to do the bridging
*/
2004-03-31 04:29:55 +00:00
# define BAD_V4PCI_BRIDGE
2004-12-18 22:04:07 +00:00
/* This one enables a half duplex bridge which may be required to prevent high pitched
* feedback when getting asterisk to do the bridging and when using certain gain settings .
*/
/* #define HALF_DUPLEX_BRIDGE */
2003-04-15 14:39:06 +00:00
2004-08-18 05:06:26 +00:00
/* This is the Native bridge code, which Asterisk will try before using its own bridging code */
2006-02-02 21:49:36 +00:00
static enum ast_bridge_result ast_vpb_bridge ( struct ast_channel * c0 , struct ast_channel * c1 , int flags , struct ast_frame * * fo , struct ast_channel * * rc , int timeoutms )
2003-04-18 14:34:46 +00:00
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p0 = ( struct vpb_pvt * ) c0 - > tech_pvt ;
struct vpb_pvt * p1 = ( struct vpb_pvt * ) c1 - > tech_pvt ;
2005-08-09 01:59:59 +00:00
int i ;
2005-08-14 22:56:34 +00:00
int res ;
2004-10-13 23:17:01 +00:00
struct ast_channel * cs [ 3 ] ;
struct ast_channel * who ;
struct ast_frame * f ;
cs [ 0 ] = c0 ;
cs [ 1 ] = c1 ;
2004-04-05 05:37:01 +00:00
# ifdef BAD_V4PCI_BRIDGE
if ( p0 - > vpb_model = = vpb_model_v4pci )
2005-08-09 01:59:59 +00:00
return AST_BRIDGE_FAILED_NOWARN ;
2004-04-05 05:37:01 +00:00
# endif
2004-08-18 05:06:26 +00:00
if ( UseNativeBridge ! = 1 ) {
2005-08-09 01:59:59 +00:00
return AST_BRIDGE_FAILED_NOWARN ;
2004-08-18 05:06:26 +00:00
}
2004-04-05 05:37:01 +00:00
2004-08-18 05:06:26 +00:00
/*
2004-05-21 02:51:05 +00:00
ast_mutex_lock ( & p0 - > lock ) ;
ast_mutex_lock ( & p1 - > lock ) ;
2004-08-18 05:06:26 +00:00
*/
2004-05-21 02:51:05 +00:00
2004-04-05 05:37:01 +00:00
/* Bridge channels, check if we can. I believe we always can, so find a slot.*/
ast_mutex_lock ( & bridge_lock ) ; {
for ( i = 0 ; i < max_bridges ; i + + )
if ( ! bridges [ i ] . inuse )
break ;
if ( i < max_bridges ) {
bridges [ i ] . inuse = 1 ;
bridges [ i ] . endbridge = 0 ;
bridges [ i ] . flags = flags ;
bridges [ i ] . rc = rc ;
bridges [ i ] . fo = fo ;
bridges [ i ] . c0 = c0 ;
bridges [ i ] . c1 = c1 ;
}
} ast_mutex_unlock ( & bridge_lock ) ;
if ( i = = max_bridges ) {
2005-02-21 04:30:42 +00:00
ast_log ( LOG_WARNING , " %s: vpb_bridge: Failed to bridge %s and %s! \n " , p0 - > dev , c0 - > name , c1 - > name ) ;
2004-05-21 02:51:05 +00:00
ast_mutex_unlock ( & p0 - > lock ) ;
ast_mutex_unlock ( & p1 - > lock ) ;
2005-08-09 01:59:59 +00:00
return AST_BRIDGE_FAILED_NOWARN ;
2004-03-31 04:29:55 +00:00
} else {
2004-04-05 05:37:01 +00:00
/* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/
ast_mutex_lock ( & p0 - > lock ) ; {
p0 - > bridge = & bridges [ i ] ;
} ast_mutex_unlock ( & p0 - > lock ) ;
ast_mutex_lock ( & p1 - > lock ) ; {
p1 - > bridge = & bridges [ i ] ;
} ast_mutex_unlock ( & p1 - > lock ) ;
if ( option_verbose > 1 )
2005-02-21 04:30:42 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: vpb_bridge: Bridging call entered with [%s, %s] \n " , p0 - > dev , c0 - > name , c1 - > name ) ;
2004-03-31 04:29:55 +00:00
}
2003-04-18 14:34:46 +00:00
2006-01-17 05:15:33 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " Native bridging %s and %s \n " , c0 - > name , c1 - > name ) ;
2004-04-05 05:37:01 +00:00
# ifdef HALF_DUPLEX_BRIDGE
2003-04-18 14:34:46 +00:00
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
2005-02-21 04:30:42 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: vpb_bridge: Starting half-duplex bridge [%s, %s] \n " , p0 - > dev , c0 - > name , c1 - > name ) ;
2004-04-05 05:37:01 +00:00
int dir = 0 ;
memset ( p0 - > buf , 0 , sizeof p0 - > buf ) ;
memset ( p1 - > buf , 0 , sizeof p1 - > buf ) ;
vpb_record_buf_start ( p0 - > handle , VPB_ALAW ) ;
vpb_record_buf_start ( p1 - > handle , VPB_ALAW ) ;
vpb_play_buf_start ( p0 - > handle , VPB_ALAW ) ;
vpb_play_buf_start ( p1 - > handle , VPB_ALAW ) ;
while ( ! bridges [ i ] . endbridge ) {
struct vpb_pvt * from , * to ;
if ( + + dir % 2 ) {
from = p0 ;
to = p1 ;
} else {
from = p1 ;
to = p0 ;
}
vpb_record_buf_sync ( from - > handle , from - > buf , VPB_SAMPLES ) ;
vpb_play_buf_sync ( to - > handle , from - > buf , VPB_SAMPLES ) ;
}
vpb_record_buf_finish ( p0 - > handle ) ;
vpb_record_buf_finish ( p1 - > handle ) ;
vpb_play_buf_finish ( p0 - > handle ) ;
vpb_play_buf_finish ( p1 - > handle ) ;
if ( option_verbose > 1 )
2005-02-21 04:30:42 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: vpb_bridge: Finished half-duplex bridge [%s, %s] \n " , p0 - > dev , c0 - > name , c1 - > name ) ;
2004-04-05 05:37:01 +00:00
res = VPB_OK ;
# else
res = vpb_bridge ( p0 - > handle , p1 - > handle , VPB_BRIDGE_ON , i + 1 /* resource 1 & 2 only for V4PCI*/ ) ;
if ( res = = VPB_OK ) {
2004-12-18 22:04:07 +00:00
/* pthread_cond_wait(&bridges[i].cond, &bridges[i].lock);*/ /* Wait for condition signal. */
2004-10-13 23:17:01 +00:00
while ( ! bridges [ i ] . endbridge ) {
2004-12-18 22:04:07 +00:00
/* Are we really ment to be doing nothing ?!?! */
2005-10-13 18:27:54 +00:00
who = ast_waitfor_n ( cs , 2 , & timeoutms ) ;
2004-10-13 23:17:01 +00:00
if ( ! who ) {
2005-10-14 17:02:20 +00:00
if ( ! timeoutms ) {
res = AST_BRIDGE_RETRY ;
break ;
}
2005-02-21 04:30:42 +00:00
ast_log ( LOG_DEBUG , " %s: vpb_bridge: Empty frame read... \n " , p0 - > dev ) ;
2004-10-13 23:17:01 +00:00
/* check for hangup / whentohangup */
if ( ast_check_hangup ( c0 ) | | ast_check_hangup ( c1 ) )
break ;
continue ;
}
f = ast_read ( who ) ;
if ( ! f | | ( ( f - > frametype = = AST_FRAME_DTMF ) & &
( ( ( who = = c0 ) & & ( flags & AST_BRIDGE_DTMF_CHANNEL_0 ) ) | |
( ( who = = c1 ) & & ( flags & AST_BRIDGE_DTMF_CHANNEL_1 ) ) ) ) ) {
* fo = f ;
* rc = who ;
2005-02-21 04:30:42 +00:00
ast_log ( LOG_DEBUG , " %s: vpb_bridge: Got a [%s] \n " , p0 - > dev , f ? " digit " : " hangup " ) ;
2004-10-13 23:17:01 +00:00
/*
2005-03-04 06:47:24 +00:00
if ( ( c0 - > tech_pvt = = pvt0 ) & & ( ! c0 - > _softhangup ) ) {
2004-10-13 23:17:01 +00:00
if ( pr0 - > set_rtp_peer ( c0 , NULL , NULL , 0 ) )
ast_log ( LOG_WARNING , " Channel '%s' failed to revert \n " , c0 - > name ) ;
}
2005-03-04 06:47:24 +00:00
if ( ( c1 - > tech_pvt = = pvt1 ) & & ( ! c1 - > _softhangup ) ) {
2004-10-13 23:17:01 +00:00
if ( pr1 - > set_rtp_peer ( c1 , NULL , NULL , 0 ) )
ast_log ( LOG_WARNING , " Channel '%s' failed to revert back \n " , c1 - > name ) ;
}
*/
/* That's all we needed */
2004-12-18 22:04:07 +00:00
/*return 0; */
2005-02-21 04:30:42 +00:00
/* Check if we need to break */
if ( break_for_dtmf ) {
break ;
}
else if ( ( f - > frametype = = AST_FRAME_DTMF ) & & ( ( f - > subclass = = ' # ' ) | | ( f - > subclass = = ' * ' ) ) ) {
break ;
}
2004-10-13 23:17:01 +00:00
} else {
if ( ( f - > frametype = = AST_FRAME_DTMF ) | |
( f - > frametype = = AST_FRAME_VOICE ) | |
( f - > frametype = = AST_FRAME_VIDEO ) )
{
/* Forward voice or DTMF frames if they happen upon us */
/* Actually I dont think we want to forward on any frames!
if ( who = = c0 ) {
ast_write ( c1 , f ) ;
} else if ( who = = c1 ) {
ast_write ( c0 , f ) ;
}
*/
}
ast_frfree ( f ) ;
}
/* Swap priority not that it's a big deal at this point */
cs [ 2 ] = cs [ 0 ] ;
cs [ 0 ] = cs [ 1 ] ;
cs [ 1 ] = cs [ 2 ] ;
} ;
2004-04-05 05:37:01 +00:00
vpb_bridge ( p0 - > handle , p1 - > handle , VPB_BRIDGE_OFF , i + 1 /* resource 1 & 2 only for V4PCI*/ ) ;
}
# endif
ast_mutex_lock ( & bridge_lock ) ; {
bridges [ i ] . inuse = 0 ;
} ast_mutex_unlock ( & bridge_lock ) ;
2004-05-21 02:51:05 +00:00
p0 - > bridge = NULL ;
p1 - > bridge = NULL ;
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Bridging call done with [%s, %s] => %d \n " , c0 - > name , c1 - > name , res ) ;
2004-08-18 05:06:26 +00:00
/*
2004-05-21 02:51:05 +00:00
ast_mutex_unlock ( & p0 - > lock ) ;
ast_mutex_unlock ( & p1 - > lock ) ;
2004-08-18 05:06:26 +00:00
*/
2005-08-09 01:59:59 +00:00
return ( res = = VPB_OK ) ? AST_BRIDGE_COMPLETE : AST_BRIDGE_FAILED ;
2004-03-31 04:29:55 +00:00
}
2004-12-18 22:04:07 +00:00
/* Caller ID can be located in different positions between the rings depending on your Telco
* Australian ( Telstra ) callerid starts 700 ms after 1 st ring and finishes 1.5 s after first ring
* Use ANALYSE_CID to record rings and determine location of callerid
*/
/* #define ANALYSE_CID */
2005-01-17 03:45:18 +00:00
# define RING_SKIP 300
2005-01-18 03:28:39 +00:00
# define CID_MSECS 2000
2004-03-31 04:29:55 +00:00
static void get_callerid ( struct vpb_pvt * p )
{
2004-12-18 22:04:07 +00:00
short buf [ CID_MSECS * 8 ] ; /* 8kHz sampling rate */
2005-07-15 23:00:47 +00:00
struct timeval cid_record_time ;
2004-04-05 05:37:01 +00:00
int rc ;
2004-10-21 05:03:00 +00:00
struct ast_channel * owner = p - > owner ;
2005-06-22 23:54:47 +00:00
/*
char callerid [ AST_MAX_EXTENSION ] = " " ;
*/
# ifdef ANALYSE_CID
2005-11-01 23:20:46 +00:00
void * ws ;
2004-11-29 23:20:16 +00:00
char * file = " cidsams.wav " ;
2005-06-22 23:54:47 +00:00
# endif
2004-03-31 04:29:55 +00:00
2004-04-05 05:37:01 +00:00
if ( ast_mutex_trylock ( & p - > record_lock ) = = 0 ) {
2004-03-31 04:29:55 +00:00
2005-07-15 23:00:47 +00:00
cid_record_time = ast_tvnow ( ) ;
2004-04-05 05:37:01 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " CID record - start \n " ) ;
2004-12-18 22:04:07 +00:00
/* Skip any trailing ringtone */
2005-11-01 23:20:46 +00:00
if ( UsePolarityCID ! = 1 ) {
vpb_sleep ( RING_SKIP ) ;
}
2004-04-05 05:37:01 +00:00
if ( option_verbose > 3 )
2006-02-02 21:49:36 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " CID record - skipped %dms trailing ring \n " ,
2005-07-15 23:00:47 +00:00
ast_tvdiff_ms ( ast_tvnow ( ) , cid_record_time ) ) ;
cid_record_time = ast_tvnow ( ) ;
2004-04-05 05:37:01 +00:00
2004-12-18 22:04:07 +00:00
/* Record bit between the rings which contains the callerid */
2004-04-05 05:37:01 +00:00
vpb_record_buf_start ( p - > handle , VPB_LINEAR ) ;
rc = vpb_record_buf_sync ( p - > handle , ( char * ) buf , sizeof ( buf ) ) ;
vpb_record_buf_finish ( p - > handle ) ;
2005-01-27 04:31:38 +00:00
# ifdef ANALYSE_CID
2004-11-29 23:20:16 +00:00
vpb_wave_open_write ( & ws , file , VPB_LINEAR ) ;
vpb_wave_write ( ws , ( char * ) buf , sizeof ( buf ) ) ;
vpb_wave_close_write ( ws ) ;
2005-01-27 04:31:38 +00:00
# endif
2004-04-05 05:37:01 +00:00
if ( option_verbose > 3 )
2006-02-02 21:49:36 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " CID record - recorded %dms between rings \n " ,
2005-07-15 23:00:47 +00:00
ast_tvdiff_ms ( ast_tvnow ( ) , cid_record_time ) ) ;
2004-04-05 05:37:01 +00:00
ast_mutex_unlock ( & p - > record_lock ) ;
if ( rc ! = VPB_OK ) {
ast_log ( LOG_ERROR , " Failed to record caller id sample on %s \n " , p - > dev ) ;
return ;
}
2004-10-21 05:03:00 +00:00
VPB_CID * cli_struct = new VPB_CID ;
cli_struct - > ra_cldn [ 0 ] = 0 ;
cli_struct - > ra_cn [ 0 ] = 0 ;
2004-12-18 22:04:07 +00:00
/* This decodes FSK 1200baud type callerid */
2004-10-21 05:03:00 +00:00
if ( ( rc = vpb_cid_decode2 ( cli_struct , buf , CID_MSECS * 8 ) ) = = VPB_OK ) {
2005-01-17 03:45:18 +00:00
/*
2004-10-21 05:03:00 +00:00
if ( owner - > cid . cid_num )
free ( owner - > cid . cid_num ) ;
owner - > cid . cid_num = NULL ;
if ( owner - > cid . cid_name )
free ( owner - > cid . cid_name ) ;
owner - > cid . cid_name = NULL ;
2005-01-17 03:45:18 +00:00
*/
2004-10-21 05:03:00 +00:00
if ( cli_struct - > ra_cldn [ 0 ] = = ' \0 ' ) {
2005-01-17 03:45:18 +00:00
/*
2004-10-21 05:03:00 +00:00
owner - > cid . cid_num = strdup ( cli_struct - > cldn ) ;
owner - > cid . cid_name = strdup ( cli_struct - > cn ) ;
2005-01-17 03:45:18 +00:00
*/
2005-11-01 23:20:46 +00:00
if ( owner ) {
ast_set_callerid ( owner , cli_struct - > cldn , cli_struct - > cn , cli_struct - > cldn ) ;
} else {
strcpy ( p - > cid_num , cli_struct - > cldn ) ;
strcpy ( p - > cid_name , cli_struct - > cn ) ;
}
2004-10-21 05:03:00 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " CID record - got [%s] [%s] \n " , owner - > cid . cid_num , owner - > cid . cid_name ) ;
2005-01-18 03:24:41 +00:00
snprintf ( p - > callerid , sizeof ( p - > callerid ) - 1 , " %s %s " , cli_struct - > cldn , cli_struct - > cn ) ;
2004-10-21 05:03:00 +00:00
}
else {
ast_log ( LOG_ERROR , " CID record - No caller id avalable on %s \n " , p - > dev ) ;
}
2004-04-05 05:37:01 +00:00
} else {
2004-10-21 05:03:00 +00:00
ast_log ( LOG_ERROR , " CID record - Failed to decode caller id on %s - %s \n " , p - > dev , vpb_strerror ( rc ) ) ;
2005-01-18 03:24:41 +00:00
strncpy ( p - > callerid , " unknown " , sizeof ( p - > callerid ) - 1 ) ;
2004-04-05 05:37:01 +00:00
}
2004-10-21 05:03:00 +00:00
delete cli_struct ;
2004-04-05 05:37:01 +00:00
} else
2004-10-21 05:03:00 +00:00
ast_log ( LOG_ERROR , " CID record - Failed to set record mode for caller id on %s \n " , p - > dev ) ;
2004-03-31 04:29:55 +00:00
}
2005-01-17 03:45:18 +00:00
2004-11-29 23:20:16 +00:00
static void get_callerid_ast ( struct vpb_pvt * p )
{
struct callerid_state * cs ;
char buf [ 1024 ] ;
char * name = NULL , * number = NULL ;
int flags ;
int rc = 0 , vrc ;
int sam_count = 0 ;
struct ast_channel * owner = p - > owner ;
int which_cid ;
2005-06-22 23:54:47 +00:00
/*
float old_gain ;
*/
# ifdef ANALYSE_CID
2004-11-29 23:20:16 +00:00
void * ws ;
char * file = " cidsams.wav " ;
2005-06-22 23:54:47 +00:00
# endif
2004-11-29 23:20:16 +00:00
2005-01-18 03:24:41 +00:00
if ( p - > callerid_type = = 1 ) {
2004-11-29 23:20:16 +00:00
if ( option_verbose > 3 ) ast_verbose ( VERBOSE_PREFIX_4 " Collected caller ID already \n " ) ;
return ;
}
2005-01-18 03:24:41 +00:00
else if ( p - > callerid_type = = 2 ) {
2004-11-29 23:20:16 +00:00
which_cid = CID_SIG_V23 ;
2005-01-18 03:24:41 +00:00
if ( option_verbose > 3 ) ast_verbose ( VERBOSE_PREFIX_4 " Collecting Caller ID v23... \n " ) ;
2004-11-29 23:20:16 +00:00
}
2005-01-18 03:24:41 +00:00
else if ( p - > callerid_type = = 3 ) {
2004-11-29 23:20:16 +00:00
which_cid = CID_SIG_BELL ;
2005-01-18 03:24:41 +00:00
if ( option_verbose > 3 ) ast_verbose ( VERBOSE_PREFIX_4 " Collecting Caller ID bell... \n " ) ;
2004-11-29 23:20:16 +00:00
}
else {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Caller ID disabled \n " ) ;
return ;
}
2004-12-18 22:04:07 +00:00
/* vpb_sleep(RING_SKIP); */
/* vpb_record_get_gain(p->handle, &old_gain); */
2004-11-29 23:20:16 +00:00
cs = callerid_new ( which_cid ) ;
if ( cs ) {
2005-01-27 04:31:38 +00:00
# ifdef ANALYSE_CID
2005-01-17 03:45:18 +00:00
vpb_wave_open_write ( & ws , file , VPB_MULAW ) ;
vpb_record_set_gain ( p - > handle , 3.0 ) ;
vpb_record_set_hw_gain ( p - > handle , 12.0 ) ;
2005-01-27 04:31:38 +00:00
# endif
2004-11-29 23:20:16 +00:00
vpb_record_buf_start ( p - > handle , VPB_MULAW ) ;
while ( ( rc = = 0 ) & & ( sam_count < 8000 * 3 ) ) {
vrc = vpb_record_buf_sync ( p - > handle , ( char * ) buf , sizeof ( buf ) ) ;
if ( vrc ! = VPB_OK )
ast_log ( LOG_ERROR , " %s: Caller ID couldnt read audio buffer! \n " , p - > dev ) ;
rc = callerid_feed ( cs , ( unsigned char * ) buf , sizeof ( buf ) , AST_FORMAT_ULAW ) ;
2005-01-27 04:31:38 +00:00
# ifdef ANALYSE_CID
2005-01-17 03:45:18 +00:00
vpb_wave_write ( ws , ( char * ) buf , sizeof ( buf ) ) ;
2005-01-27 04:31:38 +00:00
# endif
2004-11-29 23:20:16 +00:00
sam_count + = sizeof ( buf ) ;
if ( option_verbose > 3 ) ast_verbose ( VERBOSE_PREFIX_4 " Collecting Caller ID samples [%d][%d]... \n " , sam_count , rc ) ;
}
vpb_record_buf_finish ( p - > handle ) ;
2005-01-27 04:31:38 +00:00
# ifdef ANALYSE_CID
2005-01-17 03:45:18 +00:00
vpb_wave_close_write ( ws ) ;
2005-01-27 04:31:38 +00:00
# endif
2004-11-29 23:20:16 +00:00
if ( rc = = 1 ) {
callerid_get ( cs , & name , & number , & flags ) ;
if ( option_verbose > 0 )
ast_verbose ( VERBOSE_PREFIX_1 " %s: Caller ID name [%s] number [%s] flags [%d] \n " , p - > dev , name , number , flags ) ;
}
else {
ast_log ( LOG_ERROR , " %s: Failed to decode Caller ID \n " , p - > dev ) ;
}
2004-12-18 22:04:07 +00:00
/* vpb_record_set_gain(p->handle, old_gain); */
/* vpb_record_set_hw_gain(p->handle,6.0); */
2004-11-29 23:20:16 +00:00
}
else {
ast_log ( LOG_ERROR , " %s: Failed to create Caller ID struct \n " , p - > dev ) ;
}
if ( owner - > cid . cid_num ) {
free ( owner - > cid . cid_num ) ;
owner - > cid . cid_num = NULL ;
}
if ( owner - > cid . cid_name ) {
free ( owner - > cid . cid_name ) ;
owner - > cid . cid_name = NULL ;
}
if ( number )
ast_shrink_phone_number ( number ) ;
2006-07-03 04:25:21 +00:00
ast_set_callerid ( owner ,
number , name ,
owner - > cid . cid_ani ? NULL : number ) ;
if ( ! ast_strlen_zero ( name ) ) {
snprintf ( p - > callerid , ( sizeof ( p - > callerid ) - 1 ) , " %s %s " , number , name ) ;
} else {
snprintf ( p - > callerid , ( sizeof ( p - > callerid ) - 1 ) , " %s " , number ) ;
2004-11-29 23:20:16 +00:00
}
if ( cs )
callerid_free ( cs ) ;
}
2004-03-31 04:29:55 +00:00
2004-12-18 22:04:07 +00:00
/* Terminate any tones we are presently playing */
2004-03-31 04:29:55 +00:00
static void stoptone ( int handle )
{
2004-05-14 04:39:16 +00:00
int ret ;
VPB_EVENT je ;
2004-04-05 05:37:01 +00:00
while ( vpb_playtone_state ( handle ) ! = VPB_OK ) {
vpb_tone_terminate ( handle ) ;
2004-05-14 04:39:16 +00:00
ret = vpb_get_event_ch_async ( handle , & je ) ;
if ( ( ret = = VPB_OK ) & & ( je . type ! = VPB_DIALEND ) ) {
if ( option_verbose > 3 ) {
2004-08-18 05:06:26 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " Stop tone collected a wrong event!![%d] \n " , je . type ) ;
2004-05-14 04:39:16 +00:00
}
2004-12-18 22:04:07 +00:00
/* vpb_put_event(&je); */
2004-05-14 04:39:16 +00:00
}
2004-04-05 05:37:01 +00:00
vpb_sleep ( 10 ) ;
}
2004-03-31 04:29:55 +00:00
}
2004-05-14 04:39:16 +00:00
/* Safe vpb_playtone_async */
2004-03-31 04:29:55 +00:00
static int playtone ( int handle , VPB_TONE * tone )
{
2004-05-14 04:39:16 +00:00
int ret = VPB_OK ;
2004-04-05 05:37:01 +00:00
stoptone ( handle ) ;
2004-05-14 04:39:16 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " [%02d]: Playing tone \n " , handle ) ;
ret = vpb_playtone_async ( handle , tone ) ;
return ret ;
2003-04-18 14:34:46 +00:00
}
2003-04-15 14:39:06 +00:00
static inline int monitor_handle_owned ( struct vpb_pvt * p , VPB_EVENT * e )
{
2004-04-05 05:37:01 +00:00
struct ast_frame f = { AST_FRAME_CONTROL } ; /* default is control, Clear rest. */
int endbridge = 0 ;
2004-05-26 01:29:29 +00:00
int res = 0 ;
2004-04-05 05:37:01 +00:00
if ( option_verbose > 3 )
2005-02-21 00:48:35 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_owned: got event: [%d=>%d] \n " , p - > dev , e - > type , e - > data ) ;
2004-04-05 05:37:01 +00:00
2006-02-02 21:49:36 +00:00
f . src = " vpb " ;
2004-04-05 05:37:01 +00:00
switch ( e - > type ) {
case VPB_RING :
if ( p - > mode = = MODE_FXO ) {
f . subclass = AST_CONTROL_RING ;
2005-01-14 04:51:20 +00:00
vpb_timer_stop ( p - > ring_timer ) ;
vpb_timer_start ( p - > ring_timer ) ;
2004-04-05 05:37:01 +00:00
} else
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ; /* ignore ring on station port. */
2004-04-05 05:37:01 +00:00
break ;
case VPB_RING_OFF :
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
break ;
case VPB_TIMEREXP :
if ( e - > data = = p - > busy_timer_id ) {
playtone ( p - > handle , & Busytone ) ;
p - > state = VPB_STATE_PLAYBUSY ;
2004-05-24 01:43:05 +00:00
vpb_timer_stop ( p - > busy_timer ) ;
vpb_timer_start ( p - > busy_timer ) ;
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
} else if ( e - > data = = p - > ringback_timer_id ) {
playtone ( p - > handle , & Ringbacktone ) ;
2004-05-24 01:43:05 +00:00
vpb_timer_stop ( p - > ringback_timer ) ;
vpb_timer_start ( p - > ringback_timer ) ;
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2005-01-14 04:51:20 +00:00
} else if ( e - > data = = p - > ring_timer_id ) {
/* We didnt get another ring in time! */
if ( p - > owner - > _state ! = AST_STATE_UP ) {
/* Assume caller has hung up */
vpb_timer_stop ( p - > ring_timer ) ;
f . subclass = AST_CONTROL_HANGUP ;
} else {
vpb_timer_stop ( p - > ring_timer ) ;
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2005-01-14 04:51:20 +00:00
}
2004-04-05 05:37:01 +00:00
} else {
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ; /* Ignore. */
2004-04-05 05:37:01 +00:00
}
break ;
2005-02-21 00:48:35 +00:00
case VPB_DTMF_DOWN :
2004-04-05 05:37:01 +00:00
case VPB_DTMF :
2005-02-21 00:48:35 +00:00
if ( use_ast_dtmfdet ) {
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2005-02-21 00:48:35 +00:00
} else if ( p - > owner - > _state = = AST_STATE_UP ) {
2004-10-06 10:37:57 +00:00
f . frametype = AST_FRAME_DTMF ;
f . subclass = e - > data ;
2004-04-05 05:37:01 +00:00
} else
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
break ;
case VPB_TONEDETECT :
if ( e - > data = = VPB_BUSY | | e - > data = = VPB_BUSY_308 | | e - > data = = VPB_BUSY_AUST ) {
2004-09-17 00:14:48 +00:00
if ( option_verbose > 3 )
2004-09-17 00:34:51 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_owned: got event: BUSY \n " , p - > dev ) ;
2004-04-05 05:37:01 +00:00
if ( p - > owner - > _state = = AST_STATE_UP ) {
f . subclass = AST_CONTROL_HANGUP ;
}
else {
f . subclass = AST_CONTROL_BUSY ;
}
2005-03-04 00:27:52 +00:00
}
else if ( e - > data = = VPB_FAX ) {
if ( ! p - > faxhandled ) {
if ( strcmp ( p - > owner - > exten , " fax " ) ) {
2006-03-27 19:31:54 +00:00
const char * target_context = S_OR ( p - > owner - > macrocontext , p - > owner - > context ) ;
2005-06-06 03:18:51 +00:00
2005-06-08 00:10:09 +00:00
if ( ast_exists_extension ( p - > owner , target_context , " fax " , 1 , p - > owner - > cid . cid_num ) ) {
2005-03-04 00:27:52 +00:00
if ( option_verbose > 2 )
2005-06-08 00:10:09 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Redirecting %s to fax extension \n " , p - > owner - > name ) ;
2005-03-04 00:27:52 +00:00
/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2005-06-08 00:10:09 +00:00
pbx_builtin_setvar_helper ( p - > owner , " FAXEXTEN " , p - > owner - > exten ) ;
if ( ast_async_goto ( p - > owner , target_context , " fax " , 1 ) )
ast_log ( LOG_WARNING , " Failed to async goto '%s' into fax of '%s' \n " , p - > owner - > name , target_context ) ;
2005-03-04 00:27:52 +00:00
} else
ast_log ( LOG_NOTICE , " Fax detected, but no fax extension \n " ) ;
} else
ast_log ( LOG_DEBUG , " Already in a fax extension, not redirecting \n " ) ;
} else
ast_log ( LOG_DEBUG , " Fax already handled \n " ) ;
}
else if ( e - > data = = VPB_GRUNT ) {
2005-07-19 02:33:46 +00:00
if ( ast_tvdiff_ms ( ast_tvnow ( ) , p - > lastgrunt ) > gruntdetect_timeout ) {
2004-12-18 22:04:07 +00:00
/* Nothing heard on line for a very long time
* Timeout connection */
2004-04-05 05:37:01 +00:00
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " grunt timeout \n " ) ;
2004-05-14 04:39:16 +00:00
ast_log ( LOG_NOTICE , " %s: Line hangup due of lack of conversation \n " , p - > dev ) ;
2004-04-05 05:37:01 +00:00
f . subclass = AST_CONTROL_HANGUP ;
} else {
2005-07-15 23:00:47 +00:00
p - > lastgrunt = ast_tvnow ( ) ;
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
}
2005-03-04 00:27:52 +00:00
}
else {
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2005-03-04 00:27:52 +00:00
}
2004-04-05 05:37:01 +00:00
break ;
case VPB_CALLEND :
# ifdef DIAL_WITH_CALL_PROGRESS
if ( e - > data = = VPB_CALL_CONNECTED )
f . subclass = AST_CONTROL_ANSWER ;
else if ( e - > data = = VPB_CALL_NO_DIAL_TONE | | e - > data = = VPB_CALL_NO_RING_BACK )
f . subclass = AST_CONTROL_CONGESTION ;
else if ( e - > data = = VPB_CALL_NO_ANSWER | | e - > data = = VPB_CALL_BUSY )
f . subclass = AST_CONTROL_BUSY ;
else if ( e - > data = = VPB_CALL_DISCONNECTED )
f . subclass = AST_CONTROL_HANGUP ;
# else
2004-05-14 04:39:16 +00:00
ast_log ( LOG_NOTICE , " %s: Got call progress callback but blind dialing \n " , p - > dev ) ;
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
# endif
break ;
case VPB_STATION_OFFHOOK :
f . subclass = AST_CONTROL_ANSWER ;
break ;
case VPB_DROP :
2004-05-14 04:39:16 +00:00
if ( ( p - > mode = = MODE_FXO ) & & ( UseLoopDrop ) ) { /* ignore loop drop on stations */
2004-04-05 05:37:01 +00:00
if ( p - > owner - > _state = = AST_STATE_UP )
f . subclass = AST_CONTROL_HANGUP ;
else
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
}
break ;
2005-11-01 23:20:46 +00:00
case VPB_LOOP_ONHOOK :
if ( p - > owner - > _state = = AST_STATE_UP )
f . subclass = AST_CONTROL_HANGUP ;
else
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2005-11-01 23:20:46 +00:00
break ;
2004-04-05 05:37:01 +00:00
case VPB_STATION_ONHOOK :
2004-03-31 04:29:55 +00:00
f . subclass = AST_CONTROL_HANGUP ;
2004-04-05 05:37:01 +00:00
break ;
case VPB_STATION_FLASH :
f . subclass = AST_CONTROL_FLASH ;
break ;
2004-12-18 22:04:07 +00:00
/* Called when dialing has finished and ringing starts
* No indication that call has really been answered when using blind dialing
*/
2004-04-05 05:37:01 +00:00
case VPB_DIALEND :
2004-05-24 01:43:05 +00:00
if ( p - > state < 5 ) {
f . subclass = AST_CONTROL_ANSWER ;
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " %s: Dialend \n " , p - > dev ) ;
} else {
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-05-24 01:43:05 +00:00
}
2004-04-05 05:37:01 +00:00
break ;
case VPB_PLAY_UNDERFLOW :
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
vpb_reset_play_fifo_alarm ( p - > handle ) ;
break ;
case VPB_RECORD_OVERFLOW :
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
vpb_reset_record_fifo_alarm ( p - > handle ) ;
break ;
default :
2006-08-31 01:59:02 +00:00
f . frametype = AST_FRAME_NULL ;
2004-04-05 05:37:01 +00:00
break ;
}
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in handle_owned [%d] \n " , p - > dev , res ) ;
2004-08-18 05:06:26 +00:00
res = ast_mutex_lock ( & p - > lock ) ;
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING count[%d] owner[%d] \n " , p - > dev , p - > lock . __m_count , p - > lock . __m_owner ) ;
2004-08-18 23:58:07 +00:00
*/
2004-05-26 01:29:29 +00:00
{
2004-04-05 05:37:01 +00:00
if ( p - > bridge ) { /* Check what happened, see if we need to report it. */
switch ( f . frametype ) {
case AST_FRAME_DTMF :
2004-05-26 01:29:29 +00:00
if ( ! ( p - > bridge - > c0 = = p - > owner & &
2004-04-05 05:37:01 +00:00
( p - > bridge - > flags & AST_BRIDGE_DTMF_CHANNEL_0 ) ) & &
2004-05-26 01:29:29 +00:00
! ( p - > bridge - > c1 = = p - > owner & &
2004-04-05 05:37:01 +00:00
( p - > bridge - > flags & AST_BRIDGE_DTMF_CHANNEL_1 ) ) )
/* Kill bridge, this is interesting. */
endbridge = 1 ;
break ;
case AST_FRAME_CONTROL :
if ( ! ( p - > bridge - > flags & AST_BRIDGE_IGNORE_SIGS ) )
#if 0
if ( f . subclass = = AST_CONTROL_BUSY | |
f . subclass = = AST_CONTROL_CONGESTION | |
f . subclass = = AST_CONTROL_HANGUP | |
f . subclass = = AST_CONTROL_FLASH )
# endif
endbridge = 1 ;
break ;
default :
break ;
}
if ( endbridge ) {
if ( p - > bridge - > fo )
* p - > bridge - > fo = ast_frisolate ( & f ) ;
if ( p - > bridge - > rc )
* p - > bridge - > rc = p - > owner ;
ast_mutex_lock ( & p - > bridge - > lock ) ; {
p - > bridge - > endbridge = 1 ;
2005-11-01 23:20:46 +00:00
ast_cond_signal ( & p - > bridge - > cond ) ;
2004-04-05 05:37:01 +00:00
} ast_mutex_unlock ( & p - > bridge - > lock ) ;
}
2004-03-31 04:29:55 +00:00
}
2004-05-26 01:29:29 +00:00
}
2004-04-05 05:37:01 +00:00
2004-05-26 01:29:29 +00:00
if ( endbridge ) {
res = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in handle_owned [%d] \n " , p - > dev , res ) ;
2004-08-18 23:58:07 +00:00
*/
2004-05-26 01:29:29 +00:00
return 0 ;
}
2004-04-05 05:37:01 +00:00
2004-10-13 23:17:01 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_owned: Prepared frame type[%d]subclass[%d], bridge=%p owner=[%s] \n " ,
p - > dev , f . frametype , f . subclass , ( void * ) p - > bridge , p - > owner - > name ) ;
2004-12-18 22:04:07 +00:00
/* Trylock used here to avoid deadlock that can occur if we
* happen to be in here handling an event when hangup is called
* Problem is that hangup holds p - > owner - > lock
*/
2004-05-26 01:29:29 +00:00
if ( ( f . frametype > = 0 ) & & ( f . frametype ! = AST_FRAME_NULL ) & & ( p - > owner ) ) {
2004-04-05 05:37:01 +00:00
if ( ast_mutex_trylock ( & p - > owner - > lock ) = = 0 ) {
2004-04-06 22:17:32 +00:00
ast_queue_frame ( p - > owner , & f ) ;
2004-04-05 05:37:01 +00:00
ast_mutex_unlock ( & p - > owner - > lock ) ;
2004-10-13 23:17:01 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: handled_owned: Queued Frame to [%s] \n " , p - > dev , p - > owner - > name ) ;
2004-04-05 05:37:01 +00:00
} else {
2004-05-21 02:51:05 +00:00
ast_verbose ( " %s: handled_owned: Missed event %d/%d \n " ,
2004-05-14 04:39:16 +00:00
p - > dev , f . frametype , f . subclass ) ;
2004-03-31 04:29:55 +00:00
}
2004-04-05 05:37:01 +00:00
}
2004-05-26 01:29:29 +00:00
res = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in handle_owned [%d] \n " , p - > dev , res ) ;
2004-08-18 23:58:07 +00:00
*/
2004-04-05 05:37:01 +00:00
return 0 ;
2003-04-15 14:39:06 +00:00
}
static inline int monitor_handle_notowned ( struct vpb_pvt * p , VPB_EVENT * e )
{
2004-04-05 05:37:01 +00:00
char s [ 2 ] = { 0 } ;
2004-12-15 22:59:47 +00:00
struct ast_channel * owner = p - > owner ;
2005-01-17 03:45:18 +00:00
char cid_num [ 256 ] ;
char cid_name [ 256 ] ;
2005-06-22 23:54:47 +00:00
/*
2005-03-16 04:53:30 +00:00
struct ast_channel * c ;
2005-06-22 23:54:47 +00:00
*/
2004-04-05 05:37:01 +00:00
2004-05-14 04:39:16 +00:00
if ( option_verbose > 3 ) {
char str [ VPB_MAX_STR ] ;
vpb_translate_event ( e , str ) ;
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: mode=%d, event[%d][%s]=[%d] \n " ,
2004-05-14 04:39:16 +00:00
p - > dev , p - > mode , e - > type , str , e - > data ) ;
}
2004-04-05 05:37:01 +00:00
switch ( e - > type ) {
2005-11-01 23:20:46 +00:00
case VPB_LOOP_ONHOOK :
case VPB_LOOP_POLARITY :
if ( UsePolarityCID = = 1 ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Polarity reversal \n " ) ;
if ( p - > callerid_type = = 1 ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Using VPB Caller ID \n " ) ;
get_callerid ( p ) ; /* UK CID before 1st ring*/
}
2006-02-02 21:49:36 +00:00
/* get_callerid_ast(p); */ /* Caller ID using the ast functions */
2005-11-01 23:20:46 +00:00
}
break ;
2004-04-05 05:37:01 +00:00
case VPB_RING :
if ( p - > mode = = MODE_FXO ) /* FXO port ring, start * */ {
vpb_new ( p , AST_STATE_RING , p - > context ) ;
2005-11-01 23:20:46 +00:00
if ( UsePolarityCID ! = 1 ) {
if ( p - > callerid_type = = 1 ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Using VPB Caller ID \n " ) ;
get_callerid ( p ) ; /* Australian CID only between 1st and 2nd ring */
}
get_callerid_ast ( p ) ; /* Caller ID using the ast functions */
2004-11-29 23:20:16 +00:00
}
2005-11-01 23:20:46 +00:00
else {
ast_log ( LOG_ERROR , " Setting caller ID: %s %s \n " , p - > cid_num , p - > cid_name ) ;
ast_set_callerid ( p - > owner , p - > cid_num , p - > cid_name , p - > cid_num ) ;
p - > cid_num [ 0 ] = 0 ;
p - > cid_name [ 0 ] = 0 ;
}
2005-02-01 03:27:36 +00:00
vpb_timer_stop ( p - > ring_timer ) ;
vpb_timer_start ( p - > ring_timer ) ;
2004-04-05 05:37:01 +00:00
}
break ;
case VPB_RING_OFF :
break ;
case VPB_STATION_OFFHOOK :
if ( p - > mode = = MODE_IMMEDIATE )
vpb_new ( p , AST_STATE_RING , p - > context ) ;
else {
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: playing dialtone \n " , p - > dev ) ;
2004-04-05 05:37:01 +00:00
playtone ( p - > handle , & Dialtone ) ;
2004-12-15 22:59:47 +00:00
p - > state = VPB_STATE_PLAYDIAL ;
2004-04-05 05:37:01 +00:00
p - > wantdtmf = 1 ;
p - > ext [ 0 ] = 0 ; /* Just to be sure & paranoid.*/
}
break ;
case VPB_DIALEND :
if ( p - > mode = = MODE_DIALTONE ) {
if ( p - > state = = VPB_STATE_PLAYDIAL ) {
playtone ( p - > handle , & Dialtone ) ;
p - > wantdtmf = 1 ;
2004-12-18 22:04:07 +00:00
p - > ext [ 0 ] = 0 ; /* Just to be sure & paranoid. */
2004-04-05 05:37:01 +00:00
}
/* These are not needed as they have timers to restart them
else if ( p - > state = = VPB_STATE_PLAYBUSY ) {
playtone ( p - > handle , & Busytone ) ;
p - > wantdtmf = 1 ;
2004-12-20 02:34:26 +00:00
p - > ext [ 0 ] = 0 ;
2004-04-05 05:37:01 +00:00
}
else if ( p - > state = = VPB_STATE_PLAYRING ) {
playtone ( p - > handle , & Ringbacktone ) ;
p - > wantdtmf = 1 ;
2004-12-20 02:34:26 +00:00
p - > ext [ 0 ] = 0 ;
2004-04-05 05:37:01 +00:00
}
*/
2004-05-14 04:39:16 +00:00
} else {
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: Got a DIALEND when not really expected \n " , p - > dev ) ;
2004-04-05 05:37:01 +00:00
}
break ;
case VPB_STATION_ONHOOK : /* clear ext */
stoptone ( p - > handle ) ;
p - > wantdtmf = 1 ;
p - > ext [ 0 ] = 0 ;
p - > state = VPB_STATE_ONHOOK ;
break ;
2005-01-31 23:51:19 +00:00
case VPB_TIMEREXP :
if ( e - > data = = p - > dtmfidd_timer_id ) {
if ( ast_exists_extension ( NULL , p - > context , p - > ext , 1 , p - > callerid ) ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: DTMF IDD timer out, matching on [%s] in [%s] \n " , p - > dev , p - > ext , p - > context ) ;
2005-02-10 00:54:24 +00:00
2005-01-31 23:51:19 +00:00
vpb_new ( p , AST_STATE_RING , p - > context ) ;
}
2005-02-01 03:27:36 +00:00
} else if ( e - > data = = p - > ring_timer_id ) {
/* We didnt get another ring in time! */
2005-06-10 03:18:24 +00:00
if ( p - > owner ) {
if ( p - > owner - > _state ! = AST_STATE_UP ) {
/* Assume caller has hung up */
vpb_timer_stop ( p - > ring_timer ) ;
}
} else {
/* No owner any more, Assume caller has hung up */
2005-02-01 03:27:36 +00:00
vpb_timer_stop ( p - > ring_timer ) ;
}
}
2005-01-31 23:51:19 +00:00
break ;
2004-04-05 05:37:01 +00:00
case VPB_DTMF :
2004-05-14 04:39:16 +00:00
if ( p - > state = = VPB_STATE_ONHOOK ) {
/* DTMF's being passed while on-hook maybe Caller ID */
2004-12-15 22:59:47 +00:00
if ( p - > mode = = MODE_FXO ) {
if ( e - > data = = DTMF_CID_START ) { /* CallerID Start signal */
p - > dtmf_caller_pos = 0 ; /* Leaves the first digit out */
memset ( p - > callerid , 0 , AST_MAX_EXTENSION ) ;
}
else if ( e - > data = = DTMF_CID_STOP ) { /* CallerID End signal */
p - > callerid [ p - > dtmf_caller_pos ] = ' \0 ' ;
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " %s: DTMF CallerID %s \n " , p - > dev , p - > callerid ) ;
2005-01-10 22:09:19 +00:00
if ( owner ) {
2005-01-17 03:45:18 +00:00
/*
2005-01-10 22:09:19 +00:00
if ( owner - > cid . cid_num )
free ( owner - > cid . cid_num ) ;
owner - > cid . cid_num = NULL ;
if ( owner - > cid . cid_name )
free ( owner - > cid . cid_name ) ;
owner - > cid . cid_name = NULL ;
owner - > cid . cid_num = strdup ( p - > callerid ) ;
2005-01-17 03:45:18 +00:00
*/
cid_name [ 0 ] = ' \0 ' ;
cid_num [ 0 ] = ' \0 ' ;
ast_callerid_split ( p - > callerid , cid_name , sizeof ( cid_name ) , cid_num , sizeof ( cid_num ) ) ;
ast_set_callerid ( owner , cid_num , cid_name , cid_num ) ;
2005-01-10 22:09:19 +00:00
}
else {
if ( option_verbose > 2 )
ast_verbose ( VERBOSE_PREFIX_3 " %s: DTMF CallerID: no owner to assign CID \n " , p - > dev ) ;
}
2004-12-15 22:59:47 +00:00
} else if ( p - > dtmf_caller_pos < AST_MAX_EXTENSION ) {
if ( p - > dtmf_caller_pos > = 0 )
p - > callerid [ p - > dtmf_caller_pos ] = e - > data ;
p - > dtmf_caller_pos + + ;
}
}
2004-05-14 04:39:16 +00:00
break ;
}
2004-04-05 05:37:01 +00:00
if ( p - > wantdtmf = = 1 ) {
stoptone ( p - > handle ) ;
p - > wantdtmf = 0 ;
}
p - > state = VPB_STATE_GETDTMF ;
s [ 0 ] = e - > data ;
2004-07-16 04:40:54 +00:00
strncat ( p - > ext , s , sizeof ( p - > ext ) - strlen ( p - > ext ) - 1 ) ;
2005-03-16 04:53:30 +00:00
#if 0
if ( ! strcmp ( p - > ext , ast_pickup_ext ( ) ) ) {
/* Call pickup has been dialled! */
if ( ast_pickup_call ( c ) ) {
/* Call pickup wasnt possible */
}
}
else
# endif
2004-05-14 04:39:16 +00:00
if ( ast_exists_extension ( NULL , p - > context , p - > ext , 1 , p - > callerid ) ) {
2005-01-31 23:51:19 +00:00
if ( ast_canmatch_extension ( NULL , p - > context , p - > ext , 1 , p - > callerid ) ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: Multiple matches on [%s] in [%s] \n " , p - > dev , p - > ext , p - > context ) ;
/* Start DTMF IDD timer */
vpb_timer_stop ( p - > dtmfidd_timer ) ;
vpb_timer_start ( p - > dtmfidd_timer ) ;
}
else {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: Matched on [%s] in [%s] \n " , p - > dev , p - > ext , p - > context ) ;
2005-02-10 00:54:24 +00:00
vpb_new ( p , AST_STATE_UP , p - > context ) ;
2004-10-06 10:37:57 +00:00
}
2004-05-14 04:39:16 +00:00
} else if ( ! ast_canmatch_extension ( NULL , p - > context , p - > ext , 1 , p - > callerid ) ) {
if ( ast_exists_extension ( NULL , " default " , p - > ext , 1 , p - > callerid ) ) {
2005-02-10 00:54:24 +00:00
vpb_new ( p , AST_STATE_UP , " default " ) ;
2004-05-14 04:39:16 +00:00
} else if ( ! ast_canmatch_extension ( NULL , " default " , p - > ext , 1 , p - > callerid ) ) {
if ( option_verbose > 3 ) {
2005-01-31 23:51:19 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: can't match anything in %s or default \n " , p - > dev , p - > context ) ;
2004-05-14 04:39:16 +00:00
}
playtone ( p - > handle , & Busytone ) ;
2004-05-24 01:43:05 +00:00
vpb_timer_stop ( p - > busy_timer ) ;
vpb_timer_start ( p - > busy_timer ) ;
2004-05-14 04:39:16 +00:00
p - > state = VPB_STATE_PLAYBUSY ;
}
2004-04-05 05:37:01 +00:00
}
break ;
default :
/* Ignore.*/
break ;
}
if ( option_verbose > 3 )
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: handle_notowned: mode=%d, [%d=>%d] \n " ,
2004-04-05 05:37:01 +00:00
p - > dev , p - > mode , e - > type , e - > data ) ;
return 0 ;
}
2003-04-15 14:39:06 +00:00
static void * do_monitor ( void * unused )
{
2004-03-31 04:29:55 +00:00
2004-04-05 05:37:01 +00:00
/* Monitor thread, doesn't die until explicitly killed. */
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Starting vpb monitor thread[%ld] \n " ,
pthread_self ( ) ) ;
2004-03-31 04:29:55 +00:00
2004-04-05 05:37:01 +00:00
pthread_setcanceltype ( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) ;
2004-03-31 04:29:55 +00:00
2004-04-05 05:37:01 +00:00
for ( ; ; ) {
VPB_EVENT e ;
VPB_EVENT je ;
char str [ VPB_MAX_STR ] ;
struct vpb_pvt * p ;
2004-03-31 04:29:55 +00:00
2004-05-24 05:37:15 +00:00
/*
2004-05-14 04:39:16 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Monitor waiting for event \n " ) ;
2004-05-24 05:37:15 +00:00
*/
2004-04-05 05:37:01 +00:00
int res = vpb_get_event_sync ( & e , VPB_WAIT_TIMEOUT ) ;
2004-05-14 04:39:16 +00:00
if ( ( res = = VPB_NO_EVENTS ) | | ( res = = VPB_TIME_OUT ) ) {
/*
if ( option_verbose > 3 ) {
if ( res = = VPB_NO_EVENTS ) {
ast_verbose ( VERBOSE_PREFIX_4 " No events.... \n " ) ;
} else {
ast_verbose ( VERBOSE_PREFIX_4 " No events, timed out.... \n " ) ;
}
}
*/
2004-04-05 05:37:01 +00:00
continue ;
2004-05-14 04:39:16 +00:00
}
2004-04-05 05:37:01 +00:00
if ( res ! = VPB_OK ) {
ast_log ( LOG_ERROR , " Monitor get event error %s \n " , vpb_strerror ( res ) ) ;
ast_verbose ( " Monitor get event error %s \n " , vpb_strerror ( res ) ) ;
continue ;
2004-03-31 04:29:55 +00:00
}
2004-04-05 05:37:01 +00:00
str [ 0 ] = 0 ;
p = NULL ;
ast_mutex_lock ( & monlock ) ; {
if ( e . type = = VPB_NULL_EVENT ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Monitor got null event \n " ) ;
}
2004-11-29 23:20:16 +00:00
else {
vpb_translate_event ( & e , str ) ;
if ( strlen ( str ) > 1 ) {
str [ ( strlen ( str ) - 1 ) ] = ' \0 ' ;
}
2004-04-05 05:37:01 +00:00
2004-11-29 23:20:16 +00:00
ast_mutex_lock ( & iflock ) ; {
p = iflist ;
while ( p & & p - > handle ! = e . handle )
p = p - > next ;
} ast_mutex_unlock ( & iflock ) ;
2004-04-05 05:37:01 +00:00
2004-11-29 23:20:16 +00:00
if ( p & & ( option_verbose > 3 ) )
ast_verbose ( VERBOSE_PREFIX_4 " %s: Event [%d=>%s] \n " ,
p ? p - > dev : " null " , e . type , str ) ;
}
2004-04-05 05:37:01 +00:00
} ast_mutex_unlock ( & monlock ) ;
if ( ! p ) {
if ( e . type ! = VPB_NULL_EVENT ) {
ast_log ( LOG_WARNING , " Got event [%s][%d], no matching iface! \n " , str , e . type ) ;
2004-05-14 04:39:16 +00:00
if ( option_verbose > 3 ) {
ast_verbose ( VERBOSE_PREFIX_4 " vpb/ERR: No interface for Event [%d=>%s] \n " , e . type , str ) ;
}
2004-04-05 05:37:01 +00:00
}
continue ;
}
/* flush the event from the channel event Q */
vpb_get_event_ch_async ( e . handle , & je ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 4 ) {
2004-05-14 04:39:16 +00:00
vpb_translate_event ( & je , str ) ;
2004-08-18 05:06:26 +00:00
ast_verbose ( " %s: Flushing event [%d]=>%s \n " , p - > dev , je . type , str ) ;
2004-05-14 04:39:16 +00:00
}
2004-04-05 05:37:01 +00:00
2004-05-21 02:51:05 +00:00
/* Check for ownership and locks */
if ( ( p - > owner ) & & ( ! p - > golock ) ) {
/* Need to get owner lock */
/* Safely grab both p->lock and p->owner->lock so that there
cannot be a race with something from the other side */
/*
ast_mutex_lock ( & p - > lock ) ;
while ( ast_mutex_trylock ( & p - > owner - > lock ) ) {
ast_mutex_unlock ( & p - > lock ) ;
usleep ( 1 ) ;
ast_mutex_lock ( & p - > lock ) ;
if ( ! p - > owner )
break ;
}
if ( p - > owner )
p - > golock = 1 ;
*/
}
2004-04-05 05:37:01 +00:00
/* Two scenarios: Are you owned or not. */
if ( p - > owner ) {
monitor_handle_owned ( p , & e ) ;
} else {
monitor_handle_notowned ( p , & e ) ;
}
2004-05-26 01:29:29 +00:00
/* if ((!p->owner)&&(p->golock)){
2004-05-21 02:51:05 +00:00
ast_mutex_unlock ( & p - > owner - > lock ) ;
ast_mutex_unlock ( & p - > lock ) ;
}
2004-05-26 01:29:29 +00:00
*/
2004-04-05 05:37:01 +00:00
}
return NULL ;
2003-04-15 14:39:06 +00:00
}
static int restart_monitor ( void )
{
2004-04-05 05:37:01 +00:00
int error = 0 ;
/* If we're supposed to be stopped -- stay stopped */
if ( mthreadactive = = - 2 )
return 0 ;
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Restarting monitor \n " ) ;
ast_mutex_lock ( & monlock ) ; {
if ( monitor_thread = = pthread_self ( ) ) {
ast_log ( LOG_WARNING , " Cannot kill myself \n " ) ;
error = - 1 ;
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Monitor trying to kill monitor \n " ) ;
}
2004-11-29 23:20:16 +00:00
else {
if ( mthreadactive ! = - 1 ) {
/* Why do other drivers kill the thread? No need says I, simply awake thread with event. */
VPB_EVENT e ;
e . handle = 0 ;
e . type = VPB_NULL_EVENT ;
e . data = 0 ;
2004-04-05 05:37:01 +00:00
2004-11-29 23:20:16 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Trying to reawake monitor \n " ) ;
2004-04-05 05:37:01 +00:00
2004-11-29 23:20:16 +00:00
vpb_put_event ( & e ) ;
} else {
/* Start a new monitor */
int pid = ast_pthread_create ( & monitor_thread , NULL , do_monitor , NULL ) ;
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Created new monitor thread %d \n " , pid ) ;
if ( pid < 0 ) {
ast_log ( LOG_ERROR , " Unable to start monitor thread. \n " ) ;
error = - 1 ;
} else
mthreadactive = 0 ; /* Started the thread!*/
}
2004-04-05 05:37:01 +00:00
}
} ast_mutex_unlock ( & monlock ) ;
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " Monitor restarted \n " ) ;
return error ;
2003-04-15 14:39:06 +00:00
}
2004-12-18 22:04:07 +00:00
/* Per board config that must be called after vpb_open() */
2004-03-31 04:29:55 +00:00
static void mkbrd ( vpb_model_t model , int echo_cancel )
2003-04-15 14:39:06 +00:00
{
2004-04-05 05:37:01 +00:00
if ( ! bridges ) {
if ( model = = vpb_model_v4pci )
max_bridges = MAX_BRIDGES_V4PCI ;
bridges = ( vpb_bridge_t * ) malloc ( max_bridges * sizeof ( vpb_bridge_t ) ) ;
if ( ! bridges )
ast_log ( LOG_ERROR , " Failed to initialize bridges \n " ) ;
2004-06-22 17:42:14 +00:00
else {
2004-04-05 05:37:01 +00:00
memset ( bridges , 0 , max_bridges * sizeof ( vpb_bridge_t ) ) ;
2004-06-22 17:42:14 +00:00
for ( int i = 0 ; i < max_bridges ; i + + ) {
ast_mutex_init ( & bridges [ i ] . lock ) ;
2005-11-01 23:20:46 +00:00
ast_cond_init ( & bridges [ i ] . cond , NULL ) ;
2004-06-22 17:42:14 +00:00
}
}
2004-03-31 04:29:55 +00:00
}
2004-04-05 05:37:01 +00:00
if ( ! echo_cancel ) {
if ( model = = vpb_model_v4pci ) {
vpb_echo_canc_disable ( ) ;
ast_log ( LOG_NOTICE , " Voicetronix echo cancellation OFF \n " ) ;
}
else {
/* need to it port by port for OpenSwitch*/
}
} else {
if ( model = = vpb_model_v4pci ) {
vpb_echo_canc_enable ( ) ;
ast_log ( LOG_NOTICE , " Voicetronix echo cancellation ON \n " ) ;
2005-01-31 04:51:41 +00:00
if ( ec_supp_threshold > - 1 ) {
2005-11-02 01:43:03 +00:00
# ifdef VPB_PRI
2005-11-01 23:20:46 +00:00
vpb_echo_canc_set_sup_thresh ( 0 , ( short * ) & ec_supp_threshold ) ;
2005-11-02 01:43:03 +00:00
# else
vpb_echo_canc_set_sup_thresh ( ( short * ) & ec_supp_threshold ) ;
# endif
2005-01-31 04:51:41 +00:00
ast_log ( LOG_NOTICE , " Voicetronix EC Sup Thres set \n " ) ;
}
2004-04-05 05:37:01 +00:00
}
else {
2004-03-31 04:29:55 +00:00
/* need to it port by port for OpenSwitch*/
2004-04-05 05:37:01 +00:00
}
2004-03-31 04:29:55 +00:00
}
}
2003-04-15 14:39:06 +00:00
2005-02-17 04:58:03 +00:00
static struct vpb_pvt * mkif ( int board , int channel , int mode , int gains , float txgain , float rxgain ,
2004-03-31 04:29:55 +00:00
float txswgain , float rxswgain , int bal1 , int bal2 , int bal3 ,
2005-03-16 04:53:30 +00:00
char * callerid , int echo_cancel , int group , ast_group_t callgroup , ast_group_t pickupgroup )
2004-03-31 04:29:55 +00:00
{
struct vpb_pvt * tmp ;
char buf [ 64 ] ;
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
tmp = ( struct vpb_pvt * ) calloc ( 1 , sizeof * tmp ) ;
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
if ( ! tmp )
return NULL ;
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
tmp - > handle = vpb_open ( board , channel ) ;
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
if ( tmp - > handle < 0 ) {
ast_log ( LOG_WARNING , " Unable to create channel vpb/%d-%d: %s \n " ,
board , channel , strerror ( errno ) ) ;
free ( tmp ) ;
return NULL ;
}
2004-07-16 04:40:54 +00:00
snprintf ( tmp - > dev , sizeof ( tmp - > dev ) , " vpb/%d-%d " , board , channel ) ;
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
tmp - > mode = mode ;
2003-04-15 14:39:06 +00:00
2004-04-05 05:37:01 +00:00
tmp - > group = group ;
2005-03-16 04:53:30 +00:00
tmp - > callgroup = callgroup ;
tmp - > pickupgroup = pickupgroup ;
2004-04-05 05:37:01 +00:00
2005-01-05 00:33:40 +00:00
/* Initilize dtmf caller ID position variable */
tmp - > dtmf_caller_pos = 0 ;
2004-08-18 05:06:26 +00:00
2004-07-16 04:40:54 +00:00
strncpy ( tmp - > language , language , sizeof ( tmp - > language ) - 1 ) ;
strncpy ( tmp - > context , context , sizeof ( tmp - > context ) - 1 ) ;
2003-04-15 14:39:06 +00:00
2005-01-18 03:24:41 +00:00
tmp - > callerid_type = 0 ;
2004-03-31 04:29:55 +00:00
if ( callerid ) {
2005-01-18 03:24:41 +00:00
if ( strcasecmp ( callerid , " on " ) = = 0 ) {
tmp - > callerid_type = 1 ;
strncpy ( tmp - > callerid , " unknown " , sizeof ( tmp - > callerid ) - 1 ) ;
}
else if ( strcasecmp ( callerid , " v23 " ) = = 0 ) {
tmp - > callerid_type = 2 ;
strncpy ( tmp - > callerid , " unknown " , sizeof ( tmp - > callerid ) - 1 ) ;
}
else if ( strcasecmp ( callerid , " bell " ) = = 0 ) {
tmp - > callerid_type = 3 ;
strncpy ( tmp - > callerid , " unknown " , sizeof ( tmp - > callerid ) - 1 ) ;
}
else {
strncpy ( tmp - > callerid , callerid , sizeof ( tmp - > callerid ) - 1 ) ;
}
2004-03-31 04:29:55 +00:00
} else {
2004-07-16 04:40:54 +00:00
strncpy ( tmp - > callerid , " unknown " , sizeof ( tmp - > callerid ) - 1 ) ;
2004-03-31 04:29:55 +00:00
}
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
/* check if codec balances have been set in the config file */
if ( bal3 > = 0 ) {
if ( ( bal1 > = 0 ) & & ! ( bal1 & 32 ) ) bal1 | = 32 ;
vpb_set_codec_reg ( tmp - > handle , 0x42 , bal3 ) ;
}
if ( bal1 > = 0 ) vpb_set_codec_reg ( tmp - > handle , 0x32 , bal1 ) ;
if ( bal2 > = 0 ) vpb_set_codec_reg ( tmp - > handle , 0x3a , bal2 ) ;
2003-04-15 14:39:06 +00:00
2005-02-17 04:58:03 +00:00
if ( gains & VPB_GOT_TXHWG ) {
if ( txgain > MAX_VPB_GAIN ) {
tmp - > txgain = MAX_VPB_GAIN ;
}
else if ( txgain < MIN_VPB_GAIN ) {
tmp - > txgain = MIN_VPB_GAIN ;
}
else {
tmp - > txgain = txgain ;
}
ast_log ( LOG_NOTICE , " VPB setting Tx Hw gain to [%f] \n " , tmp - > txgain ) ;
vpb_play_set_hw_gain ( tmp - > handle , tmp - > txgain ) ;
}
2003-04-18 14:34:46 +00:00
2005-02-17 04:58:03 +00:00
if ( gains & VPB_GOT_RXHWG ) {
if ( rxgain > MAX_VPB_GAIN ) {
tmp - > rxgain = MAX_VPB_GAIN ;
}
else if ( rxgain < MIN_VPB_GAIN ) {
tmp - > rxgain = MIN_VPB_GAIN ;
}
else {
tmp - > rxgain = rxgain ;
}
ast_log ( LOG_NOTICE , " VPB setting Rx Hw gain to [%f] \n " , tmp - > rxgain ) ;
vpb_record_set_hw_gain ( tmp - > handle , tmp - > rxgain ) ;
}
2003-04-15 14:39:06 +00:00
2005-02-17 04:58:03 +00:00
if ( gains & VPB_GOT_TXSWG ) {
tmp - > txswgain = txswgain ;
ast_log ( LOG_NOTICE , " VPB setting Tx Sw gain to [%f] \n " , tmp - > txswgain ) ;
vpb_play_set_gain ( tmp - > handle , tmp - > txswgain ) ;
}
2003-04-18 14:34:46 +00:00
2005-02-17 04:58:03 +00:00
if ( gains & VPB_GOT_RXSWG ) {
tmp - > rxswgain = rxswgain ;
ast_log ( LOG_NOTICE , " VPB setting Rx Sw gain to [%f] \n " , tmp - > rxswgain ) ;
vpb_record_set_gain ( tmp - > handle , tmp - > rxswgain ) ;
}
2003-04-15 14:39:06 +00:00
2004-03-31 04:29:55 +00:00
tmp - > vpb_model = vpb_model_unknown ;
if ( vpb_get_model ( buf ) = = VPB_OK ) {
if ( strcmp ( buf , " V12PCI " ) = = 0 )
tmp - > vpb_model = vpb_model_v12pci ;
else if ( strcmp ( buf , " VPB4 " ) = = 0 )
tmp - > vpb_model = vpb_model_v4pci ;
}
2004-06-22 17:42:14 +00:00
ast_mutex_init ( & tmp - > owner_lock ) ;
2004-03-31 04:29:55 +00:00
ast_mutex_init ( & tmp - > lock ) ;
ast_mutex_init ( & tmp - > record_lock ) ;
ast_mutex_init ( & tmp - > play_lock ) ;
ast_mutex_init ( & tmp - > play_dtmf_lock ) ;
2004-08-18 05:06:26 +00:00
/* set default read state */
tmp - > read_state = 0 ;
2004-05-21 02:51:05 +00:00
tmp - > golock = 0 ;
2004-03-31 04:29:55 +00:00
tmp - > busy_timer_id = vpb_timer_get_unique_timer_id ( ) ;
vpb_timer_open ( & tmp - > busy_timer , tmp - > handle , tmp - > busy_timer_id , TIMER_PERIOD_BUSY ) ;
tmp - > ringback_timer_id = vpb_timer_get_unique_timer_id ( ) ;
vpb_timer_open ( & tmp - > ringback_timer , tmp - > handle , tmp - > ringback_timer_id , TIMER_PERIOD_RINGBACK ) ;
2005-01-14 04:51:20 +00:00
tmp - > ring_timer_id = vpb_timer_get_unique_timer_id ( ) ;
2005-06-22 23:54:47 +00:00
vpb_timer_open ( & tmp - > ring_timer , tmp - > handle , tmp - > ring_timer_id , timer_period_ring ) ;
2004-03-31 04:29:55 +00:00
2005-01-31 23:51:19 +00:00
tmp - > dtmfidd_timer_id = vpb_timer_get_unique_timer_id ( ) ;
vpb_timer_open ( & tmp - > dtmfidd_timer , tmp - > handle , tmp - > dtmfidd_timer_id , dtmf_idd ) ;
2004-03-31 04:29:55 +00:00
if ( mode = = MODE_FXO ) {
2005-02-21 00:48:35 +00:00
if ( use_ast_dtmfdet )
vpb_set_event_mask ( tmp - > handle , VPB_EVENTS_NODTMF ) ;
else
vpb_set_event_mask ( tmp - > handle , VPB_EVENTS_ALL ) ;
2004-03-31 04:29:55 +00:00
}
else {
2005-02-21 00:48:35 +00:00
/*
if ( use_ast_dtmfdet )
vpb_set_event_mask ( tmp - > handle , VPB_EVENTS_NODTMF ) ;
else
*/
vpb_set_event_mask ( tmp - > handle , VPB_EVENTS_STAT ) ;
2004-03-31 04:29:55 +00:00
}
if ( ( tmp - > vpb_model = = vpb_model_v12pci ) & & ( echo_cancel ) ) {
vpb_hostecho_on ( tmp - > handle ) ;
}
2005-02-21 00:48:35 +00:00
if ( use_ast_dtmfdet ) {
tmp - > vad = ast_dsp_new ( ) ;
ast_dsp_set_features ( tmp - > vad , DSP_FEATURE_DTMF_DETECT ) ;
2005-02-21 04:30:42 +00:00
ast_dsp_digitmode ( tmp - > vad , DSP_DIGITMODE_DTMF ) ;
2005-02-21 00:48:35 +00:00
if ( relaxdtmf )
2005-02-21 04:30:42 +00:00
ast_dsp_digitmode ( tmp - > vad , DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF ) ;
2005-02-21 00:48:35 +00:00
}
else {
tmp - > vad = NULL ;
}
2004-03-31 04:29:55 +00:00
/* define grunt tone */
vpb_settonedet ( tmp - > handle , & toned_ungrunt ) ;
2005-02-17 04:58:03 +00:00
ast_log ( LOG_NOTICE , " Voicetronix %s channel %s initialized (rxsg=%f/txsg=%f/rxhg=%f/txhg=%f)(0x%x/0x%x/0x%x) \n " ,
( tmp - > vpb_model = = vpb_model_v4pci ) ? " V4PCI " : ( tmp - > vpb_model = = vpb_model_v12pci ) ? " V12PCI " : " [Unknown model] " ,
2004-03-31 04:29:55 +00:00
tmp - > dev , tmp - > rxswgain , tmp - > txswgain , tmp - > rxgain , tmp - > txgain , bal1 , bal2 , bal3 ) ;
return tmp ;
}
2003-05-04 05:56:50 +00:00
2006-05-10 12:24:11 +00:00
static int vpb_indicate ( struct ast_channel * ast , int condition , const void * data , size_t datalen )
2003-05-04 05:56:50 +00:00
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) ast - > tech_pvt ;
2004-04-05 05:37:01 +00:00
int res = 0 ;
2004-05-26 01:29:29 +00:00
int tmp = 0 ;
2004-04-05 05:37:01 +00:00
2005-04-13 04:15:23 +00:00
if ( use_ast_ind = = 1 ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: vpb_indicate called when using Ast Indications !?! \n " , p - > dev ) ;
2005-03-04 06:47:24 +00:00
return 0 ;
2005-04-13 04:15:23 +00:00
}
2005-03-04 06:47:24 +00:00
2004-04-05 05:37:01 +00:00
if ( option_verbose > 3 )
2004-08-18 05:06:26 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: vpb_indicate [%d] state[%d] \n " , p - > dev , condition , ast - > _state ) ;
/*
2004-05-21 02:51:05 +00:00
if ( ast - > _state ! = AST_STATE_UP ) {
2004-08-18 05:06:26 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: vpb_indicate Not in AST_STATE_UP \n " , p - > dev , condition , ast - > _state ) ;
2004-05-21 02:51:05 +00:00
return res ;
}
2004-08-18 05:06:26 +00:00
*/
2004-04-05 05:37:01 +00:00
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in indicate \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING count[%d] owner[%d] \n " , p - > dev , p - > lock . __m_count , p - > lock . __m_owner ) ;
2004-08-18 23:58:07 +00:00
*/
2004-05-21 02:51:05 +00:00
ast_mutex_lock ( & p - > lock ) ;
2004-04-05 05:37:01 +00:00
switch ( condition ) {
case AST_CONTROL_BUSY :
case AST_CONTROL_CONGESTION :
2004-08-18 05:06:26 +00:00
if ( ast - > _state = = AST_STATE_UP ) {
playtone ( p - > handle , & Busytone ) ;
p - > state = VPB_STATE_PLAYBUSY ;
vpb_timer_stop ( p - > busy_timer ) ;
vpb_timer_start ( p - > busy_timer ) ;
}
2004-04-05 05:37:01 +00:00
break ;
case AST_CONTROL_RINGING :
2004-08-18 05:06:26 +00:00
if ( ast - > _state = = AST_STATE_UP ) {
playtone ( p - > handle , & Ringbacktone ) ;
p - > state = VPB_STATE_PLAYRING ;
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: vpb indicate: setting ringback timer [%d] \n " , p - > dev , p - > ringback_timer_id ) ;
vpb_timer_stop ( p - > ringback_timer ) ;
vpb_timer_start ( p - > ringback_timer ) ;
}
2004-04-05 05:37:01 +00:00
break ;
case AST_CONTROL_ANSWER :
case - 1 : /* -1 means stop playing? */
vpb_timer_stop ( p - > ringback_timer ) ;
vpb_timer_stop ( p - > busy_timer ) ;
stoptone ( p - > handle ) ;
break ;
case AST_CONTROL_HANGUP :
2004-08-18 05:06:26 +00:00
if ( ast - > _state = = AST_STATE_UP ) {
playtone ( p - > handle , & Busytone ) ;
p - > state = VPB_STATE_PLAYBUSY ;
vpb_timer_stop ( p - > busy_timer ) ;
vpb_timer_start ( p - > busy_timer ) ;
}
2004-04-05 05:37:01 +00:00
break ;
2006-07-19 20:44:39 +00:00
case AST_CONTROL_HOLD :
ast_moh_start ( ast , ( const char * ) data , NULL ) ;
break ;
case AST_CONTROL_UNHOLD :
ast_moh_stop ( ast ) ;
break ;
2004-04-05 05:37:01 +00:00
default :
res = 0 ;
break ;
}
2004-05-26 01:29:29 +00:00
tmp = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in indicate [%d] \n " , p - > dev , tmp ) ;
2004-08-18 23:58:07 +00:00
*/
2004-04-05 05:37:01 +00:00
return res ;
2003-05-04 05:56:50 +00:00
}
2004-04-08 00:59:39 +00:00
static int vpb_fixup ( struct ast_channel * oldchan , struct ast_channel * newchan )
2003-05-04 05:56:50 +00:00
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) newchan - > tech_pvt ;
2004-05-26 01:29:29 +00:00
int res = 0 ;
2003-05-04 05:56:50 +00:00
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in fixup \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING count[%d] owner[%d] \n " , p - > dev , p - > lock . __m_count , p - > lock . __m_owner ) ;
2004-08-18 23:58:07 +00:00
*/
2004-04-08 00:59:39 +00:00
ast_mutex_lock ( & p - > lock ) ;
2004-05-21 02:51:05 +00:00
ast_log ( LOG_DEBUG , " New owner for channel %s is %s \n " , p - > dev , newchan - > name ) ;
2004-03-31 04:29:55 +00:00
if ( p - > owner = = oldchan ) {
2003-05-04 05:56:50 +00:00
p - > owner = newchan ;
2004-03-31 04:29:55 +00:00
}
2003-05-04 05:56:50 +00:00
2004-11-30 04:14:27 +00:00
if ( newchan - > _state = = AST_STATE_RINGING ) {
2005-04-13 04:15:23 +00:00
if ( use_ast_ind = = 1 ) {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: vpb_fixup Calling ast_indicate \n " , p - > dev ) ;
2004-11-30 04:14:27 +00:00
ast_indicate ( newchan , AST_CONTROL_RINGING ) ;
2005-04-13 04:15:23 +00:00
}
else {
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: vpb_fixup Calling vpb_indicate \n " , p - > dev ) ;
2006-05-10 12:24:11 +00:00
vpb_indicate ( newchan , AST_CONTROL_RINGING , NULL , 0 ) ;
2005-04-13 04:15:23 +00:00
}
2004-11-30 04:14:27 +00:00
}
2003-05-04 05:56:50 +00:00
2004-05-26 01:29:29 +00:00
res = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in fixup [%d] \n " , p - > dev , res ) ;
2004-08-18 23:58:07 +00:00
*/
2003-05-04 05:56:50 +00:00
return 0 ;
}
2006-08-31 01:59:02 +00:00
static int vpb_digit_begin ( struct ast_channel * ast , char digit )
{
/* XXX Modify this callback to let Asterisk control the length of DTMF */
return 0 ;
}
static int vpb_digit_end ( struct ast_channel * ast , char digit )
2003-04-15 14:39:06 +00:00
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) ast - > tech_pvt ;
2004-04-05 05:37:01 +00:00
char s [ 2 ] ;
2004-05-26 01:29:29 +00:00
int res = 0 ;
2004-04-05 05:37:01 +00:00
2005-04-13 03:16:38 +00:00
if ( use_ast_dtmf ) {
if ( option_verbose > 3 )
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 ) ;
2005-03-04 06:47:24 +00:00
return 0 ;
2005-04-13 03:16:38 +00:00
}
2005-03-04 06:47:24 +00:00
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in digit \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING count[%d] owner[%d] \n " , p - > dev , p - > lock . __m_count , p - > lock . __m_owner ) ;
2004-08-18 23:58:07 +00:00
*/
2004-05-21 02:51:05 +00:00
ast_mutex_lock ( & p - > lock ) ;
2004-04-05 05:37:01 +00:00
s [ 0 ] = digit ;
s [ 1 ] = ' \0 ' ;
2003-04-15 14:39:06 +00:00
2004-05-21 02:51:05 +00:00
if ( option_verbose > 3 )
2005-02-21 04:30:42 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: vpb_digit: asked to play digit[%s] \n " , p - > dev , s ) ;
2004-05-21 02:51:05 +00:00
2004-04-05 05:37:01 +00:00
ast_mutex_lock ( & p - > play_dtmf_lock ) ;
strncat ( p - > play_dtmf , s , sizeof ( * p - > play_dtmf ) ) ;
ast_mutex_unlock ( & p - > play_dtmf_lock ) ;
2004-03-31 04:29:55 +00:00
2004-05-26 01:29:29 +00:00
res = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in digit [%d] \n " , p - > dev , res ) ;
2004-08-18 23:58:07 +00:00
*/
2004-04-05 05:37:01 +00:00
return 0 ;
2003-04-15 14:39:06 +00:00
}
2004-08-18 05:06:26 +00:00
/* Places a call out of a VPB channel */
2003-04-15 14:39:06 +00:00
static int vpb_call ( struct ast_channel * ast , char * dest , int timeout )
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) ast - > tech_pvt ;
2004-05-14 04:39:16 +00:00
int res = 0 , i ;
2004-04-05 05:37:01 +00:00
char * s = strrchr ( dest , ' / ' ) ;
2004-07-16 04:40:54 +00:00
char dialstring [ 254 ] = " " ;
2004-05-26 01:29:29 +00:00
int tmp = 0 ;
2003-04-15 14:39:06 +00:00
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in call \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING count[%d] owner[%d] \n " , p - > dev , p - > lock . __m_count , p - > lock . __m_owner ) ;
2004-08-18 23:58:07 +00:00
*/
2004-05-21 02:51:05 +00:00
ast_mutex_lock ( & p - > lock ) ;
2005-04-27 04:28:24 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: starting call to [%s] \n " , p - > dev , dest ) ;
2004-05-21 02:51:05 +00:00
2004-04-05 05:37:01 +00:00
if ( s )
s = s + 1 ;
else
s = dest ;
2004-07-16 04:40:54 +00:00
strncpy ( dialstring , s , sizeof ( dialstring ) - 1 ) ;
2004-05-14 04:39:16 +00:00
for ( i = 0 ; dialstring [ i ] ! = ' \0 ' ; i + + ) {
if ( ( dialstring [ i ] = = ' w ' ) | | ( dialstring [ i ] = = ' W ' ) )
dialstring [ i ] = ' , ' ;
else if ( ( dialstring [ i ] = = ' f ' ) | | ( dialstring [ i ] = = ' F ' ) )
dialstring [ i ] = ' & ' ;
}
2003-04-15 14:39:06 +00:00
2004-04-05 05:37:01 +00:00
if ( ast - > _state ! = AST_STATE_DOWN & & ast - > _state ! = AST_STATE_RESERVED ) {
2004-05-21 02:51:05 +00:00
ast_log ( LOG_WARNING , " vpb_call on %s neither down nor reserved! \n " , ast - > name ) ;
2004-05-26 01:29:29 +00:00
tmp = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in call [%d] \n " , p - > dev , tmp ) ;
2004-08-18 23:58:07 +00:00
*/
2004-04-05 05:37:01 +00:00
return - 1 ;
}
if ( p - > mode ! = MODE_FXO ) /* Station port, ring it. */
res = vpb_ring_station_async ( p - > handle , VPB_RING_STATION_ON , 0 ) ;
else {
VPB_CALL call ;
2004-12-18 22:04:07 +00:00
/* Dial must timeout or it can leave channels unuseable */
2004-04-05 05:37:01 +00:00
if ( timeout = = 0 )
timeout = TIMER_PERIOD_NOANSWER ;
else
2004-12-18 22:04:07 +00:00
timeout = timeout * 1000 ; /* convert from secs to ms. */
/* These timeouts are only used with call progress dialing */
call . dialtones = 1 ; /* Number of dialtones to get outside line */
call . dialtone_timeout = VPB_DIALTONE_WAIT ; /* Wait this long for dialtone (ms) */
call . ringback_timeout = VPB_RINGWAIT ; /* Wait this long for ringing after dialing (ms) */
call . inter_ringback_timeout = VPB_CONNECTED_WAIT ; /* If ringing stops for this long consider it connected (ms) */
call . answer_timeout = timeout ; /* Time to wait for answer after ringing starts (ms) */
2004-04-05 05:37:01 +00:00
memcpy ( & call . tone_map , DialToneMap , sizeof ( DialToneMap ) ) ;
vpb_set_call ( p - > handle , & call ) ;
if ( option_verbose > 1 )
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Calling %s on %s \n " , p - > dev , dialstring , ast - > name ) ;
2004-04-05 05:37:01 +00:00
if ( option_verbose > 2 ) {
int j ;
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Dial parms for %s %d/%dms/%dms/%dms/%dms \n " , p - > dev
2004-04-05 05:37:01 +00:00
, ast - > name , call . dialtones , call . dialtone_timeout
, call . ringback_timeout , call . inter_ringback_timeout
, call . answer_timeout ) ;
for ( j = 0 ; ! call . tone_map [ j ] . terminate ; j + + )
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Dial parms for %s tone %d->%d \n " , p - > dev ,
2004-04-05 05:37:01 +00:00
ast - > name , call . tone_map [ j ] . tone_id , call . tone_map [ j ] . call_id ) ;
}
2005-02-21 00:48:35 +00:00
if ( option_verbose > 3 )
2004-08-18 05:06:26 +00:00
ast_verbose ( " %s: Disabling Loop Drop detection \n " , p - > dev ) ;
vpb_disable_event ( p - > handle , VPB_MDROP ) ;
2004-04-05 05:37:01 +00:00
vpb_sethook_sync ( p - > handle , VPB_OFFHOOK ) ;
2004-05-14 04:39:16 +00:00
p - > state = VPB_STATE_OFFHOOK ;
2004-04-05 05:37:01 +00:00
# ifndef DIAL_WITH_CALL_PROGRESS
vpb_sleep ( 300 ) ;
2005-02-21 00:48:35 +00:00
if ( option_verbose > 3 )
ast_verbose ( " %s: Enabling Loop Drop detection \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
vpb_enable_event ( p - > handle , VPB_MDROP ) ;
2004-05-14 04:39:16 +00:00
res = vpb_dial_async ( p - > handle , dialstring ) ;
2004-04-05 05:37:01 +00:00
# else
2005-02-21 00:48:35 +00:00
if ( option_verbose > 3 )
ast_verbose ( " %s: Enabling Loop Drop detection \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
vpb_enable_event ( p - > handle , VPB_MDROP ) ;
2004-05-14 04:39:16 +00:00
res = vpb_call_async ( p - > handle , dialstring ) ;
2004-04-05 05:37:01 +00:00
# endif
if ( res ! = VPB_OK ) {
ast_log ( LOG_DEBUG , " Call on %s to %s failed: %s \n " , ast - > name , s , vpb_strerror ( res ) ) ;
res = - 1 ;
} else
res = 0 ;
}
if ( option_verbose > 2 )
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " %s: VPB Calling %s [t=%d] on %s returned %d \n " , p - > dev , s , timeout , ast - > name , res ) ;
2004-04-05 05:37:01 +00:00
if ( res = = 0 ) {
ast_setstate ( ast , AST_STATE_RINGING ) ;
2004-04-06 22:17:32 +00:00
ast_queue_control ( ast , AST_CONTROL_RINGING ) ;
2004-04-05 05:37:01 +00:00
}
2004-05-21 02:51:05 +00:00
if ( ! p - > readthread ) {
2004-08-18 23:58:07 +00:00
ast_pthread_create ( & p - > readthread , NULL , do_chanreads , ( void * ) p ) ;
2004-05-21 02:51:05 +00:00
}
2004-04-05 05:37:01 +00:00
2004-05-26 01:29:29 +00:00
tmp = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in call [%d] \n " , p - > dev , tmp ) ;
2004-08-18 23:58:07 +00:00
*/
2004-04-05 05:37:01 +00:00
return res ;
2003-04-15 14:39:06 +00:00
}
static int vpb_hangup ( struct ast_channel * ast )
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) ast - > tech_pvt ;
2004-05-14 04:39:16 +00:00
VPB_EVENT je ;
char str [ VPB_MAX_STR ] ;
2004-05-26 01:29:29 +00:00
int res = 0 ;
2004-04-05 05:37:01 +00:00
2004-08-18 05:06:26 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in hangup \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
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 ) ;
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING pthread_self(%d) \n " , p - > dev , pthread_self ( ) ) ;
2004-05-21 02:51:05 +00:00
ast_mutex_lock ( & p - > lock ) ;
2004-08-18 05:06:26 +00:00
*/
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
2004-05-14 04:39:16 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Hangup requested \n " , ast - > name ) ;
2003-04-15 14:39:06 +00:00
2005-03-04 06:47:24 +00:00
if ( ! ast - > tech | | ! ast - > tech_pvt ) {
2004-05-14 04:39:16 +00:00
ast_log ( LOG_WARNING , " %s: channel not connected? \n " , ast - > name ) ;
2004-05-26 01:29:29 +00:00
res = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in hangup [%d] \n " , p - > dev , res ) ;
2004-08-18 23:58:07 +00:00
*/
2005-02-21 00:48:35 +00:00
/* Free up ast dsp if we have one */
if ( ( use_ast_dtmfdet ) & & ( p - > vad ) ) {
ast_dsp_free ( p - > vad ) ;
p - > vad = NULL ;
}
2004-04-05 05:37:01 +00:00
return 0 ;
}
/* Stop record */
p - > stopreads = 1 ;
2004-05-20 01:59:03 +00:00
if ( p - > readthread ) {
2004-04-05 05:37:01 +00:00
pthread_join ( p - > readthread , NULL ) ;
2004-05-20 01:59:03 +00:00
if ( option_verbose > 3 )
2005-02-21 00:48:35 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: stopped record thread \n " , ast - > name ) ;
2004-05-20 01:59:03 +00:00
}
2004-04-05 05:37:01 +00:00
/* Stop play */
if ( p - > lastoutput ! = - 1 ) {
if ( option_verbose > 1 )
2005-02-21 00:48:35 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Ending play mode \n " , ast - > name ) ;
2004-04-05 05:37:01 +00:00
vpb_play_terminate ( p - > handle ) ;
ast_mutex_lock ( & p - > play_lock ) ; {
vpb_play_buf_finish ( p - > handle ) ;
} ast_mutex_unlock ( & p - > play_lock ) ;
}
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: Setting state down \n " , ast - > name ) ;
ast_setstate ( ast , AST_STATE_DOWN ) ;
2004-08-18 23:58:07 +00:00
/*
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in hangup \n " , p - > dev ) ;
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 ) ;
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING pthread_self(%d) \n " , p - > dev , pthread_self ( ) ) ;
2004-08-18 23:58:07 +00:00
*/
2004-08-18 05:06:26 +00:00
ast_mutex_lock ( & p - > lock ) ;
2005-02-21 00:48:35 +00:00
if ( p - > mode ! = MODE_FXO ) {
2004-05-14 04:39:16 +00:00
/* station port. */
2004-04-05 05:37:01 +00:00
vpb_ring_station_async ( p - > handle , VPB_RING_STATION_OFF , 0 ) ;
2004-05-14 04:39:16 +00:00
if ( p - > state ! = VPB_STATE_ONHOOK ) {
/* This is causing a "dial end" "play tone" loop
playtone ( p - > handle , & Busytone ) ;
p - > state = VPB_STATE_PLAYBUSY ;
if ( option_verbose > 4 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: Station offhook[%d], playing busy tone \n " ,
ast - > name , p - > state ) ;
*/
}
else {
stoptone ( p - > handle ) ;
}
2005-11-03 00:04:09 +00:00
# ifdef VPB_PRI
vpb_setloop_async ( p - > handle , VPB_OFFHOOK ) ;
2005-11-03 21:49:20 +00:00
vpb_sleep ( 100 ) ;
vpb_setloop_async ( p - > handle , VPB_ONHOOK ) ;
2005-11-03 00:04:09 +00:00
# endif
2004-04-05 05:37:01 +00:00
} else {
2004-12-18 22:04:07 +00:00
stoptone ( p - > handle ) ; /* Terminates any dialing */
2004-04-05 05:37:01 +00:00
vpb_sethook_sync ( p - > handle , VPB_ONHOOK ) ;
2004-05-14 04:39:16 +00:00
p - > state = VPB_STATE_ONHOOK ;
}
while ( VPB_OK = = vpb_get_event_ch_async ( p - > handle , & je ) ) {
if ( option_verbose > 3 ) {
vpb_translate_event ( & je , str ) ;
ast_verbose ( VERBOSE_PREFIX_4 " %s: Flushing event [%d]=>%s \n " , ast - > name , je . type , str ) ;
}
2004-04-05 05:37:01 +00:00
}
p - > readthread = 0 ;
p - > lastoutput = - 1 ;
p - > lastinput = - 1 ;
p - > last_ignore_dtmf = 1 ;
p - > ext [ 0 ] = 0 ;
p - > dialtone = 0 ;
2004-05-21 02:51:05 +00:00
p - > owner = NULL ;
2005-03-04 06:47:24 +00:00
ast - > tech_pvt = NULL ;
2004-04-05 05:37:01 +00:00
2005-02-21 00:48:35 +00:00
/* Free up ast dsp if we have one */
if ( ( use_ast_dtmfdet ) & & ( p - > vad ) ) {
ast_dsp_free ( p - > vad ) ;
p - > vad = NULL ;
}
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
2004-05-14 04:39:16 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Hangup complete \n " , ast - > name ) ;
2004-04-05 05:37:01 +00:00
restart_monitor ( ) ;
2004-08-18 23:58:07 +00:00
/*
2004-08-18 05:06:26 +00:00
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 ) ;
2004-08-18 23:58:07 +00:00
*/
2004-05-26 01:29:29 +00:00
res = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in hangup [%d] \n " , p - > dev , res ) ;
2004-08-18 05:06:26 +00:00
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 ) ;
2004-08-18 23:58:07 +00:00
*/
2003-04-15 14:39:06 +00:00
return 0 ;
}
static int vpb_answer ( struct ast_channel * ast )
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) ast - > tech_pvt ;
2004-05-26 01:29:29 +00:00
int res = 0 ;
2004-08-18 23:58:07 +00:00
/*
2005-06-22 23:54:47 +00:00
VPB_EVENT je ;
int ret ;
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING in answer \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: LOCKING count[%d] owner[%d] \n " , p - > dev , p - > lock . __m_count , p - > lock . __m_owner ) ;
2004-08-18 23:58:07 +00:00
*/
2004-05-21 02:51:05 +00:00
ast_mutex_lock ( & p - > lock ) ;
if ( option_verbose > 3 )
ast_verbose ( VERBOSE_PREFIX_4 " %s: Answering channel \n " , p - > dev ) ;
2003-04-15 14:39:06 +00:00
2004-08-20 02:55:29 +00:00
if ( p - > mode = = MODE_FXO ) {
2004-09-17 00:14:48 +00:00
if ( option_verbose > 3 )
2004-08-20 02:55:29 +00:00
ast_verbose ( " %s: Disabling Loop Drop detection \n " , p - > dev ) ;
vpb_disable_event ( p - > handle , VPB_MDROP ) ;
}
2004-08-18 05:06:26 +00:00
2004-05-20 01:59:03 +00:00
if ( ast - > _state ! = AST_STATE_UP ) {
if ( p - > mode = = MODE_FXO ) {
vpb_sethook_sync ( p - > handle , VPB_OFFHOOK ) ;
p - > state = VPB_STATE_OFFHOOK ;
2004-08-18 05:06:26 +00:00
/* vpb_sleep(500);
2004-05-20 01:59:03 +00:00
ret = vpb_get_event_ch_async ( p - > handle , & je ) ;
2004-08-18 05:06:26 +00:00
if ( ( ret = = VPB_OK ) & & ( ( je . type ! = VPB_DROP ) & & ( je . type ! = VPB_RING ) ) ) {
2004-05-20 01:59:03 +00:00
if ( option_verbose > 3 ) {
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: Answer collected a wrong event!! \n " , p - > dev ) ;
2004-05-20 01:59:03 +00:00
}
vpb_put_event ( & je ) ;
2004-05-14 04:39:16 +00:00
}
2004-08-18 05:06:26 +00:00
*/
2004-05-14 04:39:16 +00:00
}
2004-05-20 01:59:03 +00:00
ast_setstate ( ast , AST_STATE_UP ) ;
2004-03-31 04:29:55 +00:00
2004-05-20 01:59:03 +00:00
if ( option_verbose > 1 )
2004-12-18 22:04:07 +00:00
/*
ast_verbose ( VERBOSE_PREFIX_2 " %s: Answered call from %s on %s [%s] \n " , p - > dev ,
p - > owner - > callerid , ast - > name , ( p - > mode = = MODE_FXO ) ? " FXO " : " FXS " ) ;
*/
2004-10-06 10:37:57 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Answered call on %s [%s] \n " , p - > dev ,
ast - > name , ( p - > mode = = MODE_FXO ) ? " FXO " : " FXS " ) ;
2004-03-31 04:29:55 +00:00
2004-05-20 01:59:03 +00:00
ast - > rings = 0 ;
if ( ! p - > readthread ) {
2004-12-18 22:04:07 +00:00
/* res = ast_mutex_unlock(&p->lock); */
/* ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res); */
2004-08-18 23:58:07 +00:00
ast_pthread_create ( & p - > readthread , NULL , do_chanreads , ( void * ) p ) ;
2004-05-20 01:59:03 +00:00
} else {
if ( option_verbose > 3 )
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: Record thread already running!! \n " , p - > dev ) ;
2004-05-20 01:59:03 +00:00
}
} else {
if ( option_verbose > 3 ) {
2004-05-21 02:51:05 +00:00
ast_verbose ( VERBOSE_PREFIX_4 " %s: Answered state is up \n " , p - > dev ) ;
2004-05-20 01:59:03 +00:00
}
2004-12-18 22:04:07 +00:00
/* res = ast_mutex_unlock(&p->lock); */
/* ast_verbose("%s: unLOCKING in answer [%d]\n", p->dev,res); */
2004-05-20 01:59:03 +00:00
}
2004-08-18 05:06:26 +00:00
vpb_sleep ( 500 ) ;
2004-08-20 02:55:29 +00:00
if ( p - > mode = = MODE_FXO ) {
2004-09-17 00:14:48 +00:00
if ( option_verbose > 3 )
2004-08-20 02:55:29 +00:00
ast_verbose ( " %s: Re-enabling Loop Drop detection \n " , p - > dev ) ;
vpb_enable_event ( p - > handle , VPB_MDROP ) ;
}
2004-05-26 01:29:29 +00:00
res = ast_mutex_unlock ( & p - > lock ) ;
2004-08-18 23:58:07 +00:00
/*
2004-05-26 01:29:29 +00:00
if ( option_verbose > 3 ) ast_verbose ( " %s: unLOCKING in answer [%d] \n " , p - > dev , res ) ;
2004-08-18 23:58:07 +00:00
*/
2004-04-05 05:37:01 +00:00
return 0 ;
2003-04-15 14:39:06 +00:00
}
static struct ast_frame * vpb_read ( struct ast_channel * ast )
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) ast - > tech_pvt ;
2004-04-05 05:37:01 +00:00
static struct ast_frame f = { AST_FRAME_NULL } ;
2006-02-02 21:49:36 +00:00
f . src = " vpb " ;
2004-08-18 05:06:26 +00:00
ast_log ( LOG_NOTICE , " %s: vpb_read: should never be called! \n " , p - > dev ) ;
ast_verbose ( " %s: vpb_read: should never be called! \n " , p - > dev ) ;
2004-04-05 05:37:01 +00:00
return & f ;
2003-04-15 14:39:06 +00:00
}
static inline int ast2vpbformat ( int ast_format )
{
2004-04-05 05:37:01 +00:00
switch ( ast_format ) {
case AST_FORMAT_ALAW :
return VPB_ALAW ;
case AST_FORMAT_SLINEAR :
return VPB_LINEAR ;
case AST_FORMAT_ULAW :
return VPB_MULAW ;
case AST_FORMAT_ADPCM :
return VPB_OKIADPCM ;
default :
return - 1 ;
}
2003-04-15 14:39:06 +00:00
}
2004-08-18 05:06:26 +00:00
static inline char * ast2vpbformatname ( int ast_format )
{
switch ( ast_format ) {
case AST_FORMAT_ALAW :
return " AST_FORMAT_ALAW:VPB_ALAW " ;
case AST_FORMAT_SLINEAR :
return " AST_FORMAT_SLINEAR:VPB_LINEAR " ;
case AST_FORMAT_ULAW :
return " AST_FORMAT_ULAW:VPB_MULAW " ;
case AST_FORMAT_ADPCM :
return " AST_FORMAT_ADPCM:VPB_OKIADPCM " ;
default :
return " UNKN:UNKN " ;
}
}
2003-04-15 14:39:06 +00:00
static inline int astformatbits ( int ast_format )
{
2004-04-05 05:37:01 +00:00
switch ( ast_format ) {
case AST_FORMAT_ALAW :
case AST_FORMAT_ULAW :
return 8 ;
case AST_FORMAT_SLINEAR :
return 16 ;
case AST_FORMAT_ADPCM :
return 4 ;
default :
return 8 ;
}
2003-04-15 14:39:06 +00:00
}
2004-08-18 23:58:07 +00:00
int a_gain_vector ( float g , short * v , int n )
2004-05-20 01:59:03 +00:00
{
2004-04-05 05:37:01 +00:00
int i ;
2004-03-31 04:29:55 +00:00
float tmp ;
for ( i = 0 ; i < n ; i + + ) {
2004-04-05 05:37:01 +00:00
tmp = g * v [ i ] ;
if ( tmp > 32767.0 )
tmp = 32767.0 ;
if ( tmp < - 32768.0 )
tmp = - 32768.0 ;
v [ i ] = ( short ) tmp ;
2004-03-31 04:29:55 +00:00
}
return ( i ) ;
2004-04-05 05:37:01 +00:00
}
2004-03-31 04:29:55 +00:00
2004-08-18 05:06:26 +00:00
/* Writes a frame of voice data to a VPB channel */
2003-04-15 14:39:06 +00:00
static int vpb_write ( struct ast_channel * ast , struct ast_frame * frame )
{
2005-03-04 06:47:24 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) ast - > tech_pvt ;
2004-04-05 05:37:01 +00:00
int res = 0 , fmt = 0 ;
2005-07-15 23:00:47 +00:00
struct timeval play_buf_time_start ;
2005-11-03 00:04:09 +00:00
int tdiff ;
2004-12-18 22:04:07 +00:00
/* ast_mutex_lock(&p->lock); */
2004-05-24 01:43:05 +00:00
if ( option_verbose > 5 )
2004-08-18 05:06:26 +00:00
ast_verbose ( " %s: vpb_write: Writing to channel \n " , p - > dev ) ;
2004-04-05 05:37:01 +00:00
if ( frame - > frametype ! = AST_FRAME_VOICE ) {
if ( option_verbose > 3 )
2004-08-18 05:06:26 +00:00
ast_verbose ( " %s: vpb_write: Don't know how to handle from type %d \n " , ast - > name , frame - > frametype ) ;
2004-12-18 22:04:07 +00:00
/* ast_mutex_unlock(&p->lock); */
2004-04-05 05:37:01 +00:00
return 0 ;
} else if ( ast - > _state ! = AST_STATE_UP ) {
if ( option_verbose > 3 )
2005-02-10 00:54:24 +00:00
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 ) ;
2004-05-20 01:59:03 +00:00
p - > lastoutput = - 1 ;
2004-12-18 22:04:07 +00:00
/* ast_mutex_unlock(&p->lock); */
2004-04-05 05:37:01 +00:00
return 0 ;
}
2004-12-18 22:04:07 +00:00
/* ast_log(LOG_DEBUG, "%s: vpb_write: Checked frame type..\n", p->dev); */
2003-04-15 14:39:06 +00:00
2005-11-03 00:04:09 +00:00
2004-04-05 05:37:01 +00:00
fmt = ast2vpbformat ( frame - > subclass ) ;
if ( fmt < 0 ) {
2004-08-18 05:06:26 +00:00
ast_log ( LOG_WARNING , " %s: vpb_write: Cannot handle frames of %d format! \n " , ast - > name , frame - > subclass ) ;
2004-04-05 05:37:01 +00:00
return - 1 ;
}
2005-11-03 00:04:09 +00:00
tdiff = ast_tvdiff_ms ( ast_tvnow ( ) , p - > lastplay ) ;
ast_log ( LOG_DEBUG , " %s: vpb_write: time since last play(%d) \n " , p - > dev , tdiff ) ;
if ( tdiff < ( VPB_SAMPLES / 8 - 1 ) ) {
ast_log ( LOG_DEBUG , " %s: vpb_write: Asked to play too often (%d) (%d) \n " , p - > dev , tdiff , frame - > datalen ) ;
// return 0;
}
p - > lastplay = ast_tvnow ( ) ;
2005-02-10 00:54:24 +00:00
/*
ast_log ( LOG_DEBUG , " %s: vpb_write: Checked frame format.. \n " , p - > dev ) ;
*/
2004-04-05 05:37:01 +00:00
ast_mutex_lock ( & p - > play_lock ) ;
2005-02-10 00:54:24 +00:00
/*
ast_log ( LOG_DEBUG , " %s: vpb_write: Got play lock.. \n " , p - > dev ) ;
*/
2004-08-18 05:06:26 +00:00
/* Check if we have set up the play_buf */
2004-04-05 05:37:01 +00:00
if ( p - > lastoutput = = - 1 ) {
vpb_play_buf_start ( p - > handle , fmt ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 1 ) {
ast_verbose ( " %s: vpb_write: Starting play mode (codec=%d)[%s] \n " , p - > dev , fmt , ast2vpbformatname ( frame - > subclass ) ) ;
}
2005-11-02 01:02:02 +00:00
p - > lastoutput = fmt ;
ast_mutex_unlock ( & p - > play_lock ) ;
return 0 ;
2004-04-05 05:37:01 +00:00
} else if ( p - > lastoutput ! = fmt ) {
vpb_play_buf_finish ( p - > handle ) ;
vpb_play_buf_start ( p - > handle , fmt ) ;
if ( option_verbose > 1 )
2004-08-18 05:06:26 +00:00
ast_verbose ( " %s: vpb_write: Changed play format (%d=>%d) \n " , p - > dev , p - > lastoutput , fmt ) ;
2005-11-02 01:02:02 +00:00
ast_mutex_unlock ( & p - > play_lock ) ;
return 0 ;
2004-04-05 05:37:01 +00:00
}
p - > lastoutput = fmt ;
2004-08-18 05:06:26 +00:00
2004-12-18 22:04:07 +00:00
/* Apply extra gain ! */
2004-04-05 05:37:01 +00:00
if ( p - > txswgain > MAX_VPB_GAIN )
2004-08-18 23:58:07 +00:00
a_gain_vector ( p - > txswgain - MAX_VPB_GAIN , ( short * ) frame - > data , frame - > datalen / sizeof ( short ) ) ;
2004-04-05 05:37:01 +00:00
2004-12-18 22:04:07 +00:00
/* ast_log(LOG_DEBUG, "%s: vpb_write: Applied gain..\n", p->dev); */
2005-11-03 00:04:09 +00:00
/* ast_log(LOG_DEBUG, "%s: vpb_write: play_buf_time %d\n", p->dev, p->play_buf_time); */
2004-08-18 05:06:26 +00:00
if ( ( p - > read_state = = 1 ) & & ( p - > play_buf_time < 5 ) ) {
2005-07-15 23:00:47 +00:00
play_buf_time_start = ast_tvnow ( ) ;
2005-11-03 00:04:09 +00:00
/* res = vpb_play_buf_sync(p->handle, (char*)frame->data, tdiff*8*2); */
2005-06-10 03:18:24 +00:00
res = vpb_play_buf_sync ( p - > handle , ( char * ) frame - > data , frame - > datalen ) ;
2005-07-15 23:00:47 +00:00
if ( res = = VPB_OK & & option_verbose > 5 ) {
2005-06-10 03:18:24 +00:00
short * data = ( short * ) frame - > data ;
ast_verbose ( " %s: vpb_write: Wrote chan (codec=%d) %d %d \n " , p - > dev , fmt , data [ 0 ] , data [ 1 ] ) ;
}
2005-07-15 23:00:47 +00:00
p - > play_buf_time = ast_tvdiff_ms ( ast_tvnow ( ) , play_buf_time_start ) ;
2004-08-18 05:06:26 +00:00
}
else {
p - > chuck_count + + ;
ast_log ( LOG_DEBUG , " %s: vpb_write: Tossed data away, tooooo much data!![%d] \n " , p - > dev , p - > chuck_count ) ;
p - > play_buf_time = 0 ;
2004-04-05 05:37:01 +00:00
}
ast_mutex_unlock ( & p - > play_lock ) ;
2004-12-18 22:04:07 +00:00
/* ast_mutex_unlock(&p->lock); */
2004-08-18 05:06:26 +00:00
if ( option_verbose > 5 )
ast_verbose ( " %s: vpb_write: Done Writing to channel \n " , p - > dev ) ;
2003-04-15 14:39:06 +00:00
return 0 ;
}
/* Read monitor thread function. */
static void * do_chanreads ( void * pvt )
{
2004-04-05 05:37:01 +00:00
struct vpb_pvt * p = ( struct vpb_pvt * ) pvt ;
struct ast_frame * fr = & p - > fr ;
char * readbuf = ( ( char * ) p - > buf ) + AST_FRIENDLY_OFFSET ;
int bridgerec = 0 ;
2004-08-18 05:06:26 +00:00
int afmt , readlen , res , fmt , trycnt = 0 ;
2004-04-05 05:37:01 +00:00
int ignore_dtmf ;
2006-02-02 21:49:36 +00:00
const char * getdtmf_var = NULL ;
2004-04-05 05:37:01 +00:00
fr - > frametype = AST_FRAME_VOICE ;
2006-02-02 21:49:36 +00:00
fr - > src = " vpb " ;
2004-04-05 05:37:01 +00:00
fr - > mallocd = 0 ;
2004-06-24 13:27:44 +00:00
fr - > delivery . tv_sec = 0 ;
fr - > delivery . tv_usec = 0 ;
2004-04-05 05:37:01 +00:00
fr - > samples = VPB_SAMPLES ;
fr - > offset = AST_FRIENDLY_OFFSET ;
memset ( p - > buf , 0 , sizeof p - > buf ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 2 ) {
2004-05-21 02:51:05 +00:00
ast_verbose ( " %s: chanreads: starting thread \n " , p - > dev ) ;
}
2004-04-05 05:37:01 +00:00
ast_mutex_lock ( & p - > record_lock ) ;
p - > stopreads = 0 ;
2004-08-18 05:06:26 +00:00
p - > read_state = 1 ;
2004-04-05 05:37:01 +00:00
while ( ! p - > stopreads & & p - > owner ) {
2004-05-24 05:37:15 +00:00
if ( option_verbose > 4 )
ast_verbose ( " %s: chanreads: Starting cycle ... \n " , p - > dev ) ;
2004-08-18 05:06:26 +00:00
if ( option_verbose > 4 )
ast_verbose ( " %s: chanreads: Checking bridge \n " , p - > dev ) ;
if ( p - > bridge ) {
if ( p - > bridge - > c0 = = p - > owner & & ( p - > bridge - > flags & AST_BRIDGE_REC_CHANNEL_0 ) )
2004-04-05 05:37:01 +00:00
bridgerec = 1 ;
2004-08-18 05:06:26 +00:00
else if ( p - > bridge - > c1 = = p - > owner & & ( p - > bridge - > flags & AST_BRIDGE_REC_CHANNEL_1 ) )
bridgerec = 1 ;
else
bridgerec = 0 ;
2004-05-24 05:37:15 +00:00
} else {
if ( option_verbose > 4 )
2004-08-18 05:06:26 +00:00
ast_verbose ( " %s: chanreads: No native bridge. \n " , p - > dev ) ;
2004-10-28 00:51:25 +00:00
if ( p - > owner - > _bridge ) {
2004-08-18 05:06:26 +00:00
if ( option_verbose > 4 ) {
2004-10-28 00:51:25 +00:00
ast_verbose ( " %s: chanreads: Got Asterisk bridge with [%s]. \n " , p - > dev , p - > owner - > _bridge - > name ) ;
2004-08-18 05:06:26 +00:00
}
bridgerec = 1 ;
}
else {
bridgerec = 0 ;
}
2004-05-24 05:37:15 +00:00
}
2004-04-05 05:37:01 +00:00
2005-02-10 00:54:24 +00:00
/* if ( (p->owner->_state != AST_STATE_UP) || !bridgerec) */
if ( ( p - > owner - > _state ! = AST_STATE_UP ) )
{
2004-05-21 02:51:05 +00:00
if ( option_verbose > 4 ) {
2004-08-18 05:06:26 +00:00
if ( p - > owner - > _state ! = AST_STATE_UP )
ast_verbose ( " %s: chanreads: Im not up[%d] \n " , p - > dev , p - > owner - > _state ) ;
else
ast_verbose ( " %s: chanreads: No bridgerec[%d] \n " , p - > dev , bridgerec ) ;
2004-05-21 02:51:05 +00:00
}
2004-04-05 05:37:01 +00:00
vpb_sleep ( 10 ) ;
continue ;
}
2004-12-18 22:04:07 +00:00
/* Voicetronix DTMF detection can be triggered off ordinary speech
* This leads to annoying beeps during the conversation
* Avoid this problem by just setting VPB_GETDTMF when you want to listen for DTMF
*/
/* ignore_dtmf = 1; */
2004-04-05 05:37:01 +00:00
ignore_dtmf = 0 ; /* set this to 1 to turn this feature on */
getdtmf_var = pbx_builtin_getvar_helper ( p - > owner , " VPB_GETDTMF " ) ;
if ( getdtmf_var & & ( strcasecmp ( getdtmf_var , " yes " ) = = 0 ) )
ignore_dtmf = 0 ;
2005-02-21 00:48:35 +00:00
if ( ( ignore_dtmf ! = p - > last_ignore_dtmf ) & & ( ! use_ast_dtmfdet ) ) {
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
2004-05-14 04:39:16 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s:Now %s DTMF \n " ,
p - > dev , ignore_dtmf ? " ignoring " : " listening for " ) ;
2004-04-05 05:37:01 +00:00
vpb_set_event_mask ( p - > handle , ignore_dtmf ? VPB_EVENTS_NODTMF : VPB_EVENTS_ALL ) ;
}
p - > last_ignore_dtmf = ignore_dtmf ;
2004-12-18 22:04:07 +00:00
/* Play DTMF digits here to avoid problem you get if playing a digit during
* a record operation
*/
2004-05-24 05:37:15 +00:00
if ( option_verbose > 5 ) {
2004-05-21 02:51:05 +00:00
ast_verbose ( " %s: chanreads: Checking dtmf's \n " , p - > dev ) ;
}
2004-04-05 05:37:01 +00:00
ast_mutex_lock ( & p - > play_dtmf_lock ) ;
if ( p - > play_dtmf [ 0 ] ) {
2004-12-18 22:04:07 +00:00
/* Try to ignore DTMF event we get after playing digit */
/* This DTMF is played by asterisk and leads to an annoying trailing beep on CISCO phones */
2004-04-05 05:37:01 +00:00
if ( ! ignore_dtmf )
vpb_set_event_mask ( p - > handle , VPB_EVENTS_NODTMF ) ;
2004-12-20 03:18:26 +00:00
if ( p - > bridge = = NULL ) {
2004-10-06 10:54:58 +00:00
vpb_dial_sync ( p - > handle , p - > play_dtmf ) ;
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " %s: chanreads: Played DTMF %s \n " , p - > dev , p - > play_dtmf ) ;
}
else {
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " %s: chanreads: Not playing DTMF frame on native bridge \n " , p - > dev ) ;
}
2004-04-05 05:37:01 +00:00
p - > play_dtmf [ 0 ] = ' \0 ' ;
ast_mutex_unlock ( & p - > play_dtmf_lock ) ;
2004-12-18 22:04:07 +00:00
vpb_sleep ( 700 ) ; /* Long enough to miss echo and DTMF event */
2004-04-05 05:37:01 +00:00
if ( ! ignore_dtmf )
vpb_set_event_mask ( p - > handle , VPB_EVENTS_ALL ) ;
continue ;
}
ast_mutex_unlock ( & p - > play_dtmf_lock ) ;
2005-03-04 06:47:24 +00:00
/* afmt = (p->owner) ? p->owner->rawreadformat : AST_FORMAT_SLINEAR; */
2004-08-18 05:06:26 +00:00
if ( p - > owner ) {
2005-03-04 06:47:24 +00:00
afmt = p - > owner - > rawreadformat ;
2004-12-18 22:04:07 +00:00
/* ast_log(LOG_DEBUG,"%s: Record using owner format [%s]\n", p->dev, ast2vpbformatname(afmt)); */
2004-08-18 05:06:26 +00:00
}
else {
afmt = AST_FORMAT_SLINEAR ;
2004-12-18 22:04:07 +00:00
/* ast_log(LOG_DEBUG,"%s: Record using default format [%s]\n", p->dev, ast2vpbformatname(afmt)); */
2004-08-18 05:06:26 +00:00
}
2004-04-05 05:37:01 +00:00
fmt = ast2vpbformat ( afmt ) ;
if ( fmt < 0 ) {
2004-05-14 04:39:16 +00:00
ast_log ( LOG_WARNING , " %s: Record failure (unsupported format %d) \n " , p - > dev , afmt ) ;
2004-04-05 05:37:01 +00:00
return NULL ;
}
readlen = VPB_SAMPLES * astformatbits ( afmt ) / 8 ;
if ( p - > lastinput = = - 1 ) {
vpb_record_buf_start ( p - > handle , fmt ) ;
vpb_reset_record_fifo_alarm ( p - > handle ) ;
2005-11-02 01:02:02 +00:00
p - > lastinput = fmt ;
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
2004-08-18 05:06:26 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Starting record mode (codec=%d)[%s] \n " , p - > dev , fmt , ast2vpbformatname ( afmt ) ) ;
2005-11-02 01:02:02 +00:00
continue ;
2004-04-05 05:37:01 +00:00
} else if ( p - > lastinput ! = fmt ) {
vpb_record_buf_finish ( p - > handle ) ;
vpb_record_buf_start ( p - > handle , fmt ) ;
2005-11-02 01:02:02 +00:00
p - > lastinput = fmt ;
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
2004-05-14 04:39:16 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Changed record format (%d=>%d) \n " , p - > dev , p - > lastinput , fmt ) ;
2005-11-02 01:02:02 +00:00
continue ;
2004-04-05 05:37:01 +00:00
}
/* Read only if up and not bridged, or a bridge for which we can read. */
2004-05-24 05:37:15 +00:00
if ( option_verbose > 5 ) {
2004-05-21 02:51:05 +00:00
ast_verbose ( " %s: chanreads: getting buffer! \n " , p - > dev ) ;
}
2004-04-05 05:37:01 +00:00
if ( ( res = vpb_record_buf_sync ( p - > handle , readbuf , readlen ) ) = = VPB_OK ) {
2004-05-24 05:37:15 +00:00
if ( option_verbose > 5 ) {
2004-05-21 02:51:05 +00:00
ast_verbose ( " %s: chanreads: got buffer! \n " , p - > dev ) ;
}
2004-12-18 22:04:07 +00:00
/* Apply extra gain ! */
2004-04-05 05:37:01 +00:00
if ( p - > rxswgain > MAX_VPB_GAIN )
2004-08-18 23:58:07 +00:00
a_gain_vector ( p - > rxswgain - MAX_VPB_GAIN , ( short * ) readbuf , readlen / sizeof ( short ) ) ;
2004-05-24 05:37:15 +00:00
if ( option_verbose > 5 ) {
2004-05-21 02:51:05 +00:00
ast_verbose ( " %s: chanreads: applied gain \n " , p - > dev ) ;
}
2004-04-05 05:37:01 +00:00
fr - > subclass = afmt ;
fr - > data = readbuf ;
fr - > datalen = readlen ;
2005-02-21 00:48:35 +00:00
fr - > frametype = AST_FRAME_VOICE ;
2004-04-05 05:37:01 +00:00
2005-02-21 00:48:35 +00:00
if ( ( use_ast_dtmfdet ) & & ( p - > vad ) ) {
fr = ast_dsp_process ( p - > owner , p - > vad , fr ) ;
if ( fr & & ( fr - > frametype = = AST_FRAME_DTMF ) )
ast_log ( LOG_DEBUG , " %s: chanreads: Detected DTMF '%c' \n " , p - > dev , fr - > subclass ) ;
2005-02-21 04:30:42 +00:00
if ( fr - > subclass = = ' m ' ) {
/* conf mute request */
fr - > frametype = AST_FRAME_NULL ;
fr - > subclass = 0 ;
}
else if ( fr - > subclass = = ' u ' ) {
/* Unmute */
fr - > frametype = AST_FRAME_NULL ;
fr - > subclass = 0 ;
}
else if ( fr - > subclass = = ' f ' ) {
}
2005-02-21 00:48:35 +00:00
}
2004-12-18 22:04:07 +00:00
/* Using trylock here to prevent deadlock when channel is hungup
* ( ast_hangup ( ) immediately gets lock )
*/
2004-05-14 04:39:16 +00:00
if ( p - > owner & & ! p - > stopreads ) {
2004-05-24 05:37:15 +00:00
if ( option_verbose > 5 ) {
2004-08-18 05:06:26 +00:00
ast_verbose ( " %s: chanreads: queueing buffer on read frame q (state[%d]) \n " , p - > dev , p - > owner - > _state ) ;
2004-05-21 02:51:05 +00:00
}
2004-08-18 05:06:26 +00:00
do {
res = ast_mutex_trylock ( & p - > owner - > lock ) ;
trycnt + + ;
} while ( ( res ! = 0 ) & & ( trycnt < 300 ) ) ;
if ( res = = 0 ) {
ast_queue_frame ( p - > owner , fr ) ;
ast_mutex_unlock ( & p - > owner - > lock ) ;
} else {
if ( option_verbose > 4 )
ast_verbose ( " %s: chanreads: Couldnt get lock after %d tries! \n " , p - > dev , trycnt ) ;
}
trycnt = 0 ;
2004-05-21 02:51:05 +00:00
2004-08-18 05:06:26 +00:00
/*
2004-05-26 01:29:29 +00:00
res = ast_mutex_trylock ( & p - > owner - > lock ) ;
if ( res = = 0 ) {
2004-05-21 02:51:05 +00:00
ast_queue_frame ( p - > owner , fr ) ;
ast_mutex_unlock ( & p - > owner - > lock ) ;
} else {
2004-05-26 01:29:29 +00:00
if ( res = = EINVAL )
if ( option_verbose > 4 ) ast_verbose ( " %s: chanreads: try owner->lock gave me EINVAL[%d] \n " , p - > dev , res ) ;
else if ( res = = EBUSY )
if ( option_verbose > 4 ) ast_verbose ( " %s: chanreads: try owner->lock gave me EBUSY[%d] \n " , p - > dev , res ) ;
2004-08-18 05:06:26 +00:00
while ( res ! = 0 ) {
2004-05-26 01:29:29 +00:00
res = ast_mutex_trylock ( & p - > owner - > lock ) ;
2004-08-18 05:06:26 +00:00
}
2004-05-26 01:29:29 +00:00
if ( res = = 0 ) {
2004-05-24 05:37:15 +00:00
ast_queue_frame ( p - > owner , fr ) ;
ast_mutex_unlock ( & p - > owner - > lock ) ;
}
else {
2004-05-26 01:29:29 +00:00
if ( res = = EINVAL )
if ( option_verbose > 4 ) ast_verbose ( " %s: chanreads: try owner->lock gave me EINVAL[%d] \n " , p - > dev , res ) ;
else if ( res = = EBUSY )
if ( option_verbose > 4 ) ast_verbose ( " %s: chanreads: try owner->lock gave me EBUSY[%d] \n " , p - > dev , res ) ;
2004-08-18 05:06:26 +00:00
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 ) ;
2004-05-24 05:37:15 +00:00
}
2004-05-21 02:51:05 +00:00
}
2004-08-18 05:06:26 +00:00
*/
2004-05-24 05:37:15 +00:00
if ( option_verbose > 6 ) {
2004-04-05 05:37:01 +00:00
short * data = ( short * ) readbuf ;
2004-05-21 02:51:05 +00:00
ast_verbose ( " %s: Read channel (codec=%d) %d %d \n " , p - > dev , fmt , data [ 0 ] , data [ 1 ] ) ;
}
}
else {
if ( option_verbose > 4 ) {
ast_verbose ( " %s: p->stopreads[%d] p->owner[%p] \n " , p - > dev , p - > stopreads , ( void * ) p - > owner ) ;
2004-04-05 05:37:01 +00:00
}
}
}
2004-05-24 05:37:15 +00:00
if ( option_verbose > 4 )
ast_verbose ( " %s: chanreads: Finished cycle... \n " , p - > dev ) ;
2004-04-05 05:37:01 +00:00
}
2004-08-18 05:06:26 +00:00
p - > read_state = 0 ;
2003-04-15 14:39:06 +00:00
2004-04-05 05:37:01 +00:00
/* When stopreads seen, go away! */
vpb_record_buf_finish ( p - > handle ) ;
2004-08-18 05:06:26 +00:00
p - > read_state = 0 ;
2004-04-05 05:37:01 +00:00
ast_mutex_unlock ( & p - > record_lock ) ;
2003-04-18 14:34:46 +00:00
2004-04-05 05:37:01 +00:00
if ( option_verbose > 1 )
2004-05-14 04:39:16 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " %s: Ending record mode (%d/%s) \n " ,
2004-04-05 05:37:01 +00:00
p - > dev , p - > stopreads , p - > owner ? " yes " : " no " ) ;
return NULL ;
2003-04-15 14:39:06 +00:00
}
2006-08-19 00:33:44 +00:00
static struct ast_channel * vpb_new ( struct vpb_pvt * me , enum ast_channel_state state , char * context )
2003-04-15 14:39:06 +00:00
{
struct ast_channel * tmp ;
2005-01-18 03:24:41 +00:00
char cid_num [ 256 ] ;
char cid_name [ 256 ] ;
2003-04-15 14:39:06 +00:00
2004-08-18 05:06:26 +00:00
if ( me - > owner ) {
ast_log ( LOG_WARNING , " Called vpb_new on owned channel (%s) ?! \n " , me - > dev ) ;
2003-04-15 14:39:06 +00:00
return NULL ;
}
2004-08-18 05:06:26 +00:00
if ( option_verbose > 3 )
ast_verbose ( " %s: New call for context [%s] \n " , me - > dev , context ) ;
2003-04-15 14:39:06 +00:00
2006-11-07 21:47:49 +00:00
tmp = ast_channel_alloc ( 1 , state , 0 , 0 , me - > dev ) ;
2003-04-15 14:39:06 +00:00
if ( tmp ) {
2005-04-13 04:15:23 +00:00
if ( use_ast_ind = = 1 ) {
tmp - > tech = & vpb_tech_indicate ;
}
else {
tmp - > tech = & vpb_tech ;
}
2005-03-16 04:53:30 +00:00
tmp - > callgroup = me - > callgroup ;
tmp - > pickupgroup = me - > pickupgroup ;
2003-04-15 14:39:06 +00:00
2004-12-18 22:04:07 +00:00
/* Linear is the preferred format. Although Voicetronix supports other formats
* they are all converted to / from linear in the vpb code . Best for us to use
* linear since we can then adjust volume in this modules .
*/
2003-04-15 14:39:06 +00:00
tmp - > nativeformats = prefformat ;
2005-03-04 06:47:24 +00:00
tmp - > rawreadformat = AST_FORMAT_SLINEAR ;
tmp - > rawwriteformat = AST_FORMAT_SLINEAR ;
2005-01-18 03:24:41 +00:00
if ( state = = AST_STATE_RING ) {
2003-04-15 14:39:06 +00:00
tmp - > rings = 1 ;
2005-01-18 03:24:41 +00:00
cid_name [ 0 ] = ' \0 ' ;
cid_num [ 0 ] = ' \0 ' ;
ast_callerid_split ( me - > callerid , cid_name , sizeof ( cid_name ) , cid_num , sizeof ( cid_num ) ) ;
ast_set_callerid ( tmp , cid_num , cid_name , cid_num ) ;
}
2005-03-04 06:47:24 +00:00
tmp - > tech_pvt = me ;
2003-05-04 05:56:50 +00:00
2003-04-15 14:39:06 +00:00
strncpy ( tmp - > context , context , sizeof ( tmp - > context ) - 1 ) ;
2004-08-18 05:06:26 +00:00
if ( strlen ( me - > ext ) )
strncpy ( tmp - > exten , me - > ext , sizeof ( tmp - > exten ) - 1 ) ;
2003-04-15 14:39:06 +00:00
else
strncpy ( tmp - > exten , " s " , sizeof ( tmp - > exten ) - 1 ) ;
2004-08-18 05:06:26 +00:00
if ( strlen ( me - > language ) )
2006-02-02 21:49:36 +00:00
ast_string_field_set ( tmp , language , me - > language ) ;
2003-04-15 14:39:06 +00:00
2004-08-18 05:06:26 +00:00
me - > owner = tmp ;
2004-03-31 04:29:55 +00:00
2004-08-18 05:06:26 +00:00
me - > bridge = NULL ;
me - > lastoutput = - 1 ;
me - > lastinput = - 1 ;
me - > last_ignore_dtmf = 1 ;
me - > readthread = 0 ;
me - > play_dtmf [ 0 ] = ' \0 ' ;
2005-03-04 00:27:52 +00:00
me - > faxhandled = 0 ;
2003-04-15 14:39:06 +00:00
2005-07-15 23:00:47 +00:00
me - > lastgrunt = ast_tvnow ( ) ; /* Assume at least one grunt tone seen now. */
2005-11-03 00:04:09 +00:00
me - > lastplay = ast_tvnow ( ) ; /* Assume at least one grunt tone seen now. */
2003-05-04 05:56:50 +00:00
2004-04-05 05:37:01 +00:00
if ( state ! = AST_STATE_DOWN ) {
2005-02-10 00:54:24 +00:00
if ( ( me - > mode ! = MODE_FXO ) & & ( state ! = AST_STATE_UP ) ) {
vpb_answer ( tmp ) ;
}
2004-04-05 05:37:01 +00:00
if ( ast_pbx_start ( tmp ) ) {
ast_log ( LOG_WARNING , " Unable to start PBX on %s \n " , tmp - > name ) ;
ast_hangup ( tmp ) ;
}
}
} else {
2003-04-15 14:39:06 +00:00
ast_log ( LOG_WARNING , " Unable to allocate channel structure \n " ) ;
2004-04-05 05:37:01 +00:00
}
2003-04-15 14:39:06 +00:00
return tmp ;
}
2004-10-26 22:25:43 +00:00
static struct ast_channel * vpb_request ( const char * type , int format , void * data , int * cause )
2003-04-15 14:39:06 +00:00
{
2004-04-05 05:37:01 +00:00
int oldformat ;
struct vpb_pvt * p ;
struct ast_channel * tmp = NULL ;
char * name = strdup ( data ? ( char * ) data : " " ) ;
char * s , * sepstr ;
int group = - 1 ;
oldformat = format ;
format & = prefformat ;
if ( ! format ) {
ast_log ( LOG_NOTICE , " Asked to get a channel of unsupported format '%d' \n " , oldformat ) ;
return NULL ;
}
sepstr = name ;
s = strsep ( & sepstr , " / " ) ; /* Handle / issues */
if ( ! s )
s = " " ;
/* Check if we are looking for a group */
if ( toupper ( name [ 0 ] ) = = ' G ' | | toupper ( name [ 0 ] ) = = ' R ' ) {
group = atoi ( name + 1 ) ;
}
/* Search for an unowned channel */
ast_mutex_lock ( & iflock ) ; {
p = iflist ;
while ( p ) {
if ( group = = - 1 ) {
if ( strncmp ( s , p - > dev + 4 , sizeof p - > dev ) = = 0 ) {
if ( ! p - > owner ) {
tmp = vpb_new ( p , AST_STATE_DOWN , p - > context ) ;
break ;
}
}
}
else {
if ( ( p - > group = = group ) & & ( ! p - > owner ) ) {
tmp = vpb_new ( p , AST_STATE_DOWN , p - > context ) ;
break ;
}
}
p = p - > next ;
}
} ast_mutex_unlock ( & iflock ) ;
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " %s requested, got: [%s] \n " ,
name , tmp ? tmp - > name : " None " ) ;
free ( name ) ;
restart_monitor ( ) ;
return tmp ;
2003-04-15 14:39:06 +00:00
}
static float parse_gain_value ( char * gain_type , char * value )
{
float gain ;
/* try to scan number */
if ( sscanf ( value , " %f " , & gain ) ! = 1 )
{
2004-04-05 05:37:01 +00:00
ast_log ( LOG_ERROR , " Invalid %s value '%s' in '%s' config \n " , value , gain_type , config ) ;
2003-04-15 14:39:06 +00:00
return DEFAULT_GAIN ;
}
/* percentage? */
2004-12-18 22:04:07 +00:00
/*if (value[strlen(value) - 1] == '%') */
/* return gain / (float)100; */
2003-04-15 14:39:06 +00:00
return gain ;
}
2006-04-17 16:42:21 +00:00
int unload_module ( )
{
struct vpb_pvt * p ;
/* First, take us out of the channel loop */
if ( use_ast_ind = = 1 ) {
ast_channel_unregister ( & vpb_tech_indicate ) ;
}
else {
ast_channel_unregister ( & vpb_tech ) ;
}
ast_mutex_lock ( & iflock ) ; {
/* Hangup all interfaces if they have an owner */
p = iflist ;
while ( p ) {
if ( p - > owner )
ast_softhangup ( p - > owner , AST_SOFTHANGUP_APPUNLOAD ) ;
p = p - > next ;
}
iflist = NULL ;
} ast_mutex_unlock ( & iflock ) ;
ast_mutex_lock ( & monlock ) ; {
if ( mthreadactive > - 1 ) {
pthread_cancel ( monitor_thread ) ;
pthread_join ( monitor_thread , NULL ) ;
}
mthreadactive = - 2 ;
} ast_mutex_unlock ( & monlock ) ;
ast_mutex_lock ( & iflock ) ; {
/* Destroy all the interfaces and free their memory */
while ( iflist ) {
p = iflist ;
ast_mutex_destroy ( & p - > lock ) ;
pthread_cancel ( p - > readthread ) ;
ast_mutex_destroy ( & p - > owner_lock ) ;
ast_mutex_destroy ( & p - > record_lock ) ;
ast_mutex_destroy ( & p - > play_lock ) ;
ast_mutex_destroy ( & p - > play_dtmf_lock ) ;
p - > readthread = 0 ;
vpb_close ( p - > handle ) ;
iflist = iflist - > next ;
free ( p ) ;
}
iflist = NULL ;
} ast_mutex_unlock ( & iflock ) ;
ast_mutex_lock ( & bridge_lock ) ; {
memset ( bridges , 0 , sizeof bridges ) ;
} ast_mutex_unlock ( & bridge_lock ) ;
ast_mutex_destroy ( & bridge_lock ) ;
for ( int i = 0 ; i < max_bridges ; i + + ) {
ast_mutex_destroy ( & bridges [ i ] . lock ) ;
ast_cond_destroy ( & bridges [ i ] . cond ) ;
}
free ( bridges ) ;
return 0 ;
}
2003-04-15 14:39:06 +00:00
int load_module ( )
{
struct ast_config * cfg ;
struct ast_variable * v ;
struct vpb_pvt * tmp ;
int board = 0 , group = 0 ;
2005-03-16 04:53:30 +00:00
ast_group_t callgroup = 0 ;
ast_group_t pickupgroup = 0 ;
2003-04-15 14:39:06 +00:00
int mode = MODE_IMMEDIATE ;
2004-04-05 05:37:01 +00:00
float txgain = DEFAULT_GAIN , rxgain = DEFAULT_GAIN ;
float txswgain = 0 , rxswgain = 0 ;
2005-02-17 04:58:03 +00:00
int got_gain = 0 ;
2004-03-31 04:29:55 +00:00
int first_channel = 1 ;
int echo_cancel = DEFAULT_ECHO_CANCEL ;
2003-04-15 14:39:06 +00:00
int error = 0 ; /* Error flag */
2004-12-18 22:04:07 +00:00
int bal1 = - 1 ; /* Special value - means do not set */
2004-03-31 04:29:55 +00:00
int bal2 = - 1 ;
int bal3 = - 1 ;
char * callerid = NULL ;
2004-04-05 05:37:01 +00:00
2005-01-25 06:10:20 +00:00
cfg = ast_config_load ( config ) ;
2004-04-05 05:37:01 +00:00
2003-04-15 14:39:06 +00:00
/* We *must* have a config file otherwise stop immediately */
if ( ! cfg ) {
2004-04-05 05:37:01 +00:00
ast_log ( LOG_ERROR , " Unable to load config %s \n " , config ) ;
2006-08-31 21:00:20 +00:00
return AST_MODULE_LOAD_DECLINE ;
2003-04-15 14:39:06 +00:00
}
2004-04-05 05:37:01 +00:00
2004-03-31 04:29:55 +00:00
vpb_seterrormode ( VPB_ERROR_CODE ) ;
2003-08-13 15:25:16 +00:00
ast_mutex_lock ( & iflock ) ; {
2004-11-30 04:14:27 +00:00
v = ast_variable_browse ( cfg , " general " ) ;
while ( v ) {
if ( strcasecmp ( v - > name , " cards " ) = = 0 ) {
ast_log ( LOG_NOTICE , " VPB Driver configured to use [%d] cards \n " , atoi ( v - > value ) ) ;
}
else if ( strcasecmp ( v - > name , " indication " ) = = 0 ) {
use_ast_ind = 1 ;
ast_log ( LOG_NOTICE , " VPB driver using Asterisk Indication functions! \n " ) ;
}
2005-02-21 04:30:42 +00:00
else if ( strcasecmp ( v - > name , " break-for-dtmf " ) = = 0 ) {
if ( ast_true ( v - > value ) ) {
break_for_dtmf = 1 ;
}
else {
break_for_dtmf = 0 ;
ast_log ( LOG_NOTICE , " VPB driver not stopping for DTMF's in native bridge \n " ) ;
}
}
2005-02-21 00:48:35 +00:00
else if ( strcasecmp ( v - > name , " ast-dtmf " ) = = 0 ) {
use_ast_dtmf = 1 ;
ast_log ( LOG_NOTICE , " VPB driver using Asterisk DTMF play functions! \n " ) ;
}
else if ( strcasecmp ( v - > name , " ast-dtmf-det " ) = = 0 ) {
use_ast_dtmfdet = 1 ;
ast_log ( LOG_NOTICE , " VPB driver using Asterisk DTMF detection functions! \n " ) ;
}
else if ( strcasecmp ( v - > name , " relaxdtmf " ) = = 0 ) {
relaxdtmf = 1 ;
ast_log ( LOG_NOTICE , " VPB driver using Relaxed DTMF with Asterisk DTMF detections functions! \n " ) ;
}
2005-06-22 23:54:47 +00:00
else if ( strcasecmp ( v - > name , " timer_period_ring " ) = = 0 ) {
timer_period_ring = atoi ( v - > value ) ;
}
2005-01-31 04:51:41 +00:00
else if ( strcasecmp ( v - > name , " ecsuppthres " ) = = 0 ) {
ec_supp_threshold = atoi ( v - > value ) ;
}
2005-01-31 23:51:19 +00:00
else if ( strcasecmp ( v - > name , " dtmfidd " ) = = 0 ) {
dtmf_idd = atoi ( v - > value ) ;
ast_log ( LOG_NOTICE , " VPB Driver setting DTMF IDD to [%d]ms \n " , dtmf_idd ) ;
}
2004-11-30 04:14:27 +00:00
v = v - > next ;
}
2004-04-05 05:37:01 +00:00
v = ast_variable_browse ( cfg , " interfaces " ) ;
while ( v ) {
/* Create the interface list */
2004-05-14 04:39:16 +00:00
if ( strcasecmp ( v - > name , " board " ) = = 0 ) {
2004-04-05 05:37:01 +00:00
board = atoi ( v - > value ) ;
2004-05-14 04:39:16 +00:00
} else if ( strcasecmp ( v - > name , " group " ) = = 0 ) {
2004-04-05 05:37:01 +00:00
group = atoi ( v - > value ) ;
2005-03-16 04:53:30 +00:00
} else if ( strcasecmp ( v - > name , " callgroup " ) = = 0 ) {
callgroup = ast_get_group ( v - > value ) ;
} else if ( strcasecmp ( v - > name , " pickupgroup " ) = = 0 ) {
pickupgroup = ast_get_group ( v - > value ) ;
2005-11-01 23:20:46 +00:00
} else if ( strcasecmp ( v - > name , " usepolaritycid " ) = = 0 ) {
UsePolarityCID = atoi ( v - > value ) ;
2004-05-14 04:39:16 +00:00
} else if ( strcasecmp ( v - > name , " useloopdrop " ) = = 0 ) {
UseLoopDrop = atoi ( v - > value ) ;
2004-08-18 05:06:26 +00:00
} else if ( strcasecmp ( v - > name , " usenativebridge " ) = = 0 ) {
UseNativeBridge = atoi ( v - > value ) ;
2004-05-14 04:39:16 +00:00
} else if ( strcasecmp ( v - > name , " channel " ) = = 0 ) {
2004-04-05 05:37:01 +00:00
int channel = atoi ( v - > value ) ;
2005-03-16 04:53:30 +00:00
tmp = mkif ( board , channel , mode , got_gain , txgain , rxgain , txswgain , rxswgain , bal1 , bal2 , bal3 , callerid , echo_cancel , group , callgroup , pickupgroup ) ;
2004-04-05 05:37:01 +00:00
if ( tmp ) {
if ( first_channel ) {
mkbrd ( tmp - > vpb_model , echo_cancel ) ;
first_channel = 0 ;
}
tmp - > next = iflist ;
iflist = tmp ;
} else {
2004-11-29 23:20:16 +00:00
ast_log ( LOG_ERROR , " Unable to register channel '%s' \n " , v - > value ) ;
2004-04-05 05:37:01 +00:00
error = - 1 ;
goto done ;
}
} else if ( strcasecmp ( v - > name , " language " ) = = 0 ) {
strncpy ( language , v - > value , sizeof ( language ) - 1 ) ;
} else if ( strcasecmp ( v - > name , " callerid " ) = = 0 ) {
callerid = strdup ( v - > value ) ;
} else if ( strcasecmp ( v - > name , " mode " ) = = 0 ) {
if ( strncasecmp ( v - > value , " di " , 2 ) = = 0 )
mode = MODE_DIALTONE ;
else if ( strncasecmp ( v - > value , " im " , 2 ) = = 0 )
mode = MODE_IMMEDIATE ;
else if ( strncasecmp ( v - > value , " fx " , 2 ) = = 0 )
mode = MODE_FXO ;
else
ast_log ( LOG_WARNING , " Unknown mode: %s \n " , v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " context " ) ) {
strncpy ( context , v - > value , sizeof ( context ) - 1 ) ;
} else if ( ! strcasecmp ( v - > name , " echocancel " ) ) {
if ( ! strcasecmp ( v - > value , " off " ) )
echo_cancel = 0 ;
} else if ( strcasecmp ( v - > name , " txgain " ) = = 0 ) {
txswgain = parse_gain_value ( v - > name , v - > value ) ;
2005-02-17 04:58:03 +00:00
got_gain | = VPB_GOT_TXSWG ;
2004-04-05 05:37:01 +00:00
} else if ( strcasecmp ( v - > name , " rxgain " ) = = 0 ) {
rxswgain = parse_gain_value ( v - > name , v - > value ) ;
2005-02-17 04:58:03 +00:00
got_gain | = VPB_GOT_RXSWG ;
2004-04-05 05:37:01 +00:00
} else if ( strcasecmp ( v - > name , " txhwgain " ) = = 0 ) {
txgain = parse_gain_value ( v - > name , v - > value ) ;
2005-02-17 04:58:03 +00:00
got_gain | = VPB_GOT_TXHWG ;
2004-04-05 05:37:01 +00:00
} else if ( strcasecmp ( v - > name , " rxhwgain " ) = = 0 ) {
rxgain = parse_gain_value ( v - > name , v - > value ) ;
2005-02-17 04:58:03 +00:00
got_gain | = VPB_GOT_RXHWG ;
2004-04-05 05:37:01 +00:00
} else if ( strcasecmp ( v - > name , " bal1 " ) = = 0 ) {
bal1 = strtol ( v - > value , NULL , 16 ) ;
if ( bal1 < 0 | | bal1 > 255 ) {
ast_log ( LOG_WARNING , " Bad bal1 value: %d \n " , bal1 ) ;
bal1 = - 1 ;
}
} else if ( strcasecmp ( v - > name , " bal2 " ) = = 0 ) {
bal2 = strtol ( v - > value , NULL , 16 ) ;
if ( bal2 < 0 | | bal2 > 255 ) {
ast_log ( LOG_WARNING , " Bad bal2 value: %d \n " , bal2 ) ;
bal2 = - 1 ;
}
} else if ( strcasecmp ( v - > name , " bal3 " ) = = 0 ) {
bal3 = strtol ( v - > value , NULL , 16 ) ;
if ( bal3 < 0 | | bal3 > 255 ) {
ast_log ( LOG_WARNING , " Bad bal3 value: %d \n " , bal3 ) ;
bal3 = - 1 ;
}
} else if ( strcasecmp ( v - > name , " grunttimeout " ) = = 0 ) {
gruntdetect_timeout = 1000 * atoi ( v - > value ) ;
}
v = v - > next ;
}
if ( gruntdetect_timeout < 1000 )
gruntdetect_timeout = 1000 ;
done : ( void ) 0 ;
2003-08-13 15:25:16 +00:00
} ast_mutex_unlock ( & iflock ) ;
2003-04-15 14:39:06 +00:00
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2004-04-05 05:37:01 +00:00
2005-04-13 04:15:23 +00:00
if ( use_ast_ind = = 1 ) {
if ( ! error & & ast_channel_register ( & vpb_tech_indicate ) ! = 0 ) {
2006-02-02 21:49:36 +00:00
ast_log ( LOG_ERROR , " Unable to register channel class 'vpb' \n " ) ;
2005-04-13 04:15:23 +00:00
error = - 1 ;
}
else {
ast_log ( LOG_NOTICE , " VPB driver Registered (w/AstIndication) \n " ) ;
}
}
else {
if ( ! error & & ast_channel_register ( & vpb_tech ) ! = 0 ) {
2006-02-02 21:49:36 +00:00
ast_log ( LOG_ERROR , " Unable to register channel class 'vpb' \n " ) ;
2005-04-13 04:15:23 +00:00
error = - 1 ;
}
else {
ast_log ( LOG_NOTICE , " VPB driver Registered ) \n " ) ;
}
2003-04-15 14:39:06 +00:00
}
if ( error )
2004-04-05 05:37:01 +00:00
unload_module ( ) ;
2004-03-31 04:29:55 +00:00
else
2004-04-05 05:37:01 +00:00
restart_monitor ( ) ; /* And start the monitor for the first time */
2003-04-15 14:39:06 +00:00
return error ;
}
int usecount ( )
{
2005-06-24 02:15:04 +00:00
return usecnt ;
2003-04-15 14:39:06 +00:00
}
2006-04-08 22:01:19 +00:00
const char * description ( )
2003-04-15 14:39:06 +00:00
{
2005-03-04 06:47:24 +00:00
return ( char * ) desc ;
2003-04-15 14:39:06 +00:00
}
2006-04-08 22:01:19 +00:00
const char * key ( )
2003-04-15 14:39:06 +00:00
{
return ASTERISK_GPL_KEY ;
}
2004-11-29 23:20:16 +00:00
/**/
2003-04-15 14:39:06 +00:00
# if defined(__cplusplus) || defined(c_plusplus)
}
# endif
2004-11-29 23:20:16 +00:00
/**/
2006-04-24 17:11:45 +00:00