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

📄 pri.c

📁 Q921的LINUX下的驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * libpri: An implementation of Primary Rate ISDN * * Written by Mark Spencer <markster@digium.com> * * Copyright (C) 2001-2005, Digium * All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <unistd.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/select.h>#include <stdarg.h>#include "compat.h"#include "libpri.h"#include "pri_internal.h"#include "pri_facility.h"#include "pri_q921.h"#include "pri_q931.h"#include "pri_timers.h"char *pri_node2str(int node){	switch(node) {	case PRI_UNKNOWN:		return "Unknown node type";	case PRI_NETWORK:		return "Network";	case PRI_CPE:		return "CPE";	default:		return "Invalid value";	}}char *pri_switch2str(int sw){	switch(sw) {	case PRI_SWITCH_NI2:		return "National ISDN";	case PRI_SWITCH_DMS100:		return "Nortel DMS100";	case PRI_SWITCH_LUCENT5E:		return "Lucent 5E";	case PRI_SWITCH_ATT4ESS:		return "AT&T 4ESS";	case PRI_SWITCH_NI1:		return "National ISDN 1";	case PRI_SWITCH_EUROISDN_E1:		return "EuroISDN";	case PRI_SWITCH_GR303_EOC:		return "GR303 EOC";	case PRI_SWITCH_GR303_TMC:		return "GR303 TMC";	case PRI_SWITCH_QSIG:		return "Q.SIG switch";	default:		return "Unknown switchtype";	}}static void pri_default_timers(struct pri *pri, int switchtype){	int defaulttimers[20][PRI_MAX_TIMERS] = PRI_TIMERS_ALL;	int x;	for (x = 0; x<PRI_MAX_TIMERS; x++) {		pri->timers[x] = defaulttimers[switchtype][x];	}}int pri_set_timer(struct pri *pri, int timer, int value){	if (timer < 0 || timer > PRI_MAX_TIMERS || value < 0)		return -1;	pri->timers[timer] = value;	return 0;}int pri_get_timer(struct pri *pri, int timer){	if (timer < 0 || timer > PRI_MAX_TIMERS)		return -1;	return pri->timers[timer];}int pri_timer2idx(char *timer){	if (!strcasecmp(timer, "N200"))		return PRI_TIMER_N200;	else if (!strcasecmp(timer, "N201"))		return PRI_TIMER_N201;	else if (!strcasecmp(timer, "N202"))		return PRI_TIMER_N202;	else if (!strcasecmp(timer, "K"))		return PRI_TIMER_K;	else if (!strcasecmp(timer, "T200"))		return PRI_TIMER_T200;	else if (!strcasecmp(timer, "T202"))		return PRI_TIMER_T202;	else if (!strcasecmp(timer, "T203"))		return PRI_TIMER_T203;	else if (!strcasecmp(timer, "T300"))		return PRI_TIMER_T300;	else if (!strcasecmp(timer, "T301"))		return PRI_TIMER_T301;	else if (!strcasecmp(timer, "T302"))		return PRI_TIMER_T302;	else if (!strcasecmp(timer, "T303"))		return PRI_TIMER_T303;	else if (!strcasecmp(timer, "T304"))		return PRI_TIMER_T304;	else if (!strcasecmp(timer, "T305"))		return PRI_TIMER_T305;	else if (!strcasecmp(timer, "T306"))		return PRI_TIMER_T306;	else if (!strcasecmp(timer, "T307"))		return PRI_TIMER_T307;	else if (!strcasecmp(timer, "T308"))		return PRI_TIMER_T308;	else if (!strcasecmp(timer, "T309"))		return PRI_TIMER_T309;	else if (!strcasecmp(timer, "T310"))		return PRI_TIMER_T310;	else if (!strcasecmp(timer, "T313"))		return PRI_TIMER_T313;	else if (!strcasecmp(timer, "T314"))		return PRI_TIMER_T314;	else if (!strcasecmp(timer, "T316"))		return PRI_TIMER_T316;	else if (!strcasecmp(timer, "T317"))		return PRI_TIMER_T317;	else if (!strcasecmp(timer, "T318"))		return PRI_TIMER_T318;	else if (!strcasecmp(timer, "T319"))		return PRI_TIMER_T319;	else if (!strcasecmp(timer, "T320"))		return PRI_TIMER_T320;	else if (!strcasecmp(timer, "T321"))		return PRI_TIMER_T321;	else if (!strcasecmp(timer, "T322"))		return PRI_TIMER_T322;	else		return -1;}static int __pri_read(struct pri *pri, void *buf, int buflen){	int res = read(pri->fd, buf, buflen);	if (res < 0) {		if (errno != EAGAIN)			pri_error(pri, "Read on %d failed: %s\n", pri->fd, strerror(errno));		return 0;	}	return res;}static int __pri_write(struct pri *pri, void *buf, int buflen){	int res = write(pri->fd, buf, buflen);	if (res < 0) {		if (errno != EAGAIN)			pri_error(pri, "Write to %d failed: %s\n", pri->fd, strerror(errno));		return 0;	}	return res;}static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata){	struct pri *p;	p = malloc(sizeof(struct pri));	if (p) {		memset(p, 0, sizeof(struct pri));		p->fd = fd;		p->read_func = rd;		p->write_func = wr;		p->userdata = userdata;		p->localtype = node;		p->switchtype = switchtype;		p->cref = 1;		p->sapi = Q921_SAPI_CALL_CTRL;		p->tei = 0;		p->nsf = PRI_NSF_NONE;		p->protodisc = Q931_PROTOCOL_DISCRIMINATOR;		p->master = master;		p->callpool = &p->localpool;		pri_default_timers(p, switchtype);#ifdef LIBPRI_COUNTERS		p->q921_rxcount = 0;		p->q921_txcount = 0;		p->q931_rxcount = 0;		p->q931_txcount = 0;#endif		if (switchtype == PRI_SWITCH_GR303_EOC) {			p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;			p->sapi = Q921_SAPI_GR303_EOC;			p->tei = Q921_TEI_GR303_EOC_OPS;			p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL);			if (!p->subchannel) {				free(p);				p = NULL;			}		} else if (switchtype == PRI_SWITCH_GR303_TMC) {			p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;			p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;			p->tei = Q921_TEI_GR303_TMC_CALLPROC;			p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL);			if (!p->subchannel) {				free(p);				p = NULL;			}		} else if (switchtype == PRI_SWITCH_GR303_TMC_SWITCHING) {			p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;			p->sapi = Q921_SAPI_GR303_TMC_SWITCHING;			p->tei = Q921_TEI_GR303_TMC_SWITCHING;		} else if (switchtype == PRI_SWITCH_GR303_EOC_PATH) {			p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;			p->sapi = Q921_SAPI_GR303_EOC;			p->tei = Q921_TEI_GR303_EOC_PATH;		}		/* Start Q.921 layer, Wait if we're the network */		if (p)			q921_start(p, p->localtype == PRI_CPE);	}	return p;}void pri_call_set_useruser(q931_call *c, const char *userchars){	if (userchars)		libpri_copy_string(c->useruserinfo, userchars, sizeof(c->useruserinfo));}void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars){	sr->useruserinfo = userchars;}int pri_restart(struct pri *pri){	/* Restart Q.921 layer */	if (pri) {		q921_reset(pri);		q921_start(pri, pri->localtype == PRI_CPE);		}	return 0;}struct pri *pri_new(int fd, int nodetype, int switchtype){	return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL);}struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata){	if (!io_read)		io_read = __pri_read;	if (!io_write)		io_write = __pri_write;	return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata);}void *pri_get_userdata(struct pri *pri){	return pri ? pri->userdata : NULL;}void pri_set_userdata(struct pri *pri, void *userdata){	if (pri)		pri->userdata = userdata;}void pri_set_nsf(struct pri *pri, int nsf){	if (pri)		pri->nsf = nsf;}char *pri_event2str(int id){	switch(id) {	case PRI_EVENT_DCHAN_UP:		return "D-Channel Up";	case PRI_EVENT_DCHAN_DOWN:		return "D-channel Down";	case PRI_EVENT_RESTART:		return "Restart channel";	case PRI_EVENT_RING:		return "Ring";	case PRI_EVENT_HANGUP:		return "Hangup";	case PRI_EVENT_RINGING:		return "Ringing";	case PRI_EVENT_ANSWER:		return "Answer";	case PRI_EVENT_HANGUP_ACK:		return "Hangup ACK";	case PRI_EVENT_RESTART_ACK:		return "Restart ACK";	case PRI_EVENT_FACNAME:		return "FacName";	case PRI_EVENT_INFO_RECEIVED:		return "Info Received";	case PRI_EVENT_PROCEEDING:		return "Proceeding";	case PRI_EVENT_SETUP_ACK:		return "Setup ACK";	case PRI_EVENT_HANGUP_REQ:		return "Hangup Req";	case PRI_EVENT_NOTIFY:		return "Notify";	case PRI_EVENT_PROGRESS:		return "Progress";	case PRI_EVENT_CONFIG_ERR:		return "Configuration Error";	default:		return "Unknown Event";	}}pri_event *pri_check_event(struct pri *pri){	char buf[1024];	int res;	pri_event *e;	res = pri->read_func ? pri->read_func(pri, buf, sizeof(buf)) : 0;	if (!res)		return NULL;	/* Receive the q921 packet */	e = q921_receive(pri, (q921_h *)buf, res);	return e;}static int wait_pri(struct pri *pri){		struct timeval *tv, real;	fd_set fds;	int res;	FD_ZERO(&fds);	FD_SET(pri->fd, &fds);	tv = pri_schedule_next(pri);	if (tv) {		gettimeofday(&real, NULL);		real.tv_sec = tv->tv_sec - real.tv_sec;		real.tv_usec = tv->tv_usec - real.tv_usec;		if (real.tv_usec < 0) {			real.tv_usec += 1000000;			real.tv_sec -= 1;		}		if (real.tv_sec < 0) {			real.tv_sec = 0;			real.tv_usec = 0;		}	}	res = select(pri->fd + 1, &fds, NULL, NULL, tv ? &real : tv);	if (res < 0) 		return -1;	return res;}pri_event *pri_mkerror(struct pri *pri, char *errstr){	/* Return a configuration error */	pri->ev.err.e = PRI_EVENT_CONFIG_ERR;	libpri_copy_string(pri->ev.err.err, errstr, sizeof(pri->ev.err.err));	return &pri->ev;}pri_event *pri_dchannel_run(struct pri *pri, int block){	pri_event *e;	int res;	if (!pri)		return NULL;	if (block) {		do {			e =  NULL;			res = wait_pri(pri);			/* Check for error / interruption */			if (res < 0)				return NULL;			if (!res)				e = pri_schedule_run(pri);			else				e = pri_check_event(pri);		} while(!e);	} else {		e = pri_check_event(pri);		return e;	}	return e;}void pri_set_debug(struct pri *pri, int debug){	if (!pri)		return;	pri->debug = debug;	if (pri->subchannel)		pri_set_debug(pri->subchannel, debug);}int pri_get_debug(struct pri *pri){	if (!pri)		return -1;	if (pri->subchannel)

⌨️ 快捷键说明

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