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