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

📄 isdn_lib.c

📁 Asterisk-1.4.4最新内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Chan_Misdn -- Channel Driver for Asterisk * * Interface to mISDN * * Copyright (C) 2004, Christian Richter * * Christian Richter <crich@beronet.com> * * This program is free software, distributed under the terms of * the GNU General Public License */#include <syslog.h>#include <mISDNuser/isdn_debug.h>#include "isdn_lib_intern.h"#include "isdn_lib.h"void misdn_join_conf(struct misdn_bchannel *bc, int conf_id);void misdn_split_conf(struct misdn_bchannel *bc, int conf_id);int queue_cleanup_bc(struct misdn_bchannel *bc) ;int misdn_lib_get_l2_up(struct misdn_stack *stack);struct misdn_stack* get_misdn_stack( void );int misdn_lib_port_is_pri(int port){	struct misdn_stack *stack=get_misdn_stack();	for ( ; stack; stack=stack->next) {		if (stack->port == port) {			return stack->pri;		}	}		return -1;}int misdn_lib_port_block(int port){	struct misdn_stack *stack=get_misdn_stack();	for ( ; stack; stack=stack->next) {		if (stack->port == port) {			stack->blocked=1;			return 0;		}	}	return -1;}int misdn_lib_port_unblock(int port){	struct misdn_stack *stack=get_misdn_stack();	for ( ; stack; stack=stack->next) {		if (stack->port == port) {			stack->blocked=0;			return 0;		}	}	return -1;}int misdn_lib_is_port_blocked(int port){		struct misdn_stack *stack=get_misdn_stack();	for ( ; stack; stack=stack->next) {		if (stack->port == port) {			return stack->blocked;		}	}	return -1;}int misdn_lib_is_ptp(int port){	struct misdn_stack *stack=get_misdn_stack();	for ( ; stack; stack=stack->next) {		if (stack->port == port) return stack->ptp;	}	return -1;}int misdn_lib_get_maxchans(int port) {	struct misdn_stack *stack=get_misdn_stack();	for ( ; stack; stack=stack->next) {		if (stack->port == port) {			if (stack->pri) 				return 30;			else				return 2;		}	}	return -1;}struct misdn_stack* get_stack_by_bc(struct misdn_bchannel *bc){	struct misdn_stack *stack=get_misdn_stack();	if (!bc) return NULL;		for ( ; stack; stack=stack->next) {		int i;		for (i=0; i <=stack->b_num; i++) {			if ( bc->port == stack->port) return stack;		}	}	return NULL;}void get_show_stack_details(int port, char *buf){	struct misdn_stack *stack=get_misdn_stack();		for ( ; stack; stack=stack->next) {		if (stack->port == port) break;	}		if (stack) {		sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d", stack->port, stack->nt?"NT":"TE", stack->ptp?"PTP":"PMP", stack->l2link?"UP":"DOWN", stack->l1link?"UP":"DOWN",stack->blocked);	} else {		buf[0]=0;	}	}static int nt_err_cnt =0 ;enum global_states {	MISDN_INITIALIZING,	MISDN_INITIALIZED} ;static enum global_states  global_state=MISDN_INITIALIZING;#include <mISDNuser/net_l2.h>#include <mISDNuser/tone.h>#include <unistd.h>#include <semaphore.h>#include <pthread.h>#include <signal.h>#include "isdn_lib.h"struct misdn_lib {	int midev;	int midev_nt;	pthread_t event_thread;	pthread_t event_handler_thread;	void *user_data;	msg_queue_t upqueue;	msg_queue_t activatequeue;   	sem_t new_msg;  	struct misdn_stack *stack_list;} ;#ifndef ECHOCAN_ON#define ECHOCAN_ON 123#define ECHOCAN_OFF 124#endif#define MISDN_DEBUG 0void misdn_tx_jitter(struct misdn_bchannel *bc, int len);struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id);struct misdn_bchannel *find_bc_by_confid(unsigned long confid);struct misdn_bchannel *stack_holder_find_bychan(struct misdn_stack *stack, int chan);int setup_bc(struct misdn_bchannel *bc);int manager_isdn_handler(iframe_t *frm ,msg_t *msg);int misdn_lib_port_restart(int port);int misdn_lib_pid_restart(int pid);extern struct isdn_msg msgs_g[]; #define ISDN_PID_L3_B_USER 0x430000ff#define ISDN_PID_L4_B_USER 0x440000ff/* #define MISDN_IBUF_SIZE 1024 */#define MISDN_IBUF_SIZE 512/*  Fine Tuning of Inband  Signalling time */#define TONE_ALERT_CNT 41 /*  1 Sec  */#define TONE_ALERT_SILENCE_CNT 200 /*  4 Sec */#define TONE_BUSY_CNT 20 /*  ? */#define TONE_BUSY_SILENCE_CNT 48 /*  ? */static int  entity;static struct misdn_lib *glob_mgr;char tone_425_flip[TONE_425_SIZE];char tone_silence_flip[TONE_SILENCE_SIZE];static void misdn_lib_isdn_event_catcher(void *arg);static int handle_event_nt(void *dat, void *arg);void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder);void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder);struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned long l3id);/* from isdn_lib.h */int init_bc(struct misdn_stack * stack,  struct misdn_bchannel *bc, int midev, int port, int bidx, char *msn, int firsttime);struct misdn_stack* stack_init(int midev,  int port, int ptp);void stack_destroy(struct misdn_stack* stack);	/* user iface */int te_lib_init( void ) ; /* returns midev */void te_lib_destroy(int midev) ;struct misdn_bchannel *manager_find_bc_by_pid(int pid);struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc);void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len);void manager_clean_bc(struct misdn_bchannel *bc );void manager_bchannel_setup (struct misdn_bchannel *bc);void manager_bchannel_cleanup (struct misdn_bchannel *bc);void ec_chunk( struct misdn_bchannel *bc, unsigned char *rxchunk, unsigned char *txchunk, int chunk_size);	/* end */int bchdev_echocancel_activate(struct misdn_bchannel* dev);void bchdev_echocancel_deactivate(struct misdn_bchannel* dev);/* end */static char *bearer2str(int cap) {	static char *bearers[]={		"Speech",		"Audio 3.1k",		"Unres Digital",		"Res Digital",		"Unknown Bearer"	};		switch (cap) {	case INFO_CAPABILITY_SPEECH:		return bearers[0];		break;	case INFO_CAPABILITY_AUDIO_3_1K:		return bearers[1];		break;	case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:		return bearers[2];		break;	case INFO_CAPABILITY_DIGITAL_RESTRICTED:		return bearers[3];		break;	default:		return bearers[4];		break;	}}static char flip_table[256];static void init_flip_bits(void){	int i,k;		for (i = 0 ; i < 256 ; i++) {		unsigned char sample = 0 ;		for (k = 0; k<8; k++) {			if ( i & 1 << k ) sample |= 0x80 >>  k;		}		flip_table[i] = sample;	}}static char * flip_buf_bits ( char * buf , int len){	int i;	char * start = buf;		for (i = 0 ; i < len; i++) {		buf[i] = flip_table[(unsigned char)buf[i]];	}		return start;}static msg_t *create_l2msg(int prim, int dinfo, int size) /* NT only */{	int i = 0;	msg_t *dmsg;  	while(i < 10)	{		dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);		if (dmsg)			return(dmsg);      		if (!i)			printf("cannot allocate memory, trying again...\n");		i++;		usleep(300000);	}	printf("cannot allocate memory, system overloaded.\n");	exit(-1);}msg_t *create_l3msg(int prim, int mt, int dinfo, int size, int ntmode){	int i = 0;	msg_t *dmsg;	Q931_info_t *qi;	iframe_t *frm;  	if (!ntmode)		size = sizeof(Q931_info_t)+2;  	while(i < 10) {		if (ntmode) {			dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);			if (dmsg) {				return(dmsg);			}		} else {			dmsg = alloc_msg(size+256+mISDN_HEADER_LEN+DEFAULT_HEADROOM);			if (dmsg)			{				memset(msg_put(dmsg,size+mISDN_HEADER_LEN), 0, size+mISDN_HEADER_LEN);				frm = (iframe_t *)dmsg->data;				frm->prim = prim;				frm->dinfo = dinfo;				qi = (Q931_info_t *)(dmsg->data + mISDN_HEADER_LEN);				qi->type = mt;				return(dmsg);			}		}    		if (!i) printf("cannot allocate memory, trying again...\n");		i++;		usleep(300000);	}	printf("cannot allocate memory, system overloaded.\n");	exit(-1);}static int send_msg (int midev, struct misdn_bchannel *bc, msg_t *dmsg){	iframe_t *frm;	frm = (iframe_t *)dmsg->data;	struct misdn_stack *stack=get_stack_by_bc(bc);	if (!stack) {		cb_log(0,bc->port,"send_msg: IEK!! no stack\n ");		return -1;	}		frm->addr = (stack->upper_id | FLG_MSG_DOWN);	frm->dinfo = bc->l3_id;	frm->len = (dmsg->len) - mISDN_HEADER_LEN;					cb_log(4,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo);	mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC);	free_msg(dmsg);	return 0;}static int mypid=1;int misdn_cap_is_speech(int cap)/** Poor mans version **/{	if ( (cap != INFO_CAPABILITY_DIGITAL_UNRESTRICTED) &&	     (cap != INFO_CAPABILITY_DIGITAL_RESTRICTED) ) return 1;	return 0;}int misdn_inband_avail(struct misdn_bchannel *bc){	/*if ! early_bconnect we have never inband available*/	if ( ! bc->early_bconnect ) return 0;		switch (bc->progress_indicator) {	case INFO_PI_INBAND_AVAILABLE:	case INFO_PI_CALL_NOT_E2E_ISDN:	case INFO_PI_CALLED_NOT_ISDN:		return 1;	default:		return 0;	}	return 0;}static void dump_chan_list(struct misdn_stack *stack){	int i;	for (i=0; i <= stack->b_num; i++) {		cb_log(6, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1);	}}static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchannel *bc, int channel, int dec){	int i;	cb_log(5,stack->port,"find_free_chan: req_chan:%d\n",channel);	if (channel < 0 || channel > MAX_BCHANS) {		cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);		return 0;	}		channel--;	int bnums=stack->pri?stack->b_num:stack->b_num-1;  	if (dec) {		for (i = bnums; i >=0; i--) {			if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 Dchannel ;) and work with chan preselection */				if (!stack->channels[i]) {					cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);					bc->channel=i+1;					return i+1;				}			}		}	} else {		for (i = 0; i <= bnums; i++) {			if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 Dchannel ;) and work with chan preselection */				if (!stack->channels[i]) {					cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);					bc->channel=i+1;					return i+1;				}			}		}	}	cb_log (1, stack->port, " !! NO FREE CHAN IN STACK\n");	dump_chan_list(stack);  	return 0;}static int empty_chan_in_stack(struct misdn_stack *stack, int channel){	if (channel<=0 || channel>MAX_BCHANS) {		cb_log(0,stack?stack->port:0, "empty_chan_in_stack: cannot empty channel %d\n",channel);		return -1;	}		cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel); 	stack->channels[channel-1] = 0;	dump_chan_list(stack);	return 0;}char *bc_state2str(enum bchannel_state state) {	int i;		struct bchan_state_s {		char *n;		enum bchannel_state s;	} states[] = {		{"BCHAN_CLEANED", BCHAN_CLEANED },		{"BCHAN_EMPTY", BCHAN_EMPTY},		{"BCHAN_SETUP", BCHAN_SETUP},		{"BCHAN_SETUPED", BCHAN_SETUPED},		{"BCHAN_ACTIVE", BCHAN_ACTIVE},		{"BCHAN_ACTIVATED", BCHAN_ACTIVATED},		{"BCHAN_BRIDGE",  BCHAN_BRIDGE},		{"BCHAN_BRIDGED", BCHAN_BRIDGED},		{"BCHAN_RELEASE", BCHAN_RELEASE},		{"BCHAN_RELEASED", BCHAN_RELEASED},		{"BCHAN_CLEAN", BCHAN_CLEAN},		{"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST},		{"BCHAN_ERROR", BCHAN_ERROR}	};		for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++)		if ( states[i].s == state)			return states[i].n;	return "UNKNOWN";}void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state){	cb_log(5,bc->port,"BC_STATE_CHANGE: l3id:%x from:%s to:%s\n",		bc->l3_id,	       bc_state2str(bc->bc_state),	       bc_state2str(state) );		switch (state) {		case BCHAN_ACTIVATED:			if (bc->next_bc_state ==  BCHAN_BRIDGED) {				misdn_join_conf(bc, bc->conf_id);				bc->next_bc_state = BCHAN_EMPTY;				return;			}		default:			bc->bc_state=state;			break;	}}static void bc_next_state_change(struct misdn_bchannel *bc, enum bchannel_state state){	cb_log(5,bc->port,"BC_NEXT_STATE_CHANGE: from:%s to:%s\n",	       bc_state2str(bc->next_bc_state),	       bc_state2str(state) );	bc->next_bc_state=state;}static void empty_bc(struct misdn_bchannel *bc){	bc->bframe_len=0;		bc->in_use= 0;	bc->cw= 0;	bc->dec=0;	bc->channel = 0;	bc->sending_complete = 0;	bc->restart_channel=0;		bc->conf_id = 0;	bc->need_more_infos = 0;		bc->send_dtmf=0;	bc->nodsp=0;	bc->nojitter=0;	bc->time_usec=0;		bc->rxgain=0;	bc->txgain=0;	bc->crypt=0;	bc->curptx=0; bc->curprx=0;		bc->crypt_key[0] = 0;		bc->generate_tone=0;	bc->tone_cnt=0;  	bc->dnumplan=NUMPLAN_UNKNOWN;	bc->onumplan=NUMPLAN_UNKNOWN;	bc->rnumplan=NUMPLAN_UNKNOWN;	bc->cpnnumplan=NUMPLAN_UNKNOWN;		bc->active = 0;	bc->early_bconnect = 1;

⌨️ 快捷键说明

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