Mon Jun 27 16:50:54 2011

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

Generated on Mon Jun 27 16:50:54 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7