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

📄 chan_vpb.cc

📁 Asterisk中信道部分的源码 。。。。
💻 CC
📖 第 1 页 / 共 5 页
字号:
			}			continue;		} 		/* flush the event from the channel event Q */		vpb_get_event_ch_async(e.handle, &je);		vpb_translate_event(&je, str);		ast_verb(5, "%s: Flushing event [%d]=>%s\n", p->dev, je.type, str);		/* 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;			*/		}		/* Two scenarios: Are you owned or not. */		if (p->owner) {			monitor_handle_owned(p, &e);		} else {			monitor_handle_notowned(p, &e);		}		/* if ((!p->owner)&&(p->golock)) {			ast_mutex_unlock(&p->owner->lock);			ast_mutex_unlock(&p->lock);		}		*/	}	return NULL;}static int restart_monitor(void){	int error = 0;	/* If we're supposed to be stopped -- stay stopped */	if (mthreadactive == -2)		return 0;	ast_verb(4, "Restarting monitor\n");	ast_mutex_lock(&monlock);	if (monitor_thread == pthread_self()) {		ast_log(LOG_WARNING, "Cannot kill myself\n");		error = -1;		ast_verb(4, "Monitor trying to kill monitor\n");	} 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_EVT_NONE;			e.data = 0;			ast_verb(4, "Trying to reawake monitor\n");			vpb_put_event(&e);		} else {			/* Start a new monitor */			int pid = ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL); 			ast_verb(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!*/			}		}	}	ast_mutex_unlock(&monlock);	ast_verb(4, "Monitor restarted\n");	return error;}/* Per board config that must be called after vpb_open() */static void mkbrd(vpb_model_t model, int echo_cancel){	if (!bridges) {		if (model == vpb_model_v4pci) {			max_bridges = MAX_BRIDGES_V4PCI;		}		bridges = (vpb_bridge_t *)ast_calloc(1, max_bridges * sizeof(vpb_bridge_t));		if (!bridges) {			ast_log(LOG_ERROR, "Failed to initialize bridges\n");		} else {			int i;			for (i = 0; i < max_bridges; i++) {				ast_mutex_init(&bridges[i].lock);				ast_cond_init(&bridges[i].cond, NULL);			}		}	}	if (!echo_cancel) {		if (model == vpb_model_v4pci) {			vpb_echo_canc_disable();			ast_log(LOG_NOTICE, "Voicetronix echo cancellation OFF\n");		} else {			/* need to do 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");			if (ec_supp_threshold > -1) {				vpb_echo_canc_set_sup_thresh(0, &ec_supp_threshold);				ast_log(LOG_NOTICE, "Voicetronix EC Sup Thres set\n");			}		} else {			/* need to do it port by port for OpenSwitch */		}	}}static struct vpb_pvt *mkif(int board, int channel, int mode, int gains, float txgain, float rxgain,			 float txswgain, float rxswgain, int bal1, int bal2, int bal3,			 char * callerid, int echo_cancel, int group, ast_group_t callgroup, ast_group_t pickupgroup ){	struct vpb_pvt *tmp;	char buf[64];	tmp = (vpb_pvt *)ast_calloc(1, sizeof(*tmp));	if (!tmp)		return NULL;	tmp->handle = vpb_open(board, channel);	if (tmp->handle < 0) {	  		ast_log(LOG_WARNING, "Unable to create channel vpb/%d-%d: %s\n", 					board, channel, strerror(errno));		ast_free(tmp);		return NULL;	}	       	snprintf(tmp->dev, sizeof(tmp->dev), "vpb/%d-%d", board, channel);	tmp->mode = mode;	tmp->group = group;	tmp->callgroup = callgroup;	tmp->pickupgroup = pickupgroup;	/* Initilize dtmf caller ID position variable */	tmp->dtmf_caller_pos = 0;	ast_copy_string(tmp->language, language, sizeof(tmp->language));	ast_copy_string(tmp->context, context, sizeof(tmp->context));	tmp->callerid_type = 0;	if (callerid) { 		if (strcasecmp(callerid, "on") == 0) {			tmp->callerid_type = 1;			ast_copy_string(tmp->callerid, "unknown", sizeof(tmp->callerid));		} else if (strcasecmp(callerid, "v23") == 0) {			tmp->callerid_type = 2;			ast_copy_string(tmp->callerid, "unknown", sizeof(tmp->callerid));		} else if (strcasecmp(callerid, "bell") == 0) {			tmp->callerid_type = 3;			ast_copy_string(tmp->callerid, "unknown", sizeof(tmp->callerid));		} else {			ast_copy_string(tmp->callerid, callerid, sizeof(tmp->callerid));		}	} else {		ast_copy_string(tmp->callerid, "unknown", sizeof(tmp->callerid));	}	/* 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);	}	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);	}	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);	}	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);	}	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);	}	tmp->vpb_model = vpb_model_unknown;	if (vpb_get_model(tmp->handle, 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;		}	}	ast_mutex_init(&tmp->owner_lock);	ast_mutex_init(&tmp->lock);	ast_mutex_init(&tmp->record_lock);	ast_mutex_init(&tmp->play_lock);	ast_mutex_init(&tmp->play_dtmf_lock);	/* set default read state */	tmp->read_state = 0;		tmp->golock = 0;	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);	tmp->ring_timer_id = vpb_timer_get_unique_timer_id();	vpb_timer_open(&tmp->ring_timer, tmp->handle, tmp->ring_timer_id, timer_period_ring);	      	tmp->dtmfidd_timer_id = vpb_timer_get_unique_timer_id();	vpb_timer_open(&tmp->dtmfidd_timer, tmp->handle, tmp->dtmfidd_timer_id, dtmf_idd);	      	if (mode == MODE_FXO){		if (use_ast_dtmfdet)			vpb_set_event_mask(tmp->handle, VPB_EVENTS_NODTMF);		else			vpb_set_event_mask(tmp->handle, VPB_EVENTS_ALL);	} else {/*		if (use_ast_dtmfdet)			vpb_set_event_mask(tmp->handle, VPB_EVENTS_NODTMF);		else*/			vpb_set_event_mask(tmp->handle, VPB_EVENTS_STAT);	}	if ((tmp->vpb_model == vpb_model_v12pci) && (echo_cancel)) {		vpb_hostecho_on(tmp->handle);	}	if (use_ast_dtmfdet) {		tmp->vad = ast_dsp_new();		ast_dsp_set_features(tmp->vad, DSP_FEATURE_DTMF_DETECT);		ast_dsp_digitmode(tmp->vad, DSP_DIGITMODE_DTMF);		if (relaxdtmf)			ast_dsp_digitmode(tmp->vad, DSP_DIGITMODE_DTMF|DSP_DIGITMODE_RELAXDTMF);	} else {		tmp->vad = NULL;	}	/* define grunt tone */	vpb_settonedet(tmp->handle,&toned_ungrunt);	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]",		tmp->dev, tmp->rxswgain, tmp->txswgain, tmp->rxgain, tmp->txgain, bal1, bal2, bal3);	return tmp;}static int vpb_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen){	struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;	int res = 0;	int tmp = 0;	if (use_ast_ind == 1) {		ast_verb(4, "%s: vpb_indicate called when using Ast Indications !?!\n", p->dev);		return 0;	}	ast_verb(4, "%s: vpb_indicate [%d] state[%d]\n", p->dev, condition,ast->_state);/*	if (ast->_state != AST_STATE_UP) {		ast_verb(4, "%s: vpb_indicate Not in AST_STATE_UP\n", p->dev, condition,ast->_state);		return res;	}*//*	ast_verb(4, "%s: LOCKING in indicate \n", p->dev);	ast_verb(4, "%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count, p->lock.__m_owner);*/	ast_mutex_lock(&p->lock);	switch (condition) {	case AST_CONTROL_BUSY:	case AST_CONTROL_CONGESTION:		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); 		}		break;	case AST_CONTROL_RINGING:		if (ast->_state == AST_STATE_UP) {			playtone(p->handle, &Ringbacktone);			p->state = VPB_STATE_PLAYRING;			ast_verb(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);		}		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:		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);		}		break;	case AST_CONTROL_HOLD:		ast_moh_start(ast, (const char *) data, NULL);		break;	case AST_CONTROL_UNHOLD:		ast_moh_stop(ast);		break;	default:		res = 0;		break;	}	tmp = ast_mutex_unlock(&p->lock);/*	ast_verb(4, "%s: unLOCKING in indicate [%d]\n", p->dev,tmp);*/	return res;}static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan){	struct vpb_pvt *p = (struct vpb_pvt *)newchan->tech_pvt;	int res = 0;/*	ast_verb(4, "%s: LOCKING in fixup \n", p->dev);	ast_verb(4, "%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);*/	ast_mutex_lock(&p->lock);	ast_debug(1, "New owner for channel %s is %s\n", p->dev, newchan->name);	if (p->owner == oldchan) {		p->owner = newchan;	}	if (newchan->_state == AST_STATE_RINGING){		if (use_ast_ind == 1) {			ast_verb(4, "%s: vpb_fixup Calling ast_indicate\n", p->dev);			ast_indicate(newchan, AST_CONTROL_RINGING);		} else {			ast_verb(4, "%s: vpb_fixup Calling vpb_indicate\n", p->dev);			vpb_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);		}	}	res = ast_mutex_unlock(&p->lock);/*	ast_verb(4, "%s: unLOCKING in fixup [%d]\n", p->dev,res);*/	return 0;}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, unsigned int duration){	struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;	char s[2];	int res = 0;	if (use_ast_dtmf) {		ast_verb(4, "%s: vpb_digit: asked to play digit[%c] but we are using asterisk dtmf play back?!\n", p->dev, digit);		return 0;	}/*	ast_verb(4, "%s: LOCKING in digit \n", p->dev);	ast_verb(4, "%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);*/	ast_mutex_lock(&p->lock);	s[0] = digit;	s[1] = '\0';	ast_verb(4, "%s: vpb_digit: asked to play digit[%s]\n", p->dev, s);	ast_mutex_lock(&p->play_dtmf_lock);	strncat(p->play_dtmf, s, sizeof(*p->play_dtmf) - strlen(p->play_dtmf) - 1);	ast_mutex_unlock(&p->play_dtmf_lock);	res = ast_mutex_unlock(&p->lock);/*	ast_verb(4, "%s: unLOCKING in digit [%d]\n", p->dev,res);*/	return 0;}/* Places a call out of a VPB channel */static int vpb_call(struct ast_channel *ast, char *dest, int timeout){	struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;	int res = 0, i;	char *s = strrchr(dest, '/');	char dialstring[254] = "";	int tmp = 0;/*

⌨️ 快捷键说明

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