00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <syslog.h>
00022 #include <sys/time.h>
00023 #include <mISDNuser/isdn_debug.h>
00024
00025 #include "isdn_lib_intern.h"
00026 #include "isdn_lib.h"
00027
00028
00029
00030
00031
00032 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
00033
00034 #include "asterisk/causes.h"
00035
00036 void misdn_join_conf(struct misdn_bchannel *bc, int conf_id);
00037 void misdn_split_conf(struct misdn_bchannel *bc, int conf_id);
00038
00039 int queue_cleanup_bc(struct misdn_bchannel *bc) ;
00040
00041 int misdn_lib_get_l2_up(struct misdn_stack *stack);
00042
00043 struct misdn_stack* get_misdn_stack( void );
00044
00045 int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh);
00046
00047 int misdn_lib_port_is_pri(int port)
00048 {
00049 struct misdn_stack *stack=get_misdn_stack();
00050 for ( ; stack; stack=stack->next) {
00051 if (stack->port == port) {
00052 return stack->pri;
00053 }
00054 }
00055
00056 return -1;
00057 }
00058
00059 int misdn_lib_port_is_nt(int port)
00060 {
00061 struct misdn_stack *stack=get_misdn_stack();
00062 for ( ; stack; stack=stack->next) {
00063 if (stack->port == port) {
00064 return stack->nt;
00065 }
00066 }
00067
00068 return -1;
00069 }
00070
00071 void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel)
00072 {
00073 memset (dummybc,0,sizeof(struct misdn_bchannel));
00074 dummybc->port=port;
00075 if (l3id==0)
00076 dummybc->l3_id = MISDN_ID_DUMMY;
00077 else
00078 dummybc->l3_id=l3id;
00079
00080 dummybc->nt=nt;
00081 dummybc->dummy=1;
00082 dummybc->channel=channel;
00083 }
00084
00085 int misdn_lib_port_block(int port)
00086 {
00087 struct misdn_stack *stack=get_misdn_stack();
00088 for ( ; stack; stack=stack->next) {
00089 if (stack->port == port) {
00090 stack->blocked=1;
00091 return 0;
00092 }
00093 }
00094 return -1;
00095
00096 }
00097
00098 int misdn_lib_port_unblock(int port)
00099 {
00100 struct misdn_stack *stack=get_misdn_stack();
00101 for ( ; stack; stack=stack->next) {
00102 if (stack->port == port) {
00103 stack->blocked=0;
00104 return 0;
00105 }
00106 }
00107 return -1;
00108
00109 }
00110
00111 int misdn_lib_is_port_blocked(int port)
00112 {
00113 struct misdn_stack *stack=get_misdn_stack();
00114 for ( ; stack; stack=stack->next) {
00115 if (stack->port == port) {
00116 return stack->blocked;
00117 }
00118 }
00119 return -1;
00120 }
00121
00122 int misdn_lib_is_ptp(int port)
00123 {
00124 struct misdn_stack *stack=get_misdn_stack();
00125 for ( ; stack; stack=stack->next) {
00126 if (stack->port == port) return stack->ptp;
00127 }
00128 return -1;
00129 }
00130
00131 int misdn_lib_get_maxchans(int port)
00132 {
00133 struct misdn_stack *stack=get_misdn_stack();
00134 for ( ; stack; stack=stack->next) {
00135 if (stack->port == port) {
00136 if (stack->pri)
00137 return 30;
00138 else
00139 return 2;
00140 }
00141 }
00142 return -1;
00143 }
00144
00145
00146 struct misdn_stack *get_stack_by_bc(struct misdn_bchannel *bc)
00147 {
00148 struct misdn_stack *stack = get_misdn_stack();
00149
00150 if (!bc)
00151 return NULL;
00152
00153 for ( ; stack; stack = stack->next) {
00154 if (bc->port == stack->port)
00155 return stack;
00156 }
00157
00158 return NULL;
00159 }
00160
00161
00162 void get_show_stack_details(int port, char *buf)
00163 {
00164 struct misdn_stack *stack=get_misdn_stack();
00165
00166 for ( ; stack; stack=stack->next) {
00167 if (stack->port == port) break;
00168 }
00169
00170 if (stack) {
00171 sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
00172 stack->port, stack->nt ? "NT" : "TE", stack->ptp ? "PTP" : "PMP",
00173 stack->l2link ? "UP" : "DOWN", stack->l1link ? "UP" : "DOWN",
00174 stack->blocked);
00175 } else {
00176 buf[0]=0;
00177 }
00178 }
00179
00180
00181 static int nt_err_cnt =0 ;
00182
00183 enum global_states {
00184 MISDN_INITIALIZING,
00185 MISDN_INITIALIZED
00186 } ;
00187
00188 static enum global_states global_state=MISDN_INITIALIZING;
00189
00190
00191 #include <mISDNuser/net_l2.h>
00192 #include <mISDNuser/tone.h>
00193 #include <unistd.h>
00194 #include <semaphore.h>
00195 #include <pthread.h>
00196 #include <signal.h>
00197
00198 #include "isdn_lib.h"
00199
00200
00201 struct misdn_lib {
00202
00203 int midev;
00204 int midev_nt;
00205
00206 pthread_t event_thread;
00207 pthread_t event_handler_thread;
00208
00209 void *user_data;
00210
00211 msg_queue_t upqueue;
00212 msg_queue_t activatequeue;
00213
00214 sem_t new_msg;
00215
00216 struct misdn_stack *stack_list;
00217 } ;
00218
00219 #ifndef ECHOCAN_ON
00220 #define ECHOCAN_ON 123
00221 #define ECHOCAN_OFF 124
00222 #endif
00223
00224 #define MISDN_DEBUG 0
00225
00226 void misdn_tx_jitter(struct misdn_bchannel *bc, int len);
00227
00228 struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id);
00229
00230 int setup_bc(struct misdn_bchannel *bc);
00231
00232 int manager_isdn_handler(iframe_t *frm ,msg_t *msg);
00233
00234 int misdn_lib_port_restart(int port);
00235 int misdn_lib_pid_restart(int pid);
00236
00237 extern struct isdn_msg msgs_g[];
00238
00239 #define ISDN_PID_L3_B_USER 0x430000ff
00240 #define ISDN_PID_L4_B_USER 0x440000ff
00241
00242
00243 #define MISDN_IBUF_SIZE 512
00244
00245
00246 #define TONE_ALERT_CNT 41
00247 #define TONE_ALERT_SILENCE_CNT 200
00248
00249 #define TONE_BUSY_CNT 20
00250 #define TONE_BUSY_SILENCE_CNT 48
00251
00252 static int entity;
00253
00254 static struct misdn_lib *glob_mgr;
00255
00256 char tone_425_flip[TONE_425_SIZE];
00257 char tone_silence_flip[TONE_SILENCE_SIZE];
00258
00259 static void misdn_lib_isdn_event_catcher(void *arg);
00260 static int handle_event_nt(void *dat, void *arg);
00261
00262
00263 void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder);
00264 void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder);
00265 struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned long l3id);
00266
00267
00268
00269 int te_lib_init( void ) ;
00270 void te_lib_destroy(int midev) ;
00271 struct misdn_bchannel *manager_find_bc_by_pid(int pid);
00272 void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len);
00273 void manager_clean_bc(struct misdn_bchannel *bc );
00274 void manager_bchannel_setup (struct misdn_bchannel *bc);
00275 void manager_bchannel_cleanup (struct misdn_bchannel *bc);
00276
00277 void ec_chunk( struct misdn_bchannel *bc, unsigned char *rxchunk, unsigned char *txchunk, int chunk_size);
00278
00279 int bchdev_echocancel_activate(struct misdn_bchannel* dev);
00280 void bchdev_echocancel_deactivate(struct misdn_bchannel* dev);
00281
00282
00283
00284 static char *bearer2str(int cap) {
00285 static char *bearers[]={
00286 "Speech",
00287 "Audio 3.1k",
00288 "Unres Digital",
00289 "Res Digital",
00290 "Unknown Bearer"
00291 };
00292
00293 switch (cap) {
00294 case INFO_CAPABILITY_SPEECH:
00295 return bearers[0];
00296 break;
00297 case INFO_CAPABILITY_AUDIO_3_1K:
00298 return bearers[1];
00299 break;
00300 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00301 return bearers[2];
00302 break;
00303 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00304 return bearers[3];
00305 break;
00306 default:
00307 return bearers[4];
00308 break;
00309 }
00310 }
00311
00312
00313 static char flip_table[256];
00314
00315 static void init_flip_bits(void)
00316 {
00317 int i,k;
00318
00319 for (i = 0 ; i < 256 ; i++) {
00320 unsigned char sample = 0 ;
00321 for (k = 0; k<8; k++) {
00322 if ( i & 1 << k ) sample |= 0x80 >> k;
00323 }
00324 flip_table[i] = sample;
00325 }
00326 }
00327
00328 static char * flip_buf_bits ( char * buf , int len)
00329 {
00330 int i;
00331 char * start = buf;
00332
00333 for (i = 0 ; i < len; i++) {
00334 buf[i] = flip_table[(unsigned char)buf[i]];
00335 }
00336
00337 return start;
00338 }
00339
00340
00341
00342
00343 static msg_t *create_l2msg(int prim, int dinfo, int size)
00344 {
00345 int i = 0;
00346 msg_t *dmsg;
00347
00348 while(i < 10)
00349 {
00350 dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
00351 if (dmsg)
00352 return(dmsg);
00353
00354 if (!i)
00355 printf("cannot allocate memory, trying again...\n");
00356 i++;
00357 usleep(300000);
00358 }
00359 printf("cannot allocate memory, system overloaded.\n");
00360 exit(-1);
00361 }
00362
00363
00364
00365 msg_t *create_l3msg(int prim, int mt, int dinfo, int size, int ntmode)
00366 {
00367 int i = 0;
00368 msg_t *dmsg;
00369 Q931_info_t *qi;
00370 iframe_t *frm;
00371
00372 if (!ntmode)
00373 size = sizeof(Q931_info_t)+2;
00374
00375 while(i < 10) {
00376 if (ntmode) {
00377 dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
00378 if (dmsg) {
00379 return(dmsg);
00380 }
00381 } else {
00382 dmsg = alloc_msg(size+256+mISDN_HEADER_LEN+DEFAULT_HEADROOM);
00383 if (dmsg)
00384 {
00385 memset(msg_put(dmsg,size+mISDN_HEADER_LEN), 0, size+mISDN_HEADER_LEN);
00386 frm = (iframe_t *)dmsg->data;
00387 frm->prim = prim;
00388 frm->dinfo = dinfo;
00389 qi = (Q931_info_t *)(dmsg->data + mISDN_HEADER_LEN);
00390 qi->type = mt;
00391 return(dmsg);
00392 }
00393 }
00394
00395 if (!i) printf("cannot allocate memory, trying again...\n");
00396 i++;
00397 usleep(300000);
00398 }
00399 printf("cannot allocate memory, system overloaded.\n");
00400 exit(-1);
00401 }
00402
00403
00404 static int send_msg (int midev, struct misdn_bchannel *bc, msg_t *dmsg)
00405 {
00406 iframe_t *frm = (iframe_t *)dmsg->data;
00407 struct misdn_stack *stack=get_stack_by_bc(bc);
00408
00409 if (!stack) {
00410 cb_log(0,bc->port,"send_msg: IEK!! no stack\n ");
00411 return -1;
00412 }
00413
00414 frm->addr = (stack->upper_id | FLG_MSG_DOWN);
00415 frm->dinfo = bc->l3_id;
00416 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
00417
00418 cb_log(4,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo);
00419
00420 mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC);
00421 free_msg(dmsg);
00422
00423 return 0;
00424 }
00425
00426
00427 static int mypid=1;
00428
00429
00430 int misdn_cap_is_speech(int cap)
00431
00432 {
00433 if ( (cap != INFO_CAPABILITY_DIGITAL_UNRESTRICTED) &&
00434 (cap != INFO_CAPABILITY_DIGITAL_RESTRICTED) ) return 1;
00435 return 0;
00436 }
00437
00438 int misdn_inband_avail(struct misdn_bchannel *bc)
00439 {
00440
00441 if (!bc->early_bconnect) {
00442
00443 return 0;
00444 }
00445
00446 switch (bc->progress_indicator) {
00447 case INFO_PI_INBAND_AVAILABLE:
00448 case INFO_PI_CALL_NOT_E2E_ISDN:
00449 case INFO_PI_CALLED_NOT_ISDN:
00450 return 1;
00451 default:
00452 return 0;
00453 }
00454 return 0;
00455 }
00456
00457
00458 static void dump_chan_list(struct misdn_stack *stack)
00459 {
00460 int i;
00461
00462 for (i=0; i <= stack->b_num; i++) {
00463 cb_log(6, stack->port, "Idx:%d stack->cchan:%d in_use:%d Chan:%d\n",i,stack->channels[i], stack->bc[i].in_use, i+1);
00464 }
00465 }
00466
00467
00468 void misdn_dump_chanlist()
00469 {
00470 struct misdn_stack *stack=get_misdn_stack();
00471 for ( ; stack; stack=stack->next) {
00472 dump_chan_list(stack);
00473 }
00474
00475 }
00476
00477 static int set_chan_in_stack(struct misdn_stack *stack, int channel)
00478 {
00479
00480 cb_log(4,stack->port,"set_chan_in_stack: %d\n",channel);
00481 dump_chan_list(stack);
00482 if (channel >=1 && channel <= MAX_BCHANS) {
00483 if (!stack->channels[channel-1])
00484 stack->channels[channel-1] = 1;
00485 else {
00486 cb_log(4,stack->port,"channel already in use:%d\n", channel );
00487 return -1;
00488 }
00489 } else {
00490 cb_log(0,stack->port,"couldn't set channel %d in\n", channel );
00491 return -1;
00492 }
00493
00494 return 0;
00495 }
00496
00497
00498
00499 static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchannel *bc, int channel, int dec)
00500 {
00501 int i;
00502 int chan=0;
00503 int bnums = stack->pri ? stack->b_num : stack->b_num - 1;
00504
00505 if (bc->channel_found)
00506 return 0;
00507
00508 bc->channel_found=1;
00509
00510 cb_log(5,stack->port,"find_free_chan: req_chan:%d\n",channel);
00511
00512 if (channel < 0 || channel > MAX_BCHANS) {
00513 cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
00514 return 0;
00515 }
00516
00517 channel--;
00518
00519 pthread_mutex_lock(&stack->st_lock);
00520 if (dec) {
00521 for (i = bnums; i >=0; i--) {
00522 if (i != 15 && (channel < 0 || i == channel)) {
00523 if (!stack->channels[i]) {
00524 cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
00525 chan=i+1;
00526 break;
00527 }
00528 }
00529 }
00530 } else {
00531 for (i = 0; i <= bnums; i++) {
00532 if (i != 15 && (channel < 0 || i == channel)) {
00533 if (!stack->channels[i]) {
00534 cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
00535 chan=i+1;
00536 break;
00537 }
00538 }
00539 }
00540 }
00541
00542 if (!chan) {
00543 pthread_mutex_unlock(&stack->st_lock);
00544 cb_log (1, stack->port, " !! NO FREE CHAN IN STACK\n");
00545 dump_chan_list(stack);
00546 bc->out_cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
00547 return -1;
00548 }
00549
00550 if (set_chan_in_stack(stack, chan)<0) {
00551 pthread_mutex_unlock(&stack->st_lock);
00552 cb_log (0, stack->port, "Channel Already in use:%d\n", chan);
00553 bc->out_cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
00554 return -1;
00555 }
00556 pthread_mutex_unlock(&stack->st_lock);
00557
00558 bc->channel=chan;
00559 return 0;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 static int empty_chan_in_stack(struct misdn_stack *stack, int channel)
00577 {
00578 if (channel<=0 || channel>MAX_BCHANS) {
00579 cb_log(0,stack?stack->port:0, "empty_chan_in_stack: cannot empty channel %d\n",channel);
00580 return -1;
00581 }
00582
00583 cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel);
00584 stack->channels[channel-1] = 0;
00585 dump_chan_list(stack);
00586 return 0;
00587 }
00588
00589 char *bc_state2str(enum bchannel_state state) {
00590 int i;
00591
00592 struct bchan_state_s {
00593 char *n;
00594 enum bchannel_state s;
00595 } states[] = {
00596 {"BCHAN_CLEANED", BCHAN_CLEANED },
00597 {"BCHAN_EMPTY", BCHAN_EMPTY},
00598 {"BCHAN_SETUP", BCHAN_SETUP},
00599 {"BCHAN_SETUPED", BCHAN_SETUPED},
00600 {"BCHAN_ACTIVE", BCHAN_ACTIVE},
00601 {"BCHAN_ACTIVATED", BCHAN_ACTIVATED},
00602 {"BCHAN_BRIDGE", BCHAN_BRIDGE},
00603 {"BCHAN_BRIDGED", BCHAN_BRIDGED},
00604 {"BCHAN_RELEASE", BCHAN_RELEASE},
00605 {"BCHAN_RELEASED", BCHAN_RELEASED},
00606 {"BCHAN_CLEAN", BCHAN_CLEAN},
00607 {"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST},
00608 {"BCHAN_ERROR", BCHAN_ERROR}
00609 };
00610
00611 for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++)
00612 if ( states[i].s == state)
00613 return states[i].n;
00614
00615 return "UNKNOWN";
00616 }
00617
00618 void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state)
00619 {
00620 cb_log(5,bc->port,"BC_STATE_CHANGE: l3id:%x from:%s to:%s\n",
00621 bc->l3_id,
00622 bc_state2str(bc->bc_state),
00623 bc_state2str(state) );
00624
00625 switch (state) {
00626 case BCHAN_ACTIVATED:
00627 if (bc->next_bc_state == BCHAN_BRIDGED) {
00628 misdn_join_conf(bc, bc->conf_id);
00629 bc->next_bc_state = BCHAN_EMPTY;
00630 return;
00631 }
00632 default:
00633 bc->bc_state=state;
00634 break;
00635 }
00636 }
00637
00638 static void bc_next_state_change(struct misdn_bchannel *bc, enum bchannel_state state)
00639 {
00640 cb_log(5,bc->port,"BC_NEXT_STATE_CHANGE: from:%s to:%s\n",
00641 bc_state2str(bc->next_bc_state),
00642 bc_state2str(state) );
00643
00644 bc->next_bc_state=state;
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 static void empty_bc(struct misdn_bchannel *bc)
00659 {
00660 bc->dummy=0;
00661
00662 bc->bframe_len=0;
00663
00664 bc->cw= 0;
00665
00666 bc->dec=0;
00667 bc->channel = 0;
00668
00669 bc->sending_complete = 0;
00670
00671 bc->restart_channel=0;
00672
00673 bc->conf_id = 0;
00674
00675 bc->need_more_infos = 0;
00676
00677 bc->send_dtmf=0;
00678 bc->nodsp=0;
00679 bc->nojitter=0;
00680
00681 bc->time_usec=0;
00682
00683 bc->rxgain=0;
00684 bc->txgain=0;
00685
00686 bc->crypt=0;
00687 bc->curptx=0; bc->curprx=0;
00688
00689 bc->crypt_key[0] = 0;
00690
00691 bc->generate_tone=0;
00692 bc->tone_cnt=0;
00693
00694 bc->dnumplan=NUMPLAN_UNKNOWN;
00695 bc->onumplan=NUMPLAN_UNKNOWN;
00696 bc->rnumplan=NUMPLAN_UNKNOWN;
00697 bc->cpnnumplan=NUMPLAN_UNKNOWN;
00698
00699
00700 bc->active = 0;
00701
00702 bc->early_bconnect = 1;
00703
00704 #ifdef MISDN_1_2
00705 *bc->pipeline = 0;
00706 #else
00707 bc->ec_enable = 0;
00708 bc->ec_deftaps = 128;
00709 #endif
00710
00711 bc->AOCD_need_export = 0;
00712
00713 bc->orig=0;
00714
00715 bc->cause = AST_CAUSE_NORMAL_CLEARING;
00716 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
00717 bc->pres = 0;
00718
00719 bc->evq=EVENT_NOTHING;
00720
00721 bc->progress_coding=0;
00722 bc->progress_location=0;
00723 bc->progress_indicator=0;
00724
00725
00726 bc->capability=INFO_CAPABILITY_SPEECH;
00727 bc->law=INFO_CODEC_ALAW;
00728 bc->mode=0;
00729 bc->rate=0x10;
00730 bc->user1=0;
00731 bc->urate=0;
00732
00733 bc->hdlc=0;
00734
00735
00736 bc->info_dad[0] = 0;
00737 bc->display[0] = 0;
00738 bc->infos_pending[0] = 0;
00739 bc->cad[0] = 0;
00740 bc->oad[0] = 0;
00741 bc->dad[0] = 0;
00742 bc->rad[0] = 0;
00743 bc->orig_dad[0] = 0;
00744 bc->uu[0]=0;
00745 bc->uulen=0;
00746
00747 bc->fac_in.Function = Fac_None;
00748 bc->fac_out.Function = Fac_None;
00749
00750 bc->te_choose_channel = 0;
00751 bc->channel_found= 0;
00752
00753 gettimeofday(&bc->last_used, NULL);
00754 }
00755
00756
00757 static int clean_up_bc(struct misdn_bchannel *bc)
00758 {
00759 int ret=0;
00760 unsigned char buff[32];
00761 struct misdn_stack * stack;
00762
00763 cb_log(3, bc?bc->port:0, "$$$ CLEANUP CALLED pid:%d\n", bc?bc->pid:-1);
00764
00765 if (!bc ) return -1;
00766 stack=get_stack_by_bc(bc);
00767
00768 if (!stack) return -1;
00769
00770 switch (bc->bc_state ) {
00771 case BCHAN_CLEANED:
00772 cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid);
00773 return -1;
00774
00775 default:
00776 break;
00777 }
00778
00779 cb_log(2, stack->port, "$$$ Cleaning up bc with stid :%x pid:%d\n", bc->b_stid, bc->pid);
00780
00781 manager_ec_disable(bc);
00782
00783 manager_bchannel_deactivate(bc);
00784
00785 mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_TARGET|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
00786
00787 bc->b_stid = 0;
00788 bc_state_change(bc, BCHAN_CLEANED);
00789
00790 return ret;
00791 }
00792
00793
00794
00795 static void clear_l3(struct misdn_stack *stack)
00796 {
00797 int i;
00798
00799 for (i=0; i<=stack->b_num; i++) {
00800 if (global_state == MISDN_INITIALIZED) {
00801 cb_event(EVENT_CLEANUP, &stack->bc[i], NULL);
00802 empty_bc(&stack->bc[i]);
00803 clean_up_bc(&stack->bc[i]);
00804 empty_chan_in_stack(stack, i + 1);
00805 stack->bc[i].in_use = 0;
00806 }
00807
00808 }
00809 }
00810
00811 static int new_te_id = 0;
00812
00813 #define MAXPROCS 0x100
00814
00815 static int misdn_lib_get_l1_down(struct misdn_stack *stack)
00816 {
00817
00818 iframe_t act;
00819 act.prim = PH_DEACTIVATE | REQUEST;
00820 act.addr = stack->lower_id|FLG_MSG_DOWN;
00821 act.dinfo = 0;
00822 act.len = 0;
00823
00824 cb_log(1, stack->port, "SENDING PH_DEACTIVATE | REQ\n");
00825 return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00826 }
00827
00828
00829 static int misdn_lib_get_l2_down(struct misdn_stack *stack)
00830 {
00831
00832 if (stack->ptp && (stack->nt) ) {
00833 msg_t *dmsg;
00834
00835 dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
00836
00837 pthread_mutex_lock(&stack->nstlock);
00838 if (stack->nst.manager_l3(&stack->nst, dmsg))
00839 free_msg(dmsg);
00840 pthread_mutex_unlock(&stack->nstlock);
00841 } else {
00842 iframe_t act;
00843
00844 act.prim = DL_RELEASE| REQUEST;
00845 act.addr = (stack->upper_id |FLG_MSG_DOWN) ;
00846
00847 act.dinfo = 0;
00848 act.len = 0;
00849 return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00850 }
00851
00852 return 0;
00853 }
00854
00855
00856 static int misdn_lib_get_l1_up(struct misdn_stack *stack)
00857 {
00858
00859 iframe_t act;
00860 act.prim = PH_ACTIVATE | REQUEST;
00861 act.addr = (stack->upper_id | FLG_MSG_DOWN) ;
00862
00863
00864 act.dinfo = 0;
00865 act.len = 0;
00866
00867 return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00868
00869 }
00870
00871 int misdn_lib_get_l2_up(struct misdn_stack *stack)
00872 {
00873
00874 if (stack->ptp && (stack->nt) ) {
00875 msg_t *dmsg;
00876
00877 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
00878
00879 pthread_mutex_lock(&stack->nstlock);
00880 if (stack->nst.manager_l3(&stack->nst, dmsg))
00881 free_msg(dmsg);
00882 pthread_mutex_unlock(&stack->nstlock);
00883 } else {
00884 iframe_t act;
00885
00886 act.prim = DL_ESTABLISH | REQUEST;
00887 act.addr = (stack->upper_id |FLG_MSG_DOWN) ;
00888
00889 act.dinfo = 0;
00890 act.len = 0;
00891 return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00892 }
00893
00894 return 0;
00895 }
00896
00897 #if 0
00898 static int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack)
00899 {
00900 iframe_t act;
00901
00902 act.prim = DL_ESTABLISH | REQUEST;
00903 act.addr = (stack->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
00904
00905 act.dinfo = 0;
00906 act.len = 0;
00907 return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00908 return 0;
00909 }
00910 #endif
00911
00912 static int misdn_lib_get_short_status(struct misdn_stack *stack)
00913 {
00914 iframe_t act;
00915
00916
00917 act.prim = MGR_SHORTSTATUS | REQUEST;
00918
00919 act.addr = (stack->upper_id | MSG_BROADCAST) ;
00920
00921 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
00922
00923 act.len = 0;
00924 return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00925 }
00926
00927
00928
00929 static int create_process(int midev, struct misdn_bchannel *bc)
00930 {
00931 iframe_t ncr;
00932 int l3_id;
00933 int proc_id;
00934 struct misdn_stack *stack;
00935
00936 stack = get_stack_by_bc(bc);
00937 if (stack->nt) {
00938 if (find_free_chan_in_stack(stack, bc, bc->channel_preselected ? bc->channel : 0, 0) < 0) {
00939 return -1;
00940 }
00941 cb_log(4, stack->port, " --> found channel: %d\n", bc->channel);
00942
00943 for (proc_id = 0; proc_id < MAXPROCS; ++proc_id) {
00944 if (stack->procids[proc_id] == 0) {
00945 break;
00946 }
00947 }
00948 if (proc_id == MAXPROCS) {
00949 cb_log(0, stack->port, "Couldn't Create New ProcId.\n");
00950 return -1;
00951 }
00952
00953 stack->procids[proc_id] = 1;
00954
00955 l3_id = 0xff00 | proc_id;
00956 bc->l3_id = l3_id;
00957 cb_log(3, stack->port, " --> new_l3id %x\n", l3_id);
00958 } else {
00959 if ((stack->pri && stack->ptp) || bc->te_choose_channel) {
00960
00961 if (find_free_chan_in_stack(stack, bc, bc->channel_preselected ? bc->channel : 0, bc->dec) < 0) {
00962 return -1;
00963 }
00964 cb_log(2, stack->port, " --> found channel: %d\n", bc->channel);
00965 } else {
00966
00967 bc->channel = 0xff;
00968 }
00969
00970
00971 if (++new_te_id > 0xffff) {
00972 new_te_id = 0x0001;
00973 }
00974
00975 l3_id = (entity << 16) | new_te_id;
00976 bc->l3_id = l3_id;
00977 cb_log(3, stack->port, "--> new_l3id %x\n", l3_id);
00978
00979
00980 ncr.prim = CC_NEW_CR | REQUEST;
00981 ncr.addr = (stack->upper_id | FLG_MSG_DOWN);
00982 ncr.dinfo = l3_id;
00983 ncr.len = 0;
00984 mISDN_write(midev, &ncr, mISDN_HEADER_LEN + ncr.len, TIMEOUT_1SEC);
00985 }
00986
00987 return l3_id;
00988 }
00989
00990
00991 void misdn_lib_setup_bc(struct misdn_bchannel *bc)
00992 {
00993 clean_up_bc(bc);
00994 setup_bc(bc);
00995 }
00996
00997
00998 int setup_bc(struct misdn_bchannel *bc)
00999 {
01000 unsigned char buff[1025];
01001 int midev;
01002 int channel;
01003 int b_stid;
01004 int i;
01005 mISDN_pid_t pid;
01006 int ret;
01007
01008 struct misdn_stack *stack=get_stack_by_bc(bc);
01009
01010 if (!stack) {
01011 cb_log(0, bc->port, "setup_bc: NO STACK FOUND!!\n");
01012 return -1;
01013 }
01014
01015 midev = stack->midev;
01016 channel = bc->channel - 1 - (bc->channel > 16);
01017 b_stid = stack->b_stids[channel >= 0 ? channel : 0];
01018
01019 switch (bc->bc_state) {
01020 case BCHAN_CLEANED:
01021 break;
01022 default:
01023 cb_log(4, stack->port, "$$$ bc already setup stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) );
01024 return -1;
01025 }
01026
01027 cb_log(5, stack->port, "$$$ Setting up bc with stid :%x\n", b_stid);
01028
01029
01030 for (i=0; i <= stack->b_num; i++) {
01031 if (stack->bc[i].b_stid == b_stid) {
01032 cb_log(0, bc->port, "setup_bc: b_stid:%x already in use !!!\n", b_stid);
01033 return -1;
01034 }
01035 }
01036
01037 if (b_stid <= 0) {
01038 cb_log(0, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel);
01039
01040 bc_state_change(bc,BCHAN_ERROR);
01041 return 1;
01042 }
01043
01044 bc->b_stid = b_stid;
01045
01046 {
01047 layer_info_t li;
01048 memset(&li, 0, sizeof(li));
01049
01050 li.object_id = -1;
01051 li.extentions = 0;
01052
01053 li.st = bc->b_stid;
01054
01055
01056 #define MISDN_DSP
01057 #ifndef MISDN_DSP
01058 bc->nodsp=1;
01059 #endif
01060 if ( bc->hdlc || bc->nodsp) {
01061 cb_log(4, stack->port,"setup_bc: without dsp\n");
01062 {
01063 int l = sizeof(li.name);
01064 strncpy(li.name, "B L3", l);
01065 li.name[l-1] = 0;
01066 }
01067 li.pid.layermask = ISDN_LAYER((3));
01068 li.pid.protocol[3] = ISDN_PID_L3_B_USER;
01069
01070 bc->layer=3;
01071 } else {
01072 cb_log(4, stack->port,"setup_bc: with dsp\n");
01073 {
01074 int l = sizeof(li.name);
01075 strncpy(li.name, "B L4", l);
01076 li.name[l-1] = 0;
01077 }
01078 li.pid.layermask = ISDN_LAYER((4));
01079 li.pid.protocol[4] = ISDN_PID_L4_B_USER;
01080
01081 bc->layer=4;
01082 }
01083
01084 ret = mISDN_new_layer(midev, &li);
01085 if (ret ) {
01086 cb_log(0, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno));
01087
01088 bc_state_change(bc,BCHAN_ERROR);
01089 return(-EINVAL);
01090 }
01091
01092 bc->layer_id = li.id;
01093 }
01094
01095 memset(&pid, 0, sizeof(pid));
01096
01097
01098
01099 cb_log(4, stack->port," --> Channel is %d\n", bc->channel);
01100
01101 if (bc->nodsp) {
01102 cb_log(2, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n");
01103 pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
01104 pid.protocol[2] = ISDN_PID_L2_B_TRANS;
01105 pid.protocol[3] = ISDN_PID_L3_B_USER;
01106 pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3));
01107
01108 } else if ( bc->hdlc ) {
01109 cb_log(2, stack->port," --> HDLC Mode\n");
01110 pid.protocol[1] = ISDN_PID_L1_B_64HDLC ;
01111 pid.protocol[2] = ISDN_PID_L2_B_TRANS ;
01112 pid.protocol[3] = ISDN_PID_L3_B_USER;
01113 pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) ;
01114 } else {
01115 cb_log(2, stack->port," --> TRANSPARENT Mode\n");
01116 pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
01117 pid.protocol[2] = ISDN_PID_L2_B_TRANS;
01118 pid.protocol[3] = ISDN_PID_L3_B_DSP;
01119 pid.protocol[4] = ISDN_PID_L4_B_USER;
01120 pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
01121
01122 }
01123
01124 ret = mISDN_set_stack(midev, bc->b_stid, &pid);
01125
01126 if (ret){
01127 cb_log(0, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno));
01128
01129 mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
01130
01131 bc_state_change(bc,BCHAN_ERROR);
01132 cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
01133 return(-EINVAL);
01134 }
01135
01136 ret = mISDN_get_setstack_ind(midev, bc->layer_id);
01137
01138 if (ret) {
01139 cb_log(0, stack->port,"$$$ Set StackIND Err: %d %s\n",ret,strerror(errno));
01140 mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
01141
01142 bc_state_change(bc,BCHAN_ERROR);
01143 cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
01144 return(-EINVAL);
01145 }
01146
01147 ret = mISDN_get_layerid(midev, bc->b_stid, bc->layer) ;
01148
01149 bc->addr = ret>0? ret : 0;
01150
01151 if (!bc->addr) {
01152 cb_log(0, stack->port,"$$$ Get Layerid Err: %d %s\n",ret,strerror(errno));
01153 mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
01154
01155 bc_state_change(bc,BCHAN_ERROR);
01156 cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
01157 return (-EINVAL);
01158 }
01159
01160 manager_bchannel_activate(bc);
01161
01162 bc_state_change(bc,BCHAN_ACTIVATED);
01163
01164 return 0;
01165 }
01166
01167
01168
01169
01170 static int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, int port, int bidx, char *msn, int firsttime)
01171 {
01172 unsigned char buff[1025] = "";
01173 iframe_t *frm = (iframe_t *)buff;
01174 int ret;
01175
01176 if (!bc) return -1;
01177
01178 cb_log(8, port, "Init.BC %d.\n",bidx);
01179
01180 memset(bc, 0,sizeof(struct misdn_bchannel));
01181
01182 bc->send_lock=malloc(sizeof(struct send_lock));
01183 if (!bc->send_lock) {
01184 return -1;
01185 }
01186 pthread_mutex_init(&bc->send_lock->lock, NULL);
01187
01188 if (msn) {
01189 int l = sizeof(bc->msn);
01190 strncpy(bc->msn,msn, l);
01191 bc->msn[l-1] = 0;
01192 }
01193
01194
01195 empty_bc(bc);
01196 bc_state_change(bc, BCHAN_CLEANED);
01197
01198 bc->port=stack->port;
01199 bc->nt=stack->nt?1:0;
01200 bc->pri=stack->pri;
01201
01202 {
01203 ibuffer_t* ibuf= init_ibuffer(MISDN_IBUF_SIZE);
01204
01205 if (!ibuf) return -1;
01206
01207 clear_ibuffer( ibuf);
01208
01209 ibuf->rsem=malloc(sizeof(sem_t));
01210 if (!ibuf->rsem) {
01211 return -1;
01212 }
01213
01214 bc->astbuf=ibuf;
01215
01216 if (sem_init(ibuf->rsem,1,0)<0)
01217 sem_init(ibuf->rsem,0,0);
01218
01219 }
01220
01221 {
01222 stack_info_t *stinf;
01223 ret = mISDN_get_stack_info(midev, stack->port, buff, sizeof(buff));
01224 if (ret < 0) {
01225 cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
01226 return -1;
01227 }
01228
01229 stinf = (stack_info_t *)&frm->data.p;
01230
01231 cb_log(8, port, " --> Child %x\n",stinf->child[bidx]);
01232 }
01233
01234 return 0;
01235 }
01236
01237
01238
01239 static struct misdn_stack *stack_init(int midev, int port, int ptp)
01240 {
01241 int ret;
01242 unsigned char buff[1025];
01243 iframe_t *frm = (iframe_t *)buff;
01244 stack_info_t *stinf;
01245 int i;
01246 layer_info_t li;
01247
01248 struct misdn_stack *stack = malloc(sizeof(struct misdn_stack));
01249 if (!stack ) return NULL;
01250
01251
01252 cb_log(8, port, "Init. Stack.\n");
01253
01254 memset(stack,0,sizeof(struct misdn_stack));
01255
01256 for (i=0; i<MAX_BCHANS + 1; i++ ) stack->channels[i]=0;
01257
01258 stack->port=port;
01259 stack->midev=midev;
01260 stack->ptp=ptp;
01261
01262 stack->holding=NULL;
01263 stack->pri=0;
01264
01265 msg_queue_init(&stack->downqueue);
01266 msg_queue_init(&stack->upqueue);
01267
01268 pthread_mutex_init(&stack->st_lock, NULL);
01269
01270
01271 ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff));
01272 if (ret < 0) {
01273 cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
01274 return(NULL);
01275 }
01276
01277 stinf = (stack_info_t *)&frm->data.p;
01278
01279 stack->d_stid = stinf->id;
01280 stack->b_num = stinf->childcnt;
01281
01282 for (i=0; i<=stinf->childcnt; i++)
01283 stack->b_stids[i] = stinf->child[i];
01284
01285 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) {
01286 case ISDN_PID_L0_TE_S0:
01287 stack->nt=0;
01288 break;
01289 case ISDN_PID_L0_NT_S0:
01290 cb_log(8, port, "NT Stack\n");
01291
01292 stack->nt=1;
01293 break;
01294 case ISDN_PID_L0_TE_E1:
01295 cb_log(8, port, "TE S2M Stack\n");
01296 stack->nt=0;
01297 stack->pri=1;
01298 break;
01299 case ISDN_PID_L0_NT_E1:
01300 cb_log(8, port, "TE S2M Stack\n");
01301 stack->nt=1;
01302 stack->pri=1;
01303
01304 break;
01305 default:
01306 cb_log(0, port, "this is a unknown port type 0x%08x\n", stinf->pid.protocol[0]);
01307
01308 }
01309
01310 if (!stack->nt) {
01311 if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) {
01312 stack->ptp = 1;
01313 } else {
01314 stack->ptp = 0;
01315 }
01316 }
01317
01318 {
01319 int ret;
01320 int nt=stack->nt;
01321
01322 cb_log(8, port, "Init. Stack.\n");
01323
01324 memset(&li, 0, sizeof(li));
01325 {
01326 int l = sizeof(li.name);
01327 strncpy(li.name,nt?"net l2":"user l4", l);
01328 li.name[l-1] = 0;
01329 }
01330 li.object_id = -1;
01331 li.extentions = 0;
01332 li.pid.protocol[nt?2:4] = nt?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
01333 li.pid.layermask = ISDN_LAYER((nt?2:4));
01334 li.st = stack->d_stid;
01335
01336
01337 ret = mISDN_new_layer(midev, &li);
01338 if (ret) {
01339 cb_log(0, port, "%s: Cannot add layer %d to this port.\n", __FUNCTION__, nt?2:4);
01340 return(NULL);
01341 }
01342
01343
01344 stack->upper_id = li.id;
01345 ret = mISDN_register_layer(midev, stack->d_stid, stack->upper_id);
01346 if (ret)
01347 {
01348 cb_log(0,port,"Cannot register layer %d of this port.\n", nt?2:4);
01349 return(NULL);
01350 }
01351
01352 stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3);
01353 if (stack->lower_id < 0) {
01354 cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, nt?1:3);
01355 return(NULL);
01356 }
01357
01358 stack->upper_id = mISDN_get_layerid(midev, stack->d_stid, nt?2:4);
01359 if (stack->upper_id < 0) {
01360 cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, 2);
01361 return(NULL);
01362 }
01363
01364 cb_log(8, port, "NT Stacks upper_id %x\n",stack->upper_id);
01365
01366
01367
01368 if (nt) {
01369
01370 memset(&stack->nst, 0, sizeof(net_stack_t));
01371 memset(&stack->mgr, 0, sizeof(manager_t));
01372
01373 stack->mgr.nst = &stack->nst;
01374 stack->nst.manager = &stack->mgr;
01375
01376 stack->nst.l3_manager = handle_event_nt;
01377 stack->nst.device = midev;
01378 stack->nst.cardnr = port;
01379 stack->nst.d_stid = stack->d_stid;
01380
01381 stack->nst.feature = FEATURE_NET_HOLD;
01382 if (stack->ptp)
01383 stack->nst.feature |= FEATURE_NET_PTP;
01384 if (stack->pri)
01385 stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
01386
01387 stack->nst.l1_id = stack->lower_id;
01388 stack->nst.l2_id = stack->upper_id;
01389
01390 msg_queue_init(&stack->nst.down_queue);
01391 pthread_mutex_init(&stack->nstlock, NULL);
01392
01393 Isdnl2Init(&stack->nst);
01394 Isdnl3Init(&stack->nst);
01395
01396 }
01397
01398 if (!stack->nt) {
01399
01400
01401 stack->l1link=0;
01402 }
01403 stack->l1link=0;
01404 stack->l2link=0;
01405 #if 0
01406 if (!stack->nt) {
01407 misdn_lib_get_short_status(stack);
01408 } else {
01409 misdn_lib_get_l1_up(stack);
01410 if (!stack->ptp) misdn_lib_get_l1_up(stack);
01411 misdn_lib_get_l2_up(stack);
01412 }
01413 #endif
01414
01415 misdn_lib_get_short_status(stack);
01416 misdn_lib_get_l1_up(stack);
01417 misdn_lib_get_l2_up(stack);
01418
01419 }
01420
01421 cb_log(8,0,"stack_init: port:%d lowerId:%x upperId:%x\n",stack->port,stack->lower_id, stack->upper_id);
01422
01423 return stack;
01424 }
01425
01426
01427 static void stack_destroy(struct misdn_stack *stack)
01428 {
01429 char buf[1024];
01430 if (!stack) return;
01431
01432 if (stack->nt) {
01433 pthread_mutex_destroy(&stack->nstlock);
01434 cleanup_Isdnl2(&stack->nst);
01435 cleanup_Isdnl3(&stack->nst);
01436 }
01437
01438 if (stack->lower_id)
01439 mISDN_write_frame(stack->midev, buf, stack->lower_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
01440
01441 if (stack->upper_id)
01442 mISDN_write_frame(stack->midev, buf, stack->upper_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
01443
01444 pthread_mutex_destroy(&stack->st_lock);
01445 }
01446
01447
01448 static struct misdn_stack * find_stack_by_addr(int addr)
01449 {
01450 struct misdn_stack *stack;
01451
01452 for (stack=glob_mgr->stack_list;
01453 stack;
01454 stack=stack->next) {
01455 if ( (stack->upper_id&STACK_ID_MASK) == (addr&STACK_ID_MASK)) return stack;
01456
01457 }
01458
01459 return NULL;
01460 }
01461
01462
01463 static struct misdn_stack * find_stack_by_port(int port)
01464 {
01465 struct misdn_stack *stack;
01466
01467 for (stack=glob_mgr->stack_list;
01468 stack;
01469 stack=stack->next)
01470 if (stack->port == port) return stack;
01471
01472 return NULL;
01473 }
01474
01475 static struct misdn_stack * find_stack_by_mgr(manager_t* mgr_nt)
01476 {
01477 struct misdn_stack *stack;
01478
01479 for (stack=glob_mgr->stack_list;
01480 stack;
01481 stack=stack->next)
01482 if ( &stack->mgr == mgr_nt) return stack;
01483
01484 return NULL;
01485 }
01486
01487 static struct misdn_bchannel *find_bc_by_masked_l3id(struct misdn_stack *stack, unsigned long l3id, unsigned long mask)
01488 {
01489 int i;
01490
01491 for (i = 0; i <= stack->b_num; i++) {
01492 if (stack->bc[i].in_use && (stack->bc[i].l3_id & mask) == (l3id & mask)) {
01493 return &stack->bc[i];
01494 }
01495 }
01496 return stack_holder_find(stack,l3id);
01497 }
01498
01499
01500 struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id)
01501 {
01502 int i;
01503
01504 for (i = 0; i <= stack->b_num; i++) {
01505 if (stack->bc[i].in_use && stack->bc[i].l3_id == l3id) {
01506 return &stack->bc[i];
01507 }
01508 }
01509 return stack_holder_find(stack,l3id);
01510 }
01511
01512 static struct misdn_bchannel *find_bc_by_addr(unsigned long addr)
01513 {
01514 struct misdn_stack *stack;
01515 int i;
01516
01517 for (stack = glob_mgr->stack_list; stack; stack = stack->next) {
01518 for (i = 0; i <= stack->b_num; i++) {
01519 if (stack->bc[i].in_use
01520 && ((stack->bc[i].addr & STACK_ID_MASK) == (addr & STACK_ID_MASK)
01521 || stack->bc[i].layer_id == addr)) {
01522 return &stack->bc[i];
01523 }
01524 }
01525 }
01526
01527 return NULL;
01528 }
01529
01530 static struct misdn_bchannel *find_bc_by_confid(unsigned long confid)
01531 {
01532 struct misdn_stack *stack;
01533 int i;
01534
01535 for (stack = glob_mgr->stack_list; stack; stack = stack->next) {
01536 for (i = 0; i <= stack->b_num; i++) {
01537 if (stack->bc[i].in_use && stack->bc[i].conf_id == confid) {
01538 return &stack->bc[i];
01539 }
01540 }
01541 }
01542 return NULL;
01543 }
01544
01545
01546 static struct misdn_bchannel *find_bc_by_channel(int port, int channel)
01547 {
01548 struct misdn_stack *stack = find_stack_by_port(port);
01549 int i;
01550
01551 if (!stack) {
01552 return NULL;
01553 }
01554
01555 for (i = 0; i <= stack->b_num; i++) {
01556 if (stack->bc[i].in_use && stack->bc[i].channel == channel) {
01557 return &stack->bc[i];
01558 }
01559 }
01560
01561 return NULL;
01562 }
01563
01564
01565
01566
01567
01568 static int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
01569 {
01570 struct misdn_stack *stack=get_stack_by_bc(bc);
01571
01572 if (!stack->nt) {
01573
01574 switch (event) {
01575
01576 case EVENT_CONNECT_ACKNOWLEDGE:
01577 setup_bc(bc);
01578
01579 if ( *bc->crypt_key ) {
01580 cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
01581 manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
01582 }
01583
01584 if (misdn_cap_is_speech(bc->capability)) {
01585 if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
01586 manager_ec_enable(bc);
01587
01588 if ( bc->txgain != 0 ) {
01589 cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
01590 manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
01591 }
01592 if ( bc->rxgain != 0 ) {
01593 cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);
01594 manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
01595 }
01596 }
01597
01598 break;
01599 case EVENT_CONNECT:
01600
01601 if ( *bc->crypt_key ) {
01602 cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
01603 manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
01604 }
01605 case EVENT_ALERTING:
01606 case EVENT_PROGRESS:
01607 case EVENT_PROCEEDING:
01608 case EVENT_SETUP_ACKNOWLEDGE:
01609 case EVENT_SETUP:
01610 {
01611 if (bc->channel == 0xff || bc->channel<=0)
01612 bc->channel=0;
01613
01614 if (find_free_chan_in_stack(stack, bc, bc->channel, 0)<0){
01615 if (!stack->pri && !stack->ptp) {
01616 bc->cw=1;
01617 break;
01618 }
01619
01620 if (!bc->channel)
01621 cb_log(0, stack->port, "Any Channel Requested, but we have no more!!\n");
01622 else
01623 cb_log(0, stack->port,
01624 "Requested Channel Already in Use releasing this call with cause %d!!!!\n",
01625 bc->out_cause);
01626
01627
01628
01629
01630
01631 bc->channel=0;
01632
01633 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
01634 return -1;
01635 }
01636 }
01637
01638 setup_bc(bc);
01639 break;
01640
01641 case EVENT_RELEASE_COMPLETE:
01642 case EVENT_RELEASE:
01643 break;
01644 default:
01645 break;
01646 }
01647 } else {
01648
01649 }
01650 return 0;
01651 }
01652
01653 static int handle_cr ( struct misdn_stack *stack, iframe_t *frm)
01654 {
01655 struct misdn_bchannel *bc;
01656
01657 if (!stack) return -1;
01658
01659 switch (frm->prim) {
01660 case CC_NEW_CR|INDICATION:
01661 cb_log(7, stack->port, " --> lib: NEW_CR Ind with l3id:%x on this port.\n",frm->dinfo);
01662
01663 bc = misdn_lib_get_free_bc(stack->port, 0, 1, 0);
01664 if (!bc) {
01665 cb_log(0, stack->port, " --> !! lib: No free channel!\n");
01666 return -1;
01667 }
01668
01669 cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo);
01670 bc->l3_id=frm->dinfo;
01671 return 1;
01672 case CC_NEW_CR|CONFIRM:
01673 return 1;
01674 case CC_NEW_CR|REQUEST:
01675 return 1;
01676 case CC_RELEASE_CR|REQUEST:
01677 return 1;
01678 case CC_RELEASE_CR|CONFIRM:
01679 break;
01680 case CC_RELEASE_CR|INDICATION:
01681 cb_log(4, stack->port, " --> lib: RELEASE_CR Ind with l3id:%x\n",frm->dinfo);
01682 {
01683 struct misdn_bchannel *bc=find_bc_by_l3id(stack, frm->dinfo);
01684 struct misdn_bchannel dummybc;
01685
01686 if (!bc) {
01687 cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
01688 misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
01689
01690 bc=&dummybc;
01691 }
01692
01693 if (bc) {
01694 int channel = bc->channel;
01695 cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo);
01696
01697
01698 bc->need_disconnect=0;
01699 bc->need_release=0;
01700 bc->need_release_complete=0;
01701
01702 cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data);
01703
01704 empty_bc(bc);
01705 clean_up_bc(bc);
01706
01707 if (channel>0)
01708 empty_chan_in_stack(stack,channel);
01709 bc->in_use=0;
01710
01711 dump_chan_list(stack);
01712
01713 if (bc->stack_holder) {
01714 cb_log(4,stack->port, "REMOVING Holder\n");
01715 stack_holder_remove( stack, bc);
01716 free(bc);
01717 }
01718 }
01719 else {
01720 if (stack->nt)
01721 cb_log(4, stack->port, "BC with dinfo: %x not found.. (prim was %x and addr %x)\n",frm->dinfo, frm->prim, frm->addr);
01722 }
01723
01724 return 1;
01725 }
01726 break;
01727 }
01728
01729 return 0;
01730 }
01731
01732
01733
01734 void misdn_lib_release(struct misdn_bchannel *bc)
01735 {
01736 int channel;
01737 struct misdn_stack *stack=get_stack_by_bc(bc);
01738
01739 if (!stack) {
01740 cb_log(1,0,"misdn_release: No Stack found\n");
01741 return;
01742 }
01743
01744 channel = bc->channel;
01745 empty_bc(bc);
01746 clean_up_bc(bc);
01747 if (channel > 0) {
01748 empty_chan_in_stack(stack, channel);
01749 }
01750 bc->in_use=0;
01751 }
01752
01753
01754
01755
01756 int misdn_lib_get_port_up (int port)
01757 {
01758 struct misdn_stack *stack;
01759
01760 for (stack=glob_mgr->stack_list;
01761 stack;
01762 stack=stack->next) {
01763
01764 if (stack->port == port) {
01765
01766 if (!stack->l1link)
01767 misdn_lib_get_l1_up(stack);
01768 if (!stack->l2link)
01769 misdn_lib_get_l2_up(stack);
01770
01771 return 0;
01772 }
01773 }
01774 return 0;
01775 }
01776
01777
01778 int misdn_lib_get_port_down (int port)
01779 {
01780 struct misdn_stack *stack;
01781 for (stack=glob_mgr->stack_list;
01782 stack;
01783 stack=stack->next) {
01784 if (stack->port == port) {
01785 if (stack->l2link)
01786 misdn_lib_get_l2_down(stack);
01787 misdn_lib_get_l1_down(stack);
01788 return 0;
01789 }
01790 }
01791 return 0;
01792 }
01793
01794 int misdn_lib_port_up(int port, int check)
01795 {
01796 struct misdn_stack *stack;
01797
01798
01799 for (stack=glob_mgr->stack_list;
01800 stack;
01801 stack=stack->next) {
01802
01803 if (stack->port == port) {
01804
01805 if (stack->blocked) {
01806 cb_log(0,port, "Port Blocked:%d L2:%d L1:%d\n", stack->blocked, stack->l2link, stack->l1link);
01807 return -1;
01808 }
01809
01810 if (stack->ptp ) {
01811
01812 if (stack->l1link && stack->l2link) {
01813 return 1;
01814 } else {
01815 cb_log(1,port, "Port Down L2:%d L1:%d\n",
01816 stack->l2link, stack->l1link);
01817 return 0;
01818 }
01819 } else {
01820 if ( !check || stack->l1link )
01821 return 1;
01822 else {
01823 cb_log(1,port, "Port down PMP\n");
01824 return 0;
01825 }
01826 }
01827 }
01828 }
01829
01830 return -1;
01831 }
01832
01833
01834 int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh)
01835 {
01836 struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
01837 struct misdn_bchannel dummybc;
01838 iframe_t frm;
01839 frm.dinfo = hh->dinfo;
01840
01841 frm.addr=stack->upper_id | FLG_MSG_DOWN;
01842
01843 frm.prim = CC_RELEASE_CR|INDICATION;
01844 cb_log(4, stack->port, " --> CC_RELEASE_CR: Faking Release_cr for %x l3id:%x\n",frm.addr, frm.dinfo);
01845
01846 if (!bc) {
01847 cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", hh->dinfo);
01848 misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0);
01849 bc=&dummybc;
01850 }
01851
01852 if (bc) {
01853 if ( (bc->l3_id & 0xff00) == 0xff00) {
01854 cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", bc->l3_id&0xff);
01855 stack->procids[bc->l3_id&0xff] = 0 ;
01856 }
01857 }
01858 else cb_log(0, stack->port, "Couldn't find BC so I couldn't remove the Process!!!! this is a bad port.\n");
01859
01860 if (handle_cr(stack, &frm)<0) {
01861 }
01862
01863 return 0 ;
01864 }
01865
01866 int
01867 handle_event_nt(void *dat, void *arg)
01868 {
01869 manager_t *mgr = (manager_t *)dat;
01870 msg_t *msg = (msg_t *)arg;
01871 mISDNuser_head_t *hh;
01872 struct misdn_stack *stack;
01873 int reject=0;
01874
01875 if (!msg || !mgr)
01876 return(-EINVAL);
01877
01878 stack = find_stack_by_mgr(mgr);
01879 hh=(mISDNuser_head_t*)msg->data;
01880
01881
01882
01883
01884
01885
01886 pthread_mutex_unlock(&stack->nstlock);
01887
01888 cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo);
01889 {
01890 switch(hh->prim){
01891 case CC_RETRIEVE|INDICATION:
01892 {
01893 struct misdn_bchannel *bc;
01894 struct misdn_bchannel *hold_bc;
01895
01896 iframe_t frm;
01897 frm.dinfo = hh->dinfo;
01898
01899 frm.addr=stack->upper_id | FLG_MSG_DOWN;
01900
01901 frm.prim = CC_NEW_CR|INDICATION;
01902
01903 if (handle_cr( stack, &frm)< 0) {
01904 msg_t *dmsg;
01905 cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
01906 dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
01907 pthread_mutex_lock(&stack->nstlock);
01908 stack->nst.manager_l3(&stack->nst, dmsg);
01909 free_msg(msg);
01910 return 0;
01911 }
01912
01913 bc = find_bc_by_l3id(stack, hh->dinfo);
01914 hold_bc = stack_holder_find(stack, bc->l3_id);
01915 cb_log(4, stack->port, "bc_l3id:%x holded_bc_l3id:%x\n",bc->l3_id, hold_bc->l3_id);
01916
01917 if (hold_bc) {
01918 cb_log(4, stack->port, "REMOVING Holder\n");
01919
01920
01921 stack_holder_remove(stack, hold_bc);
01922 memcpy(bc, hold_bc, sizeof(*bc));
01923 free(hold_bc);
01924
01925 bc->holded=0;
01926 bc->b_stid=0;
01927 }
01928
01929 }
01930
01931 break;
01932
01933 case CC_SETUP|CONFIRM:
01934 {
01935 struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
01936 int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE));
01937 cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n",l3id );
01938
01939 if (bc) {
01940 cb_log (2, bc->port, "I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id);
01941 bc->l3_id = l3id;
01942 cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data);
01943 } else {
01944 cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n");
01945 }
01946 }
01947 free_msg(msg);
01948 pthread_mutex_lock(&stack->nstlock);
01949 return 0;
01950
01951 case CC_SETUP|INDICATION:
01952 {
01953 struct misdn_bchannel* bc=misdn_lib_get_free_bc(stack->port, 0, 1, 0);
01954 if (!bc) {
01955 msg_t *dmsg;
01956 cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
01957 dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
01958 pthread_mutex_lock(&stack->nstlock);
01959 stack->nst.manager_l3(&stack->nst, dmsg);
01960 free_msg(msg);
01961 return 0;
01962 }
01963
01964 cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo);
01965 bc->l3_id=hh->dinfo;
01966 }
01967 break;
01968
01969 case CC_CONNECT_ACKNOWLEDGE|INDICATION:
01970 break;
01971
01972 case CC_ALERTING|INDICATION:
01973 case CC_PROCEEDING|INDICATION:
01974 case CC_SETUP_ACKNOWLEDGE|INDICATION:
01975 if(!stack->ptp) break;
01976 case CC_CONNECT|INDICATION:
01977 break;
01978 case CC_DISCONNECT|INDICATION:
01979 {
01980 struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
01981 if (!bc) {
01982 bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
01983 if (bc) {
01984 int myprocid=bc->l3_id&0x0000ffff;
01985 hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
01986 cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause);
01987 reject=1;
01988 }
01989 }
01990 }
01991 break;
01992
01993 case CC_FACILITY|INDICATION:
01994 {
01995 struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
01996 if (!bc) {
01997 bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
01998 if (bc) {
01999 int myprocid=bc->l3_id&0x0000ffff;
02000 hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
02001 cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo);
02002 }
02003 }
02004 }
02005 break;
02006
02007 case CC_RELEASE_COMPLETE|INDICATION:
02008 break;
02009
02010 case CC_SUSPEND|INDICATION:
02011 {
02012 msg_t *dmsg;
02013 cb_log(4, stack->port, " --> Got Suspend, sending Reject for now\n");
02014 dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST,MT_SUSPEND_REJECT, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
02015 pthread_mutex_lock(&stack->nstlock);
02016 stack->nst.manager_l3(&stack->nst, dmsg);
02017 free_msg(msg);
02018 return 0;
02019 }
02020 break;
02021 case CC_RESUME|INDICATION:
02022 break;
02023
02024 case CC_RELEASE|CONFIRM:
02025 {
02026 struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
02027
02028 if (bc) {
02029 cb_log(1, stack->port, "CC_RELEASE|CONFIRM (l3id:%x), sending RELEASE_COMPLETE\n", hh->dinfo);
02030 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
02031 }
02032 }
02033 break;
02034
02035 case CC_RELEASE|INDICATION:
02036 break;
02037
02038 case CC_RELEASE_CR|INDICATION:
02039 release_cr(stack, hh);
02040 free_msg(msg);
02041 pthread_mutex_lock(&stack->nstlock);
02042 return 0 ;
02043 break;
02044
02045 case CC_NEW_CR|INDICATION:
02046
02047
02048 {
02049 struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
02050 int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE));
02051 if (!bc) {
02052 cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n");
02053 pthread_mutex_lock(&stack->nstlock);
02054 return -1;
02055 }
02056 if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) {
02057 cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", 0xff&bc->l3_id);
02058 stack->procids[bc->l3_id&0xff] = 0 ;
02059 }
02060 cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID is %x\n",l3id );
02061
02062 bc->l3_id =l3id;
02063 cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data);
02064
02065 free_msg(msg);
02066 pthread_mutex_lock(&stack->nstlock);
02067 return 0;
02068 }
02069
02070 case DL_ESTABLISH | INDICATION:
02071 case DL_ESTABLISH | CONFIRM:
02072 {
02073 cb_log(3, stack->port, "%% GOT L2 Activate Info.\n");
02074
02075 if (stack->ptp && stack->l2link) {
02076 cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n");
02077 cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
02078 }
02079
02080 if (stack->ptp && !stack->restart_sent) {
02081
02082
02083 stack->restart_sent=1;
02084 misdn_lib_send_restart(stack->port, -1);
02085
02086 }
02087
02088
02089 stack->l2link = 1;
02090 stack->l2upcnt=0;
02091
02092 free_msg(msg);
02093 pthread_mutex_lock(&stack->nstlock);
02094 return 0;
02095 }
02096 break;
02097
02098
02099 case DL_RELEASE | INDICATION:
02100 case DL_RELEASE | CONFIRM:
02101 {
02102 if (stack->ptp) {
02103 cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n");
02104
02105 if (stack->l2upcnt>3) {
02106 cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attempts!!!\n");
02107 } else {
02108 #if 0
02109 if (stack->nt) misdn_lib_reinit_nt_stack(stack->port);
02110 #endif
02111 if (stack->l1link) {
02112 misdn_lib_get_l2_up(stack);
02113 stack->l2upcnt++;
02114 }
02115 }
02116
02117 } else
02118 cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n");
02119
02120 stack->l2link = 0;
02121 free_msg(msg);
02122 pthread_mutex_lock(&stack->nstlock);
02123 return 0;
02124 }
02125 break;
02126 }
02127 }
02128
02129 {
02130
02131 struct misdn_bchannel *bc;
02132 struct misdn_bchannel dummybc;
02133
02134 enum event_e event = isdn_msg_get_event(msgs_g, msg, 1);
02135
02136 bc=find_bc_by_l3id(stack, hh->dinfo);
02137
02138 if (!bc) {
02139 cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x).\n", hh->dinfo);
02140 misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0);
02141 bc=&dummybc;
02142 }
02143 if (bc ) {
02144 isdn_msg_parse_event(msgs_g,msg,bc, 1);
02145
02146 switch (event) {
02147 case EVENT_SETUP:
02148 if (bc->channel<=0 || bc->channel==0xff)
02149 bc->channel=0;
02150
02151 if (find_free_chan_in_stack(stack,bc, bc->channel,0)<0) {
02152 msg_t *dmsg;
02153 cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
02154 dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
02155 pthread_mutex_lock(&stack->nstlock);
02156 stack->nst.manager_l3(&stack->nst, dmsg);
02157 free_msg(msg);
02158 return 0;
02159 }
02160 break;
02161 case EVENT_RELEASE:
02162 case EVENT_RELEASE_COMPLETE:
02163 {
02164 int channel=bc->channel;
02165 int tmpcause=bc->cause;
02166 empty_bc(bc);
02167 bc->cause=tmpcause;
02168 clean_up_bc(bc);
02169
02170 if (channel>0)
02171 empty_chan_in_stack(stack,channel);
02172 bc->in_use=0;
02173 }
02174 break;
02175
02176 default:
02177 break;
02178 }
02179
02180 if(!isdn_get_info(msgs_g,event,1)) {
02181 cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n",hh->prim, hh->dinfo);
02182 } else {
02183 if (reject) {
02184 switch(bc->cause){
02185 case AST_CAUSE_USER_BUSY:
02186 cb_log(1, stack->port, "Siemens Busy reject..\n");
02187
02188 break;
02189 default:
02190 break;
02191 }
02192 }
02193 cb_event(event, bc, glob_mgr->user_data);
02194 }
02195 } else {
02196 cb_log(4, stack->port, "No BC found with l3id: prim %x dinfo %x\n",hh->prim, hh->dinfo);
02197 }
02198
02199 free_msg(msg);
02200 }
02201
02202
02203 pthread_mutex_lock(&stack->nstlock);
02204 return 0;
02205 }
02206
02207
02208 static int handle_timers(msg_t* msg)
02209 {
02210 iframe_t *frm= (iframe_t*)msg->data;
02211 struct misdn_stack *stack;
02212
02213
02214 switch (frm->prim) {
02215 case MGR_INITTIMER | CONFIRM:
02216 case MGR_ADDTIMER | CONFIRM:
02217 case MGR_DELTIMER | CONFIRM:
02218 case MGR_REMOVETIMER | CONFIRM:
02219 free_msg(msg);
02220 return(1);
02221 }
02222
02223
02224
02225 if (frm->prim==(MGR_TIMER | INDICATION) ) {
02226 for (stack = glob_mgr->stack_list;
02227 stack;
02228 stack = stack->next) {
02229 itimer_t *it;
02230
02231 if (!stack->nt) continue;
02232
02233 it = stack->nst.tlist;
02234
02235 for(it=stack->nst.tlist;
02236 it;
02237 it=it->next) {
02238 if (it->id == (int)frm->addr)
02239 break;
02240 }
02241 if (it) {
02242 int ret;
02243 ret = mISDN_write_frame(stack->midev, msg->data, frm->addr,
02244 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
02245 test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
02246 pthread_mutex_lock(&stack->nstlock);
02247 ret = it->function(it->data);
02248 pthread_mutex_unlock(&stack->nstlock);
02249 free_msg(msg);
02250 return 1;
02251 }
02252 }
02253
02254 cb_log(0, 0, "Timer Msg without Timer ??\n");
02255 free_msg(msg);
02256 return 1;
02257 }
02258
02259 return 0;
02260 }
02261
02262
02263
02264 void misdn_lib_tone_generator_start(struct misdn_bchannel *bc)
02265 {
02266 bc->generate_tone=1;
02267 }
02268
02269 void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc)
02270 {
02271 bc->generate_tone=0;
02272 }
02273
02274
02275 static int do_tone(struct misdn_bchannel *bc, int len)
02276 {
02277 bc->tone_cnt=len;
02278
02279 if (bc->generate_tone) {
02280 cb_event(EVENT_TONE_GENERATE, bc, glob_mgr->user_data);
02281
02282 if ( !bc->nojitter ) {
02283 misdn_tx_jitter(bc,len);
02284 }
02285
02286 return 1;
02287 }
02288
02289 return 0;
02290 }
02291
02292
02293 #ifdef MISDN_SAVE_DATA
02294 static void misdn_save_data(int id, char *p1, int l1, char *p2, int l2)
02295 {
02296 char n1[32],n2[32];
02297 FILE *rx, *tx;
02298
02299 sprintf(n1,"/tmp/misdn-rx-%d.raw",id);
02300 sprintf(n2,"/tmp/misdn-tx-%d.raw",id);
02301
02302 rx = fopen(n1,"a+");
02303 tx = fopen(n2,"a+");
02304
02305 if (!rx || !tx) {
02306 cb_log(0,0,"Couldn't open files: %s\n",strerror(errno));
02307 if (rx)
02308 fclose(rx);
02309 if (tx)
02310 fclose(tx);
02311 return ;
02312 }
02313
02314 fwrite(p1,1,l1,rx);
02315 fwrite(p2,1,l2,tx);
02316
02317 fclose(rx);
02318 fclose(tx);
02319
02320 }
02321 #endif
02322
02323 void misdn_tx_jitter(struct misdn_bchannel *bc, int len)
02324 {
02325 char buf[4096 + mISDN_HEADER_LEN];
02326 char *data=&buf[mISDN_HEADER_LEN];
02327 iframe_t *txfrm= (iframe_t*)buf;
02328 int jlen, r;
02329
02330 jlen=cb_jb_empty(bc,data,len);
02331
02332 if (jlen) {
02333 #ifdef MISDN_SAVE_DATA
02334 misdn_save_data((bc->port*100+bc->channel), data, jlen, bc->bframe, bc->bframe_len);
02335 #endif
02336 flip_buf_bits( data, jlen);
02337
02338 if (jlen < len) {
02339 cb_log(1, bc->port, "Jitterbuffer Underrun. Got %d of expected %d\n", jlen, len);
02340 }
02341
02342 txfrm->prim = DL_DATA|REQUEST;
02343
02344 txfrm->dinfo = 0;
02345
02346 txfrm->addr = bc->addr|FLG_MSG_DOWN;
02347
02348 txfrm->len =jlen;
02349 cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len);
02350
02351 r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 );
02352 } else {
02353 #define MISDN_GEN_SILENCE
02354 #ifdef MISDN_GEN_SILENCE
02355 int cnt=len/TONE_SILENCE_SIZE;
02356 int rest=len%TONE_SILENCE_SIZE;
02357 int i;
02358
02359 for (i=0; i<cnt; i++) {
02360 memcpy(data, tone_silence_flip, TONE_SILENCE_SIZE );
02361 data +=TONE_SILENCE_SIZE;
02362 }
02363
02364 if (rest) {
02365 memcpy(data, tone_silence_flip, rest);
02366 }
02367
02368 txfrm->prim = DL_DATA|REQUEST;
02369
02370 txfrm->dinfo = 0;
02371
02372 txfrm->addr = bc->addr|FLG_MSG_DOWN;
02373
02374 txfrm->len =len;
02375 cb_log(5, bc->port, "Transmitting %d samples of silence to misdn\n", len);
02376
02377 r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 );
02378 #else
02379 r = 0;
02380 #endif
02381 }
02382
02383 if (r < 0) {
02384 cb_log(1, bc->port, "Error in mISDN_write (%s)\n", strerror(errno));
02385 }
02386 }
02387
02388 static int handle_bchan(msg_t *msg)
02389 {
02390 iframe_t *frm= (iframe_t*)msg->data;
02391 struct misdn_bchannel *bc=find_bc_by_addr(frm->addr);
02392 struct misdn_stack *stack;
02393
02394 if (!bc) {
02395 cb_log(1,0,"handle_bchan: BC not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
02396 return 0 ;
02397 }
02398
02399 stack = get_stack_by_bc(bc);
02400
02401 if (!stack) {
02402 cb_log(0, bc->port,"handle_bchan: STACK not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
02403 return 0;
02404 }
02405
02406 switch (frm->prim) {
02407
02408 case MGR_SETSTACK| CONFIRM:
02409 cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|CONFIRM pid:%d\n",bc->pid);
02410 break;
02411
02412 case MGR_SETSTACK| INDICATION:
02413 cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|IND pid:%d\n",bc->pid);
02414 break;
02415 #if 0
02416 AGAIN:
02417 bc->addr = mISDN_get_layerid(stack->midev, bc->b_stid, bc->layer);
02418 if (!bc->addr) {
02419
02420 if (errno == EAGAIN) {
02421 usleep(1000);
02422 goto AGAIN;
02423 }
02424
02425 cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno));
02426
02427
02428
02429 bc->addr= frm->addr;
02430 } else if ( bc->addr < 0) {
02431 cb_log(0, stack->port,"$$$ bc->addr <0 Error:%s\n",strerror(errno));
02432 bc->addr=0;
02433 }
02434
02435 cb_log(4, stack->port," --> Got Adr %x\n", bc->addr);
02436
02437 free_msg(msg);
02438
02439
02440 switch(bc->bc_state) {
02441 case BCHAN_SETUP:
02442 bc_state_change(bc,BCHAN_SETUPED);
02443 break;
02444
02445 case BCHAN_CLEAN_REQUEST:
02446 default:
02447 cb_log(0, stack->port," --> STATE WASN'T SETUP (but %s) in SETSTACK|IND pid:%d\n",bc_state2str(bc->bc_state), bc->pid);
02448 clean_up_bc(bc);
02449 }
02450 return 1;
02451 #endif
02452
02453 case MGR_DELLAYER| INDICATION:
02454 cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|IND pid:%d\n",bc->pid);
02455 break;
02456
02457 case MGR_DELLAYER| CONFIRM:
02458 cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|CNF pid:%d\n",bc->pid);
02459
02460 bc->pid=0;
02461 bc->addr=0;
02462
02463 free_msg(msg);
02464 return 1;
02465
02466 case PH_ACTIVATE | INDICATION:
02467 case DL_ESTABLISH | INDICATION:
02468 cb_log(3, stack->port, "BCHAN: ACT Ind pid:%d\n", bc->pid);
02469
02470 free_msg(msg);
02471 return 1;
02472
02473 case PH_ACTIVATE | CONFIRM:
02474 case DL_ESTABLISH | CONFIRM:
02475
02476 cb_log(3, stack->port, "BCHAN: bchan ACT Confirm pid:%d\n",bc->pid);
02477 free_msg(msg);
02478
02479 return 1;
02480
02481 case DL_ESTABLISH | REQUEST:
02482 {
02483 char buf[128];
02484 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_ESTABLISH | CONFIRM, 0,0, NULL, TIMEOUT_1SEC);
02485 }
02486 free_msg(msg);
02487 return 1;
02488
02489 case DL_RELEASE|REQUEST:
02490 {
02491 char buf[128];
02492 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_RELEASE| CONFIRM, 0,0, NULL, TIMEOUT_1SEC);
02493 }
02494 free_msg(msg);
02495 return 1;
02496
02497 case PH_DEACTIVATE | INDICATION:
02498 case DL_RELEASE | INDICATION:
02499 cb_log (3, stack->port, "BCHAN: DeACT Ind pid:%d\n",bc->pid);
02500
02501 free_msg(msg);
02502 return 1;
02503
02504 case PH_DEACTIVATE | CONFIRM:
02505 case DL_RELEASE | CONFIRM:
02506 cb_log(3, stack->port, "BCHAN: DeACT Conf pid:%d\n",bc->pid);
02507
02508 free_msg(msg);
02509 return 1;
02510
02511 case PH_CONTROL|INDICATION:
02512 {
02513 unsigned int *cont = (unsigned int *) &frm->data.p;
02514
02515 cb_log(4, stack->port, "PH_CONTROL: channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
02516
02517 if ((*cont & ~DTMF_TONE_MASK) == DTMF_TONE_VAL) {
02518 int dtmf = *cont & DTMF_TONE_MASK;
02519 cb_log(4, stack->port, " --> DTMF TONE: %c\n",dtmf);
02520 bc->dtmf=dtmf;
02521 cb_event(EVENT_DTMF_TONE, bc, glob_mgr->user_data);
02522
02523 free_msg(msg);
02524 return 1;
02525 }
02526 if (*cont == BF_REJECT) {
02527 cb_log(4, stack->port, " --> BF REJECT\n");
02528 free_msg(msg);
02529 return 1;
02530 }
02531 if (*cont == BF_ACCEPT) {
02532 cb_log(4, stack->port, " --> BF ACCEPT\n");
02533 free_msg(msg);
02534 return 1;
02535 }
02536 }
02537 break;
02538
02539 case PH_DATA|REQUEST:
02540 case DL_DATA|REQUEST:
02541 cb_log(0, stack->port, "DL_DATA REQUEST \n");
02542 do_tone(bc, 64);
02543
02544 free_msg(msg);
02545 return 1;
02546
02547
02548 case PH_DATA|INDICATION:
02549 case DL_DATA|INDICATION:
02550 {
02551 bc->bframe = (void*)&frm->data.i;
02552 bc->bframe_len = frm->len;
02553
02554
02555 if ( misdn_cap_is_speech(bc->capability) )
02556 flip_buf_bits(bc->bframe, bc->bframe_len);
02557
02558
02559 if (!bc->bframe_len) {
02560 cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
02561 free_msg(msg);
02562 return 1;
02563 }
02564
02565 if ( (bc->addr&STACK_ID_MASK) != (frm->addr&STACK_ID_MASK) ) {
02566 cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
02567 free_msg(msg);
02568 return 1;
02569 }
02570
02571 #if MISDN_DEBUG
02572 cb_log(0, stack->port, "DL_DATA INDICATION Len %d\n", frm->len);
02573
02574 #endif
02575
02576 if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) {
02577 int t;
02578
02579 #ifdef MISDN_B_DEBUG
02580 cb_log(0,bc->port,"do_tone START\n");
02581 #endif
02582 t=do_tone(bc,frm->len);
02583
02584 #ifdef MISDN_B_DEBUG
02585 cb_log(0,bc->port,"do_tone STOP (%d)\n",t);
02586 #endif
02587 if ( !t ) {
02588 int i;
02589
02590 if ( misdn_cap_is_speech(bc->capability)) {
02591 if ( !bc->nojitter ) {
02592 #ifdef MISDN_B_DEBUG
02593 cb_log(0,bc->port,"tx_jitter START\n");
02594 #endif
02595 misdn_tx_jitter(bc,frm->len);
02596 #ifdef MISDN_B_DEBUG
02597 cb_log(0,bc->port,"tx_jitter STOP\n");
02598 #endif
02599 }
02600 }
02601
02602 #ifdef MISDN_B_DEBUG
02603 cb_log(0,bc->port,"EVENT_B_DATA START\n");
02604 #endif
02605
02606 i = cb_event(EVENT_BCHAN_DATA, bc, glob_mgr->user_data);
02607 #ifdef MISDN_B_DEBUG
02608 cb_log(0,bc->port,"EVENT_B_DATA STOP\n");
02609 #endif
02610
02611 if (i<0) {
02612 cb_log(10,stack->port,"cb_event returned <0\n");
02613
02614 }
02615 }
02616 }
02617 free_msg(msg);
02618 return 1;
02619 }
02620
02621
02622 case PH_CONTROL | CONFIRM:
02623 cb_log(4, stack->port, "PH_CONTROL|CNF bc->addr:%x\n", frm->addr);
02624 free_msg(msg);
02625 return 1;
02626
02627 case PH_DATA | CONFIRM:
02628 case DL_DATA|CONFIRM:
02629 #if MISDN_DEBUG
02630
02631 cb_log(0, stack->port, "Data confirmed\n");
02632
02633 #endif
02634 free_msg(msg);
02635 return 1;
02636 case DL_DATA|RESPONSE:
02637 #if MISDN_DEBUG
02638 cb_log(0, stack->port, "Data response\n");
02639
02640 #endif
02641 break;
02642 }
02643
02644 return 0;
02645 }
02646
02647
02648
02649 static int handle_frm_nt(msg_t *msg)
02650 {
02651 iframe_t *frm= (iframe_t*)msg->data;
02652 struct misdn_stack *stack;
02653 int err=0;
02654
02655 stack=find_stack_by_addr( frm->addr );
02656
02657
02658
02659 if (!stack || !stack->nt) {
02660 return 0;
02661 }
02662
02663
02664 pthread_mutex_lock(&stack->nstlock);
02665 if ((err=stack->nst.l1_l2(&stack->nst,msg))) {
02666 pthread_mutex_unlock(&stack->nstlock);
02667 if (nt_err_cnt > 0 ) {
02668 if (nt_err_cnt < 100) {
02669 nt_err_cnt++;
02670 cb_log(0, stack->port, "NT Stack sends us error: %d \n", err);
02671 } else if (nt_err_cnt < 105){
02672 cb_log(0, stack->port, "NT Stack sends us error: %d over 100 times, so I'll stop this message\n", err);
02673 nt_err_cnt = - 1;
02674 }
02675 }
02676 free_msg(msg);
02677 return 1;
02678 }
02679 pthread_mutex_unlock(&stack->nstlock);
02680 return 1;
02681 }
02682
02683
02684 static int handle_frm(msg_t *msg)
02685 {
02686 iframe_t *frm = (iframe_t*) msg->data;
02687
02688 struct misdn_stack *stack=find_stack_by_addr(frm->addr);
02689
02690 if (!stack || stack->nt) {
02691 return 0;
02692 }
02693
02694 cb_log(4,stack?stack->port:0,"handle_frm: frm->addr:%x frm->prim:%x\n",frm->addr,frm->prim);
02695
02696 {
02697 struct misdn_bchannel dummybc;
02698 struct misdn_bchannel *bc;
02699 int ret=handle_cr(stack, frm);
02700
02701 if (ret<0) {
02702 cb_log(3,stack?stack->port:0,"handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr);
02703
02704
02705 }
02706
02707 if(ret) {
02708 free_msg(msg);
02709 return 1;
02710 }
02711
02712 bc=find_bc_by_l3id(stack, frm->dinfo);
02713
02714 if (!bc && (frm->prim==(CC_RESTART|CONFIRM)) ) {
02715 misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
02716 bc=&dummybc;
02717 }
02718
02719 if (!bc && (frm->prim==(CC_SETUP|INDICATION)) ) {
02720 misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
02721 dummybc.port=stack->port;
02722 dummybc.l3_id=frm->dinfo;
02723 bc=&dummybc;
02724
02725 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
02726
02727 free_msg(msg);
02728 return 1;
02729 }
02730
02731
02732 handle_frm_bc:
02733 if (bc ) {
02734 enum event_e event = isdn_msg_get_event(msgs_g, msg, 0);
02735 enum event_response_e response=RESPONSE_OK;
02736 int ret;
02737
02738 isdn_msg_parse_event(msgs_g,msg,bc, 0);
02739
02740
02741 ret = handle_event(bc, event, frm);
02742 if (ret<0) {
02743 cb_log(0,stack->port,"couldn't handle event\n");
02744 free_msg(msg);
02745 return 1;
02746 }
02747
02748 cb_log(5, stack->port, "lib Got Prim: Addr %x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo);
02749
02750 if(!isdn_get_info(msgs_g,event,0))
02751 cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo);
02752 else
02753 response=cb_event(event, bc, glob_mgr->user_data);
02754 #if 1
02755 if (event == EVENT_SETUP) {
02756 switch (response) {
02757 case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE:
02758
02759 cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n");
02760
02761 break;
02762 case RESPONSE_IGNORE_SETUP:
02763
02764 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
02765
02766 case RESPONSE_RELEASE_SETUP:
02767 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
02768 if (bc->channel>0)
02769 empty_chan_in_stack(stack, bc->channel);
02770 empty_bc(bc);
02771 bc_state_change(bc,BCHAN_CLEANED);
02772 bc->in_use=0;
02773
02774 cb_log(0, stack->port, "GOT IGNORE SETUP\n");
02775 break;
02776 case RESPONSE_OK:
02777 cb_log(4, stack->port, "GOT SETUP OK\n");
02778
02779
02780 break;
02781 default:
02782 break;
02783 }
02784 }
02785
02786 if (event == EVENT_RELEASE_COMPLETE) {
02787
02788 int channel=bc->channel;
02789 int tmpcause=bc->cause;
02790 int tmp_out_cause=bc->out_cause;
02791 empty_bc(bc);
02792 bc->cause=tmpcause;
02793 bc->out_cause=tmp_out_cause;
02794 clean_up_bc(bc);
02795 bc->in_use = 0;
02796
02797 if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) {
02798 cb_log(0, stack->port, "**** Received CAUSE:%d, restarting channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel);
02799 misdn_lib_send_restart(stack->port, channel);
02800 }
02801 if (channel > 0) {
02802 empty_chan_in_stack(stack, channel);
02803 }
02804 }
02805
02806 if (event == EVENT_RESTART) {
02807 cb_log(0, stack->port, "**** Received RESTART channel:%d\n", bc->restart_channel);
02808 empty_chan_in_stack(stack, bc->restart_channel);
02809 }
02810
02811 cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim);
02812
02813
02814 free_msg(msg);
02815 return 1;
02816 #endif
02817
02818 } else {
02819 struct misdn_bchannel dummybc;
02820 if (frm->prim!=(CC_FACILITY|INDICATION))
02821 cb_log(0, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
02822 else
02823 cb_log(5, stack->port, " --> Using Dummy BC for FACILITy\n");
02824
02825 memset (&dummybc,0,sizeof(dummybc));
02826 dummybc.port=stack->port;
02827 dummybc.l3_id=frm->dinfo;
02828 bc=&dummybc;
02829 goto handle_frm_bc;
02830 }
02831 }
02832
02833 cb_log(4, stack->port, "TE_FRM_HANDLER: Returning 0 on prim:%x \n",frm->prim);
02834 return 0;
02835 }
02836
02837
02838 static int handle_l1(msg_t *msg)
02839 {
02840 iframe_t *frm = (iframe_t*) msg->data;
02841 struct misdn_stack *stack = find_stack_by_addr(frm->addr);
02842 int i ;
02843
02844 if (!stack) return 0 ;
02845
02846 switch (frm->prim) {
02847 case PH_ACTIVATE | CONFIRM:
02848 case PH_ACTIVATE | INDICATION:
02849 cb_log (3, stack->port, "L1: PH L1Link Up!\n");
02850 stack->l1link=1;
02851
02852 if (stack->nt) {
02853
02854 pthread_mutex_lock(&stack->nstlock);
02855 if (stack->nst.l1_l2(&stack->nst, msg))
02856 free_msg(msg);
02857 pthread_mutex_unlock(&stack->nstlock);
02858
02859 if (stack->ptp)
02860 misdn_lib_get_l2_up(stack);
02861 } else {
02862 free_msg(msg);
02863 }
02864
02865 for (i=0;i<=stack->b_num; i++) {
02866 if (stack->bc[i].evq != EVENT_NOTHING) {
02867 cb_log(4, stack->port, "Firing Queued Event %s because L1 got up\n", isdn_get_info(msgs_g, stack->bc[i].evq, 0));
02868 misdn_lib_send_event(&stack->bc[i],stack->bc[i].evq);
02869 stack->bc[i].evq=EVENT_NOTHING;
02870 }
02871
02872 }
02873 return 1;
02874
02875 case PH_ACTIVATE | REQUEST:
02876 free_msg(msg);
02877 cb_log(3,stack->port,"L1: PH_ACTIVATE|REQUEST \n");
02878 return 1;
02879
02880 case PH_DEACTIVATE | REQUEST:
02881 free_msg(msg);
02882 cb_log(3,stack->port,"L1: PH_DEACTIVATE|REQUEST \n");
02883 return 1;
02884
02885 case PH_DEACTIVATE | CONFIRM:
02886 case PH_DEACTIVATE | INDICATION:
02887 cb_log (3, stack->port, "L1: PH L1Link Down! \n");
02888
02889 #if 0
02890 for (i=0; i<=stack->b_num; i++) {
02891 if (global_state == MISDN_INITIALIZED) {
02892 cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data);
02893 }
02894 }
02895 #endif
02896
02897 if (stack->nt) {
02898 pthread_mutex_lock(&stack->nstlock);
02899 if (stack->nst.l1_l2(&stack->nst, msg))
02900 free_msg(msg);
02901 pthread_mutex_unlock(&stack->nstlock);
02902 } else {
02903 free_msg(msg);
02904 }
02905
02906 stack->l1link=0;
02907 stack->l2link=0;
02908 return 1;
02909 }
02910
02911 return 0;
02912 }
02913
02914 static int handle_l2(msg_t *msg)
02915 {
02916 iframe_t *frm = (iframe_t*) msg->data;
02917
02918 struct misdn_stack *stack = find_stack_by_addr(frm->addr);
02919
02920 if (!stack) {
02921 return 0 ;
02922 }
02923
02924 switch(frm->prim) {
02925
02926 case DL_ESTABLISH | REQUEST:
02927 cb_log(1,stack->port,"DL_ESTABLISH|REQUEST \n");
02928 free_msg(msg);
02929 return 1;
02930 case DL_RELEASE | REQUEST:
02931 cb_log(1,stack->port,"DL_RELEASE|REQUEST \n");
02932 free_msg(msg);
02933 return 1;
02934
02935 case DL_ESTABLISH | INDICATION:
02936 case DL_ESTABLISH | CONFIRM:
02937 {
02938 cb_log (3, stack->port, "L2: L2Link Up! \n");
02939 if (stack->ptp && stack->l2link) {
02940 cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n");
02941 cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
02942 }
02943 stack->l2link=1;
02944 free_msg(msg);
02945 return 1;
02946 }
02947 break;
02948
02949 case DL_RELEASE | INDICATION:
02950 case DL_RELEASE | CONFIRM:
02951 {
02952 cb_log (3, stack->port, "L2: L2Link Down! \n");
02953 stack->l2link=0;
02954
02955 free_msg(msg);
02956 return 1;
02957 }
02958 break;
02959 }
02960 return 0;
02961 }
02962
02963 static int handle_mgmt(msg_t *msg)
02964 {
02965 iframe_t *frm = (iframe_t*) msg->data;
02966 struct misdn_stack *stack;
02967
02968 if ( (frm->addr == 0) && (frm->prim == (MGR_DELLAYER|CONFIRM)) ) {
02969 cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: 0 !\n") ;
02970 free_msg(msg);
02971 return 1;
02972 }
02973
02974 stack = find_stack_by_addr(frm->addr);
02975
02976 if (!stack) {
02977 if (frm->prim == (MGR_DELLAYER|CONFIRM)) {
02978 cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: %x !\n",
02979 frm->addr) ;
02980 free_msg(msg);
02981 return 1;
02982 }
02983
02984 return 0;
02985 }
02986
02987 switch(frm->prim) {
02988 case MGR_SHORTSTATUS | INDICATION:
02989 case MGR_SHORTSTATUS | CONFIRM:
02990 cb_log(5, stack->port, "MGMT: Short status dinfo %x\n",frm->dinfo);
02991
02992 switch (frm->dinfo) {
02993 case SSTATUS_L1_ACTIVATED:
02994 cb_log(3, stack->port, "MGMT: SSTATUS: L1_ACTIVATED \n");
02995 stack->l1link=1;
02996
02997 break;
02998 case SSTATUS_L1_DEACTIVATED:
02999 cb_log(3, stack->port, "MGMT: SSTATUS: L1_DEACTIVATED \n");
03000 stack->l1link=0;
03001 #if 0
03002 clear_l3(stack);
03003 #endif
03004 break;
03005
03006 case SSTATUS_L2_ESTABLISHED:
03007 cb_log(3, stack->port, "MGMT: SSTATUS: L2_ESTABLISH \n");
03008 stack->l2link=1;
03009 break;
03010
03011 case SSTATUS_L2_RELEASED:
03012 cb_log(3, stack->port, "MGMT: SSTATUS: L2_RELEASED \n");
03013 stack->l2link=0;
03014 break;
03015 }
03016
03017 free_msg(msg);
03018 return 1;
03019
03020 case MGR_SETSTACK | INDICATION:
03021 cb_log(4, stack->port, "MGMT: SETSTACK|IND dinfo %x\n",frm->dinfo);
03022 free_msg(msg);
03023 return 1;
03024 case MGR_DELLAYER | CONFIRM:
03025 cb_log(4, stack->port, "MGMT: DELLAYER|CNF dinfo %x\n",frm->dinfo) ;
03026 free_msg(msg);
03027 return 1;
03028
03029 }
03030
03031
03032
03033
03034
03035
03036
03037
03038 return 0;
03039 }
03040
03041
03042 static msg_t *fetch_msg(int midev)
03043 {
03044 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
03045 int r;
03046
03047 if (!msg) {
03048 cb_log(0, 0, "fetch_msg: alloc msg failed !!");
03049 return NULL;
03050 }
03051
03052 AGAIN:
03053 r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, TIMEOUT_10SEC);
03054 msg->len=r;
03055
03056 if (r==0) {
03057 free_msg(msg);
03058 cb_log(6,0,"Got empty Msg..\n");
03059 return NULL;
03060 }
03061
03062 if (r<0) {
03063 if (errno == EAGAIN) {
03064
03065 cb_log(4,0,"mISDN_read wants us to wait\n");
03066 usleep(5000);
03067 goto AGAIN;
03068 }
03069
03070 cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno);
03071 }
03072
03073 #if 0
03074 if (!(frm->prim == (DL_DATA|INDICATION) )|| (frm->prim == (PH_DATA|INDICATION)))
03075 cb_log(0,0,"prim: %x dinfo:%x addr:%x msglen:%d frm->len:%d\n",frm->prim, frm->dinfo, frm->addr, msg->len,frm->len );
03076 #endif
03077 return msg;
03078 }
03079
03080 void misdn_lib_isdn_l1watcher(int port)
03081 {
03082 struct misdn_stack *stack;
03083
03084 for (stack = glob_mgr->stack_list; stack && (stack->port != port); stack = stack->next)
03085 ;
03086
03087 if (stack) {
03088 cb_log(4, port, "Checking L1 State\n");
03089 if (!stack->l1link) {
03090 cb_log(4, port, "L1 State Down, trying to get it up again\n");
03091 misdn_lib_get_short_status(stack);
03092 misdn_lib_get_l1_up(stack);
03093 misdn_lib_get_l2_up(stack);
03094 }
03095 }
03096 }
03097
03098
03099 static void misdn_lib_isdn_event_catcher(void *arg)
03100 {
03101 struct misdn_lib *mgr = arg;
03102 int zero_frm=0 , fff_frm=0 ;
03103 int midev= mgr->midev;
03104 int port=0;
03105
03106 while (1) {
03107 msg_t *msg = fetch_msg(midev);
03108 iframe_t *frm;
03109
03110
03111 if (!msg) continue;
03112
03113 frm = (iframe_t*) msg->data;
03114
03115
03116 if (frm->len == 0 && frm->addr == 0 && frm->dinfo == 0 && frm->prim == 0 ) {
03117 zero_frm++;
03118 free_msg(msg);
03119 continue;
03120 } else {
03121 if (zero_frm) {
03122 cb_log(0, port, "*** Alert: %d zero_frms caught\n", zero_frm);
03123 zero_frm = 0 ;
03124 }
03125 }
03126
03127
03128 if (frm->len == 0 && frm->dinfo == 0 && frm->prim == 0xffffffff ) {
03129 fff_frm++;
03130 free_msg(msg);
03131 continue;
03132 } else {
03133 if (fff_frm) {
03134 cb_log(0, port, "*** Alert: %d fff_frms caught\n", fff_frm);
03135 fff_frm = 0 ;
03136 }
03137 }
03138
03139 manager_isdn_handler(frm, msg);
03140 }
03141
03142 }
03143
03144
03145
03146
03147 int te_lib_init() {
03148 char buff[1025] = "";
03149 iframe_t *frm=(iframe_t*)buff;
03150 int midev=mISDN_open();
03151 int ret;
03152
03153 if (midev<=0) return midev;
03154
03155
03156 mISDN_write_frame(midev, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
03157 ret = mISDN_read_frame(midev, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
03158
03159 if (ret < mISDN_HEADER_LEN) {
03160 noentity:
03161 fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n",strerror(errno));
03162 exit(-1);
03163 }
03164
03165 entity = frm->dinfo & 0xffff ;
03166
03167 if (!entity)
03168 goto noentity;
03169
03170 return midev;
03171
03172 }
03173
03174 void te_lib_destroy(int midev)
03175 {
03176 char buf[1024];
03177 mISDN_write_frame(midev, buf, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
03178
03179 cb_log(4, 0, "Entity deleted\n");
03180 mISDN_close(midev);
03181 cb_log(4, 0, "midev closed\n");
03182 }
03183
03184 struct misdn_bchannel *manager_find_bc_by_pid(int pid)
03185 {
03186 struct misdn_stack *stack;
03187 int i;
03188
03189 for (stack = glob_mgr->stack_list; stack; stack = stack->next) {
03190 for (i = 0; i <= stack->b_num; i++) {
03191 if (stack->bc[i].in_use && stack->bc[i].pid == pid) {
03192 return &stack->bc[i];
03193 }
03194 }
03195 }
03196
03197 return NULL;
03198 }
03199
03200 static int test_inuse(struct misdn_bchannel *bc)
03201 {
03202 struct timeval now;
03203 gettimeofday(&now, NULL);
03204 if (!bc->in_use) {
03205 if (misdn_lib_port_is_pri(bc->port) && bc->last_used.tv_sec == now.tv_sec ) {
03206 cb_log(2,bc->port, "channel with stid:%x for one second still in use! (n:%d lu:%d)\n", bc->b_stid, (int) now.tv_sec, (int) bc->last_used.tv_sec);
03207 return 1;
03208 }
03209
03210
03211 cb_log(3,bc->port, "channel with stid:%x not in use!\n", bc->b_stid);
03212 return 0;
03213 }
03214
03215 cb_log(2,bc->port, "channel with stid:%x in use!\n", bc->b_stid);
03216 return 1;
03217 }
03218
03219
03220 static void prepare_bc(struct misdn_bchannel*bc, int channel)
03221 {
03222 bc->channel = channel;
03223 bc->channel_preselected = channel?1:0;
03224 bc->need_disconnect=1;
03225 bc->need_release=1;
03226 bc->need_release_complete=1;
03227 bc->cause = AST_CAUSE_NORMAL_CLEARING;
03228
03229 if (++mypid>5000) mypid=1;
03230 bc->pid=mypid;
03231
03232 #if 0
03233 bc->addr=0;
03234 bc->b_stid=0;
03235 bc->layer_id=0;
03236 #endif
03237
03238 bc->in_use = 1;
03239 }
03240
03241 struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel, int inout, int dec)
03242 {
03243 struct misdn_stack *stack;
03244 int i;
03245
03246 if (channel < 0 || channel > MAX_BCHANS) {
03247 cb_log(0,port,"Requested channel out of bounds (%d)\n",channel);
03248 return NULL;
03249 }
03250
03251 for (stack=glob_mgr->stack_list; stack; stack=stack->next) {
03252
03253 if (stack->port == port) {
03254 int maxnum;
03255
03256 if (stack->blocked) {
03257 cb_log(0,port,"Port is blocked\n");
03258 return NULL;
03259 }
03260
03261 pthread_mutex_lock(&stack->st_lock);
03262 if (channel > 0) {
03263 if (channel <= stack->b_num) {
03264 for (i = 0; i < stack->b_num; i++) {
03265 if ( stack->bc[i].channel == channel) {
03266 if (test_inuse(&stack->bc[i])) {
03267 pthread_mutex_unlock(&stack->st_lock);
03268 cb_log(0,port,"Requested channel:%d on port:%d is already in use\n",channel, port);
03269 return NULL;
03270
03271 } else {
03272 prepare_bc(&stack->bc[i], channel);
03273 pthread_mutex_unlock(&stack->st_lock);
03274 return &stack->bc[i];
03275 }
03276 }
03277 }
03278 } else {
03279 pthread_mutex_unlock(&stack->st_lock);
03280 cb_log(0,port,"Requested channel:%d is out of bounds on port:%d\n",channel, port);
03281 return NULL;
03282 }
03283 }
03284
03285 maxnum = inout && !stack->pri && !stack->ptp ? stack->b_num + 1 : stack->b_num;
03286
03287 if (dec) {
03288 for (i = maxnum-1; i>=0; i--) {
03289 if (!test_inuse(&stack->bc[i])) {
03290
03291 if (!stack->pri && i==stack->b_num)
03292 stack->bc[i].cw=1;
03293
03294 prepare_bc(&stack->bc[i], channel);
03295 stack->bc[i].dec=1;
03296 pthread_mutex_unlock(&stack->st_lock);
03297 return &stack->bc[i];
03298 }
03299 }
03300 } else {
03301 for (i = 0; i <maxnum; i++) {
03302 if (!test_inuse(&stack->bc[i])) {
03303
03304 if (!stack->pri && i==stack->b_num)
03305 stack->bc[i].cw=1;
03306
03307 prepare_bc(&stack->bc[i], channel);
03308 pthread_mutex_unlock(&stack->st_lock);
03309 return &stack->bc[i];
03310 }
03311 }
03312 }
03313 pthread_mutex_unlock(&stack->st_lock);
03314
03315 cb_log(1,port,"There is no free channel on port (%d)\n",port);
03316 return NULL;
03317 }
03318 }
03319
03320 cb_log(0,port,"Port is not configured (%d)\n",port);
03321 return NULL;
03322 }
03323
03324
03325
03326
03327
03328
03329
03330 static const char *fac2str(enum FacFunction facility)
03331 {
03332 static const struct {
03333 enum FacFunction facility;
03334 char *name;
03335 } arr[] = {
03336
03337 { Fac_None, "Fac_None" },
03338 { Fac_GetSupportedServices, "Fac_GetSupportedServices" },
03339 { Fac_Listen, "Fac_Listen" },
03340 { Fac_Suspend, "Fac_Suspend" },
03341 { Fac_Resume, "Fac_Resume" },
03342 { Fac_CFActivate, "Fac_CFActivate" },
03343 { Fac_CFDeactivate, "Fac_CFDeactivate" },
03344 { Fac_CFInterrogateParameters, "Fac_CFInterrogateParameters" },
03345 { Fac_CFInterrogateNumbers, "Fac_CFInterrogateNumbers" },
03346 { Fac_CD, "Fac_CD" },
03347 { Fac_AOCDCurrency, "Fac_AOCDCurrency" },
03348 { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" },
03349
03350 };
03351
03352 unsigned index;
03353
03354 for (index = 0; index < ARRAY_LEN(arr); ++index) {
03355 if (arr[index].facility == facility) {
03356 return arr[index].name;
03357 }
03358 }
03359
03360 return "unknown";
03361 }
03362
03363 void misdn_lib_log_ies(struct misdn_bchannel *bc)
03364 {
03365 struct misdn_stack *stack;
03366
03367 if (!bc) return;
03368
03369 stack = get_stack_by_bc(bc);
03370
03371 if (!stack) return;
03372
03373 cb_log(2, stack->port, " --> channel:%d mode:%s cause:%d ocause:%d rad:%s cad:%s\n", bc->channel, stack->nt?"NT":"TE", bc->cause, bc->out_cause, bc->rad, bc->cad);
03374
03375 cb_log(2, stack->port,
03376 " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c cpnnumplan:%c\n",
03377 bc->info_dad,
03378 bc->onumplan>=0?'0'+bc->onumplan:' ',
03379 bc->dnumplan>=0?'0'+bc->dnumplan:' ',
03380 bc->rnumplan>=0?'0'+bc->rnumplan:' ',
03381 bc->cpnnumplan>=0?'0'+bc->cpnnumplan:' '
03382 );
03383
03384 cb_log(3, stack->port, " --> caps:%s pi:%x keypad:%s sending_complete:%d\n", bearer2str(bc->capability),bc->progress_indicator, bc->keypad, bc->sending_complete);
03385 cb_log(4, stack->port, " --> screen:%d --> pres:%d\n",
03386 bc->screen, bc->pres);
03387
03388 cb_log(4, stack->port, " --> addr:%x l3id:%x b_stid:%x layer_id:%x\n", bc->addr, bc->l3_id, bc->b_stid, bc->layer_id);
03389
03390 cb_log(4, stack->port, " --> facility:%s out_facility:%s\n",fac2str(bc->fac_in.Function),fac2str(bc->fac_out.Function));
03391
03392 cb_log(5, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1);
03393
03394 cb_log(5, stack->port, " --> bc:%p h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);
03395 }
03396
03397
03398 #define RETURN(a,b) {retval=a; goto b;}
03399
03400 static void misdn_send_lock(struct misdn_bchannel *bc)
03401 {
03402
03403 if (bc->send_lock)
03404 pthread_mutex_lock(&bc->send_lock->lock);
03405 }
03406
03407 static void misdn_send_unlock(struct misdn_bchannel *bc)
03408 {
03409
03410 if (bc->send_lock)
03411 pthread_mutex_unlock(&bc->send_lock->lock);
03412 }
03413
03414 int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
03415 {
03416 msg_t *msg;
03417 int retval=0;
03418 struct misdn_stack *stack;
03419 struct misdn_bchannel *held_bc;
03420
03421 if (!bc) RETURN(-1,OUT_POST_UNLOCK);
03422
03423 stack = get_stack_by_bc(bc);
03424
03425 if (!stack) {
03426 cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad);
03427 RETURN(-1,OUT);
03428 }
03429
03430 misdn_send_lock(bc);
03431
03432
03433 cb_log(6,stack->port,"SENDEVENT: stack->nt:%d stack->upperid:%x\n",stack->nt, stack->upper_id);
03434
03435 if ( stack->nt && !stack->l1link) {
03436
03437 bc->evq=event;
03438 cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0));
03439 misdn_lib_get_l1_up(stack);
03440 RETURN(0,OUT);
03441 }
03442
03443 cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid);
03444 cb_log(4, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
03445 misdn_lib_log_ies(bc);
03446
03447 switch (event) {
03448 case EVENT_SETUP:
03449 if (create_process(glob_mgr->midev, bc)<0) {
03450 cb_log(0, stack->port, " No free channel at the moment @ send_event\n");
03451
03452 RETURN(-ENOCHAN,OUT);
03453 }
03454 break;
03455
03456 case EVENT_PROGRESS:
03457 case EVENT_ALERTING:
03458 case EVENT_PROCEEDING:
03459 case EVENT_SETUP_ACKNOWLEDGE:
03460 case EVENT_CONNECT:
03461 if (!stack->nt) break;
03462
03463 case EVENT_RETRIEVE_ACKNOWLEDGE:
03464
03465 if (stack->nt) {
03466 if (bc->channel <=0 ) {
03467 if (find_free_chan_in_stack(stack, bc, 0, 0)<0) {
03468 cb_log(0, stack->port, " No free channel at the moment\n");
03469
03470 RETURN(-ENOCHAN,OUT);
03471 }
03472 }
03473
03474 }
03475
03476 retval=setup_bc(bc);
03477 if (retval == -EINVAL) {
03478 cb_log(0,bc->port,"send_event: setup_bc failed\n");
03479 }
03480
03481 if (misdn_cap_is_speech(bc->capability)) {
03482 if ((event==EVENT_CONNECT)||(event==EVENT_RETRIEVE_ACKNOWLEDGE)) {
03483 if ( *bc->crypt_key ) {
03484 cb_log(4, stack->port, " --> ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
03485
03486 manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
03487 }
03488
03489 if (!bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
03490 manager_ec_enable(bc);
03491
03492 if (bc->txgain != 0) {
03493 cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
03494 manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
03495 }
03496
03497 if ( bc->rxgain != 0 ) {
03498 cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);
03499 manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
03500 }
03501 }
03502 }
03503 break;
03504
03505 case EVENT_HOLD_ACKNOWLEDGE:
03506 held_bc = malloc(sizeof(struct misdn_bchannel));
03507 if (!held_bc) {
03508 cb_log(0, bc->port, "Could not allocate held_bc!!!\n");
03509 RETURN(-1,OUT);
03510 }
03511
03512
03513 *held_bc = *bc;
03514 held_bc->holded = 1;
03515 held_bc->channel = 0;
03516 held_bc->channel_preselected = 0;
03517 held_bc->channel_found = 0;
03518 bc_state_change(held_bc, BCHAN_CLEANED);
03519 stack_holder_add(stack, held_bc);
03520
03521
03522 if (stack->nt) {
03523 int channel;
03524 if (bc->bc_state == BCHAN_BRIDGED) {
03525 struct misdn_bchannel *bc2;
03526
03527 misdn_split_conf(bc,bc->conf_id);
03528 bc2 = find_bc_by_confid(bc->conf_id);
03529 if (!bc2) {
03530 cb_log(0,bc->port,"We have no second bc in bridge???\n");
03531 } else {
03532 misdn_split_conf(bc2,bc->conf_id);
03533 }
03534 }
03535
03536 channel = bc->channel;
03537
03538 empty_bc(bc);
03539 clean_up_bc(bc);
03540
03541 if (channel>0)
03542 empty_chan_in_stack(stack,channel);
03543
03544 bc->in_use=0;
03545 }
03546 break;
03547
03548
03549 case EVENT_DISCONNECT:
03550 if (!bc->need_disconnect) {
03551 cb_log(0,bc->port," --> we have already send Disconnect\n");
03552 RETURN(-1,OUT);
03553 }
03554
03555 bc->need_disconnect=0;
03556 break;
03557 case EVENT_RELEASE:
03558 if (!bc->need_release) {
03559 cb_log(0,bc->port," --> we have already send Release\n");
03560 RETURN(-1,OUT);
03561 }
03562 bc->need_disconnect=0;
03563 bc->need_release=0;
03564 break;
03565 case EVENT_RELEASE_COMPLETE:
03566 if (!bc->need_release_complete) {
03567 cb_log(0,bc->port," --> we have already send Release_complete\n");
03568 RETURN(-1,OUT);
03569 }
03570 bc->need_disconnect=0;
03571 bc->need_release=0;
03572 bc->need_release_complete=0;
03573
03574 if (!stack->nt) {
03575
03576 int channel=bc->channel;
03577
03578 int tmpcause=bc->cause;
03579 int tmp_out_cause=bc->out_cause;
03580 empty_bc(bc);
03581 bc->cause=tmpcause;
03582 bc->out_cause=tmp_out_cause;
03583 clean_up_bc(bc);
03584
03585 if (channel>0)
03586 empty_chan_in_stack(stack,channel);
03587
03588 bc->in_use=0;
03589 }
03590 break;
03591
03592 case EVENT_CONNECT_ACKNOWLEDGE:
03593
03594 if ( bc->nt || misdn_cap_is_speech(bc->capability)) {
03595 int retval=setup_bc(bc);
03596 if (retval == -EINVAL){
03597 cb_log(0,bc->port,"send_event: setup_bc failed\n");
03598
03599 }
03600 }
03601
03602 if (misdn_cap_is_speech(bc->capability)) {
03603 if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
03604 manager_ec_enable(bc);
03605
03606 if ( bc->txgain != 0 ) {
03607 cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
03608 manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
03609 }
03610 if ( bc->rxgain != 0 ) {
03611 cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);
03612 manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
03613 }
03614 }
03615 break;
03616
03617 default:
03618 break;
03619 }
03620
03621
03622 msg = isdn_msg_build_event(msgs_g, bc, event, stack->nt);
03623 msg_queue_tail(&stack->downqueue, msg);
03624 sem_post(&glob_mgr->new_msg);
03625
03626 OUT:
03627 misdn_send_unlock(bc);
03628
03629 OUT_POST_UNLOCK:
03630 return retval;
03631 }
03632
03633
03634 static int handle_err(msg_t *msg)
03635 {
03636 iframe_t *frm = (iframe_t*) msg->data;
03637
03638
03639 if (!frm->addr) {
03640 static int cnt=0;
03641 if (!cnt)
03642 cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x\n",frm->prim,frm->dinfo);
03643 cnt++;
03644 if (cnt>100) {
03645 cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo);
03646 cnt=0;
03647 }
03648
03649 free_msg(msg);
03650 return 1;
03651
03652 }
03653
03654 switch (frm->prim) {
03655 case MGR_SETSTACK|INDICATION:
03656 return handle_bchan(msg);
03657 break;
03658
03659 case MGR_SETSTACK|CONFIRM:
03660 case MGR_CLEARSTACK|CONFIRM:
03661 free_msg(msg) ;
03662 return 1;
03663 break;
03664
03665 case DL_DATA|CONFIRM:
03666 cb_log(4,0,"DL_DATA|CONFIRM\n");
03667 free_msg(msg);
03668 return 1;
03669
03670 case PH_CONTROL|CONFIRM:
03671 cb_log(4,0,"PH_CONTROL|CONFIRM\n");
03672 free_msg(msg);
03673 return 1;
03674
03675 case DL_DATA|INDICATION:
03676 {
03677 int port=(frm->addr&MASTER_ID_MASK) >> 8;
03678 int channel=(frm->addr&CHILD_ID_MASK) >> 16;
03679 struct misdn_bchannel *bc;
03680
03681
03682
03683 cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel);
03684
03685 free_msg(msg);
03686 return 1;
03687
03688
03689 bc = find_bc_by_channel(port, channel);
03690
03691 if (!bc) {
03692 struct misdn_stack *stack = find_stack_by_port(port);
03693
03694 if (!stack) {
03695 cb_log(0,0," --> stack not found\n");
03696 free_msg(msg);
03697 return 1;
03698 }
03699
03700 cb_log(0,0," --> bc not found by channel\n");
03701 if (stack->l2link)
03702 misdn_lib_get_l2_down(stack);
03703
03704 if (stack->l1link)
03705 misdn_lib_get_l1_down(stack);
03706
03707 free_msg(msg);
03708 return 1;
03709 }
03710
03711 cb_log(3,port," --> BC in state:%s\n", bc_state2str(bc->bc_state));
03712 }
03713 }
03714
03715 return 0;
03716 }
03717
03718 #if 0
03719 static int queue_l2l3(msg_t *msg)
03720 {
03721 iframe_t *frm= (iframe_t*)msg->data;
03722 struct misdn_stack *stack;
03723 stack=find_stack_by_addr( frm->addr );
03724
03725
03726 if (!stack) {
03727 return 0;
03728 }
03729
03730 msg_queue_tail(&stack->upqueue, msg);
03731 sem_post(&glob_mgr->new_msg);
03732 return 1;
03733 }
03734 #endif
03735
03736 int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
03737 {
03738
03739 if (frm->dinfo==0xffffffff && frm->prim==(PH_DATA|CONFIRM)) {
03740 cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
03741 }
03742
03743 if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) {
03744 static int unhandled_bmsg_count=1000;
03745 if (handle_bchan(msg)) {
03746 return 0 ;
03747 }
03748
03749 if (unhandled_bmsg_count==1000) {
03750 cb_log(0, 0, "received 1k Unhandled Bchannel Messages: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
03751 unhandled_bmsg_count=0;
03752 }
03753
03754 unhandled_bmsg_count++;
03755 free_msg(msg);
03756 return 0;
03757 }
03758
03759 #ifdef RECV_FRM_SYSLOG_DEBUG
03760 syslog(LOG_NOTICE,"mISDN recv: P(%02d): ADDR:%x PRIM:%x DINFO:%x\n",stack->port, frm->addr, frm->prim, frm->dinfo);
03761 #endif
03762
03763 if (handle_timers(msg))
03764 return 0 ;
03765
03766
03767 if (handle_mgmt(msg))
03768 return 0 ;
03769
03770 if (handle_l2(msg))
03771 return 0 ;
03772
03773
03774 if (handle_l1(msg))
03775 return 0 ;
03776
03777 if (handle_frm_nt(msg)) {
03778 return 0;
03779 }
03780
03781 if (handle_frm(msg)) {
03782 return 0;
03783 }
03784
03785 if (handle_err(msg)) {
03786 return 0 ;
03787 }
03788
03789 cb_log(0, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
03790 free_msg(msg);
03791
03792
03793 return 0;
03794 }
03795
03796
03797
03798
03799 int misdn_lib_get_port_info(int port)
03800 {
03801 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
03802 iframe_t *frm;
03803 struct misdn_stack *stack=find_stack_by_port(port);
03804 if (!msg) {
03805 cb_log(0, port, "misdn_lib_get_port_info: alloc_msg failed!\n");
03806 return -1;
03807 }
03808 frm=(iframe_t*)msg->data;
03809 if (!stack ) {
03810 cb_log(0, port, "There is no Stack for this port.\n");
03811 return -1;
03812 }
03813
03814 frm->prim = CC_STATUS_ENQUIRY | REQUEST;
03815
03816 frm->addr = stack->upper_id| FLG_MSG_DOWN;
03817
03818 frm->dinfo = 0;
03819 frm->len = 0;
03820
03821 msg_queue_tail(&glob_mgr->activatequeue, msg);
03822 sem_post(&glob_mgr->new_msg);
03823
03824
03825 return 0;
03826 }
03827
03828
03829 int queue_cleanup_bc(struct misdn_bchannel *bc)
03830 {
03831 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
03832 iframe_t *frm;
03833 if (!msg) {
03834 cb_log(0, bc->port, "queue_cleanup_bc: alloc_msg failed!\n");
03835 return -1;
03836 }
03837 frm=(iframe_t*)msg->data;
03838
03839
03840 frm->prim = MGR_CLEARSTACK| REQUEST;
03841
03842 frm->addr = bc->l3_id;
03843
03844 frm->dinfo = bc->port;
03845 frm->len = 0;
03846
03847 msg_queue_tail(&glob_mgr->activatequeue, msg);
03848 sem_post(&glob_mgr->new_msg);
03849
03850 return 0;
03851
03852 }
03853
03854 int misdn_lib_pid_restart(int pid)
03855 {
03856 struct misdn_bchannel *bc=manager_find_bc_by_pid(pid);
03857
03858 if (bc) {
03859 manager_clean_bc(bc);
03860 }
03861 return 0;
03862 }
03863
03864
03865 int misdn_lib_send_restart(int port, int channel)
03866 {
03867 struct misdn_stack *stack=find_stack_by_port(port);
03868 struct misdn_bchannel dummybc;
03869
03870 cb_log(0, port, "Sending Restarts on this port.\n");
03871
03872 misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
03873
03874
03875 if (channel <0) {
03876 dummybc.channel=-1;
03877 cb_log(0, port, "Restarting and all Interfaces\n");
03878 misdn_lib_send_event(&dummybc, EVENT_RESTART);
03879
03880 return 0;
03881 }
03882
03883
03884 if (channel >0) {
03885 int cnt;
03886 dummybc.channel=channel;
03887 cb_log(0, port, "Restarting and cleaning channel %d\n",channel);
03888 misdn_lib_send_event(&dummybc, EVENT_RESTART);
03889
03890
03891 for (cnt=0; cnt<=stack->b_num; cnt++) {
03892 if (stack->bc[cnt].in_use && stack->bc[cnt].channel == channel) {
03893 empty_bc(&stack->bc[cnt]);
03894 clean_up_bc(&stack->bc[cnt]);
03895 stack->bc[cnt].in_use=0;
03896 }
03897 }
03898 }
03899
03900 return 0;
03901 }
03902
03903
03904 int misdn_lib_port_restart(int port)
03905 {
03906 struct misdn_stack *stack=find_stack_by_port(port);
03907
03908 cb_log(0, port, "Restarting this port.\n");
03909 if (stack) {
03910 cb_log(0, port, "Stack:%p\n",stack);
03911
03912 clear_l3(stack);
03913 {
03914 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
03915 iframe_t *frm;
03916
03917 if (!msg) {
03918 cb_log(0, port, "port_restart: alloc_msg failed\n");
03919 return -1;
03920 }
03921
03922 frm=(iframe_t*)msg->data;
03923
03924
03925 frm->prim = DL_RELEASE | REQUEST;
03926 frm->addr = stack->upper_id | FLG_MSG_DOWN;
03927
03928 frm->dinfo = 0;
03929 frm->len = 0;
03930 msg_queue_tail(&glob_mgr->activatequeue, msg);
03931 sem_post(&glob_mgr->new_msg);
03932 }
03933
03934 if (stack->nt)
03935 misdn_lib_reinit_nt_stack(stack->port);
03936
03937 }
03938
03939 return 0;
03940 }
03941
03942
03943
03944 sem_t handler_started;
03945
03946
03947 static void manager_event_handler(void *arg)
03948 {
03949 sem_post(&handler_started);
03950 while (1) {
03951 struct misdn_stack *stack;
03952 msg_t *msg;
03953
03954
03955 sem_wait(&glob_mgr->new_msg);
03956
03957 for (msg=msg_dequeue(&glob_mgr->activatequeue);
03958 msg;
03959 msg=msg_dequeue(&glob_mgr->activatequeue)
03960 )
03961 {
03962
03963 iframe_t *frm = (iframe_t*) msg->data ;
03964
03965 switch ( frm->prim) {
03966
03967 case MGR_CLEARSTACK | REQUEST:
03968
03969 {
03970 struct misdn_stack *stack=find_stack_by_port(frm->dinfo);
03971 struct misdn_bchannel *bc;
03972 if (!stack) {
03973 cb_log(0,0,"no stack found with port [%d]!! so we cannot cleanup the bc\n",frm->dinfo);
03974 free_msg(msg);
03975 break;
03976 }
03977
03978 bc = find_bc_by_l3id(stack, frm->addr);
03979 if (bc) {
03980 cb_log(1,bc->port,"CLEARSTACK queued, cleaning up\n");
03981 clean_up_bc(bc);
03982 } else {
03983 cb_log(0,stack->port,"bc could not be cleaned correctly !! addr [%x]\n",frm->addr);
03984 }
03985 }
03986 free_msg(msg);
03987 break;
03988 case MGR_SETSTACK | REQUEST :
03989 free_msg(msg);
03990 break;
03991 default:
03992 mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
03993 free_msg(msg);
03994 }
03995 }
03996
03997 for (stack=glob_mgr->stack_list;
03998 stack;
03999 stack=stack->next ) {
04000
04001 while ( (msg=msg_dequeue(&stack->upqueue)) ) {
04002
04003 if (!handle_frm_nt(msg)) {
04004
04005 if (!handle_frm(msg)) {
04006
04007 cb_log(0,stack->port,"Wow we've got a strange issue while dequeueing a Frame\n");
04008 }
04009 }
04010 }
04011
04012
04013
04014
04015
04016
04017 while ( (msg=msg_dequeue(&stack->downqueue)) ) {
04018 if (stack->nt ) {
04019 pthread_mutex_lock(&stack->nstlock);
04020 if (stack->nst.manager_l3(&stack->nst, msg))
04021 cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");
04022 pthread_mutex_unlock(&stack->nstlock);
04023 } else {
04024 iframe_t *frm = (iframe_t *)msg->data;
04025 struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
04026 if (bc)
04027 send_msg(glob_mgr->midev, bc, msg);
04028 else {
04029 if (frm->dinfo == MISDN_ID_GLOBAL || frm->dinfo == MISDN_ID_DUMMY ) {
04030 struct misdn_bchannel dummybc;
04031 cb_log(5,0," --> GLOBAL/DUMMY\n");
04032 misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
04033 send_msg(glob_mgr->midev, &dummybc, msg);
04034 } else {
04035 cb_log(0,0,"No bc for Message\n");
04036 }
04037 }
04038 }
04039 }
04040 }
04041 }
04042 }
04043
04044
04045 int misdn_lib_maxports_get(void)
04046 {
04047
04048
04049 int i = mISDN_open();
04050 int max=0;
04051
04052 if (i<0)
04053 return -1;
04054
04055 max = mISDN_get_stack_count(i);
04056
04057 mISDN_close(i);
04058
04059 return max;
04060 }
04061
04062
04063 void misdn_lib_nt_keepcalls( int kc)
04064 {
04065 #ifdef FEATURE_NET_KEEPCALLS
04066 if (kc) {
04067 struct misdn_stack *stack=get_misdn_stack();
04068 for ( ; stack; stack=stack->next) {
04069 stack->nst.feature |= FEATURE_NET_KEEPCALLS;
04070 }
04071 }
04072 #endif
04073 }
04074
04075 void misdn_lib_nt_debug_init( int flags, char *file )
04076 {
04077 static int init=0;
04078 char *f;
04079
04080 if (!flags)
04081 f=NULL;
04082 else
04083 f=file;
04084
04085 if (!init) {
04086 debug_init( flags , f, f, f);
04087 init=1;
04088 } else {
04089 debug_close();
04090 debug_init( flags , f, f, f);
04091 }
04092 }
04093
04094
04095 int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data)
04096 {
04097 struct misdn_lib *mgr=calloc(1, sizeof(struct misdn_lib));
04098 char *tok, *tokb;
04099 char plist[1024];
04100 int midev;
04101 int port_count=0;
04102
04103 cb_log = iface->cb_log;
04104 cb_event = iface->cb_event;
04105 cb_jb_empty = iface->cb_jb_empty;
04106
04107 glob_mgr = mgr;
04108
04109 msg_init();
04110
04111 misdn_lib_nt_debug_init(0,NULL);
04112
04113 if (!portlist || (*portlist == 0) ) return 1;
04114
04115 init_flip_bits();
04116
04117 {
04118 strncpy(plist,portlist, 1024);
04119 plist[1023] = 0;
04120 }
04121
04122 memcpy(tone_425_flip,tone_425,TONE_425_SIZE);
04123 flip_buf_bits(tone_425_flip,TONE_425_SIZE);
04124
04125 memcpy(tone_silence_flip,tone_SILENCE,TONE_SILENCE_SIZE);
04126 flip_buf_bits(tone_silence_flip,TONE_SILENCE_SIZE);
04127
04128 midev=te_lib_init();
04129 mgr->midev=midev;
04130
04131 port_count=mISDN_get_stack_count(midev);
04132
04133 msg_queue_init(&mgr->activatequeue);
04134
04135 if (sem_init(&mgr->new_msg, 1, 0)<0)
04136 sem_init(&mgr->new_msg, 0, 0);
04137
04138 for (tok=strtok_r(plist," ,",&tokb );
04139 tok;
04140 tok=strtok_r(NULL," ,",&tokb)) {
04141 int port = atoi(tok);
04142 struct misdn_stack *stack;
04143 static int first=1;
04144 int ptp=0;
04145
04146 if (strstr(tok, "ptp"))
04147 ptp=1;
04148
04149 if (port > port_count) {
04150 cb_log(0, port, "Couldn't Initialize this port since we have only %d ports\n", port_count);
04151 exit(1);
04152 }
04153 stack=stack_init(midev, port, ptp);
04154
04155 if (!stack) {
04156 perror("stack_init");
04157 exit(1);
04158 }
04159
04160 {
04161 int i;
04162 for(i=0;i<=stack->b_num; i++) {
04163 int r;
04164 if ((r=init_bc(stack, &stack->bc[i], stack->midev,port,i, "", 1))<0) {
04165 cb_log(0, port, "Got Err @ init_bc :%d\n",r);
04166 exit(1);
04167 }
04168 }
04169 }
04170
04171 if (stack && first) {
04172 mgr->stack_list=stack;
04173 first=0;
04174 continue;
04175 }
04176
04177 if (stack) {
04178 struct misdn_stack * help;
04179 for ( help=mgr->stack_list; help; help=help->next )
04180 if (help->next == NULL) break;
04181 help->next=stack;
04182 }
04183
04184 }
04185
04186 if (sem_init(&handler_started, 1, 0)<0)
04187 sem_init(&handler_started, 0, 0);
04188
04189 cb_log(8, 0, "Starting Event Handler\n");
04190 pthread_create( &mgr->event_handler_thread, NULL,(void*)manager_event_handler, mgr);
04191
04192 sem_wait(&handler_started) ;
04193 cb_log(8, 0, "Starting Event Catcher\n");
04194 pthread_create( &mgr->event_thread, NULL, (void*)misdn_lib_isdn_event_catcher, mgr);
04195
04196 cb_log(8, 0, "Event Catcher started\n");
04197
04198 global_state= MISDN_INITIALIZED;
04199
04200 return (mgr == NULL);
04201 }
04202
04203 void misdn_lib_destroy(void)
04204 {
04205 struct misdn_stack *help;
04206 int i;
04207
04208 for ( help=glob_mgr->stack_list; help; help=help->next ) {
04209 for(i=0;i<=help->b_num; i++) {
04210 char buf[1024];
04211 mISDN_write_frame(help->midev, buf, help->bc[i].addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
04212 help->bc[i].addr = 0;
04213 }
04214 cb_log (1, help->port, "Destroying this port.\n");
04215 stack_destroy(help);
04216 }
04217
04218 if (global_state == MISDN_INITIALIZED) {
04219 cb_log(4, 0, "Killing Handler Thread\n");
04220 if ( pthread_cancel(glob_mgr->event_handler_thread) == 0 ) {
04221 cb_log(4, 0, "Joining Handler Thread\n");
04222 pthread_join(glob_mgr->event_handler_thread, NULL);
04223 }
04224
04225 cb_log(4, 0, "Killing Main Thread\n");
04226 if ( pthread_cancel(glob_mgr->event_thread) == 0 ) {
04227 cb_log(4, 0, "Joining Main Thread\n");
04228 pthread_join(glob_mgr->event_thread, NULL);
04229 }
04230 }
04231
04232 cb_log(1, 0, "Closing mISDN device\n");
04233 te_lib_destroy(glob_mgr->midev);
04234 }
04235
04236 char *manager_isdn_get_info(enum event_e event)
04237 {
04238 return isdn_get_info(msgs_g , event, 0);
04239 }
04240
04241 void manager_bchannel_activate(struct misdn_bchannel *bc)
04242 {
04243 char buf[128];
04244
04245 struct misdn_stack *stack=get_stack_by_bc(bc);
04246
04247 if (!stack) {
04248 cb_log(0, bc->port, "bchannel_activate: Stack not found !");
04249 return ;
04250 }
04251
04252
04253 clear_ibuffer(bc->astbuf);
04254
04255 cb_log(5, stack->port, "$$$ Bchan Activated addr %x\n", bc->addr);
04256
04257 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_ESTABLISH | REQUEST, 0,0, NULL, TIMEOUT_1SEC);
04258
04259 return ;
04260 }
04261
04262
04263 void manager_bchannel_deactivate(struct misdn_bchannel * bc)
04264 {
04265 struct misdn_stack *stack=get_stack_by_bc(bc);
04266 iframe_t dact;
04267 char buf[128];
04268
04269 switch (bc->bc_state) {
04270 case BCHAN_ACTIVATED:
04271 break;
04272 case BCHAN_BRIDGED:
04273 misdn_split_conf(bc,bc->conf_id);
04274 break;
04275 default:
04276 cb_log( 4, bc->port,"bchan_deactivate: called but not activated\n");
04277 return ;
04278
04279 }
04280
04281 cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr);
04282
04283 bc->generate_tone=0;
04284
04285 dact.prim = DL_RELEASE | REQUEST;
04286 dact.addr = bc->addr | FLG_MSG_DOWN;
04287 dact.dinfo = 0;
04288 dact.len = 0;
04289 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_RELEASE|REQUEST,0,0,NULL, TIMEOUT_1SEC);
04290
04291 clear_ibuffer(bc->astbuf);
04292
04293 bc_state_change(bc,BCHAN_RELEASE);
04294
04295 return;
04296 }
04297
04298
04299 int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len)
04300 {
04301 struct misdn_stack *stack=get_stack_by_bc(bc);
04302 char buf[4096 + mISDN_HEADER_LEN];
04303 iframe_t *frm = (iframe_t*)buf;
04304 int r;
04305
04306 switch (bc->bc_state) {
04307 case BCHAN_ACTIVATED:
04308 case BCHAN_BRIDGED:
04309 break;
04310 default:
04311 cb_log(3, bc->port, "BC not yet activated (state:%s)\n",bc_state2str(bc->bc_state));
04312 return -1;
04313 }
04314
04315 frm->prim = DL_DATA|REQUEST;
04316 frm->dinfo = 0;
04317 frm->addr = bc->addr | FLG_MSG_DOWN ;
04318
04319 frm->len = len;
04320 memcpy(&buf[mISDN_HEADER_LEN], data,len);
04321
04322 if ( misdn_cap_is_speech(bc->capability) )
04323 flip_buf_bits( &buf[mISDN_HEADER_LEN], len);
04324 else
04325 cb_log(6, stack->port, "Writing %d data bytes\n",len);
04326
04327 cb_log(9, stack->port, "Writing %d bytes 2 mISDN\n",len);
04328 r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT);
04329 return 0;
04330 }
04331
04332
04333
04334
04335
04336
04337 void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2)
04338 {
04339 unsigned char buffer[mISDN_HEADER_LEN+2*sizeof(int)];
04340 iframe_t *ctrl = (iframe_t *)buffer;
04341 unsigned int *d = (unsigned int*)&ctrl->data.p;
04342
04343
04344 cb_log(4,bc->port,"ph_control: c1:%x c2:%x\n",c1,c2);
04345
04346 ctrl->prim = PH_CONTROL | REQUEST;
04347 ctrl->addr = bc->addr | FLG_MSG_DOWN;
04348 ctrl->dinfo = 0;
04349 ctrl->len = sizeof(unsigned int)*2;
04350 *d++ = c1;
04351 *d++ = c2;
04352 mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
04353 }
04354
04355
04356
04357
04358 void isdn_lib_update_rxgain (struct misdn_bchannel *bc)
04359 {
04360 manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
04361 }
04362
04363 void isdn_lib_update_txgain (struct misdn_bchannel *bc)
04364 {
04365 manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
04366 }
04367
04368 void isdn_lib_update_ec (struct misdn_bchannel *bc)
04369 {
04370 #ifdef MISDN_1_2
04371 if (*bc->pipeline)
04372 #else
04373 if (bc->ec_enable)
04374 #endif
04375 manager_ec_enable(bc);
04376 else
04377 manager_ec_disable(bc);
04378 }
04379
04380 void isdn_lib_stop_dtmf (struct misdn_bchannel *bc)
04381 {
04382 manager_ph_control(bc, DTMF_TONE_STOP, 0);
04383 }
04384
04385
04386
04387
04388 void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len)
04389 {
04390 unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
04391 iframe_t *ctrl = (iframe_t *)buffer;
04392 unsigned int *d = (unsigned int *)&ctrl->data.p;
04393
04394
04395 ctrl->prim = PH_CONTROL | REQUEST;
04396 ctrl->addr = bc->addr | FLG_MSG_DOWN;
04397 ctrl->dinfo = 0;
04398 ctrl->len = sizeof(unsigned int) + c2_len;
04399 *d++ = c1;
04400 memcpy(d, c2, c2_len);
04401 mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
04402 }
04403
04404
04405
04406
04407 void manager_clean_bc(struct misdn_bchannel *bc )
04408 {
04409 struct misdn_stack *stack=get_stack_by_bc(bc);
04410
04411 if (bc->channel>0)
04412 empty_chan_in_stack(stack, bc->channel);
04413 empty_bc(bc);
04414 bc->in_use=0;
04415
04416 cb_event(EVENT_CLEANUP, bc, NULL);
04417 }
04418
04419
04420 void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder)
04421 {
04422 struct misdn_bchannel *help;
04423 cb_log(4,stack->port, "*HOLDER: add %x\n",holder->l3_id);
04424
04425 holder->stack_holder=1;
04426 holder->next=NULL;
04427
04428 if (!stack->holding) {
04429 stack->holding = holder;
04430 return;
04431 }
04432
04433 for (help=stack->holding;
04434 help;
04435 help=help->next) {
04436 if (!help->next) {
04437 help->next=holder;
04438 break;
04439 }
04440 }
04441
04442 }
04443
04444 void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder)
04445 {
04446 struct misdn_bchannel *h1;
04447
04448 if (!holder->stack_holder) return;
04449
04450 holder->stack_holder=0;
04451
04452 cb_log(4,stack->port, "*HOLDER: remove %x\n",holder->l3_id);
04453 if (!stack || ! stack->holding) return;
04454
04455 if (holder == stack->holding) {
04456 stack->holding = stack->holding->next;
04457 return;
04458 }
04459
04460 for (h1=stack->holding;
04461 h1;
04462 h1=h1->next) {
04463 if (h1->next == holder) {
04464 h1->next=h1->next->next;
04465 return ;
04466 }
04467 }
04468 }
04469
04470 struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned long l3id)
04471 {
04472 struct misdn_bchannel *help;
04473
04474 cb_log(4,stack?stack->port:0, "*HOLDER: find %lx\n",l3id);
04475
04476 if (!stack) return NULL;
04477
04478 for (help=stack->holding;
04479 help;
04480 help=help->next) {
04481 if (help->l3_id == l3id) {
04482 cb_log(4,stack->port, "*HOLDER: found bc\n");
04483 return help;
04484 }
04485 }
04486
04487 cb_log(4,stack->port, "*HOLDER: find nothing\n");
04488 return NULL;
04489 }
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499 struct misdn_bchannel *misdn_lib_find_held_bc(int port, int l3_id)
04500 {
04501 struct misdn_bchannel *bc;
04502 struct misdn_stack *stack;
04503
04504 bc = NULL;
04505 for (stack = get_misdn_stack(); stack; stack = stack->next) {
04506 if (stack->port == port) {
04507 bc = stack_holder_find(stack, l3_id);
04508 break;
04509 }
04510 }
04511
04512 return bc;
04513 }
04514
04515 void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone)
04516 {
04517 char buf[mISDN_HEADER_LEN + 128] = "";
04518 iframe_t *frm = (iframe_t*)buf;
04519
04520 switch(tone) {
04521 case TONE_DIAL:
04522 manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE);
04523 break;
04524
04525 case TONE_ALERTING:
04526 manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING);
04527 break;
04528
04529 case TONE_HANGUP:
04530 manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP);
04531 break;
04532
04533 case TONE_NONE:
04534 default:
04535 manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP);
04536 }
04537
04538 frm->prim=DL_DATA|REQUEST;
04539 frm->addr=bc->addr|FLG_MSG_DOWN;
04540 frm->dinfo=0;
04541 frm->len=128;
04542
04543 mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
04544 }
04545
04546
04547 void manager_ec_enable(struct misdn_bchannel *bc)
04548 {
04549 struct misdn_stack *stack=get_stack_by_bc(bc);
04550
04551 cb_log(4, stack?stack->port:0,"ec_enable\n");
04552
04553 if (!misdn_cap_is_speech(bc->capability)) {
04554 cb_log(1, stack?stack->port:0, " --> no speech? cannot enable EC\n");
04555 } else {
04556
04557 #ifdef MISDN_1_2
04558 if (*bc->pipeline) {
04559 cb_log(3, stack?stack->port:0,"Sending Control PIPELINE_CFG %s\n",bc->pipeline);
04560 manager_ph_control_block(bc, PIPELINE_CFG, bc->pipeline, strlen(bc->pipeline) + 1);
04561 }
04562 #else
04563 int ec_arr[2];
04564
04565 if (bc->ec_enable) {
04566 cb_log(3, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d\n",bc->ec_deftaps);
04567
04568 switch (bc->ec_deftaps) {
04569 case 4:
04570 case 8:
04571 case 16:
04572 case 32:
04573 case 64:
04574 case 128:
04575 case 256:
04576 case 512:
04577 case 1024:
04578 cb_log(4, stack->port, "Taps is %d\n",bc->ec_deftaps);
04579 break;
04580 default:
04581 cb_log(0, stack->port, "Taps should be power of 2\n");
04582 bc->ec_deftaps=128;
04583 }
04584
04585 ec_arr[0]=bc->ec_deftaps;
04586 ec_arr[1]=0;
04587
04588 manager_ph_control_block(bc, ECHOCAN_ON, ec_arr, sizeof(ec_arr));
04589 }
04590 #endif
04591 }
04592 }
04593
04594
04595
04596 void manager_ec_disable(struct misdn_bchannel *bc)
04597 {
04598 struct misdn_stack *stack=get_stack_by_bc(bc);
04599
04600 cb_log(4, stack?stack->port:0," --> ec_disable\n");
04601
04602 if (!misdn_cap_is_speech(bc->capability)) {
04603 cb_log(1, stack?stack->port:0, " --> no speech? cannot disable EC\n");
04604 return;
04605 }
04606
04607 #ifdef MISDN_1_2
04608 manager_ph_control_block(bc, PIPELINE_CFG, "", 0);
04609 #else
04610 if ( ! bc->ec_enable) {
04611 cb_log(3, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n");
04612 manager_ph_control(bc, ECHOCAN_OFF, 0);
04613 }
04614 #endif
04615 }
04616
04617 struct misdn_stack* get_misdn_stack() {
04618 return glob_mgr->stack_list;
04619 }
04620
04621
04622
04623 void misdn_join_conf(struct misdn_bchannel *bc, int conf_id)
04624 {
04625 char data[16] = "";
04626
04627 bc_state_change(bc,BCHAN_BRIDGED);
04628 manager_ph_control(bc, CMX_RECEIVE_OFF, 0);
04629 manager_ph_control(bc, CMX_CONF_JOIN, conf_id);
04630
04631 cb_log(3,bc->port, "Joining bc:%x in conf:%d\n",bc->addr,conf_id);
04632
04633 misdn_lib_tx2misdn_frm(bc, data, sizeof(data) - 1);
04634 }
04635
04636
04637 void misdn_split_conf(struct misdn_bchannel *bc, int conf_id)
04638 {
04639 bc_state_change(bc,BCHAN_ACTIVATED);
04640 manager_ph_control(bc, CMX_RECEIVE_ON, 0);
04641 manager_ph_control(bc, CMX_CONF_SPLIT, conf_id);
04642
04643 cb_log(4,bc->port, "Splitting bc:%x in conf:%d\n",bc->addr,conf_id);
04644 }
04645
04646 void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2)
04647 {
04648 int conf_id = bc1->pid + 1;
04649 struct misdn_bchannel *bc_list[] = { bc1, bc2, NULL };
04650 struct misdn_bchannel **bc;
04651
04652 cb_log(4, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port);
04653
04654 for (bc=bc_list; *bc; bc++) {
04655 (*bc)->conf_id=conf_id;
04656 cb_log(4, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr);
04657
04658 switch((*bc)->bc_state) {
04659 case BCHAN_ACTIVATED:
04660 misdn_join_conf(*bc,conf_id);
04661 break;
04662 default:
04663 bc_next_state_change(*bc,BCHAN_BRIDGED);
04664 break;
04665 }
04666 }
04667 }
04668
04669 void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2)
04670 {
04671
04672 struct misdn_bchannel *bc_list[]={
04673 bc1,bc2,NULL
04674 };
04675 struct misdn_bchannel **bc;
04676
04677 for (bc=bc_list; *bc; bc++) {
04678 if ( (*bc)->bc_state == BCHAN_BRIDGED){
04679 misdn_split_conf( *bc, (*bc)->conf_id);
04680 } else {
04681 cb_log( 2, (*bc)->port, "BC not bridged (state:%s) so not splitting it\n",bc_state2str((*bc)->bc_state));
04682 }
04683 }
04684
04685 }
04686
04687
04688
04689 void misdn_lib_echo(struct misdn_bchannel *bc, int onoff)
04690 {
04691 cb_log(3,bc->port, " --> ECHO %s\n", onoff?"ON":"OFF");
04692 manager_ph_control(bc, onoff?CMX_ECHO_ON:CMX_ECHO_OFF, 0);
04693 }
04694
04695
04696
04697 void misdn_lib_reinit_nt_stack(int port)
04698 {
04699 struct misdn_stack *stack=find_stack_by_port(port);
04700
04701 if (stack) {
04702 stack->l2link=0;
04703 stack->blocked=0;
04704
04705 cleanup_Isdnl3(&stack->nst);
04706 cleanup_Isdnl2(&stack->nst);
04707
04708
04709 memset(&stack->nst, 0, sizeof(net_stack_t));
04710 memset(&stack->mgr, 0, sizeof(manager_t));
04711
04712 stack->mgr.nst = &stack->nst;
04713 stack->nst.manager = &stack->mgr;
04714
04715 stack->nst.l3_manager = handle_event_nt;
04716 stack->nst.device = glob_mgr->midev;
04717 stack->nst.cardnr = port;
04718 stack->nst.d_stid = stack->d_stid;
04719
04720 stack->nst.feature = FEATURE_NET_HOLD;
04721 if (stack->ptp)
04722 stack->nst.feature |= FEATURE_NET_PTP;
04723 if (stack->pri)
04724 stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
04725
04726 stack->nst.l1_id = stack->lower_id;
04727 stack->nst.l2_id = stack->upper_id;
04728
04729 msg_queue_init(&stack->nst.down_queue);
04730
04731 Isdnl2Init(&stack->nst);
04732 Isdnl3Init(&stack->nst);
04733
04734 if (!stack->ptp)
04735 misdn_lib_get_l1_up(stack);
04736 misdn_lib_get_l2_up(stack);
04737 }
04738 }
04739
04740