Mon Jun 18 2012 03:55:35

Asterisk developer's documentation


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