Wed Aug 18 22:33:52 2010

Asterisk developer's documentation


isdn_lib.c

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

Generated on Wed Aug 18 22:33:53 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7