Fri Aug 24 02:22:15 2007

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

Generated on Fri Aug 24 02:22:16 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1