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

📄 chan_phone.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 3 页
字号:
				/* Reset the extension */				i->ext[0] = '\0';				/* Play the dialtone */				i->dialtone++;				ioctl(i->fd, PHONE_PLAY_STOP);				ioctl(i->fd, PHONE_PLAY_CODEC, ULAW);				ioctl(i->fd, PHONE_PLAY_START);				i->lastformat = -1;			} else if (i->mode == MODE_SIGMA) {				ast_module_ref(ast_module_info->self);				/* Reset the extension */				i->ext[0] = '\0';				/* Play the dialtone */				i->dialtone++;				ioctl(i->fd, PHONE_DIALTONE);			}		} else {			if (i->dialtone)				ast_module_unref(ast_module_info->self);			memset(i->ext, 0, sizeof(i->ext));			if (i->cpt)			{				ioctl(i->fd, PHONE_CPT_STOP);				i->cpt = 0;			}			ioctl(i->fd, PHONE_PLAY_STOP);			ioctl(i->fd, PHONE_REC_STOP);			i->dialtone = 0;			i->lastformat = -1;		}	}	if (phonee.bits.pstn_ring) {		ast_verbose("Unit is ringing\n");		phone_new(i, AST_STATE_RING, i->context);	}	if (phonee.bits.caller_id)		ast_verbose("We have caller ID\n");		}static void *do_monitor(void *data){	fd_set rfds, efds;	int n, res;	struct phone_pvt *i;	int tonepos = 0;	/* The tone we're playing this round */	struct timeval tv = {0,0};	int dotone;	/* This thread monitors all the frame relay interfaces which are not yet in use	   (and thus do not have a separate thread) indefinitely */	while (monitor) {		/* Don't let anybody kill us right away.  Nobody should lock the interface list		   and wait for the monitor list, but the other way around is okay. */		/* Lock the interface list */		if (ast_mutex_lock(&iflock)) {			ast_log(LOG_ERROR, "Unable to grab interface lock\n");			return NULL;		}		/* Build the stuff we're going to select on, that is the socket of every		   phone_pvt that does not have an associated owner channel */		n = -1;		FD_ZERO(&rfds);		FD_ZERO(&efds);		i = iflist;		dotone = 0;		while (i) {			if (FD_ISSET(i->fd, &rfds)) 				ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);			if (!i->owner) {				/* This needs to be watched, as it lacks an owner */				FD_SET(i->fd, &rfds);				FD_SET(i->fd, &efds);				if (i->fd > n)					n = i->fd;				if (i->dialtone && i->mode != MODE_SIGMA) {					/* Remember we're going to have to come back and play					   more dialtones */					if (ast_tvzero(tv)) {						/* If we're due for a dialtone, play one */						if (write(i->fd, DialTone + tonepos, 240) != 240)							ast_log(LOG_WARNING, "Dial tone write error\n");					}					dotone++;				}			}						i = i->next;		}		/* Okay, now that we know what to do, release the interface lock */		ast_mutex_unlock(&iflock);		/* Wait indefinitely for something to happen */		if (dotone && i && i->mode != MODE_SIGMA) {			/* If we're ready to recycle the time, set it to 30 ms */			tonepos += 240;			if (tonepos >= sizeof(DialTone))					tonepos = 0;			if (ast_tvzero(tv)) {				tv = ast_tv(30000, 0);			}			res = ast_select(n + 1, &rfds, NULL, &efds, &tv);		} else {			res = ast_select(n + 1, &rfds, NULL, &efds, NULL);			tv = ast_tv(0,0);			tonepos = 0;		}		/* Okay, select has finished.  Let's see what happened.  */		if (res < 0) {			ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno));			continue;		}		/* If there are no fd's changed, just continue, it's probably time		   to play some more dialtones */		if (!res)			continue;		/* Alright, lock the interface list again, and let's look and see what has		   happened */		if (ast_mutex_lock(&iflock)) {			ast_log(LOG_WARNING, "Unable to lock the interface list\n");			continue;		}		i = iflist;		for(; i; i=i->next) {			if (FD_ISSET(i->fd, &rfds)) {				if (i->owner) {					continue;				}				phone_mini_packet(i);			}			if (FD_ISSET(i->fd, &efds)) {				if (i->owner) {					continue;				}				phone_check_exception(i);			}		}		ast_mutex_unlock(&iflock);	}	return NULL;	}static int restart_monitor(){	/* If we're supposed to be stopped -- stay stopped */	if (monitor_thread == AST_PTHREADT_STOP)		return 0;	if (ast_mutex_lock(&monlock)) {		ast_log(LOG_WARNING, "Unable to lock monitor\n");		return -1;	}	if (monitor_thread == pthread_self()) {		ast_mutex_unlock(&monlock);		ast_log(LOG_WARNING, "Cannot kill myself\n");		return -1;	}	if (monitor_thread != AST_PTHREADT_NULL) {		if (ast_mutex_lock(&iflock)) {			ast_mutex_unlock(&monlock);			ast_log(LOG_WARNING, "Unable to lock the interface list\n");			return -1;		}		monitor = 0;		while (pthread_kill(monitor_thread, SIGURG) == 0)			sched_yield();		pthread_join(monitor_thread, NULL);		ast_mutex_unlock(&iflock);	}	monitor = 1;	/* Start a new monitor */	if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {		ast_mutex_unlock(&monlock);		ast_log(LOG_ERROR, "Unable to start monitor thread.\n");		return -1;	}	ast_mutex_unlock(&monlock);	return 0;}static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain){	/* Make a phone_pvt structure for this interface */	struct phone_pvt *tmp;	int flags;			tmp = malloc(sizeof(struct phone_pvt));	if (tmp) {		tmp->fd = open(iface, O_RDWR);		if (tmp->fd < 0) {			ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);			free(tmp);			return NULL;		}		if (mode == MODE_FXO) {			if (ioctl(tmp->fd, IXJCTL_PORT, PORT_PSTN)) 				ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");		} else {			if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 				 if (mode != MODE_FXS)				      ast_log(LOG_DEBUG, "Unable to set port to POTS\n");		}		ioctl(tmp->fd, PHONE_PLAY_STOP);		ioctl(tmp->fd, PHONE_REC_STOP);		ioctl(tmp->fd, PHONE_RING_STOP);		ioctl(tmp->fd, PHONE_CPT_STOP);		if (ioctl(tmp->fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK)) 			ast_log(LOG_DEBUG, "ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(errno));		if (echocancel != AEC_OFF)			ioctl(tmp->fd, IXJCTL_AEC_START, echocancel);		if (silencesupression) 			tmp->silencesupression = 1;#ifdef PHONE_VAD		ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression);#endif		tmp->mode = mode;		flags = fcntl(tmp->fd, F_GETFL);		fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);		tmp->owner = NULL;		tmp->lastformat = -1;		tmp->lastinput = -1;		tmp->ministate = 0;		memset(tmp->ext, 0, sizeof(tmp->ext));		ast_copy_string(tmp->language, language, sizeof(tmp->language));		ast_copy_string(tmp->dev, iface, sizeof(tmp->dev));		ast_copy_string(tmp->context, context, sizeof(tmp->context));		tmp->next = NULL;		tmp->obuflen = 0;		tmp->dialtone = 0;		tmp->cpt = 0;		ast_copy_string(tmp->cid_num, cid_num, sizeof(tmp->cid_num));		ast_copy_string(tmp->cid_name, cid_name, sizeof(tmp->cid_name));		tmp->txgain = txgain;		ioctl(tmp->fd, PHONE_PLAY_VOLUME, tmp->txgain);		tmp->rxgain = rxgain;		ioctl(tmp->fd, PHONE_REC_VOLUME, tmp->rxgain);	}	return tmp;}static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause){	int oldformat;	struct phone_pvt *p;	struct ast_channel *tmp = NULL;	char *name = data;	/* Search for an unowned channel */	if (ast_mutex_lock(&iflock)) {		ast_log(LOG_ERROR, "Unable to lock interface list???\n");		return NULL;	}	p = iflist;	while(p) {		if (p->mode == MODE_FXS ||		    format & (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) {		    size_t length = strlen(p->dev + 5);    		if (strncmp(name, p->dev + 5, length) == 0 &&    		    !isalnum(name[length])) {    		    if (!p->owner) {                     tmp = phone_new(p, AST_STATE_DOWN, p->context);                     break;                } else                     *cause = AST_CAUSE_BUSY;            }		}		p = p->next;	}	ast_mutex_unlock(&iflock);	restart_monitor();	if (tmp == NULL) {		oldformat = format;		format &= (AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);		if (!format) {			ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);			return NULL;		}	}	return tmp;}/* parse gain value from config file */static int parse_gain_value(char *gain_type, char *value){	float gain;	/* try to scan number */	if (sscanf(value, "%f", &gain) != 1)	{		ast_log(LOG_ERROR, "Invalid %s value '%s' in '%s' config\n",			value, gain_type, config);		return DEFAULT_GAIN;	}	/* multiplicate gain by 1.0 gain value */ 	gain = gain * (float)DEFAULT_GAIN;	/* percentage? */	if (value[strlen(value) - 1] == '%')		return (int)(gain / (float)100);	return (int)gain;}static int __unload_module(void){	struct phone_pvt *p, *pl;	/* First, take us out of the channel loop */	if (cur_tech)		ast_channel_unregister(cur_tech);	if (!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);	} else {		ast_log(LOG_WARNING, "Unable to lock the monitor\n");		return -1;	}	if (!ast_mutex_lock(&monlock)) {		if (monitor_thread > AST_PTHREADT_NULL) {			monitor = 0;			while (pthread_kill(monitor_thread, SIGURG) == 0)				sched_yield();			pthread_join(monitor_thread, NULL);		}		monitor_thread = AST_PTHREADT_STOP;		ast_mutex_unlock(&monlock);	} else {		ast_log(LOG_WARNING, "Unable to lock the monitor\n");		return -1;	}	if (!ast_mutex_lock(&iflock)) {		/* Destroy all the interfaces and free their memory */		p = iflist;		while(p) {			/* Close the socket, assuming it's real */			if (p->fd > -1)				close(p->fd);			pl = p;			p = p->next;			/* Free associated memory */			free(pl);		}		iflist = NULL;		ast_mutex_unlock(&iflock);	} else {		ast_log(LOG_WARNING, "Unable to lock the monitor\n");		return -1;	}			return 0;}static int unload_module(void){	return __unload_module();}static int load_module(void){	struct ast_config *cfg;	struct ast_variable *v;	struct phone_pvt *tmp;	int mode = MODE_IMMEDIATE;	int txgain = DEFAULT_GAIN, rxgain = DEFAULT_GAIN; /* default gain 1.0 */	cfg = ast_config_load(config);	/* We *must* have a config file otherwise stop immediately */	if (!cfg) {		ast_log(LOG_ERROR, "Unable to load config %s\n", config);		return AST_MODULE_LOAD_DECLINE;	}	if (ast_mutex_lock(&iflock)) {		/* It's a little silly to lock it, but we mind as well just to be sure */		ast_log(LOG_ERROR, "Unable to lock interface list???\n");		return AST_MODULE_LOAD_FAILURE;	}	v = ast_variable_browse(cfg, "interfaces");	while(v) {		/* Create the interface list */		if (!strcasecmp(v->name, "device")) {				tmp = mkif(v->value, mode, txgain, rxgain);				if (tmp) {					tmp->next = iflist;					iflist = tmp;									} else {					ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);					ast_config_destroy(cfg);					ast_mutex_unlock(&iflock);					__unload_module();					return AST_MODULE_LOAD_FAILURE;				}		} else if (!strcasecmp(v->name, "silencesupression")) {			silencesupression = ast_true(v->value);		} else if (!strcasecmp(v->name, "language")) {			ast_copy_string(language, v->value, sizeof(language));		} else if (!strcasecmp(v->name, "callerid")) {			ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));		} else if (!strcasecmp(v->name, "mode")) {			if (!strncasecmp(v->value, "di", 2)) 				mode = MODE_DIALTONE;			else if (!strncasecmp(v->value, "sig", 3))				mode = MODE_SIGMA;			else if (!strncasecmp(v->value, "im", 2))				mode = MODE_IMMEDIATE;			else if (!strncasecmp(v->value, "fxs", 3)) {				mode = MODE_FXS;				prefformat = 0x01ff0000; /* All non-voice */			}			else if (!strncasecmp(v->value, "fx", 2))				mode = MODE_FXO;			else				ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);		} else if (!strcasecmp(v->name, "context")) {			ast_copy_string(context, v->value, sizeof(context));		} else if (!strcasecmp(v->name, "format")) {			if (!strcasecmp(v->value, "g723.1")) {				prefformat = AST_FORMAT_G723_1;			} else if (!strcasecmp(v->value, "slinear")) {				if (mode == MODE_FXS)				    prefformat |= AST_FORMAT_SLINEAR;				else prefformat = AST_FORMAT_SLINEAR;			} else if (!strcasecmp(v->value, "ulaw")) {				prefformat = AST_FORMAT_ULAW;			} else				ast_log(LOG_WARNING, "Unknown format '%s'\n", v->value);		} else if (!strcasecmp(v->name, "echocancel")) {			if (!strcasecmp(v->value, "off")) {				echocancel = AEC_OFF;			} else if (!strcasecmp(v->value, "low")) {				echocancel = AEC_LOW;			} else if (!strcasecmp(v->value, "medium")) {				echocancel = AEC_MED;			} else if (!strcasecmp(v->value, "high")) {				echocancel = AEC_HIGH;			} else 				ast_log(LOG_WARNING, "Unknown echo cancellation '%s'\n", v->value);		} else if (!strcasecmp(v->name, "txgain")) {			txgain = parse_gain_value(v->name, v->value);		} else if (!strcasecmp(v->name, "rxgain")) {			rxgain = parse_gain_value(v->name, v->value);		}			v = v->next;	}	ast_mutex_unlock(&iflock);	if (mode == MODE_FXS) {		phone_tech_fxs.capabilities = prefformat;		cur_tech = &phone_tech_fxs;	} else		cur_tech = (struct ast_channel_tech *) &phone_tech;	/* Make sure we can register our Adtranphone channel type */	if (ast_channel_register(cur_tech)) {		ast_log(LOG_ERROR, "Unable to register channel class 'Phone'\n");		ast_config_destroy(cfg);		__unload_module();		return AST_MODULE_LOAD_FAILURE;	}	ast_config_destroy(cfg);	/* And start the monitor for the first time */	restart_monitor();	return AST_MODULE_LOAD_SUCCESS;}AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Linux Telephony API Support");

⌨️ 快捷键说明

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