⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan_vpb.cc

📁 Asterisk中信道部分的源码 。。。。
💻 CC
📖 第 1 页 / 共 5 页
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2003, Paul Bagyenda * Paul Bagyenda <bagyenda@dsmagic.com> * Copyright (C) 2004 - 2005, Ben Kramer * Ben Kramer <ben@voicetronix.com.au> * * 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 * * 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. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief VoiceTronix Interface driver *  * \ingroup channel_drivers *//*** MODULEINFO	<depend>vpbapi</depend> ***/#include <vpbapi.h>extern "C" {#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 114180 $")#include <stdio.h>#include <string.h>#include "asterisk/lock.h"#include "asterisk/utils.h"#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/logger.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/options.h"#include "asterisk/callerid.h"#include "asterisk/dsp.h"#include "asterisk/features.h"#include "asterisk/musiconhold.h"}#include <sys/socket.h>#include <sys/time.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <arpa/inet.h>#include <fcntl.h>#include <sys/ioctl.h>#include <ctype.h>#include <assert.h>#ifdef pthread_create#undef pthread_create#endif#define DEFAULT_GAIN 0#define DEFAULT_ECHO_CANCEL 1  #define VPB_SAMPLES 160 #define VPB_MAX_BUF VPB_SAMPLES*4 + AST_FRIENDLY_OFFSET#define VPB_NULL_EVENT 200#define VPB_WAIT_TIMEOUT 4000#define MAX_VPB_GAIN 12.0#define MIN_VPB_GAIN -12.0#define DTMF_CALLERID  #define DTMF_CID_START 'D'#define DTMF_CID_STOP 'C'/**/#if defined(__cplusplus) || defined(c_plusplus) extern "C" {#endif/**/static const char desc[] = "VoiceTronix V6PCI/V12PCI/V4PCI  API Support";static const char tdesc[] = "Standard VoiceTronix API Driver";static const char config[] = "vpb.conf";/* Backwards compatibility from trunk */#define ast_verb(level, ...) do { \	if (option_verbose >= level) { \		if (level >= 4) \			ast_verbose(VERBOSE_PREFIX_4 __VA_ARGS__); \		else if (level == 3) \			ast_verbose(VERBOSE_PREFIX_3 __VA_ARGS__); \		else if (level == 2) \			ast_verbose(VERBOSE_PREFIX_2 __VA_ARGS__); \		else if (level == 1) \			ast_verbose(VERBOSE_PREFIX_1 __VA_ARGS__); \		else \			ast_verbose(__VA_ARGS__); \	} \} while (0)#define ast_debug(level, ...) do {       \	if (option_debug >= (level)) \		ast_log(LOG_DEBUG, __VA_ARGS__); \} while (0)/* Default context for dialtone mode */static char context[AST_MAX_EXTENSION] = "default";/* Default language */static char language[MAX_LANGUAGE] = "";static int gruntdetect_timeout = 3600000; /* Grunt detect timeout is 1hr. */static const int prefformat = AST_FORMAT_SLINEAR;/* Protect the interface list (of vpb_pvt's) */AST_MUTEX_DEFINE_STATIC(iflock);/* Protect the monitoring thread, so only one process can kill or start it, and not   when it's doing something critical. */AST_MUTEX_DEFINE_STATIC(monlock);/* This is the thread for the monitor which checks for input on the channels   which are not currently in use.  */static pthread_t monitor_thread;static int mthreadactive = -1; /* Flag for monitoring monitorthread.*/static int restart_monitor(void);/* The private structures of the VPB channels are    linked for selecting outgoing channels */   #define MODE_DIALTONE 	1#define MODE_IMMEDIATE	2#define MODE_FXO	3/* Pick a country or add your own! *//* These are the tones that are played to the user */#define TONES_AU/* #define TONES_USA */#ifdef TONES_AUstatic 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_USAstatic 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};#endif/* grunt tone defn's */#if 0static 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 } } };#endifstatic VPB_DETECT toned_ungrunt = { 2, VPB_GRUNT, 1, 2000, 1, 0, 0, -40, 0, 0, 30, 40, { { 0, 0, 0, 0 } } };/* Use loop polarity detection for CID */static int UsePolarityCID=0;/* Use loop drop detection */static int UseLoopDrop=1;/* To use or not to use Native bridging */static int UseNativeBridge=1;/* Use Asterisk Indication or VPB */static int use_ast_ind=0;/* 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;/* Break for DTMF on native bridge ? */static int break_for_dtmf=1;/* Set EC suppression threshold */static short ec_supp_threshold=-1;/* Inter Digit Delay for collecting DTMF's */static int dtmf_idd = 3000;#define TIMER_PERIOD_RINGBACK 2000#define TIMER_PERIOD_BUSY 700#define TIMER_PERIOD_RING 4000static int timer_period_ring = TIMER_PERIOD_RING;	  #define VPB_EVENTS_ALL (VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP \			|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \			|VPB_MRING_OFF|VPB_MDROP|VPB_MSTATION_FLASH)#define VPB_EVENTS_NODROP (VPB_MRING|VPB_MDIGIT|VPB_MDTMF|VPB_MTONEDETECT|VPB_MTIMEREXP \			|VPB_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \			|VPB_MRING_OFF|VPB_MSTATION_FLASH)#define VPB_EVENTS_NODTMF (VPB_MRING|VPB_MDIGIT|VPB_MTONEDETECT|VPB_MTIMEREXP \			|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_MSTATION_OFFHOOK|VPB_MSTATION_ONHOOK \			|VPB_MRING_OFF|VPB_MSTATION_FLASH)/* Dialing parameters for Australia *//* #define DIAL_WITH_CALL_PROGRESS */VPB_TONE_MAP DialToneMap[] = { 	{ VPB_BUSY, VPB_CALL_DISCONNECT, 0 },  				{ VPB_DIAL, VPB_CALL_DIALTONE, 0 },				{ VPB_RINGBACK, VPB_CALL_RINGBACK, 0 },				{ VPB_BUSY, 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#define VPB_GOT_RXHWG		1#define VPB_GOT_TXHWG		2#define VPB_GOT_RXSWG		4#define VPB_GOT_TXSWG		8typedef struct  {	int inuse;	struct ast_channel *c0, *c1, **rc;	struct ast_frame **fo;	int flags;	ast_mutex_t lock;	ast_cond_t cond;	int endbridge;} vpb_bridge_t;static vpb_bridge_t * bridges;static int max_bridges = MAX_BRIDGES_V4PCI;AST_MUTEX_DEFINE_STATIC(bridge_lock);typedef enum {	vpb_model_unknown = 0, 	vpb_model_v4pci,	vpb_model_v12pci} vpb_model_t;static struct vpb_pvt {	ast_mutex_t owner_lock;			/* Protect blocks that expect ownership to remain the same */	struct ast_channel *owner;		/* Channel who owns us, possibly NULL */	int golock;				/* Got owner lock ? */	int mode;				/* fxo/imediate/dialtone*/	int handle;				/* Handle for vpb interface */	int state;				/* used to keep port state (internal to driver) */	int group;				/* Which group this port belongs to */	ast_group_t callgroup;                  /* Call group */	ast_group_t pickupgroup;                /* Pickup group */	char dev[256];				/* Device name, eg vpb/1-1 */	vpb_model_t vpb_model;			/* card model */	struct ast_frame f, fr;			/* Asterisk frame interface */	char buf[VPB_MAX_BUF];			/* Static buffer for reading frames */	int dialtone;				/* NOT USED */	float txgain, rxgain;			/* Hardware gain control */	float txswgain, rxswgain;		/* Software gain control */	int wantdtmf;				/* Waiting for DTMF. */	char context[AST_MAX_EXTENSION];	/* The context for this channel */	char ext[AST_MAX_EXTENSION];		/* DTMF buffer for the ext[ens] */	char language[MAX_LANGUAGE];		/* language being used */	char callerid[AST_MAX_EXTENSION];	/* CallerId used for directly connected phone */	int  callerid_type;			/* Caller ID type: 0=>none 1=>vpb 2=>AstV23 3=>AstBell */	char cid_num[AST_MAX_EXTENSION];	char cid_name[AST_MAX_EXTENSION];	int dtmf_caller_pos;			/* DTMF CallerID detection (Brazil)*/	int lastoutput;				/* Holds the last Audio format output'ed */	int lastinput;				/* Holds the last Audio format input'ed */	int last_ignore_dtmf;	void *busy_timer;			/* Void pointer for busy vpb_timer */	int busy_timer_id;			/* unique timer ID for busy timer */	void *ringback_timer; 			/* Void pointer for ringback vpb_timer */	int ringback_timer_id;			/* unique timer ID for ringback timer */	void *ring_timer;			/* Void pointer for ring vpb_timer */	int ring_timer_id;			/* unique timer ID for ring timer */	void *dtmfidd_timer;			/* Void pointer for DTMF IDD vpb_timer */	int dtmfidd_timer_id;			/* unique timer ID for DTMF IDD timer */	struct ast_dsp *vad;			/* AST  Voice Activation Detection dsp */	struct timeval lastgrunt;			/* time stamp of last grunt event */	ast_mutex_t lock;			/* This one just protects bridge ptr below */	vpb_bridge_t *bridge;	int stopreads; 				/* Stop reading...*/	int read_state;				/* Read state */	int chuck_count;			/* a count of packets weve chucked away!*/	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 */	int  play_buf_time;			/* How long the last play_buf took */	struct timeval lastplay;		/* Last play time */	ast_mutex_t play_dtmf_lock;	char play_dtmf[16];	int faxhandled;				/* has a fax tone been handled ? */	struct vpb_pvt *next;			/* Next channel in list */} *iflist = NULL;static struct ast_channel *vpb_new(struct vpb_pvt *i, enum ast_channel_state state, const char *context);static void *do_chanreads(void *pvt);static struct ast_channel *vpb_request(const char *type, int format, void *data, int *cause);static int vpb_digit_begin(struct ast_channel *ast, char digit);static int vpb_digit_end(struct ast_channel *ast, char digit, unsigned int duration);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);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);static int vpb_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);static struct ast_channel_tech vpb_tech = {	type: "vpb",	description: tdesc,	capabilities: AST_FORMAT_SLINEAR,	properties: 0,	requester: vpb_request,	devicestate: NULL,	send_digit_begin: vpb_digit_begin,	send_digit_end: vpb_digit_end,	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,	bridge: ast_vpb_bridge,	indicate: vpb_indicate,	fixup: vpb_fixup,	setoption: NULL,	queryoption: NULL,	transfer: NULL,	write_video: NULL,	bridged_channel: NULL};static struct ast_channel_tech vpb_tech_indicate = {	type: "vpb",	description: tdesc,	capabilities: AST_FORMAT_SLINEAR,	properties: 0,	requester: vpb_request,	devicestate: NULL,	send_digit_begin: vpb_digit_begin,	send_digit_end: vpb_digit_end,	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,	bridge: ast_vpb_bridge,	indicate: NULL,	fixup: vpb_fixup,	setoption: NULL,	queryoption: NULL,	transfer: NULL,	write_video: NULL,	bridged_channel: NULL};/* Can't get ast_vpb_bridge() working on v4pci without either a horrible *  high pitched feedback noise or bad hiss noise depending on gain settings*  Get asterisk to do the bridging*/#define BAD_V4PCI_BRIDGE/* 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 *//* This is the Native bridge code, which Asterisk will try before using its own bridging code */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){	struct vpb_pvt *p0 = (struct vpb_pvt *)c0->tech_pvt;	struct vpb_pvt *p1 = (struct vpb_pvt *)c1->tech_pvt;	int i;	int res;	struct ast_channel *cs[3];	struct ast_channel *who;	struct ast_frame *f;	cs[0] = c0;	cs[1] = c1;	#ifdef BAD_V4PCI_BRIDGE	if (p0->vpb_model==vpb_model_v4pci)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -