isdn_lib.c

来自「asterisk 是一个很有知名度开源软件」· C语言 代码 · 共 2,934 行 · 第 1/5 页

C
2,934
字号
		{"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->dummy=0;	bc->bframe_len=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;	#ifdef MISDN_1_2	*bc->pipeline = 0;#else	bc->ec_enable = 0;	bc->ec_deftaps = 128;#endif	bc->AOCD_need_export = 0;	bc->orig=0;  	bc->cause=16;	bc->out_cause=16;	bc->pres=0 ; /* screened */		bc->evq=EVENT_NOTHING;	bc->progress_coding=0;	bc->progress_location=0;	bc->progress_indicator=0;	/** Set Default Bearer Caps **/	bc->capability=INFO_CAPABILITY_SPEECH;	bc->law=INFO_CODEC_ALAW;	bc->mode=0;	bc->rate=0x10;	bc->user1=0;	bc->urate=0;		bc->hdlc=0;			bc->info_dad[0] = 0;	bc->display[0] = 0;	bc->infos_pending[0] = 0;	bc->cad[0] = 0;	bc->oad[0] = 0;	bc->dad[0] = 0;	bc->rad[0] = 0;	bc->orig_dad[0] = 0;	bc->uu[0]=0;	bc->uulen=0;		bc->fac_in.Function = Fac_None;	bc->fac_out.Function = Fac_None;		bc->te_choose_channel = 0;	bc->channel_found= 0;	gettimeofday(&bc->last_used, NULL);}static int clean_up_bc(struct misdn_bchannel *bc){	int ret=0;	unsigned char buff[32];	struct misdn_stack * stack;	cb_log(3, bc?bc->port:0, "$$$ CLEANUP CALLED pid:%d\n", bc?bc->pid:-1);		if (!bc  ) return -1;	stack=get_stack_by_bc(bc);		if (!stack) return -1;		switch (bc->bc_state ) {	case BCHAN_CLEANED:		cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid);		return -1;			default:		break;	}		cb_log(2, stack->port, "$$$ Cleaning up bc with stid :%x pid:%d\n", bc->b_stid, bc->pid);		manager_ec_disable(bc);	manager_bchannel_deactivate(bc);	mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_TARGET|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);		bc->b_stid = 0;	bc_state_change(bc, BCHAN_CLEANED);		return ret;}static void clear_l3(struct misdn_stack *stack){	int i;	for (i=0; i<=stack->b_num; i++) {		if (global_state == MISDN_INITIALIZED)  {			cb_event(EVENT_CLEANUP, &stack->bc[i], NULL); 			empty_chan_in_stack(stack,i+1);			empty_bc(&stack->bc[i]);			clean_up_bc(&stack->bc[i]);			stack->bc[i].in_use = 0;		}			} }static int new_te_id = 0;#define MAXPROCS 0x100static int misdn_lib_get_l1_down(struct misdn_stack *stack){	/* Pull Up L1 */ 	iframe_t act;	act.prim = PH_DEACTIVATE | REQUEST; 	act.addr = stack->lower_id|FLG_MSG_DOWN;	act.dinfo = 0;	act.len = 0;	cb_log(1, stack->port, "SENDING PH_DEACTIVATE | REQ\n");	return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);}static int misdn_lib_get_l2_down(struct misdn_stack *stack){		if (stack->ptp && (stack->nt) ) {		msg_t *dmsg;		/* L2 */		dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);				if (stack->nst.manager_l3(&stack->nst, dmsg))			free_msg(dmsg);			} else {		iframe_t act;				act.prim = DL_RELEASE| REQUEST;		act.addr = (stack->upper_id |FLG_MSG_DOWN)  ;				act.dinfo = 0;		act.len = 0;		return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);	}		return 0;}static int misdn_lib_get_l1_up(struct misdn_stack *stack){	/* Pull Up L1 */ 	iframe_t act;	act.prim = PH_ACTIVATE | REQUEST; 	act.addr = (stack->upper_id | FLG_MSG_DOWN)  ;		act.dinfo = 0;	act.len = 0;	return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);}int misdn_lib_get_l2_up(struct misdn_stack *stack){		if (stack->ptp && (stack->nt) ) {		msg_t *dmsg;		/* L2 */		dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);				if (stack->nst.manager_l3(&stack->nst, dmsg))			free_msg(dmsg);			} else {		iframe_t act;				act.prim = DL_ESTABLISH | REQUEST;		act.addr = (stack->upper_id |FLG_MSG_DOWN)  ;				act.dinfo = 0;		act.len = 0;		return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);	}		return 0;}#if 0static int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack){	iframe_t act;			act.prim = DL_ESTABLISH | REQUEST;	act.addr = (stack->upper_id  & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;			act.dinfo = 0;	act.len = 0;	return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);	return 0;}#endifstatic int misdn_lib_get_short_status(struct misdn_stack *stack){	iframe_t act;			act.prim = MGR_SHORTSTATUS | REQUEST; 		act.addr = (stack->upper_id | MSG_BROADCAST)  ;	act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;		act.len = 0;	return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);}static int create_process(int midev, struct misdn_bchannel *bc){	iframe_t ncr;	int l3_id;	int proc_id;	struct misdn_stack *stack;	stack = get_stack_by_bc(bc);	if (stack->nt) {		if (find_free_chan_in_stack(stack, bc, bc->channel_preselected ? bc->channel : 0, 0) < 0) {			return -1;		}		cb_log(4, stack->port, " -->  found channel: %d\n", bc->channel);		for (proc_id = 0; proc_id < MAXPROCS; ++proc_id) {			if (stack->procids[proc_id] == 0) {				break;			}		}	/* end for */		if (proc_id == MAXPROCS) {			cb_log(0, stack->port, "Couldnt Create New ProcId.\n");			return -1;		}		stack->procids[proc_id] = 1;		l3_id = 0xff00 | proc_id;		bc->l3_id = l3_id;		cb_log(3, stack->port, " --> new_l3id %x\n", l3_id);	} else {		if (stack->ptp || bc->te_choose_channel) {			/* we know exactly which channels are in use */			if (find_free_chan_in_stack(stack, bc, bc->channel_preselected ? bc->channel : 0, bc->dec) < 0) {				return -1;			}			cb_log(2, stack->port, " -->  found channel: %d\n", bc->channel);		} else {			/* other phones could have made a call also on this port (ptmp) */			bc->channel = 0xff;		}		/* if we are in te-mode, we need to create a process first */		if (++new_te_id > 0xffff) {			new_te_id = 0x0001;		}		l3_id = (entity << 16) | new_te_id;		bc->l3_id = l3_id;		cb_log(3, stack->port, "--> new_l3id %x\n", l3_id);		/* send message */		ncr.prim = CC_NEW_CR | REQUEST;		ncr.addr = (stack->upper_id | FLG_MSG_DOWN);		ncr.dinfo = l3_id;		ncr.len = 0;		mISDN_write(midev, &ncr, mISDN_HEADER_LEN + ncr.len, TIMEOUT_1SEC);	}	return l3_id;}void misdn_lib_setup_bc(struct misdn_bchannel *bc){	clean_up_bc(bc);	setup_bc(bc);}int setup_bc(struct misdn_bchannel *bc){	unsigned char buff[1025];	int midev, channel, b_stid, i;	mISDN_pid_t pid;	int ret;	struct misdn_stack *stack=get_stack_by_bc(bc);	if (!stack) {		cb_log(0, bc->port, "setup_bc: NO STACK FOUND!!\n");		return -1;	}		midev = stack->midev;	channel = bc->channel - 1 - (bc->channel > 16);	b_stid = stack->b_stids[channel >= 0 ? channel : 0];	switch (bc->bc_state) {		case BCHAN_CLEANED:			break;		default:			cb_log(4, stack->port, "$$$ bc already upsetted stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) );			return -1;	}		cb_log(5, stack->port, "$$$ Setting up bc with stid :%x\n", b_stid);		/*check if the b_stid is alread initialized*/	for (i=0; i <= stack->b_num; i++) {		if (stack->bc[i].b_stid == b_stid) {			cb_log(0, bc->port, "setup_bc: b_stid:%x already in use !!!\n", b_stid);			return -1;		}	}		if (b_stid <= 0) {		cb_log(0, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel);				bc_state_change(bc,BCHAN_ERROR);		return 1;	}	bc->b_stid = b_stid;	{		layer_info_t li;		memset(&li, 0, sizeof(li));    		li.object_id = -1;		li.extentions = 0;				li.st = bc->b_stid; /*  given idx */#define MISDN_DSP#ifndef MISDN_DSP		bc->nodsp=1;#endif		if ( bc->hdlc || bc->nodsp) {			cb_log(4, stack->port,"setup_bc: without dsp\n");			{ 				int l = sizeof(li.name);				strncpy(li.name, "B L3", l);				li.name[l-1] = 0;			}			li.pid.layermask = ISDN_LAYER((3));			li.pid.protocol[3] = ISDN_PID_L3_B_USER;						bc->layer=3;		} else {			cb_log(4, stack->port,"setup_bc: with dsp\n");			{ 				int l = sizeof(li.name);				strncpy(li.name, "B L4", l);				li.name[l-1] = 0;			}			li.pid.layermask = ISDN_LAYER((4));			li.pid.protocol[4] = ISDN_PID_L4_B_USER;			bc->layer=4;					}  				ret = mISDN_new_layer(midev, &li);		if (ret ) {			cb_log(0, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno));			bc_state_change(bc,BCHAN_ERROR);			return(-EINVAL);		}				bc->layer_id = li.id;	}		memset(&pid, 0, sizeof(pid));				cb_log(4, stack->port," --> Channel is %d\n", bc->channel);		if (bc->nodsp) {		cb_log(2, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n");		pid.protocol[1] = ISDN_PID_L1_B_64TRANS;		pid.protocol[2] = ISDN_PID_L2_B_TRANS;		pid.protocol[3] = ISDN_PID_L3_B_USER;		pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3));			} else if ( bc->hdlc ) {		cb_log(2, stack->port," --> HDLC Mode\n");		pid.protocol[1] = ISDN_PID_L1_B_64HDLC ;		pid.protocol[2] = ISDN_PID_L2_B_TRANS  ;		pid.protocol[3] = ISDN_PID_L3_B_USER;		pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) ;	} else {		cb_log(2, stack->port," --> TRANSPARENT Mode\n");		pid.protocol[1] = ISDN_PID_L1_B_64TRANS;		pid.protocol[2] = ISDN_PID_L2_B_TRANS;		pid.protocol[3] = ISDN_PID_L3_B_DSP;		pid.protocol[4] = ISDN_PID_L4_B_USER;		pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));			} 	ret = mISDN_set_stack(midev, bc->b_stid, &pid);	if (ret){		cb_log(0, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno));				mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);				bc_state_change(bc,BCHAN_ERROR);		cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);		return(-EINVAL);	}	ret = mISDN_get_setstack_ind(midev, bc->layer_id);	if (ret) {		cb_log(0, stack->port,"$$$ Set StackIND Err: %d %s\n",ret,strerror(errno));		mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);				bc_state_change(bc,BCHAN_ERROR);		cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);		return(-EINVAL);	}	ret = mISDN_get_layerid(midev, bc->b_stid, bc->layer) ;	bc->addr = ret>0? ret : 0;	if (!bc->addr) {		cb_log(0, stack->port,"$$$ Get Layerid Err: %d %s\n",ret,strerror(errno));		mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);				bc_state_change(bc,BCHAN_ERROR);		cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);		return (-EINVAL);	}	manager_bchannel_activate(bc);		bc_state_change(bc,BCHAN_ACTIVATED);	return 0;}/** IFACE **/int init_bc(struct misdn_stack *stack,  struct misdn_bchannel *bc, int midev, int port, int bidx,  char *msn, int firsttime){	unsigned char buff[1025] = "";	iframe_t *frm = (iframe_t *)buff;	int ret;  	if (!bc) return -1;  	cb_log(8, port, "Init.BC %d.\n",bidx);		memset(bc, 0,sizeof(struct misdn_bchannel));	bc->send_lock=malloc(sizeof(struct send_lock));	pthread_mutex_init(&bc->send_lock->lock, NULL);		if (msn) {		int l = sizeof(bc->msn);		strncpy(bc->msn,msn, l);		bc->msn[l-1] = 0;	}			empty_bc(bc);	bc_state_change(bc, BCHAN_CLEANED);		bc->port=stack->port;	bc->nt=stack->nt?1:0;	bc->pri=stack->pri;		{		ibuffer_t* ibuf= init_ibuffer(MISDN_IBUF_SIZE);		if (!ibuf) return -1;				clear_ibuffer( ibuf);				ibuf->rsem=malloc(sizeof(sem_t));

⌨️ 快捷键说明

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