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 int ret;
02320 ret = mISDN_write_frame(stack->midev, msg->data, frm->addr,
02321 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
02322 test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
02323 pthread_mutex_lock(&stack->nstlock);
02324 ret = it->function(it->data);
02325 pthread_mutex_unlock(&stack->nstlock);
02326 free_msg(msg);
02327 return 1;
02328 }
02329 }
02330
02331 cb_log(0, 0, "Timer Msg without Timer ??\n");
02332 free_msg(msg);
02333 return 1;
02334 }
02335
02336 return 0;
02337 }
02338
02339
02340
02341 void misdn_lib_tone_generator_start(struct misdn_bchannel *bc)
02342 {
02343 bc->generate_tone=1;
02344 }
02345
02346 void misdn_lib_tone_generator_stop(struct misdn_bchannel *bc)
02347 {
02348 bc->generate_tone=0;
02349 }
02350
02351
02352 static int do_tone(struct misdn_bchannel *bc, int len)
02353 {
02354 bc->tone_cnt=len;
02355
02356 if (bc->generate_tone) {
02357 cb_event(EVENT_TONE_GENERATE, bc, glob_mgr->user_data);
02358
02359 if ( !bc->nojitter ) {
02360 misdn_tx_jitter(bc,len);
02361 }
02362
02363 return 1;
02364 }
02365
02366 return 0;
02367 }
02368
02369
02370 #ifdef MISDN_SAVE_DATA
02371 static void misdn_save_data(int id, char *p1, int l1, char *p2, int l2)
02372 {
02373 char n1[32],n2[32];
02374 FILE *rx, *tx;
02375
02376 sprintf(n1,"/tmp/misdn-rx-%d.raw",id);
02377 sprintf(n2,"/tmp/misdn-tx-%d.raw",id);
02378
02379 rx = fopen(n1,"a+");
02380 tx = fopen(n2,"a+");
02381
02382 if (!rx || !tx) {
02383 cb_log(0,0,"Couldn't open files: %s\n",strerror(errno));
02384 if (rx)
02385 fclose(rx);
02386 if (tx)
02387 fclose(tx);
02388 return ;
02389 }
02390
02391 fwrite(p1,1,l1,rx);
02392 fwrite(p2,1,l2,tx);
02393
02394 fclose(rx);
02395 fclose(tx);
02396
02397 }
02398 #endif
02399
02400 void misdn_tx_jitter(struct misdn_bchannel *bc, int len)
02401 {
02402 char buf[4096 + mISDN_HEADER_LEN];
02403 char *data=&buf[mISDN_HEADER_LEN];
02404 iframe_t *txfrm= (iframe_t*)buf;
02405 int jlen, r;
02406
02407 jlen=cb_jb_empty(bc,data,len);
02408
02409 if (jlen) {
02410 #ifdef MISDN_SAVE_DATA
02411 misdn_save_data((bc->port*100+bc->channel), data, jlen, bc->bframe, bc->bframe_len);
02412 #endif
02413 flip_buf_bits( data, jlen);
02414
02415 if (jlen < len) {
02416 cb_log(1, bc->port, "Jitterbuffer Underrun. Got %d of expected %d\n", jlen, len);
02417 }
02418
02419 txfrm->prim = DL_DATA|REQUEST;
02420
02421 txfrm->dinfo = 0;
02422
02423 txfrm->addr = bc->addr|FLG_MSG_DOWN;
02424
02425 txfrm->len =jlen;
02426 cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len);
02427
02428 r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 );
02429 } else {
02430 #define MISDN_GEN_SILENCE
02431 #ifdef MISDN_GEN_SILENCE
02432 int cnt=len/TONE_SILENCE_SIZE;
02433 int rest=len%TONE_SILENCE_SIZE;
02434 int i;
02435
02436 for (i=0; i<cnt; i++) {
02437 memcpy(data, tone_silence_flip, TONE_SILENCE_SIZE );
02438 data +=TONE_SILENCE_SIZE;
02439 }
02440
02441 if (rest) {
02442 memcpy(data, tone_silence_flip, rest);
02443 }
02444
02445 txfrm->prim = DL_DATA|REQUEST;
02446
02447 txfrm->dinfo = 0;
02448
02449 txfrm->addr = bc->addr|FLG_MSG_DOWN;
02450
02451 txfrm->len =len;
02452 cb_log(5, bc->port, "Transmitting %d samples of silence to misdn\n", len);
02453
02454 r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 );
02455 #else
02456 r = 0;
02457 #endif
02458 }
02459
02460 if (r < 0) {
02461 cb_log(1, bc->port, "Error in mISDN_write (%s)\n", strerror(errno));
02462 }
02463 }
02464
02465 static int handle_bchan(msg_t *msg)
02466 {
02467 iframe_t *frm= (iframe_t*)msg->data;
02468 struct misdn_bchannel *bc=find_bc_by_addr(frm->addr);
02469 struct misdn_stack *stack;
02470
02471 if (!bc) {
02472 cb_log(1,0,"handle_bchan: BC not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
02473 return 0 ;
02474 }
02475
02476 stack = get_stack_by_bc(bc);
02477
02478 if (!stack) {
02479 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);
02480 return 0;
02481 }
02482
02483 switch (frm->prim) {
02484
02485 case MGR_SETSTACK| CONFIRM:
02486 cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|CONFIRM pid:%d\n",bc->pid);
02487 break;
02488
02489 case MGR_SETSTACK| INDICATION:
02490 cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|IND pid:%d\n",bc->pid);
02491 break;
02492 #if 0
02493 AGAIN:
02494 bc->addr = mISDN_get_layerid(stack->midev, bc->b_stid, bc->layer);
02495 if (!bc->addr) {
02496
02497 if (errno == EAGAIN) {
02498 usleep(1000);
02499 goto AGAIN;
02500 }
02501
02502 cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno));
02503
02504
02505
02506 bc->addr= frm->addr;
02507 } else if ( bc->addr < 0) {
02508 cb_log(0, stack->port,"$$$ bc->addr <0 Error:%s\n",strerror(errno));
02509 bc->addr=0;
02510 }
02511
02512 cb_log(4, stack->port," --> Got Adr %x\n", bc->addr);
02513
02514 free_msg(msg);
02515
02516
02517 switch(bc->bc_state) {
02518 case BCHAN_SETUP:
02519 bc_state_change(bc,BCHAN_SETUPED);
02520 break;
02521
02522 case BCHAN_CLEAN_REQUEST:
02523 default:
02524 cb_log(0, stack->port," --> STATE WASN'T SETUP (but %s) in SETSTACK|IND pid:%d\n",bc_state2str(bc->bc_state), bc->pid);
02525 clean_up_bc(bc);
02526 }
02527 return 1;
02528 #endif
02529
02530 case MGR_DELLAYER| INDICATION:
02531 cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|IND pid:%d\n",bc->pid);
02532 break;
02533
02534 case MGR_DELLAYER| CONFIRM:
02535 cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|CNF pid:%d\n",bc->pid);
02536
02537 bc->pid=0;
02538 bc->addr=0;
02539
02540 free_msg(msg);
02541 return 1;
02542
02543 case PH_ACTIVATE | INDICATION:
02544 case DL_ESTABLISH | INDICATION:
02545 cb_log(3, stack->port, "BCHAN: ACT Ind pid:%d\n", bc->pid);
02546
02547 free_msg(msg);
02548 return 1;
02549
02550 case PH_ACTIVATE | CONFIRM:
02551 case DL_ESTABLISH | CONFIRM:
02552
02553 cb_log(3, stack->port, "BCHAN: bchan ACT Confirm pid:%d\n",bc->pid);
02554 free_msg(msg);
02555
02556 return 1;
02557
02558 case DL_ESTABLISH | REQUEST:
02559 {
02560 char buf[128];
02561 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_ESTABLISH | CONFIRM, 0,0, NULL, TIMEOUT_1SEC);
02562 }
02563 free_msg(msg);
02564 return 1;
02565
02566 case DL_RELEASE|REQUEST:
02567 {
02568 char buf[128];
02569 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_TARGET | FLG_MSG_DOWN, DL_RELEASE| CONFIRM, 0,0, NULL, TIMEOUT_1SEC);
02570 }
02571 free_msg(msg);
02572 return 1;
02573
02574 case PH_DEACTIVATE | INDICATION:
02575 case DL_RELEASE | INDICATION:
02576 cb_log (3, stack->port, "BCHAN: DeACT Ind pid:%d\n",bc->pid);
02577
02578 free_msg(msg);
02579 return 1;
02580
02581 case PH_DEACTIVATE | CONFIRM:
02582 case DL_RELEASE | CONFIRM:
02583 cb_log(3, stack->port, "BCHAN: DeACT Conf pid:%d\n",bc->pid);
02584
02585 free_msg(msg);
02586 return 1;
02587
02588 case PH_CONTROL|INDICATION:
02589 {
02590 unsigned int *cont = (unsigned int *) &frm->data.p;
02591
02592 cb_log(4, stack->port,
02593 "PH_CONTROL: channel:%d caller%d:\"%s\" <%s> dialed%d:%s \n",
02594 bc->channel,
02595 bc->caller.number_type,
02596 bc->caller.name,
02597 bc->caller.number,
02598 bc->dialed.number_type,
02599 bc->dialed.number);
02600
02601 if ((*cont & ~DTMF_TONE_MASK) == DTMF_TONE_VAL) {
02602 int dtmf = *cont & DTMF_TONE_MASK;
02603 cb_log(4, stack->port, " --> DTMF TONE: %c\n",dtmf);
02604 bc->dtmf=dtmf;
02605 cb_event(EVENT_DTMF_TONE, bc, glob_mgr->user_data);
02606
02607 free_msg(msg);
02608 return 1;
02609 }
02610 if (*cont == BF_REJECT) {
02611 cb_log(4, stack->port, " --> BF REJECT\n");
02612 free_msg(msg);
02613 return 1;
02614 }
02615 if (*cont == BF_ACCEPT) {
02616 cb_log(4, stack->port, " --> BF ACCEPT\n");
02617 free_msg(msg);
02618 return 1;
02619 }
02620 }
02621 break;
02622
02623 case PH_DATA|REQUEST:
02624 case DL_DATA|REQUEST:
02625 cb_log(0, stack->port, "DL_DATA REQUEST \n");
02626 do_tone(bc, 64);
02627
02628 free_msg(msg);
02629 return 1;
02630
02631
02632 case PH_DATA|INDICATION:
02633 case DL_DATA|INDICATION:
02634 {
02635 bc->bframe = (void*)&frm->data.i;
02636 bc->bframe_len = frm->len;
02637
02638
02639 if ( misdn_cap_is_speech(bc->capability) )
02640 flip_buf_bits(bc->bframe, bc->bframe_len);
02641
02642
02643 if (!bc->bframe_len) {
02644 cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
02645 free_msg(msg);
02646 return 1;
02647 }
02648
02649 if ( (bc->addr&STACK_ID_MASK) != (frm->addr&STACK_ID_MASK) ) {
02650 cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
02651 free_msg(msg);
02652 return 1;
02653 }
02654
02655 #if MISDN_DEBUG
02656 cb_log(0, stack->port, "DL_DATA INDICATION Len %d\n", frm->len);
02657
02658 #endif
02659
02660 if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) {
02661 int t;
02662
02663 #ifdef MISDN_B_DEBUG
02664 cb_log(0,bc->port,"do_tone START\n");
02665 #endif
02666 t=do_tone(bc,frm->len);
02667
02668 #ifdef MISDN_B_DEBUG
02669 cb_log(0,bc->port,"do_tone STOP (%d)\n",t);
02670 #endif
02671 if ( !t ) {
02672 int i;
02673
02674 if ( misdn_cap_is_speech(bc->capability)) {
02675 if ( !bc->nojitter ) {
02676 #ifdef MISDN_B_DEBUG
02677 cb_log(0,bc->port,"tx_jitter START\n");
02678 #endif
02679 misdn_tx_jitter(bc,frm->len);
02680 #ifdef MISDN_B_DEBUG
02681 cb_log(0,bc->port,"tx_jitter STOP\n");
02682 #endif
02683 }
02684 }
02685
02686 #ifdef MISDN_B_DEBUG
02687 cb_log(0,bc->port,"EVENT_B_DATA START\n");
02688 #endif
02689
02690 i = cb_event(EVENT_BCHAN_DATA, bc, glob_mgr->user_data);
02691 #ifdef MISDN_B_DEBUG
02692 cb_log(0,bc->port,"EVENT_B_DATA STOP\n");
02693 #endif
02694
02695 if (i<0) {
02696 cb_log(10,stack->port,"cb_event returned <0\n");
02697
02698 }
02699 }
02700 }
02701 free_msg(msg);
02702 return 1;
02703 }
02704
02705
02706 case PH_CONTROL | CONFIRM:
02707 cb_log(4, stack->port, "PH_CONTROL|CNF bc->addr:%x\n", frm->addr);
02708 free_msg(msg);
02709 return 1;
02710
02711 case PH_DATA | CONFIRM:
02712 case DL_DATA|CONFIRM:
02713 #if MISDN_DEBUG
02714
02715 cb_log(0, stack->port, "Data confirmed\n");
02716
02717 #endif
02718 free_msg(msg);
02719 return 1;
02720 case DL_DATA|RESPONSE:
02721 #if MISDN_DEBUG
02722 cb_log(0, stack->port, "Data response\n");
02723
02724 #endif
02725 break;
02726 }
02727
02728 return 0;
02729 }
02730
02731
02732
02733 static int handle_frm_nt(msg_t *msg)
02734 {
02735 iframe_t *frm= (iframe_t*)msg->data;
02736 struct misdn_stack *stack;
02737 int err=0;
02738
02739 stack=find_stack_by_addr( frm->addr );
02740
02741
02742
02743 if (!stack || !stack->nt) {
02744 return 0;
02745 }
02746
02747
02748 pthread_mutex_lock(&stack->nstlock);
02749 if ((err=stack->nst.l1_l2(&stack->nst,msg))) {
02750 pthread_mutex_unlock(&stack->nstlock);
02751 if (nt_err_cnt > 0 ) {
02752 if (nt_err_cnt < 100) {
02753 nt_err_cnt++;
02754 cb_log(0, stack->port, "NT Stack sends us error: %d \n", err);
02755 } else if (nt_err_cnt < 105){
02756 cb_log(0, stack->port, "NT Stack sends us error: %d over 100 times, so I'll stop this message\n", err);
02757 nt_err_cnt = - 1;
02758 }
02759 }
02760 free_msg(msg);
02761 return 1;
02762 }
02763 pthread_mutex_unlock(&stack->nstlock);
02764 return 1;
02765 }
02766
02767
02768 static int handle_frm(msg_t *msg)
02769 {
02770 struct misdn_bchannel dummybc;
02771 struct misdn_bchannel *bc;
02772 iframe_t *frm;
02773 struct misdn_stack *stack;
02774 enum event_e event;
02775 enum event_response_e response;
02776 int ret;
02777 int channel;
02778 int tmpcause;
02779 int tmp_out_cause;
02780
02781 frm = (iframe_t*) msg->data;
02782 stack = find_stack_by_addr(frm->addr);
02783 if (!stack || stack->nt) {
02784 return 0;
02785 }
02786
02787 cb_log(4, stack ? stack->port : 0, "handle_frm: frm->addr:%x frm->prim:%x\n", frm->addr, frm->prim);
02788
02789 ret = handle_cr(stack, frm);
02790 if (ret < 0) {
02791 cb_log(3, stack ? stack->port : 0, "handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr);
02792 }
02793 if (ret) {
02794 free_msg(msg);
02795 return 1;
02796 }
02797
02798 bc = find_bc_by_l3id(stack, frm->dinfo);
02799 if (!bc) {
02800 misdn_make_dummy(&dummybc, stack->port, 0, stack->nt, 0);
02801 switch (frm->prim) {
02802 case CC_RESTART | CONFIRM:
02803 dummybc.l3_id = MISDN_ID_GLOBAL;
02804 bc = &dummybc;
02805 break;
02806 case CC_SETUP | INDICATION:
02807 dummybc.l3_id = frm->dinfo;
02808 bc = &dummybc;
02809
02810 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
02811
02812 free_msg(msg);
02813 return 1;
02814 default:
02815 if (frm->prim == (CC_FACILITY | INDICATION)) {
02816 cb_log(5, stack->port, " --> Using Dummy BC for FACILITY\n");
02817 } else {
02818 cb_log(0, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
02819 dummybc.l3_id = frm->dinfo;
02820 }
02821 bc = &dummybc;
02822 break;
02823 }
02824 }
02825
02826 event = isdn_msg_get_event(msgs_g, msg, 0);
02827 isdn_msg_parse_event(msgs_g, msg, bc, 0);
02828
02829
02830 ret = handle_event(bc, event, frm);
02831 if (ret < 0) {
02832 cb_log(0, stack->port, "couldn't handle event\n");
02833 free_msg(msg);
02834 return 1;
02835 }
02836
02837
02838 cb_log(5, stack->port, "lib Got Prim: Addr %x prim %x dinfo %x\n", frm->addr, frm->prim, frm->dinfo);
02839
02840 if (!isdn_get_info(msgs_g, event, 0)) {
02841 cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n", frm->addr, frm->prim, frm->dinfo);
02842 response = RESPONSE_OK;
02843 } else {
02844 response = cb_event(event, bc, glob_mgr->user_data);
02845 }
02846
02847 switch (event) {
02848 case EVENT_SETUP:
02849 switch (response) {
02850 case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE:
02851 cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n");
02852 break;
02853 case RESPONSE_IGNORE_SETUP:
02854
02855 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
02856
02857 case RESPONSE_RELEASE_SETUP:
02858 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
02859 if (bc->channel > 0) {
02860 empty_chan_in_stack(stack, bc->channel);
02861 }
02862 empty_bc(bc);
02863 bc_state_change(bc, BCHAN_CLEANED);
02864 bc->in_use = 0;
02865
02866 cb_log(0, stack->port, "GOT IGNORE SETUP\n");
02867 break;
02868 case RESPONSE_OK:
02869 cb_log(4, stack->port, "GOT SETUP OK\n");
02870 break;
02871 default:
02872 break;
02873 }
02874 break;
02875 case EVENT_RELEASE_COMPLETE:
02876
02877 channel = bc->channel;
02878 tmpcause = bc->cause;
02879 tmp_out_cause = bc->out_cause;
02880
02881 empty_bc(bc);
02882 bc->cause = tmpcause;
02883 bc->out_cause = tmp_out_cause;
02884 clean_up_bc(bc);
02885 bc->in_use = 0;
02886
02887 if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) {
02888 cb_log(0, stack->port, "**** Received CAUSE:%d, restarting channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel);
02889 misdn_lib_send_restart(stack->port, channel);
02890 }
02891 if (channel > 0) {
02892 empty_chan_in_stack(stack, channel);
02893 }
02894 break;
02895 case EVENT_RESTART:
02896 cb_log(0, stack->port, "**** Received RESTART channel:%d\n", bc->restart_channel);
02897 empty_chan_in_stack(stack, bc->restart_channel);
02898 break;
02899 default:
02900 break;
02901 }
02902
02903 cb_log(5, stack->port, "Freeing Msg on prim:%x \n", frm->prim);
02904 free_msg(msg);
02905 return 1;
02906 }
02907
02908
02909 static int handle_l1(msg_t *msg)
02910 {
02911 iframe_t *frm = (iframe_t*) msg->data;
02912 struct misdn_stack *stack = find_stack_by_addr(frm->addr);
02913 int i ;
02914
02915 if (!stack) return 0 ;
02916
02917 switch (frm->prim) {
02918 case PH_ACTIVATE | CONFIRM:
02919 case PH_ACTIVATE | INDICATION:
02920 cb_log (3, stack->port, "L1: PH L1Link Up!\n");
02921 stack->l1link=1;
02922
02923 if (stack->nt) {
02924
02925 pthread_mutex_lock(&stack->nstlock);
02926 if (stack->nst.l1_l2(&stack->nst, msg))
02927 free_msg(msg);
02928 pthread_mutex_unlock(&stack->nstlock);
02929
02930 if (stack->ptp)
02931 misdn_lib_get_l2_up(stack);
02932 } else {
02933 free_msg(msg);
02934 }
02935
02936 for (i=0;i<=stack->b_num; i++) {
02937 if (stack->bc[i].evq != EVENT_NOTHING) {
02938 cb_log(4, stack->port, "Firing Queued Event %s because L1 got up\n", isdn_get_info(msgs_g, stack->bc[i].evq, 0));
02939 misdn_lib_send_event(&stack->bc[i],stack->bc[i].evq);
02940 stack->bc[i].evq=EVENT_NOTHING;
02941 }
02942
02943 }
02944 return 1;
02945
02946 case PH_ACTIVATE | REQUEST:
02947 free_msg(msg);
02948 cb_log(3,stack->port,"L1: PH_ACTIVATE|REQUEST \n");
02949 return 1;
02950
02951 case PH_DEACTIVATE | REQUEST:
02952 free_msg(msg);
02953 cb_log(3,stack->port,"L1: PH_DEACTIVATE|REQUEST \n");
02954 return 1;
02955
02956 case PH_DEACTIVATE | CONFIRM:
02957 case PH_DEACTIVATE | INDICATION:
02958 cb_log (3, stack->port, "L1: PH L1Link Down! \n");
02959
02960 #if 0
02961 for (i=0; i<=stack->b_num; i++) {
02962 if (global_state == MISDN_INITIALIZED) {
02963 cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data);
02964 }
02965 }
02966 #endif
02967
02968 if (stack->nt) {
02969 pthread_mutex_lock(&stack->nstlock);
02970 if (stack->nst.l1_l2(&stack->nst, msg))
02971 free_msg(msg);
02972 pthread_mutex_unlock(&stack->nstlock);
02973 } else {
02974 free_msg(msg);
02975 }
02976
02977 stack->l1link=0;
02978 stack->l2link=0;
02979 return 1;
02980 }
02981
02982 return 0;
02983 }
02984
02985 static int handle_l2(msg_t *msg)
02986 {
02987 iframe_t *frm = (iframe_t*) msg->data;
02988
02989 struct misdn_stack *stack = find_stack_by_addr(frm->addr);
02990
02991 if (!stack) {
02992 return 0 ;
02993 }
02994
02995 switch(frm->prim) {
02996
02997 case DL_ESTABLISH | REQUEST:
02998 cb_log(1,stack->port,"DL_ESTABLISH|REQUEST \n");
02999 free_msg(msg);
03000 return 1;
03001 case DL_RELEASE | REQUEST:
03002 cb_log(1,stack->port,"DL_RELEASE|REQUEST \n");
03003 free_msg(msg);
03004 return 1;
03005
03006 case DL_ESTABLISH | INDICATION:
03007 case DL_ESTABLISH | CONFIRM:
03008 {
03009 cb_log (3, stack->port, "L2: L2Link Up! \n");
03010 if (stack->ptp && stack->l2link) {
03011 cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n");
03012 cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
03013 }
03014 stack->l2link=1;
03015 free_msg(msg);
03016 return 1;
03017 }
03018 break;
03019
03020 case DL_RELEASE | INDICATION:
03021 case DL_RELEASE | CONFIRM:
03022 {
03023 cb_log (3, stack->port, "L2: L2Link Down! \n");
03024 stack->l2link=0;
03025
03026 free_msg(msg);
03027 return 1;
03028 }
03029 break;
03030 }
03031 return 0;
03032 }
03033
03034 static int handle_mgmt(msg_t *msg)
03035 {
03036 iframe_t *frm = (iframe_t*) msg->data;
03037 struct misdn_stack *stack;
03038
03039 if ( (frm->addr == 0) && (frm->prim == (MGR_DELLAYER|CONFIRM)) ) {
03040 cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: 0 !\n") ;
03041 free_msg(msg);
03042 return 1;
03043 }
03044
03045 stack = find_stack_by_addr(frm->addr);
03046
03047 if (!stack) {
03048 if (frm->prim == (MGR_DELLAYER|CONFIRM)) {
03049 cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: %x !\n",
03050 frm->addr) ;
03051 free_msg(msg);
03052 return 1;
03053 }
03054
03055 return 0;
03056 }
03057
03058 switch(frm->prim) {
03059 case MGR_SHORTSTATUS | INDICATION:
03060 case MGR_SHORTSTATUS | CONFIRM:
03061 cb_log(5, stack->port, "MGMT: Short status dinfo %x\n",frm->dinfo);
03062
03063 switch (frm->dinfo) {
03064 case SSTATUS_L1_ACTIVATED:
03065 cb_log(3, stack->port, "MGMT: SSTATUS: L1_ACTIVATED \n");
03066 stack->l1link=1;
03067
03068 break;
03069 case SSTATUS_L1_DEACTIVATED:
03070 cb_log(3, stack->port, "MGMT: SSTATUS: L1_DEACTIVATED \n");
03071 stack->l1link=0;
03072 #if 0
03073 clear_l3(stack);
03074 #endif
03075 break;
03076
03077 case SSTATUS_L2_ESTABLISHED:
03078 cb_log(3, stack->port, "MGMT: SSTATUS: L2_ESTABLISH \n");
03079 stack->l2link=1;
03080 break;
03081
03082 case SSTATUS_L2_RELEASED:
03083 cb_log(3, stack->port, "MGMT: SSTATUS: L2_RELEASED \n");
03084 stack->l2link=0;
03085 break;
03086 }
03087
03088 free_msg(msg);
03089 return 1;
03090
03091 case MGR_SETSTACK | INDICATION:
03092 cb_log(4, stack->port, "MGMT: SETSTACK|IND dinfo %x\n",frm->dinfo);
03093 free_msg(msg);
03094 return 1;
03095 case MGR_DELLAYER | CONFIRM:
03096 cb_log(4, stack->port, "MGMT: DELLAYER|CNF dinfo %x\n",frm->dinfo) ;
03097 free_msg(msg);
03098 return 1;
03099
03100 }
03101
03102
03103
03104
03105
03106
03107
03108
03109 return 0;
03110 }
03111
03112
03113 static msg_t *fetch_msg(int midev)
03114 {
03115 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
03116 int r;
03117
03118 if (!msg) {
03119 cb_log(0, 0, "fetch_msg: alloc msg failed !!");
03120 return NULL;
03121 }
03122
03123 AGAIN:
03124 r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, TIMEOUT_10SEC);
03125 msg->len=r;
03126
03127 if (r==0) {
03128 free_msg(msg);
03129 cb_log(6,0,"Got empty Msg..\n");
03130 return NULL;
03131 }
03132
03133 if (r<0) {
03134 if (errno == EAGAIN) {
03135
03136 cb_log(4,0,"mISDN_read wants us to wait\n");
03137 usleep(5000);
03138 goto AGAIN;
03139 }
03140
03141 cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno);
03142 }
03143
03144 #if 0
03145 if (!(frm->prim == (DL_DATA|INDICATION) )|| (frm->prim == (PH_DATA|INDICATION)))
03146 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 );
03147 #endif
03148 return msg;
03149 }
03150
03151 void misdn_lib_isdn_l1watcher(int port)
03152 {
03153 struct misdn_stack *stack;
03154
03155 for (stack = glob_mgr->stack_list; stack && (stack->port != port); stack = stack->next)
03156 ;
03157
03158 if (stack) {
03159 cb_log(4, port, "Checking L1 State\n");
03160 if (!stack->l1link) {
03161 cb_log(4, port, "L1 State Down, trying to get it up again\n");
03162 misdn_lib_get_short_status(stack);
03163 misdn_lib_get_l1_up(stack);
03164 misdn_lib_get_l2_up(stack);
03165 }
03166 }
03167 }
03168
03169
03170 static void misdn_lib_isdn_event_catcher(void *arg)
03171 {
03172 struct misdn_lib *mgr = arg;
03173 int zero_frm=0 , fff_frm=0 ;
03174 int midev= mgr->midev;
03175 int port=0;
03176
03177 while (1) {
03178 msg_t *msg = fetch_msg(midev);
03179 iframe_t *frm;
03180
03181
03182 if (!msg) continue;
03183
03184 frm = (iframe_t*) msg->data;
03185
03186
03187 if (frm->len == 0 && frm->addr == 0 && frm->dinfo == 0 && frm->prim == 0 ) {
03188 zero_frm++;
03189 free_msg(msg);
03190 continue;
03191 } else {
03192 if (zero_frm) {
03193 cb_log(0, port, "*** Alert: %d zero_frms caught\n", zero_frm);
03194 zero_frm = 0 ;
03195 }
03196 }
03197
03198
03199 if (frm->len == 0 && frm->dinfo == 0 && frm->prim == 0xffffffff ) {
03200 fff_frm++;
03201 free_msg(msg);
03202 continue;
03203 } else {
03204 if (fff_frm) {
03205 cb_log(0, port, "*** Alert: %d fff_frms caught\n", fff_frm);
03206 fff_frm = 0 ;
03207 }
03208 }
03209
03210 manager_isdn_handler(frm, msg);
03211 }
03212
03213 }
03214
03215
03216
03217
03218 static int te_lib_init(void)
03219 {
03220 char buff[1025] = "";
03221 iframe_t *frm = (iframe_t *) buff;
03222 int midev;
03223 int ret;
03224
03225 midev = mISDN_open();
03226 if (midev <= 0) {
03227 return midev;
03228 }
03229
03230
03231 mISDN_write_frame(midev, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
03232
03233 ret = mISDN_read_frame(midev, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
03234 entity = frm->dinfo & 0xffff;
03235 if (ret < mISDN_HEADER_LEN || !entity) {
03236 fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n", strerror(errno));
03237 exit(-1);
03238 }
03239
03240 return midev;
03241 }
03242
03243 void te_lib_destroy(int midev)
03244 {
03245 char buf[1024];
03246 mISDN_write_frame(midev, buf, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
03247
03248 cb_log(4, 0, "Entity deleted\n");
03249 mISDN_close(midev);
03250 cb_log(4, 0, "midev closed\n");
03251 }
03252
03253 struct misdn_bchannel *manager_find_bc_by_pid(int pid)
03254 {
03255 struct misdn_stack *stack;
03256 int i;
03257
03258 for (stack = glob_mgr->stack_list; stack; stack = stack->next) {
03259 for (i = 0; i <= stack->b_num; i++) {
03260 if (stack->bc[i].in_use && stack->bc[i].pid == pid) {
03261 return &stack->bc[i];
03262 }
03263 }
03264 }
03265
03266 return NULL;
03267 }
03268
03269 static int test_inuse(struct misdn_bchannel *bc)
03270 {
03271 struct timeval now;
03272
03273 if (!bc->in_use) {
03274 gettimeofday(&now, NULL);
03275 if (bc->last_used.tv_sec == now.tv_sec
03276 && misdn_lib_port_is_pri(bc->port)) {
03277 cb_log(2, bc->port, "channel with stid:%x for one second still in use! (n:%d lu:%d)\n",
03278 bc->b_stid, (int) now.tv_sec, (int) bc->last_used.tv_sec);
03279 return 1;
03280 }
03281
03282 cb_log(3,bc->port, "channel with stid:%x not in use!\n", bc->b_stid);
03283 return 0;
03284 }
03285
03286 cb_log(2,bc->port, "channel with stid:%x in use!\n", bc->b_stid);
03287 return 1;
03288 }
03289
03290
03291 static void prepare_bc(struct misdn_bchannel*bc, int channel)
03292 {
03293 bc->channel = channel;
03294 bc->channel_preselected = channel?1:0;
03295 bc->need_disconnect=1;
03296 bc->need_release=1;
03297 bc->need_release_complete=1;
03298 bc->cause = AST_CAUSE_NORMAL_CLEARING;
03299
03300 if (++mypid>5000) mypid=1;
03301 bc->pid=mypid;
03302
03303 #if 0
03304 bc->addr=0;
03305 bc->b_stid=0;
03306 bc->layer_id=0;
03307 #endif
03308
03309 bc->in_use = 1;
03310 }
03311
03312 struct misdn_bchannel *misdn_lib_get_free_bc(int port, int channel, int inout, int dec)
03313 {
03314 struct misdn_stack *stack;
03315 int i;
03316 int maxnum;
03317
03318 if (channel < 0 || channel > MAX_BCHANS) {
03319 cb_log(0, port, "Requested channel out of bounds (%d)\n", channel);
03320 return NULL;
03321 }
03322
03323
03324 stack = find_stack_by_port(port);
03325 if (!stack) {
03326 cb_log(0, port, "Port is not configured (%d)\n", port);
03327 return NULL;
03328 }
03329
03330 if (stack->blocked) {
03331 cb_log(0, port, "Port is blocked\n");
03332 return NULL;
03333 }
03334
03335 pthread_mutex_lock(&stack->st_lock);
03336 if (channel > 0) {
03337 if (channel <= stack->b_num) {
03338 for (i = 0; i < stack->b_num; i++) {
03339 if (stack->bc[i].channel == channel) {
03340 if (test_inuse(&stack->bc[i])) {
03341 pthread_mutex_unlock(&stack->st_lock);
03342 cb_log(0, port, "Requested channel:%d on port:%d is already in use\n", channel, port);
03343 return NULL;
03344 } else {
03345 prepare_bc(&stack->bc[i], channel);
03346 pthread_mutex_unlock(&stack->st_lock);
03347 return &stack->bc[i];
03348 }
03349 }
03350 }
03351 } else {
03352 pthread_mutex_unlock(&stack->st_lock);
03353 cb_log(0, port, "Requested channel:%d is out of bounds on port:%d\n", channel, port);
03354 return NULL;
03355 }
03356 }
03357
03358
03359 maxnum = (inout && !stack->pri && !stack->ptp) ? stack->b_num + 1 : stack->b_num;
03360 if (dec) {
03361 for (i = maxnum - 1; i >= 0; --i) {
03362 if (!test_inuse(&stack->bc[i])) {
03363
03364 if (!stack->pri && i == stack->b_num) {
03365 stack->bc[i].cw = 1;
03366 }
03367
03368 prepare_bc(&stack->bc[i], channel);
03369 stack->bc[i].dec = 1;
03370 pthread_mutex_unlock(&stack->st_lock);
03371 return &stack->bc[i];
03372 }
03373 }
03374 } else {
03375 for (i = 0; i < maxnum; ++i) {
03376 if (!test_inuse(&stack->bc[i])) {
03377
03378 if (!stack->pri && i == stack->b_num) {
03379 stack->bc[i].cw = 1;
03380 }
03381
03382 prepare_bc(&stack->bc[i], channel);
03383 pthread_mutex_unlock(&stack->st_lock);
03384 return &stack->bc[i];
03385 }
03386 }
03387 }
03388 pthread_mutex_unlock(&stack->st_lock);
03389
03390 cb_log(1, port, "There is no free channel on port (%d)\n", port);
03391 return NULL;
03392 }
03393
03394 #if defined(AST_MISDN_ENHANCEMENTS)
03395
03396
03397
03398
03399
03400
03401
03402
03403 struct misdn_bchannel *misdn_lib_get_register_bc(int port)
03404 {
03405 struct misdn_stack *stack;
03406 struct misdn_bchannel *bc;
03407 unsigned index;
03408
03409
03410 stack = find_stack_by_port(port);
03411 if (!stack) {
03412 cb_log(0, port, "Port is not configured (%d)\n", port);
03413 return NULL;
03414 }
03415
03416 if (stack->blocked) {
03417 cb_log(0, port, "Port is blocked\n");
03418 return NULL;
03419 }
03420
03421 pthread_mutex_lock(&stack->st_lock);
03422 for (index = MAX_BCHANS + 1; index < ARRAY_LEN(stack->bc); ++index) {
03423 bc = &stack->bc[index];
03424 if (!test_inuse(bc)) {
03425 prepare_bc(bc, 0);
03426 bc->need_disconnect = 0;
03427 bc->need_release = 0;
03428 pthread_mutex_unlock(&stack->st_lock);
03429 return bc;
03430 }
03431 }
03432 pthread_mutex_unlock(&stack->st_lock);
03433
03434 cb_log(1, port, "There is no free REGISTER link on port (%d)\n", port);
03435 return NULL;
03436 }
03437 #endif
03438
03439
03440
03441
03442
03443
03444
03445 static const char *fac2str(enum FacFunction facility)
03446 {
03447 static const struct {
03448 enum FacFunction facility;
03449 char *name;
03450 } arr[] = {
03451
03452 { Fac_None, "Fac_None" },
03453 #if defined(AST_MISDN_ENHANCEMENTS)
03454 { Fac_ERROR, "Fac_ERROR" },
03455 { Fac_RESULT, "Fac_RESULT" },
03456 { Fac_REJECT, "Fac_REJECT" },
03457
03458 { Fac_ActivationDiversion, "Fac_ActivationDiversion" },
03459 { Fac_DeactivationDiversion, "Fac_DeactivationDiversion" },
03460 { Fac_ActivationStatusNotificationDiv, "Fac_ActivationStatusNotificationDiv" },
03461 { Fac_DeactivationStatusNotificationDiv, "Fac_DeactivationStatusNotificationDiv" },
03462 { Fac_InterrogationDiversion, "Fac_InterrogationDiversion" },
03463 { Fac_DiversionInformation, "Fac_DiversionInformation" },
03464 { Fac_CallDeflection, "Fac_CallDeflection" },
03465 { Fac_CallRerouteing, "Fac_CallRerouteing" },
03466 { Fac_DivertingLegInformation2, "Fac_DivertingLegInformation2" },
03467 { Fac_InterrogateServedUserNumbers, "Fac_InterrogateServedUserNumbers" },
03468 { Fac_DivertingLegInformation1, "Fac_DivertingLegInformation1" },
03469 { Fac_DivertingLegInformation3, "Fac_DivertingLegInformation3" },
03470
03471 { Fac_EctExecute, "Fac_EctExecute" },
03472 { Fac_ExplicitEctExecute, "Fac_ExplicitEctExecute" },
03473 { Fac_RequestSubaddress, "Fac_RequestSubaddress" },
03474 { Fac_SubaddressTransfer, "Fac_SubaddressTransfer" },
03475 { Fac_EctLinkIdRequest, "Fac_EctLinkIdRequest" },
03476 { Fac_EctInform, "Fac_EctInform" },
03477 { Fac_EctLoopTest, "Fac_EctLoopTest" },
03478
03479 { Fac_ChargingRequest, "Fac_ChargingRequest" },
03480 { Fac_AOCSCurrency, "Fac_AOCSCurrency" },
03481 { Fac_AOCSSpecialArr, "Fac_AOCSSpecialArr" },
03482 { Fac_AOCDCurrency, "Fac_AOCDCurrency" },
03483 { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" },
03484 { Fac_AOCECurrency, "Fac_AOCECurrency" },
03485 { Fac_AOCEChargingUnit, "Fac_AOCEChargingUnit" },
03486
03487 { Fac_StatusRequest, "Fac_StatusRequest" },
03488
03489 { Fac_CallInfoRetain, "Fac_CallInfoRetain" },
03490 { Fac_EraseCallLinkageID, "Fac_EraseCallLinkageID" },
03491 { Fac_CCBSDeactivate, "Fac_CCBSDeactivate" },
03492 { Fac_CCBSErase, "Fac_CCBSErase" },
03493 { Fac_CCBSRemoteUserFree, "Fac_CCBSRemoteUserFree" },
03494 { Fac_CCBSCall, "Fac_CCBSCall" },
03495 { Fac_CCBSStatusRequest, "Fac_CCBSStatusRequest" },
03496 { Fac_CCBSBFree, "Fac_CCBSBFree" },
03497 { Fac_CCBSStopAlerting, "Fac_CCBSStopAlerting" },
03498
03499 { Fac_CCBSRequest, "Fac_CCBSRequest" },
03500 { Fac_CCBSInterrogate, "Fac_CCBSInterrogate" },
03501
03502 { Fac_CCNRRequest, "Fac_CCNRRequest" },
03503 { Fac_CCNRInterrogate, "Fac_CCNRInterrogate" },
03504
03505 { Fac_CCBS_T_Call, "Fac_CCBS_T_Call" },
03506 { Fac_CCBS_T_Suspend, "Fac_CCBS_T_Suspend" },
03507 { Fac_CCBS_T_Resume, "Fac_CCBS_T_Resume" },
03508 { Fac_CCBS_T_RemoteUserFree, "Fac_CCBS_T_RemoteUserFree" },
03509 { Fac_CCBS_T_Available, "Fac_CCBS_T_Available" },
03510
03511 { Fac_CCBS_T_Request, "Fac_CCBS_T_Request" },
03512
03513 { Fac_CCNR_T_Request, "Fac_CCNR_T_Request" },
03514
03515 #else
03516
03517 { Fac_CFActivate, "Fac_CFActivate" },
03518 { Fac_CFDeactivate, "Fac_CFDeactivate" },
03519 { Fac_CD, "Fac_CD" },
03520
03521 { Fac_AOCDCurrency, "Fac_AOCDCurrency" },
03522 { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" },
03523 #endif
03524
03525 };
03526
03527 unsigned index;
03528
03529 for (index = 0; index < ARRAY_LEN(arr); ++index) {
03530 if (arr[index].facility == facility) {
03531 return arr[index].name;
03532 }
03533 }
03534
03535 return "unknown";
03536 }
03537
03538 void misdn_lib_log_ies(struct misdn_bchannel *bc)
03539 {
03540 struct misdn_stack *stack;
03541
03542 if (!bc) return;
03543
03544 stack = get_stack_by_bc(bc);
03545
03546 if (!stack) return;
03547
03548 cb_log(2, stack->port,
03549 " --> channel:%d mode:%s cause:%d ocause:%d\n",
03550 bc->channel,
03551 stack->nt ? "NT" : "TE",
03552 bc->cause,
03553 bc->out_cause);
03554
03555 cb_log(2, stack->port,
03556 " --> info_dad:%s dialed numtype:%d plan:%d\n",
03557 bc->info_dad,
03558 bc->dialed.number_type,
03559 bc->dialed.number_plan);
03560
03561 cb_log(2, stack->port,
03562 " --> caller:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
03563 bc->caller.name,
03564 bc->caller.number,
03565 bc->caller.number_type,
03566 bc->caller.number_plan,
03567 bc->caller.presentation,
03568 bc->caller.screening);
03569
03570 cb_log(2, stack->port,
03571 " --> redirecting-from:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
03572 bc->redirecting.from.name,
03573 bc->redirecting.from.number,
03574 bc->redirecting.from.number_type,
03575 bc->redirecting.from.number_plan,
03576 bc->redirecting.from.presentation,
03577 bc->redirecting.from.screening);
03578 cb_log(2, stack->port,
03579 " --> redirecting-to:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
03580 bc->redirecting.to.name,
03581 bc->redirecting.to.number,
03582 bc->redirecting.to.number_type,
03583 bc->redirecting.to.number_plan,
03584 bc->redirecting.to.presentation,
03585 bc->redirecting.to.screening);
03586 cb_log(2, stack->port,
03587 " --> redirecting reason:%d count:%d\n",
03588 bc->redirecting.reason,
03589 bc->redirecting.count);
03590
03591 cb_log(2, stack->port,
03592 " --> connected:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
03593 bc->connected.name,
03594 bc->connected.number,
03595 bc->connected.number_type,
03596 bc->connected.number_plan,
03597 bc->connected.presentation,
03598 bc->connected.screening);
03599
03600 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);
03601
03602 cb_log(4, stack->port, " --> set_pres:%d pres:%d\n", bc->set_presentation, bc->presentation);
03603
03604 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);
03605
03606 cb_log(4, stack->port, " --> facility in:%s out:%s\n", fac2str(bc->fac_in.Function), fac2str(bc->fac_out.Function));
03607
03608 cb_log(5, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1);
03609
03610 cb_log(5, stack->port, " --> bc:%p h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);
03611 }
03612
03613
03614 #define RETURN(a,b) {retval=a; goto b;}
03615
03616 static void misdn_send_lock(struct misdn_bchannel *bc)
03617 {
03618
03619 if (bc->send_lock)
03620 pthread_mutex_lock(&bc->send_lock->lock);
03621 }
03622
03623 static void misdn_send_unlock(struct misdn_bchannel *bc)
03624 {
03625
03626 if (bc->send_lock)
03627 pthread_mutex_unlock(&bc->send_lock->lock);
03628 }
03629
03630 int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
03631 {
03632 msg_t *msg;
03633 struct misdn_bchannel *bc2;
03634 struct misdn_bchannel *held_bc;
03635 struct misdn_stack *stack;
03636 int retval = 0;
03637 int channel;
03638 int tmpcause;
03639 int tmp_out_cause;
03640
03641 if (!bc)
03642 RETURN(-1,OUT_POST_UNLOCK);
03643
03644 stack = get_stack_by_bc(bc);
03645 if (!stack) {
03646 cb_log(0,bc->port,
03647 "SENDEVENT: no Stack for event:%s caller:\"%s\" <%s> dialed:%s \n",
03648 isdn_get_info(msgs_g, event, 0),
03649 bc->caller.name,
03650 bc->caller.number,
03651 bc->dialed.number);
03652 RETURN(-1,OUT);
03653 }
03654
03655 misdn_send_lock(bc);
03656
03657
03658 cb_log(6,stack->port,"SENDEVENT: stack->nt:%d stack->upperid:%x\n",stack->nt, stack->upper_id);
03659
03660 if ( stack->nt && !stack->l1link) {
03661
03662 bc->evq=event;
03663 cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0));
03664 misdn_lib_get_l1_up(stack);
03665 RETURN(0,OUT);
03666 }
03667
03668 cb_log(1, stack->port,
03669 "I SEND:%s caller:\"%s\" <%s> dialed:%s pid:%d\n",
03670 isdn_get_info(msgs_g, event, 0),
03671 bc->caller.name,
03672 bc->caller.number,
03673 bc->dialed.number,
03674 bc->pid);
03675 cb_log(4, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
03676 misdn_lib_log_ies(bc);
03677
03678 switch (event) {
03679 case EVENT_REGISTER:
03680 case EVENT_SETUP:
03681 if (create_process(glob_mgr->midev, bc) < 0) {
03682 cb_log(0, stack->port, " No free channel at the moment @ send_event\n");
03683
03684 RETURN(-ENOCHAN,OUT);
03685 }
03686 break;
03687
03688 case EVENT_PROGRESS:
03689 case EVENT_ALERTING:
03690 case EVENT_PROCEEDING:
03691 case EVENT_SETUP_ACKNOWLEDGE:
03692 case EVENT_CONNECT:
03693 if (!stack->nt)
03694 break;
03695
03696 case EVENT_RETRIEVE_ACKNOWLEDGE:
03697 if (stack->nt) {
03698 if (bc->channel <=0 ) {
03699 if (find_free_chan_in_stack(stack, bc, 0, 0)<0) {
03700 cb_log(0, stack->port, " No free channel at the moment\n");
03701
03702 RETURN(-ENOCHAN,OUT);
03703 }
03704 }
03705
03706 }
03707
03708 retval=setup_bc(bc);
03709 if (retval == -EINVAL) {
03710 cb_log(0,bc->port,"send_event: setup_bc failed\n");
03711 }
03712
03713 if (misdn_cap_is_speech(bc->capability)) {
03714 if ((event==EVENT_CONNECT)||(event==EVENT_RETRIEVE_ACKNOWLEDGE)) {
03715 if ( *bc->crypt_key ) {
03716 cb_log(4, stack->port,
03717 " --> ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
03718 bc->channel,
03719 bc->caller.number_type,
03720 bc->caller.name,
03721 bc->caller.number,
03722 bc->dialed.number_type,
03723 bc->dialed.number);
03724
03725 manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
03726 }
03727
03728 if (!bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
03729 manager_ec_enable(bc);
03730
03731 if (bc->txgain != 0) {
03732 cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
03733 manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
03734 }
03735
03736 if ( bc->rxgain != 0 ) {
03737 cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);
03738 manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
03739 }
03740 }
03741 }
03742 break;
03743
03744 case EVENT_HOLD_ACKNOWLEDGE:
03745 held_bc = malloc(sizeof(struct misdn_bchannel));
03746 if (!held_bc) {
03747 cb_log(0, bc->port, "Could not allocate held_bc!!!\n");
03748 RETURN(-1,OUT);
03749 }
03750
03751
03752 *held_bc = *bc;
03753 held_bc->holded = 1;
03754 held_bc->channel = 0;
03755 held_bc->channel_preselected = 0;
03756 held_bc->channel_found = 0;
03757 bc_state_change(held_bc, BCHAN_CLEANED);
03758 stack_holder_add(stack, held_bc);
03759
03760
03761 if (stack->nt) {
03762 if (bc->bc_state == BCHAN_BRIDGED) {
03763 misdn_split_conf(bc,bc->conf_id);
03764 bc2 = find_bc_by_confid(bc->conf_id);
03765 if (!bc2) {
03766 cb_log(0,bc->port,"We have no second bc in bridge???\n");
03767 } else {
03768 misdn_split_conf(bc2,bc->conf_id);
03769 }
03770 }
03771
03772 channel = bc->channel;
03773
03774 empty_bc(bc);
03775 clean_up_bc(bc);
03776
03777 if (channel>0)
03778 empty_chan_in_stack(stack,channel);
03779
03780 bc->in_use=0;
03781 }
03782 break;
03783
03784
03785 case EVENT_DISCONNECT:
03786 if (!bc->need_disconnect) {
03787 cb_log(0, bc->port, " --> we have already sent DISCONNECT\n");
03788 RETURN(-1,OUT);
03789 }
03790
03791 bc->need_disconnect=0;
03792 break;
03793 case EVENT_RELEASE:
03794 if (!bc->need_release) {
03795 cb_log(0, bc->port, " --> we have already sent RELEASE\n");
03796 RETURN(-1,OUT);
03797 }
03798 bc->need_disconnect=0;
03799 bc->need_release=0;
03800 break;
03801 case EVENT_RELEASE_COMPLETE:
03802 if (!bc->need_release_complete) {
03803 cb_log(0, bc->port, " --> we have already sent RELEASE_COMPLETE\n");
03804 RETURN(-1,OUT);
03805 }
03806 bc->need_disconnect=0;
03807 bc->need_release=0;
03808 bc->need_release_complete=0;
03809
03810 if (!stack->nt) {
03811
03812 channel = bc->channel;
03813 tmpcause = bc->cause;
03814 tmp_out_cause = bc->out_cause;
03815
03816 empty_bc(bc);
03817 bc->cause=tmpcause;
03818 bc->out_cause=tmp_out_cause;
03819 clean_up_bc(bc);
03820
03821 if (channel>0)
03822 empty_chan_in_stack(stack,channel);
03823
03824 bc->in_use=0;
03825 }
03826 break;
03827
03828 case EVENT_CONNECT_ACKNOWLEDGE:
03829 if ( bc->nt || misdn_cap_is_speech(bc->capability)) {
03830 int retval=setup_bc(bc);
03831 if (retval == -EINVAL){
03832 cb_log(0,bc->port,"send_event: setup_bc failed\n");
03833
03834 }
03835 }
03836
03837 if (misdn_cap_is_speech(bc->capability)) {
03838 if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
03839 manager_ec_enable(bc);
03840
03841 if ( bc->txgain != 0 ) {
03842 cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
03843 manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
03844 }
03845 if ( bc->rxgain != 0 ) {
03846 cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);
03847 manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
03848 }
03849 }
03850 break;
03851
03852 default:
03853 break;
03854 }
03855
03856
03857 msg = isdn_msg_build_event(msgs_g, bc, event, stack->nt);
03858 if (!msg) {
03859
03860
03861
03862
03863
03864
03865
03866 RETURN(-1, OUT);
03867 } else {
03868 msg_queue_tail(&stack->downqueue, msg);
03869 sem_post(&glob_mgr->new_msg);
03870 }
03871
03872 OUT:
03873 misdn_send_unlock(bc);
03874
03875 OUT_POST_UNLOCK:
03876 return retval;
03877 }
03878
03879
03880 static int handle_err(msg_t *msg)
03881 {
03882 iframe_t *frm = (iframe_t*) msg->data;
03883
03884
03885 if (!frm->addr) {
03886 static int cnt=0;
03887 if (!cnt)
03888 cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x\n",frm->prim,frm->dinfo);
03889 cnt++;
03890 if (cnt>100) {
03891 cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo);
03892 cnt=0;
03893 }
03894
03895 free_msg(msg);
03896 return 1;
03897
03898 }
03899
03900 switch (frm->prim) {
03901 case MGR_SETSTACK|INDICATION:
03902 return handle_bchan(msg);
03903 break;
03904
03905 case MGR_SETSTACK|CONFIRM:
03906 case MGR_CLEARSTACK|CONFIRM:
03907 free_msg(msg) ;
03908 return 1;
03909 break;
03910
03911 case DL_DATA|CONFIRM:
03912 cb_log(4,0,"DL_DATA|CONFIRM\n");
03913 free_msg(msg);
03914 return 1;
03915
03916 case PH_CONTROL|CONFIRM:
03917 cb_log(4,0,"PH_CONTROL|CONFIRM\n");
03918 free_msg(msg);
03919 return 1;
03920
03921 case DL_DATA|INDICATION:
03922 {
03923 int port=(frm->addr&MASTER_ID_MASK) >> 8;
03924 int channel=(frm->addr&CHILD_ID_MASK) >> 16;
03925 struct misdn_bchannel *bc;
03926
03927
03928
03929 cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel);
03930
03931 free_msg(msg);
03932 return 1;
03933
03934
03935 bc = find_bc_by_channel(port, channel);
03936
03937 if (!bc) {
03938 struct misdn_stack *stack = find_stack_by_port(port);
03939
03940 if (!stack) {
03941 cb_log(0,0," --> stack not found\n");
03942 free_msg(msg);
03943 return 1;
03944 }
03945
03946 cb_log(0,0," --> bc not found by channel\n");
03947 if (stack->l2link)
03948 misdn_lib_get_l2_down(stack);
03949
03950 if (stack->l1link)
03951 misdn_lib_get_l1_down(stack);
03952
03953 free_msg(msg);
03954 return 1;
03955 }
03956
03957 cb_log(3,port," --> BC in state:%s\n", bc_state2str(bc->bc_state));
03958 }
03959 }
03960
03961 return 0;
03962 }
03963
03964 #if 0
03965 static int queue_l2l3(msg_t *msg)
03966 {
03967 iframe_t *frm= (iframe_t*)msg->data;
03968 struct misdn_stack *stack;
03969 stack=find_stack_by_addr( frm->addr );
03970
03971
03972 if (!stack) {
03973 return 0;
03974 }
03975
03976 msg_queue_tail(&stack->upqueue, msg);
03977 sem_post(&glob_mgr->new_msg);
03978 return 1;
03979 }
03980 #endif
03981
03982 int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
03983 {
03984
03985 if (frm->dinfo==0xffffffff && frm->prim==(PH_DATA|CONFIRM)) {
03986 cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
03987 }
03988
03989 if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) {
03990 static int unhandled_bmsg_count=1000;
03991 if (handle_bchan(msg)) {
03992 return 0 ;
03993 }
03994
03995 if (unhandled_bmsg_count==1000) {
03996 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);
03997 unhandled_bmsg_count=0;
03998 }
03999
04000 unhandled_bmsg_count++;
04001 free_msg(msg);
04002 return 0;
04003 }
04004
04005 #ifdef RECV_FRM_SYSLOG_DEBUG
04006 syslog(LOG_NOTICE,"mISDN recv: P(%02d): ADDR:%x PRIM:%x DINFO:%x\n",stack->port, frm->addr, frm->prim, frm->dinfo);
04007 #endif
04008
04009 if (handle_timers(msg))
04010 return 0 ;
04011
04012
04013 if (handle_mgmt(msg))
04014 return 0 ;
04015
04016 if (handle_l2(msg))
04017 return 0 ;
04018
04019
04020 if (handle_l1(msg))
04021 return 0 ;
04022
04023 if (handle_frm_nt(msg)) {
04024 return 0;
04025 }
04026
04027 if (handle_frm(msg)) {
04028 return 0;
04029 }
04030
04031 if (handle_err(msg)) {
04032 return 0 ;
04033 }
04034
04035 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);
04036 free_msg(msg);
04037
04038
04039 return 0;
04040 }
04041
04042
04043
04044
04045 int misdn_lib_get_port_info(int port)
04046 {
04047 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
04048 iframe_t *frm;
04049 struct misdn_stack *stack=find_stack_by_port(port);
04050 if (!msg) {
04051 cb_log(0, port, "misdn_lib_get_port_info: alloc_msg failed!\n");
04052 return -1;
04053 }
04054 frm=(iframe_t*)msg->data;
04055 if (!stack ) {
04056 cb_log(0, port, "There is no Stack for this port.\n");
04057 return -1;
04058 }
04059
04060 frm->prim = CC_STATUS_ENQUIRY | REQUEST;
04061
04062 frm->addr = stack->upper_id| FLG_MSG_DOWN;
04063
04064 frm->dinfo = 0;
04065 frm->len = 0;
04066
04067 msg_queue_tail(&glob_mgr->activatequeue, msg);
04068 sem_post(&glob_mgr->new_msg);
04069
04070
04071 return 0;
04072 }
04073
04074
04075 int queue_cleanup_bc(struct misdn_bchannel *bc)
04076 {
04077 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
04078 iframe_t *frm;
04079 if (!msg) {
04080 cb_log(0, bc->port, "queue_cleanup_bc: alloc_msg failed!\n");
04081 return -1;
04082 }
04083 frm=(iframe_t*)msg->data;
04084
04085
04086 frm->prim = MGR_CLEARSTACK| REQUEST;
04087
04088 frm->addr = bc->l3_id;
04089
04090 frm->dinfo = bc->port;
04091 frm->len = 0;
04092
04093 msg_queue_tail(&glob_mgr->activatequeue, msg);
04094 sem_post(&glob_mgr->new_msg);
04095
04096 return 0;
04097
04098 }
04099
04100 int misdn_lib_pid_restart(int pid)
04101 {
04102 struct misdn_bchannel *bc=manager_find_bc_by_pid(pid);
04103
04104 if (bc) {
04105 manager_clean_bc(bc);
04106 }
04107 return 0;
04108 }
04109
04110
04111 int misdn_lib_send_restart(int port, int channel)
04112 {
04113 struct misdn_stack *stack=find_stack_by_port(port);
04114 struct misdn_bchannel dummybc;
04115
04116 cb_log(0, port, "Sending Restarts on this port.\n");
04117
04118 misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
04119
04120
04121 if (channel <0) {
04122 dummybc.channel=-1;
04123 cb_log(0, port, "Restarting and all Interfaces\n");
04124 misdn_lib_send_event(&dummybc, EVENT_RESTART);
04125
04126 return 0;
04127 }
04128
04129
04130 if (channel >0) {
04131 int cnt;
04132 dummybc.channel=channel;
04133 cb_log(0, port, "Restarting and cleaning channel %d\n",channel);
04134 misdn_lib_send_event(&dummybc, EVENT_RESTART);
04135
04136
04137 for (cnt=0; cnt<=stack->b_num; cnt++) {
04138 if (stack->bc[cnt].in_use && stack->bc[cnt].channel == channel) {
04139 empty_bc(&stack->bc[cnt]);
04140 clean_up_bc(&stack->bc[cnt]);
04141 stack->bc[cnt].in_use=0;
04142 }
04143 }
04144 }
04145
04146 return 0;
04147 }
04148
04149
04150 int misdn_lib_port_restart(int port)
04151 {
04152 struct misdn_stack *stack=find_stack_by_port(port);
04153
04154 cb_log(0, port, "Restarting this port.\n");
04155 if (stack) {
04156 cb_log(0, port, "Stack:%p\n",stack);
04157
04158 clear_l3(stack);
04159 {
04160 msg_t *msg=alloc_msg(MAX_MSG_SIZE);
04161 iframe_t *frm;
04162
04163 if (!msg) {
04164 cb_log(0, port, "port_restart: alloc_msg failed\n");
04165 return -1;
04166 }
04167
04168 frm=(iframe_t*)msg->data;
04169
04170
04171 frm->prim = DL_RELEASE | REQUEST;
04172 frm->addr = stack->upper_id | FLG_MSG_DOWN;
04173
04174 frm->dinfo = 0;
04175 frm->len = 0;
04176 msg_queue_tail(&glob_mgr->activatequeue, msg);
04177 sem_post(&glob_mgr->new_msg);
04178 }
04179
04180 if (stack->nt)
04181 misdn_lib_reinit_nt_stack(stack->port);
04182
04183 }
04184
04185 return 0;
04186 }
04187
04188
04189
04190 static sem_t handler_started;
04191
04192
04193 static void manager_event_handler(void *arg)
04194 {
04195 sem_post(&handler_started);
04196 while (1) {
04197 struct misdn_stack *stack;
04198 msg_t *msg;
04199
04200
04201 sem_wait(&glob_mgr->new_msg);
04202
04203 for (msg=msg_dequeue(&glob_mgr->activatequeue);
04204 msg;
04205 msg=msg_dequeue(&glob_mgr->activatequeue)
04206 )
04207 {
04208
04209 iframe_t *frm = (iframe_t*) msg->data ;
04210
04211 switch ( frm->prim) {
04212
04213 case MGR_CLEARSTACK | REQUEST:
04214
04215 {
04216 struct misdn_stack *stack=find_stack_by_port(frm->dinfo);
04217 struct misdn_bchannel *bc;
04218 if (!stack) {
04219 cb_log(0,0,"no stack found with port [%d]!! so we cannot cleanup the bc\n",frm->dinfo);
04220 free_msg(msg);
04221 break;
04222 }
04223
04224 bc = find_bc_by_l3id(stack, frm->addr);
04225 if (bc) {
04226 cb_log(1,bc->port,"CLEARSTACK queued, cleaning up\n");
04227 clean_up_bc(bc);
04228 } else {
04229 cb_log(0,stack->port,"bc could not be cleaned correctly !! addr [%x]\n",frm->addr);
04230 }
04231 }
04232 free_msg(msg);
04233 break;
04234 case MGR_SETSTACK | REQUEST :
04235 free_msg(msg);
04236 break;
04237 default:
04238 mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
04239 free_msg(msg);
04240 }
04241 }
04242
04243 for (stack=glob_mgr->stack_list;
04244 stack;
04245 stack=stack->next ) {
04246
04247 while ( (msg=msg_dequeue(&stack->upqueue)) ) {
04248
04249 if (!handle_frm_nt(msg)) {
04250
04251 if (!handle_frm(msg)) {
04252
04253 cb_log(0,stack->port,"Wow we've got a strange issue while dequeueing a Frame\n");
04254 }
04255 }
04256 }
04257
04258
04259
04260
04261
04262
04263 while ( (msg=msg_dequeue(&stack->downqueue)) ) {
04264 if (stack->nt ) {
04265 pthread_mutex_lock(&stack->nstlock);
04266 if (stack->nst.manager_l3(&stack->nst, msg))
04267 cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");
04268 pthread_mutex_unlock(&stack->nstlock);
04269 } else {
04270 iframe_t *frm = (iframe_t *)msg->data;
04271 struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
04272 if (bc)
04273 send_msg(glob_mgr->midev, bc, msg);
04274 else {
04275 if (frm->dinfo == MISDN_ID_GLOBAL || frm->dinfo == MISDN_ID_DUMMY ) {
04276 struct misdn_bchannel dummybc;
04277 cb_log(5,0," --> GLOBAL/DUMMY\n");
04278 misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
04279 send_msg(glob_mgr->midev, &dummybc, msg);
04280 } else {
04281 cb_log(0,0,"No bc for Message\n");
04282 }
04283 }
04284 }
04285 }
04286 }
04287 }
04288 }
04289
04290
04291 int misdn_lib_maxports_get(void)
04292 {
04293
04294
04295 int i = mISDN_open();
04296 int max=0;
04297
04298 if (i<0)
04299 return -1;
04300
04301 max = mISDN_get_stack_count(i);
04302
04303 mISDN_close(i);
04304
04305 return max;
04306 }
04307
04308
04309 void misdn_lib_nt_keepcalls( int kc)
04310 {
04311 #ifdef FEATURE_NET_KEEPCALLS
04312 if (kc) {
04313 struct misdn_stack *stack=get_misdn_stack();
04314 for ( ; stack; stack=stack->next) {
04315 stack->nst.feature |= FEATURE_NET_KEEPCALLS;
04316 }
04317 }
04318 #endif
04319 }
04320
04321 void misdn_lib_nt_debug_init( int flags, char *file )
04322 {
04323 static int init=0;
04324 char *f;
04325
04326 if (!flags)
04327 f=NULL;
04328 else
04329 f=file;
04330
04331 if (!init) {
04332 debug_init( flags , f, f, f);
04333 init=1;
04334 } else {
04335 debug_close();
04336 debug_init( flags , f, f, f);
04337 }
04338 }
04339
04340 int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data)
04341 {
04342 struct misdn_lib *mgr=calloc(1, sizeof(struct misdn_lib));
04343 char *tok, *tokb;
04344 char plist[1024];
04345 int midev;
04346 int port_count=0;
04347
04348 cb_log = iface->cb_log;
04349 cb_event = iface->cb_event;
04350 cb_jb_empty = iface->cb_jb_empty;
04351
04352 glob_mgr = mgr;
04353
04354 msg_init();
04355
04356 misdn_lib_nt_debug_init(0,NULL);
04357
04358 if (!portlist || (*portlist == 0) ) return 1;
04359
04360 init_flip_bits();
04361
04362 {
04363 strncpy(plist,portlist, 1024);
04364 plist[1023] = 0;
04365 }
04366
04367 memcpy(tone_425_flip,tone_425,TONE_425_SIZE);
04368 flip_buf_bits(tone_425_flip,TONE_425_SIZE);
04369
04370 memcpy(tone_silence_flip,tone_SILENCE,TONE_SILENCE_SIZE);
04371 flip_buf_bits(tone_silence_flip,TONE_SILENCE_SIZE);
04372
04373 midev=te_lib_init();
04374 mgr->midev=midev;
04375
04376 port_count=mISDN_get_stack_count(midev);
04377
04378 msg_queue_init(&mgr->activatequeue);
04379
04380 if (sem_init(&mgr->new_msg, 1, 0)<0)
04381 sem_init(&mgr->new_msg, 0, 0);
04382
04383 for (tok=strtok_r(plist," ,",&tokb );
04384 tok;
04385 tok=strtok_r(NULL," ,",&tokb)) {
04386 int port = atoi(tok);
04387 struct misdn_stack *stack;
04388 struct misdn_stack *help;
04389 int ptp=0;
04390 int i;
04391 int r;
04392
04393 if (strstr(tok, "ptp"))
04394 ptp=1;
04395
04396 if (port > port_count) {
04397 cb_log(0, port, "Couldn't Initialize this port since we have only %d ports\n", port_count);
04398 exit(1);
04399 }
04400
04401 stack = stack_init(midev, port, ptp);
04402 if (!stack) {
04403 perror("stack_init");
04404 exit(1);
04405 }
04406
04407
04408 for (i = 0; i <= stack->b_num; i++) {
04409 r = init_bc(stack, &stack->bc[i], stack->midev, port, i);
04410 if (r < 0) {
04411 cb_log(0, port, "Got Err @ init_bc :%d\n", r);
04412 exit(1);
04413 }
04414 }
04415 #if defined(AST_MISDN_ENHANCEMENTS)
04416
04417 for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) {
04418 r = init_bc(stack, &stack->bc[i], stack->midev, port, i);
04419 if (r < 0) {
04420 cb_log(0, port, "Got Err @ init_bc :%d\n", r);
04421 exit(1);
04422 }
04423 stack->bc[i].is_register_pool = 1;
04424 }
04425 #endif
04426
04427
04428 help = mgr->stack_list;
04429 if (!help) {
04430 mgr->stack_list = stack;
04431 } else {
04432 while (help->next) {
04433 help = help->next;
04434 }
04435 help->next = stack;
04436 }
04437 }
04438
04439 if (sem_init(&handler_started, 1, 0)<0)
04440 sem_init(&handler_started, 0, 0);
04441
04442 cb_log(8, 0, "Starting Event Handler\n");
04443 pthread_create( &mgr->event_handler_thread, NULL,(void*)manager_event_handler, mgr);
04444
04445 sem_wait(&handler_started) ;
04446 cb_log(8, 0, "Starting Event Catcher\n");
04447 pthread_create( &mgr->event_thread, NULL, (void*)misdn_lib_isdn_event_catcher, mgr);
04448
04449 cb_log(8, 0, "Event Catcher started\n");
04450
04451 global_state= MISDN_INITIALIZED;
04452
04453 return (mgr == NULL);
04454 }
04455
04456 void misdn_lib_destroy(void)
04457 {
04458 struct misdn_stack *help;
04459 int i;
04460
04461 for ( help=glob_mgr->stack_list; help; help=help->next ) {
04462 for(i=0;i<=help->b_num; i++) {
04463 char buf[1024];
04464 mISDN_write_frame(help->midev, buf, help->bc[i].addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
04465 help->bc[i].addr = 0;
04466 }
04467 cb_log (1, help->port, "Destroying this port.\n");
04468 stack_destroy(help);
04469 }
04470
04471 if (global_state == MISDN_INITIALIZED) {
04472 cb_log(4, 0, "Killing Handler Thread\n");
04473 if ( pthread_cancel(glob_mgr->event_handler_thread) == 0 ) {
04474 cb_log(4, 0, "Joining Handler Thread\n");
04475 pthread_join(glob_mgr->event_handler_thread, NULL);
04476 }
04477
04478 cb_log(4, 0, "Killing Main Thread\n");
04479 if ( pthread_cancel(glob_mgr->event_thread) == 0 ) {
04480 cb_log(4, 0, "Joining Main Thread\n");
04481 pthread_join(glob_mgr->event_thread, NULL);
04482 }
04483 }
04484
04485 cb_log(1, 0, "Closing mISDN device\n");
04486 te_lib_destroy(glob_mgr->midev);
04487 }
04488
04489 char *manager_isdn_get_info(enum event_e event)
04490 {
04491 return isdn_get_info(msgs_g , event, 0);
04492 }
04493
04494 void manager_bchannel_activate(struct misdn_bchannel *bc)
04495 {
04496 char buf[128];
04497
04498 struct misdn_stack *stack=get_stack_by_bc(bc);
04499
04500 if (!stack) {
04501 cb_log(0, bc->port, "bchannel_activate: Stack not found !");
04502 return ;
04503 }
04504
04505
04506 clear_ibuffer(bc->astbuf);
04507
04508 cb_log(5, stack->port, "$$$ Bchan Activated addr %x\n", bc->addr);
04509
04510 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_ESTABLISH | REQUEST, 0,0, NULL, TIMEOUT_1SEC);
04511
04512 return ;
04513 }
04514
04515
04516 void manager_bchannel_deactivate(struct misdn_bchannel * bc)
04517 {
04518 struct misdn_stack *stack=get_stack_by_bc(bc);
04519 iframe_t dact;
04520 char buf[128];
04521
04522 switch (bc->bc_state) {
04523 case BCHAN_ACTIVATED:
04524 break;
04525 case BCHAN_BRIDGED:
04526 misdn_split_conf(bc,bc->conf_id);
04527 break;
04528 default:
04529 cb_log( 4, bc->port,"bchan_deactivate: called but not activated\n");
04530 return ;
04531
04532 }
04533
04534 cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr);
04535
04536 bc->generate_tone=0;
04537
04538 dact.prim = DL_RELEASE | REQUEST;
04539 dact.addr = bc->addr | FLG_MSG_DOWN;
04540 dact.dinfo = 0;
04541 dact.len = 0;
04542 mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_RELEASE|REQUEST,0,0,NULL, TIMEOUT_1SEC);
04543
04544 clear_ibuffer(bc->astbuf);
04545
04546 bc_state_change(bc,BCHAN_RELEASE);
04547
04548 return;
04549 }
04550
04551
04552 int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len)
04553 {
04554 struct misdn_stack *stack=get_stack_by_bc(bc);
04555 char buf[4096 + mISDN_HEADER_LEN];
04556 iframe_t *frm = (iframe_t*)buf;
04557 int r;
04558
04559 switch (bc->bc_state) {
04560 case BCHAN_ACTIVATED:
04561 case BCHAN_BRIDGED:
04562 break;
04563 default:
04564 cb_log(3, bc->port, "BC not yet activated (state:%s)\n",bc_state2str(bc->bc_state));
04565 return -1;
04566 }
04567
04568 frm->prim = DL_DATA|REQUEST;
04569 frm->dinfo = 0;
04570 frm->addr = bc->addr | FLG_MSG_DOWN ;
04571
04572 frm->len = len;
04573 memcpy(&buf[mISDN_HEADER_LEN], data,len);
04574
04575 if ( misdn_cap_is_speech(bc->capability) )
04576 flip_buf_bits( &buf[mISDN_HEADER_LEN], len);
04577 else
04578 cb_log(6, stack->port, "Writing %d data bytes\n",len);
04579
04580 cb_log(9, stack->port, "Writing %d bytes 2 mISDN\n",len);
04581 r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT);
04582 return 0;
04583 }
04584
04585
04586
04587
04588
04589
04590 void manager_ph_control(struct misdn_bchannel *bc, int c1, int c2)
04591 {
04592 unsigned char buffer[mISDN_HEADER_LEN+2*sizeof(int)];
04593 iframe_t *ctrl = (iframe_t *)buffer;
04594 unsigned int *d = (unsigned int*)&ctrl->data.p;
04595
04596
04597 cb_log(4,bc->port,"ph_control: c1:%x c2:%x\n",c1,c2);
04598
04599 ctrl->prim = PH_CONTROL | REQUEST;
04600 ctrl->addr = bc->addr | FLG_MSG_DOWN;
04601 ctrl->dinfo = 0;
04602 ctrl->len = sizeof(unsigned int)*2;
04603 *d++ = c1;
04604 *d++ = c2;
04605 mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
04606 }
04607
04608
04609
04610
04611 void isdn_lib_update_rxgain (struct misdn_bchannel *bc)
04612 {
04613 manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
04614 }
04615
04616 void isdn_lib_update_txgain (struct misdn_bchannel *bc)
04617 {
04618 manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
04619 }
04620
04621 void isdn_lib_update_ec (struct misdn_bchannel *bc)
04622 {
04623 #ifdef MISDN_1_2
04624 if (*bc->pipeline)
04625 #else
04626 if (bc->ec_enable)
04627 #endif
04628 manager_ec_enable(bc);
04629 else
04630 manager_ec_disable(bc);
04631 }
04632
04633 void isdn_lib_stop_dtmf (struct misdn_bchannel *bc)
04634 {
04635 manager_ph_control(bc, DTMF_TONE_STOP, 0);
04636 }
04637
04638
04639
04640
04641 void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len)
04642 {
04643 unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
04644 iframe_t *ctrl = (iframe_t *)buffer;
04645 unsigned int *d = (unsigned int *)&ctrl->data.p;
04646
04647
04648 ctrl->prim = PH_CONTROL | REQUEST;
04649 ctrl->addr = bc->addr | FLG_MSG_DOWN;
04650 ctrl->dinfo = 0;
04651 ctrl->len = sizeof(unsigned int) + c2_len;
04652 *d++ = c1;
04653 memcpy(d, c2, c2_len);
04654 mISDN_write(glob_mgr->midev, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
04655 }
04656
04657
04658
04659
04660 void manager_clean_bc(struct misdn_bchannel *bc )
04661 {
04662 struct misdn_stack *stack=get_stack_by_bc(bc);
04663
04664 if (stack && bc->channel > 0) {
04665 empty_chan_in_stack(stack, bc->channel);
04666 }
04667 empty_bc(bc);
04668 bc->in_use=0;
04669
04670 cb_event(EVENT_CLEANUP, bc, NULL);
04671 }
04672
04673
04674 void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder)
04675 {
04676 struct misdn_bchannel *help;
04677 cb_log(4,stack->port, "*HOLDER: add %x\n",holder->l3_id);
04678
04679 holder->stack_holder=1;
04680 holder->next=NULL;
04681
04682 if (!stack->holding) {
04683 stack->holding = holder;
04684 return;
04685 }
04686
04687 for (help=stack->holding;
04688 help;
04689 help=help->next) {
04690 if (!help->next) {
04691 help->next=holder;
04692 break;
04693 }
04694 }
04695
04696 }
04697
04698 void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder)
04699 {
04700 struct misdn_bchannel *h1;
04701
04702 if (!holder->stack_holder) return;
04703
04704 holder->stack_holder=0;
04705
04706 cb_log(4,stack->port, "*HOLDER: remove %x\n",holder->l3_id);
04707 if (!stack || ! stack->holding) return;
04708
04709 if (holder == stack->holding) {
04710 stack->holding = stack->holding->next;
04711 return;
04712 }
04713
04714 for (h1=stack->holding;
04715 h1;
04716 h1=h1->next) {
04717 if (h1->next == holder) {
04718 h1->next=h1->next->next;
04719 return ;
04720 }
04721 }
04722 }
04723
04724 struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned long l3id)
04725 {
04726 struct misdn_bchannel *help;
04727
04728 cb_log(4,stack?stack->port:0, "*HOLDER: find %lx\n",l3id);
04729
04730 if (!stack) return NULL;
04731
04732 for (help=stack->holding;
04733 help;
04734 help=help->next) {
04735 if (help->l3_id == l3id) {
04736 cb_log(4,stack->port, "*HOLDER: found bc\n");
04737 return help;
04738 }
04739 }
04740
04741 cb_log(4,stack->port, "*HOLDER: find nothing\n");
04742 return NULL;
04743 }
04744
04745
04746
04747
04748
04749
04750
04751
04752
04753 struct misdn_bchannel *misdn_lib_find_held_bc(int port, int l3_id)
04754 {
04755 struct misdn_bchannel *bc;
04756 struct misdn_stack *stack;
04757
04758 bc = NULL;
04759 for (stack = get_misdn_stack(); stack; stack = stack->next) {
04760 if (stack->port == port) {
04761 bc = stack_holder_find(stack, l3_id);
04762 break;
04763 }
04764 }
04765
04766 return bc;
04767 }
04768
04769 void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone)
04770 {
04771 char buf[mISDN_HEADER_LEN + 128] = "";
04772 iframe_t *frm = (iframe_t*)buf;
04773
04774 switch(tone) {
04775 case TONE_DIAL:
04776 manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE);
04777 break;
04778
04779 case TONE_ALERTING:
04780 manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING);
04781 break;
04782
04783 case TONE_HANGUP:
04784 manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP);
04785 break;
04786
04787 case TONE_NONE:
04788 default:
04789 manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP);
04790 }
04791
04792 frm->prim=DL_DATA|REQUEST;
04793 frm->addr=bc->addr|FLG_MSG_DOWN;
04794 frm->dinfo=0;
04795 frm->len=128;
04796
04797 mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
04798 }
04799
04800
04801 void manager_ec_enable(struct misdn_bchannel *bc)
04802 {
04803 struct misdn_stack *stack=get_stack_by_bc(bc);
04804
04805 cb_log(4, stack?stack->port:0,"ec_enable\n");
04806
04807 if (!misdn_cap_is_speech(bc->capability)) {
04808 cb_log(1, stack?stack->port:0, " --> no speech? cannot enable EC\n");
04809 } else {
04810
04811 #ifdef MISDN_1_2
04812 if (*bc->pipeline) {
04813 cb_log(3, stack?stack->port:0,"Sending Control PIPELINE_CFG %s\n",bc->pipeline);
04814 manager_ph_control_block(bc, PIPELINE_CFG, bc->pipeline, strlen(bc->pipeline) + 1);
04815 }
04816 #else
04817 int ec_arr[2];
04818
04819 if (bc->ec_enable) {
04820 cb_log(3, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d\n",bc->ec_deftaps);
04821
04822 switch (bc->ec_deftaps) {
04823 case 4:
04824 case 8:
04825 case 16:
04826 case 32:
04827 case 64:
04828 case 128:
04829 case 256:
04830 case 512:
04831 case 1024:
04832 cb_log(4, stack->port, "Taps is %d\n",bc->ec_deftaps);
04833 break;
04834 default:
04835 cb_log(0, stack->port, "Taps should be power of 2\n");
04836 bc->ec_deftaps=128;
04837 }
04838
04839 ec_arr[0]=bc->ec_deftaps;
04840 ec_arr[1]=0;
04841
04842 manager_ph_control_block(bc, ECHOCAN_ON, ec_arr, sizeof(ec_arr));
04843 }
04844 #endif
04845 }
04846 }
04847
04848
04849
04850 void manager_ec_disable(struct misdn_bchannel *bc)
04851 {
04852 struct misdn_stack *stack=get_stack_by_bc(bc);
04853
04854 cb_log(4, stack?stack->port:0," --> ec_disable\n");
04855
04856 if (!misdn_cap_is_speech(bc->capability)) {
04857 cb_log(1, stack?stack->port:0, " --> no speech? cannot disable EC\n");
04858 return;
04859 }
04860
04861 #ifdef MISDN_1_2
04862 manager_ph_control_block(bc, PIPELINE_CFG, "", 0);
04863 #else
04864 if ( ! bc->ec_enable) {
04865 cb_log(3, stack?stack->port:0, "Sending Control ECHOCAN_OFF\n");
04866 manager_ph_control(bc, ECHOCAN_OFF, 0);
04867 }
04868 #endif
04869 }
04870
04871 struct misdn_stack *get_misdn_stack(void)
04872 {
04873 return glob_mgr->stack_list;
04874 }
04875
04876
04877
04878 void misdn_join_conf(struct misdn_bchannel *bc, int conf_id)
04879 {
04880 char data[16] = "";
04881
04882 bc_state_change(bc,BCHAN_BRIDGED);
04883 manager_ph_control(bc, CMX_RECEIVE_OFF, 0);
04884 manager_ph_control(bc, CMX_CONF_JOIN, conf_id);
04885
04886 cb_log(3,bc->port, "Joining bc:%x in conf:%d\n",bc->addr,conf_id);
04887
04888 misdn_lib_tx2misdn_frm(bc, data, sizeof(data) - 1);
04889 }
04890
04891
04892 void misdn_split_conf(struct misdn_bchannel *bc, int conf_id)
04893 {
04894 bc_state_change(bc,BCHAN_ACTIVATED);
04895 manager_ph_control(bc, CMX_RECEIVE_ON, 0);
04896 manager_ph_control(bc, CMX_CONF_SPLIT, conf_id);
04897
04898 cb_log(4,bc->port, "Splitting bc:%x in conf:%d\n",bc->addr,conf_id);
04899 }
04900
04901 void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2)
04902 {
04903 int conf_id = bc1->pid + 1;
04904 struct misdn_bchannel *bc_list[] = { bc1, bc2, NULL };
04905 struct misdn_bchannel **bc;
04906
04907 cb_log(4, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port);
04908
04909 for (bc=bc_list; *bc; bc++) {
04910 (*bc)->conf_id=conf_id;
04911 cb_log(4, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr);
04912
04913 switch((*bc)->bc_state) {
04914 case BCHAN_ACTIVATED:
04915 misdn_join_conf(*bc,conf_id);
04916 break;
04917 default:
04918 bc_next_state_change(*bc,BCHAN_BRIDGED);
04919 break;
04920 }
04921 }
04922 }
04923
04924 void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2)
04925 {
04926
04927 struct misdn_bchannel *bc_list[]={
04928 bc1,bc2,NULL
04929 };
04930 struct misdn_bchannel **bc;
04931
04932 for (bc=bc_list; *bc; bc++) {
04933 if ( (*bc)->bc_state == BCHAN_BRIDGED){
04934 misdn_split_conf( *bc, (*bc)->conf_id);
04935 } else {
04936 cb_log( 2, (*bc)->port, "BC not bridged (state:%s) so not splitting it\n",bc_state2str((*bc)->bc_state));
04937 }
04938 }
04939
04940 }
04941
04942
04943
04944 void misdn_lib_echo(struct misdn_bchannel *bc, int onoff)
04945 {
04946 cb_log(3,bc->port, " --> ECHO %s\n", onoff?"ON":"OFF");
04947 manager_ph_control(bc, onoff?CMX_ECHO_ON:CMX_ECHO_OFF, 0);
04948 }
04949
04950
04951
04952 void misdn_lib_reinit_nt_stack(int port)
04953 {
04954 struct misdn_stack *stack=find_stack_by_port(port);
04955
04956 if (stack) {
04957 stack->l2link=0;
04958 stack->blocked=0;
04959
04960 cleanup_Isdnl3(&stack->nst);
04961 cleanup_Isdnl2(&stack->nst);
04962
04963
04964 memset(&stack->nst, 0, sizeof(net_stack_t));
04965 memset(&stack->mgr, 0, sizeof(manager_t));
04966
04967 stack->mgr.nst = &stack->nst;
04968 stack->nst.manager = &stack->mgr;
04969
04970 stack->nst.l3_manager = handle_event_nt;
04971 stack->nst.device = glob_mgr->midev;
04972 stack->nst.cardnr = port;
04973 stack->nst.d_stid = stack->d_stid;
04974
04975 stack->nst.feature = FEATURE_NET_HOLD;
04976 if (stack->ptp)
04977 stack->nst.feature |= FEATURE_NET_PTP;
04978 if (stack->pri)
04979 stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
04980
04981 stack->nst.l1_id = stack->lower_id;
04982 stack->nst.l2_id = stack->upper_id;
04983
04984 msg_queue_init(&stack->nst.down_queue);
04985
04986 Isdnl2Init(&stack->nst);
04987 Isdnl3Init(&stack->nst);
04988
04989 if (!stack->ptp)
04990 misdn_lib_get_l1_up(stack);
04991 misdn_lib_get_l2_up(stack);
04992 }
04993 }
04994
04995