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

📄 chan_phone.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 3 页
字号:
{	if (c == 12)		return '#';	else if (c == 11)		return '*';	else if ((c < 10) && (c >= 0))		return '0' + c - 1;	else		return '?';}#endifstatic struct ast_frame  *phone_exception(struct ast_channel *ast){	int res;	union telephony_exception phonee;	struct phone_pvt *p = ast->tech_pvt;	char digit;	/* Some nice norms */	p->fr.datalen = 0;	p->fr.samples = 0;	p->fr.data =  NULL;	p->fr.src = "Phone";	p->fr.offset = 0;	p->fr.mallocd=0;	p->fr.delivery = ast_tv(0,0);		phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);	if (phonee.bits.dtmf_ready)  {		if (option_debug)			ast_log(LOG_DEBUG, "phone_exception(): DTMF\n");			/* We've got a digit -- Just handle this nicely and easily */		digit =  ioctl(p->fd, PHONE_GET_DTMF_ASCII);		p->fr.subclass = digit;		p->fr.frametype = AST_FRAME_DTMF;		return &p->fr;	}	if (phonee.bits.hookstate) {		if (option_debug)			ast_log(LOG_DEBUG, "Hookstate changed\n");		res = ioctl(p->fd, PHONE_HOOKSTATE);		/* See if we've gone on hook, if so, notify by returning NULL */		if (option_debug)			ast_log(LOG_DEBUG, "New hookstate: %d\n", res);		if (!res && (p->mode != MODE_FXO))			return NULL;		else {			if (ast->_state == AST_STATE_RINGING) {				/* They've picked up the phone */				p->fr.frametype = AST_FRAME_CONTROL;				p->fr.subclass = AST_CONTROL_ANSWER;				phone_setup(ast);				ast_setstate(ast, AST_STATE_UP);				return &p->fr;			}  else 				ast_log(LOG_WARNING, "Got off hook in weird state %d\n", ast->_state);		}	}#if 1	if (phonee.bits.pstn_ring)		ast_verbose("Unit is ringing\n");	if (phonee.bits.caller_id) {		ast_verbose("We have caller ID\n");	}	if (phonee.bits.pstn_wink)		ast_verbose("Detected Wink\n");#endif	/* Strange -- nothing there.. */	p->fr.frametype = AST_FRAME_NULL;	p->fr.subclass = 0;	return &p->fr;}static struct ast_frame  *phone_read(struct ast_channel *ast){	int res;	struct phone_pvt *p = ast->tech_pvt;		/* Some nice norms */	p->fr.datalen = 0;	p->fr.samples = 0;	p->fr.data =  NULL;	p->fr.src = "Phone";	p->fr.offset = 0;	p->fr.mallocd=0;	p->fr.delivery = ast_tv(0,0);	/* Try to read some data... */	CHECK_BLOCKING(ast);	res = read(p->fd, p->buf, PHONE_MAX_BUF);	ast_clear_flag(ast, AST_FLAG_BLOCKING);	if (res < 0) {#if 0		if (errno == EAGAIN) {			ast_log(LOG_WARNING, "Null frame received\n");			p->fr.frametype = AST_FRAME_NULL;			p->fr.subclass = 0;			return &p->fr;		}#endif		ast_log(LOG_WARNING, "Error reading: %s\n", strerror(errno));		return NULL;	}	p->fr.data = p->buf;	if (p->mode != MODE_FXS)	switch(p->buf[0] & 0x3) {	case '0':	case '1':		/* Normal */		break;	case '2':	case '3':		/* VAD/CNG, only send two words */		res = 4;		break;	}	p->fr.samples = 240;	p->fr.datalen = res;	p->fr.frametype = p->lastinput <= AST_FORMAT_MAX_AUDIO ?                          AST_FRAME_VOICE : 			  p->lastinput <= AST_FORMAT_PNG ? AST_FRAME_IMAGE 			  : AST_FRAME_VIDEO;	p->fr.subclass = p->lastinput;	p->fr.offset = AST_FRIENDLY_OFFSET;	/* Byteswap from little-endian to native-endian */	if (p->fr.subclass == AST_FORMAT_SLINEAR)		ast_frame_byteswap_le(&p->fr);	return &p->fr;}static int phone_write_buf(struct phone_pvt *p, const char *buf, int len, int frlen, int swap){	int res;	/* Store as much of the buffer as we can, then write fixed frames */	int space = sizeof(p->obuf) - p->obuflen;	/* Make sure we have enough buffer space to store the frame */	if (space < len)		len = space;	if (swap)		ast_swapcopy_samples(p->obuf+p->obuflen, buf, len/2);	else		memcpy(p->obuf + p->obuflen, buf, len);	p->obuflen += len;	while(p->obuflen > frlen) {		res = write(p->fd, p->obuf, frlen);		if (res != frlen) {			if (res < 1) {/* * Card is in non-blocking mode now and it works well now, but there are * lot of messages like this. So, this message is temporarily disabled. */				return 0;			} else {				ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frlen);			}		}		p->obuflen -= frlen;		/* Move memory if necessary */		if (p->obuflen) 			memmove(p->obuf, p->obuf + frlen, p->obuflen);	}	return len;}static int phone_send_text(struct ast_channel *ast, const char *text){    int length = strlen(text);    return phone_write_buf(ast->tech_pvt, text, length, length, 0) ==            length ? 0 : -1;}static int phone_write(struct ast_channel *ast, struct ast_frame *frame){	struct phone_pvt *p = ast->tech_pvt;	int res;	int maxfr=0;	char *pos;	int sofar;	int expected;	int codecset = 0;	char tmpbuf[4];	/* Write a frame of (presumably voice) data */	if (frame->frametype != AST_FRAME_VOICE && p->mode != MODE_FXS) {		if (frame->frametype != AST_FRAME_IMAGE)			ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);		return 0;	}	if (!(frame->subclass &		(AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW)) && 	    p->mode != MODE_FXS) {		ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);		return -1;	}#if 0	/* If we're not in up mode, go into up mode now */	if (ast->_state != AST_STATE_UP) {		ast_setstate(ast, AST_STATE_UP);		phone_setup(ast);	}#else	if (ast->_state != AST_STATE_UP) {		/* Don't try tos end audio on-hook */		return 0;	}#endif		if (frame->subclass == AST_FORMAT_G723_1) {		if (p->lastformat != AST_FORMAT_G723_1) {			ioctl(p->fd, PHONE_PLAY_STOP);			ioctl(p->fd, PHONE_REC_STOP);			if (ioctl(p->fd, PHONE_PLAY_CODEC, G723_63)) {				ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");				return -1;			}			if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {				ast_log(LOG_WARNING, "Unable to set G723.1 mode\n");				return -1;			}			p->lastformat = AST_FORMAT_G723_1;			p->lastinput = AST_FORMAT_G723_1;			/* Reset output buffer */			p->obuflen = 0;			codecset = 1;		}		if (frame->datalen > 24) {			ast_log(LOG_WARNING, "Frame size too large for G.723.1 (%d bytes)\n", frame->datalen);			return -1;		}		maxfr = 24;	} else if (frame->subclass == AST_FORMAT_SLINEAR) {		if (p->lastformat != AST_FORMAT_SLINEAR) {			ioctl(p->fd, PHONE_PLAY_STOP);			ioctl(p->fd, PHONE_REC_STOP);			if (ioctl(p->fd, PHONE_PLAY_CODEC, LINEAR16)) {				ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");				return -1;			}			if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {				ast_log(LOG_WARNING, "Unable to set 16-bit linear mode\n");				return -1;			}			p->lastformat = AST_FORMAT_SLINEAR;			p->lastinput = AST_FORMAT_SLINEAR;			codecset = 1;			/* Reset output buffer */			p->obuflen = 0;		}		maxfr = 480;	} else if (frame->subclass == AST_FORMAT_ULAW) {		if (p->lastformat != AST_FORMAT_ULAW) {			ioctl(p->fd, PHONE_PLAY_STOP);			ioctl(p->fd, PHONE_REC_STOP);			if (ioctl(p->fd, PHONE_PLAY_CODEC, ULAW)) {				ast_log(LOG_WARNING, "Unable to set uLaw mode\n");				return -1;			}			if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {				ast_log(LOG_WARNING, "Unable to set uLaw mode\n");				return -1;			}			p->lastformat = AST_FORMAT_ULAW;			p->lastinput = AST_FORMAT_ULAW;			codecset = 1;			/* Reset output buffer */			p->obuflen = 0;		}		maxfr = 240;	} else {		if (p->lastformat != frame->subclass) {			ioctl(p->fd, PHONE_PLAY_STOP);			ioctl(p->fd, PHONE_REC_STOP);			if (ioctl(p->fd, PHONE_PLAY_CODEC, frame->subclass)) {				ast_log(LOG_WARNING, "Unable to set %d mode\n",					frame->subclass);				return -1;			}			if (ioctl(p->fd, PHONE_REC_CODEC, frame->subclass)) {				ast_log(LOG_WARNING, "Unable to set %d mode\n",					frame->subclass);				return -1;			}			p->lastformat = frame->subclass;			p->lastinput = frame->subclass;			codecset = 1;			/* Reset output buffer */			p->obuflen = 0;		}		maxfr = 480;	} 	if (codecset) {		ioctl(p->fd, PHONE_REC_DEPTH, 3);		ioctl(p->fd, PHONE_PLAY_DEPTH, 3);		if (ioctl(p->fd, PHONE_PLAY_START)) {			ast_log(LOG_WARNING, "Failed to start playback\n");			return -1;		}		if (ioctl(p->fd, PHONE_REC_START)) {			ast_log(LOG_WARNING, "Failed to start recording\n");			return -1;		}	}	/* If we get here, we have a frame of Appropriate data */	sofar = 0;	pos = frame->data;	while(sofar < frame->datalen) {		/* Write in no more than maxfr sized frames */		expected = frame->datalen - sofar;		if (maxfr < expected)			expected = maxfr;		/* XXX Internet Phone Jack does not handle the 4-byte VAD frame properly! XXX 		   we have to pad it to 24 bytes still.  */		if (frame->datalen == 4) {			if (p->silencesupression) {				memset(tmpbuf + 4, 0, sizeof(tmpbuf) - 4);				memcpy(tmpbuf, frame->data, 4);				expected = 24;				res = phone_write_buf(p, tmpbuf, expected, maxfr, 0);			}			res = 4;			expected=4;		} else {			int swap = 0;#if __BYTE_ORDER == __BIG_ENDIAN			if (frame->subclass == AST_FORMAT_SLINEAR)				swap = 1; /* Swap big-endian samples to little-endian as we copy */#endif			res = phone_write_buf(p, pos, expected, maxfr, swap);		}		if (res != expected) {			if ((errno != EAGAIN) && (errno != EINTR)) {				if (res < 0) 					ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));	/*	 * Card is in non-blocking mode now and it works well now, but there are	 * lot of messages like this. So, this message is temporarily disabled.	 */#if 0				else					ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);#endif				return -1;			} else /* Pretend it worked */				res = expected;		}		sofar += res;		pos += res;	}	return 0;}static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *context){	struct ast_channel *tmp;	struct phone_codec_data codec;	tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, 0, "Phone/%s", i->dev + 5);	if (tmp) {		tmp->tech = cur_tech;		tmp->fds[0] = i->fd;		/* XXX Switching formats silently causes kernel panics XXX */		if (i->mode == MODE_FXS &&		    ioctl(i->fd, PHONE_QUERY_CODEC, &codec) == 0) {			if (codec.type == LINEAR16)				tmp->nativeformats =				tmp->rawreadformat =				tmp->rawwriteformat =				AST_FORMAT_SLINEAR;			else {				tmp->nativeformats =				tmp->rawreadformat =				tmp->rawwriteformat =				prefformat & ~AST_FORMAT_SLINEAR;			}		}		else {			tmp->nativeformats = prefformat;			tmp->rawreadformat = prefformat;			tmp->rawwriteformat = prefformat;		}		/* no need to call ast_setstate: the channel_alloc already did its job */		if (state == AST_STATE_RING)			tmp->rings = 1;		tmp->tech_pvt = i;		ast_copy_string(tmp->context, context, sizeof(tmp->context));		if (!ast_strlen_zero(i->ext))			ast_copy_string(tmp->exten, i->ext, sizeof(tmp->exten));		else			strcpy(tmp->exten, "s");		if (!ast_strlen_zero(i->language))			ast_string_field_set(tmp, language, i->language);		/* Don't use ast_set_callerid() here because it will		 * generate a NewCallerID event before the NewChannel event */		tmp->cid.cid_ani = ast_strdup(i->cid_num);		i->owner = tmp;		ast_module_ref(ast_module_info->self);		if (state != AST_STATE_DOWN) {			if (state == AST_STATE_RING) {				ioctl(tmp->fds[0], PHONE_RINGBACK);				i->cpt = 1;			}			if (ast_pbx_start(tmp)) {				ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);				ast_hangup(tmp);			}		}	} else		ast_log(LOG_WARNING, "Unable to allocate channel structure\n");	return tmp;}static void phone_mini_packet(struct phone_pvt *i){	int res;	char buf[1024];	/* Ignore stuff we read... */	res = read(i->fd, buf, sizeof(buf));	if (res < 1) {		ast_log(LOG_WARNING, "Read returned %d: %s\n", res, strerror(errno));		return;	}}static void phone_check_exception(struct phone_pvt *i){	int offhook=0;	char digit[2] = {0 , 0};	union telephony_exception phonee;	/* XXX Do something XXX */#if 0	ast_log(LOG_DEBUG, "Exception!\n");#endif	phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION);	if (phonee.bits.dtmf_ready)  {		digit[0] = ioctl(i->fd, PHONE_GET_DTMF_ASCII);		if (i->mode == MODE_DIALTONE || i->mode == MODE_FXS || i->mode == MODE_SIGMA) {			ioctl(i->fd, PHONE_PLAY_STOP);			ioctl(i->fd, PHONE_REC_STOP);			ioctl(i->fd, PHONE_CPT_STOP);			i->dialtone = 0;			if (strlen(i->ext) < AST_MAX_EXTENSION - 1)				strncat(i->ext, digit, sizeof(i->ext) - strlen(i->ext) - 1);			if ((i->mode != MODE_FXS ||			     !(phonee.bytes = ioctl(i->fd, PHONE_EXCEPTION)) ||			     !phonee.bits.dtmf_ready) &&			    ast_exists_extension(NULL, i->context, i->ext, 1, i->cid_num)) {				/* It's a valid extension in its context, get moving! */				phone_new(i, AST_STATE_RING, i->context);				/* No need to restart monitor, we are the monitor */			} else if (!ast_canmatch_extension(NULL, i->context, i->ext, 1, i->cid_num)) {				/* There is nothing in the specified extension that can match anymore.				   Try the default */				if (ast_exists_extension(NULL, "default", i->ext, 1, i->cid_num)) {					/* Check the default, too... */					phone_new(i, AST_STATE_RING, "default");					/* XXX This should probably be justified better XXX */				}  else if (!ast_canmatch_extension(NULL, "default", i->ext, 1, i->cid_num)) {					/* It's not a valid extension, give a busy signal */					if (option_debug)						ast_log(LOG_DEBUG, "%s can't match anything in %s or default\n", i->ext, i->context);					ioctl(i->fd, PHONE_BUSY);					i->cpt = 1;				}			}#if 0			ast_verbose("Extension is %s\n", i->ext);#endif		}	}	if (phonee.bits.hookstate) {		offhook = ioctl(i->fd, PHONE_HOOKSTATE);		if (offhook) {			if (i->mode == MODE_IMMEDIATE) {				phone_new(i, AST_STATE_RING, i->context);			} else if (i->mode == MODE_DIALTONE) {				ast_module_ref(ast_module_info->self);

⌨️ 快捷键说明

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