📄 isdn_lib.c
字号:
#ifdef MISDN_1_2 *bc->pipeline = 0;#else bc->ec_enable = 0; bc->ec_deftaps = 128;#endif 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;}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]); } } }static int set_chan_in_stack(struct misdn_stack *stack, int channel){ cb_log(4,stack->port,"set_chan_in_stack: %d\n",channel); dump_chan_list(stack); if (channel >=1 && channel <= MAX_BCHANS) { if (!stack->channels[channel-1]) stack->channels[channel-1] = 1; else { cb_log(4,stack->port,"channel already in use:%d\n", channel ); return -1; } } else { cb_log(0,stack->port,"couldn't set channel %d in\n", channel ); return -1; } return 0;}#if 0static int chan_in_stack_free(struct misdn_stack *stack, int channel){ if (stack->channels[channel-1]) return 0; return 1;}#endifstatic int newteid=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->upper_id | FLG_MSG_DOWN) ; act.dinfo = 0; act.len = 0; 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 i; struct misdn_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)) return -1; /*bc->channel=free_chan;*/ if (set_chan_in_stack(stack ,bc->channel)<0) return -1; cb_log(4,stack->port, " --> found channel: %d\n", bc->channel); for (i=0; i <= MAXPROCS; i++) if (stack->procids[i]==0) break; if (i== MAXPROCS) { cb_log(0, stack->port, "Couldnt Create New ProcId.\n"); return -1; } stack->procids[i]=1; l3_id = 0xff00 | i; ncr.prim = CC_NEW_CR | REQUEST; ncr.addr = (stack->upper_id | FLG_MSG_DOWN) ; ncr.dinfo = l3_id; ncr.len = 0; 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, 0)) return -1; /*bc->channel=free_chan;*/ cb_log(2,stack->port, " --> found channel: %d\n", bc->channel); if (set_chan_in_stack(stack ,bc->channel)<0) return -1; } 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 (newteid++ > 0xffff) newteid = 0x0001; l3_id = (entity<<16) | newteid; /* preparing message */ ncr.prim = CC_NEW_CR | REQUEST; ncr.addr = (stack->upper_id | FLG_MSG_DOWN) ; ncr.dinfo =l3_id; ncr.len = 0; /* send message */ bc->l3_id = l3_id; cb_log(3, stack->port, "--> new_l3id %x\n",l3_id); 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]; 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; } int midev=stack->midev; int channel=bc->channel-1-(bc->channel>16); int 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); 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)); 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; { ibuffer_t* ibuf= init_ibuffer(MISDN_IBUF_SIZE); if (!ibuf) return -1; clear_ibuffer( ibuf); ibuf->rsem=malloc(sizeof(sem_t)); bc->astbuf=ibuf; if (sem_init(ibuf->rsem,1,0)<0) sem_init(ibuf->rsem,0,0); } { stack_info_t *stinf; ret = mISDN_get_stack_info(midev, stack->port, buff, sizeof(buff)); if (ret < 0) { cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret); return -1; } stinf = (stack_info_t *)&frm->data.p; cb_log(8, port, " --> Child %x\n",stinf->child[bidx]); } return 0;}struct misdn_stack* stack_init( int midev, int port, int ptp ){ int ret; unsigned char buff[1025]; iframe_t *frm = (iframe_t *)buff; stack_info_t *stinf; int i; layer_info_t li; struct misdn_stack *stack = malloc(sizeof(struct misdn_stack)); if (!stack ) return NULL; cb_log(8, port, "Init. Stack.\n"); memset(stack,0,sizeof(struct misdn_stack)); for (i=0; i<MAX_BCHANS + 1; i++ ) stack->channels[i]=0; stack->port=port; stack->midev=midev; stack->ptp=ptp; stack->holding=NULL; stack->pri=0; msg_queue_init(&stack->downqueue); msg_queue_init(&stack->upqueue); /* query port's requirements */ ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff)); if (ret < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -