Thu Oct 11 06:33:48 2012

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

Generated on Thu Oct 11 06:33:48 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6