Sat Nov 1 06:28:34 2008

Asterisk developer's documentation


isdn_lib.c

Go to the documentation of this file.
00001 /*
00002  * Chan_Misdn -- Channel Driver for Asterisk
00003  *
00004  * Interface to mISDN
00005  *
00006  * Copyright (C) 2004, Christian Richter
00007  *
00008  * Christian Richter <crich@beronet.com>
00009  *
00010  * This program is free software, distributed under the terms of
00011  * the GNU General Public License
00012  */
00013 
00014 /*! \file 
00015  * \brief Interface to mISDN
00016  * \author Christian Richter <crich@beronet.com>
00017  */
00018 
00019 
00020 
00021 #include <syslog.h>
00022 #include <sys/time.h>
00023 #include <mISDNuser/isdn_debug.h>
00024 
00025 #include "isdn_lib_intern.h"
00026 #include "isdn_lib.h"
00027 
00028 /* 
00029  * Define ARRAY_LEN() because I cannot
00030  * #include "asterisk/utils.h"
00031  */
00032 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
00033 
00034 #include "asterisk/causes.h"
00035 
00036 void misdn_join_conf(struct misdn_bchannel *bc, int conf_id);
00037 void misdn_split_conf(struct misdn_bchannel *bc, int conf_id);
00038 
00039 int queue_cleanup_bc(struct misdn_bchannel *bc) ;
00040 
00041 int misdn_lib_get_l2_up(struct misdn_stack *stack);
00042 
00043 struct misdn_stack* get_misdn_stack( void );
00044 
00045 static int set_chan_in_stack(struct misdn_stack *stack, int channel);
00046 
00047 int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh);
00048 
00049 int misdn_lib_port_is_pri(int port)
00050 {
00051    struct misdn_stack *stack=get_misdn_stack();
00052    for ( ; stack; stack=stack->next) {
00053       if (stack->port == port) {
00054          return stack->pri;
00055       }
00056    }
00057    
00058    return -1;
00059 }
00060 
00061 static void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel) 
00062 {
00063    memset (dummybc,0,sizeof(struct misdn_bchannel));
00064    dummybc->port=port;
00065    dummybc->l3_id=l3id;
00066    dummybc->nt=nt;
00067    dummybc->dummy=1;
00068    dummybc->channel=channel;
00069 }
00070 
00071 int misdn_lib_port_block(int port)
00072 {
00073    struct misdn_stack *stack=get_misdn_stack();
00074    for ( ; stack; stack=stack->next) {
00075       if (stack->port == port) {
00076          stack->blocked=1;
00077          return 0;
00078       }
00079    }
00080    return -1;
00081 
00082 }
00083 
00084 int misdn_lib_port_unblock(int port)
00085 {
00086    struct misdn_stack *stack=get_misdn_stack();
00087    for ( ; stack; stack=stack->next) {
00088       if (stack->port == port) {
00089          stack->blocked=0;
00090          return 0;
00091       }
00092    }
00093    return -1;
00094 
00095 }
00096 
00097 int misdn_lib_is_port_blocked(int port)
00098 {  
00099    struct misdn_stack *stack=get_misdn_stack();
00100    for ( ; stack; stack=stack->next) {
00101       if (stack->port == port) {
00102          return stack->blocked;
00103       }
00104    }
00105    return -1;
00106 }
00107 
00108 int misdn_lib_is_ptp(int port)
00109 {
00110    struct misdn_stack *stack=get_misdn_stack();
00111    for ( ; stack; stack=stack->next) {
00112       if (stack->port == port) return stack->ptp;
00113    }
00114    return -1;
00115 }
00116 
00117 int misdn_lib_get_maxchans(int port) 
00118 {
00119    struct misdn_stack *stack=get_misdn_stack();
00120    for ( ; stack; stack=stack->next) {
00121       if (stack->port == port) {
00122          if (stack->pri) 
00123             return 30;
00124          else
00125             return 2;
00126       }
00127    }
00128    return -1;
00129 }
00130 
00131 
00132 struct misdn_stack *get_stack_by_bc(struct misdn_bchannel *bc)
00133 {
00134    struct misdn_stack *stack = get_misdn_stack();
00135 
00136    if (!bc)
00137       return NULL;
00138    
00139    for ( ; stack; stack = stack->next) {
00140       if (bc->port == stack->port)
00141          return stack;
00142    }
00143 
00144    return NULL;
00145 }
00146 
00147 
00148 void get_show_stack_details(int port, char *buf)
00149 {
00150    struct misdn_stack *stack=get_misdn_stack();
00151    
00152    for ( ; stack; stack=stack->next) {
00153       if (stack->port == port) break;
00154    }
00155    
00156    if (stack) {
00157       sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
00158          stack->port, stack->nt ? "NT" : "TE", stack->ptp ? "PTP" : "PMP",
00159          stack->l2link ? "UP" : "DOWN", stack->l1link ? "UP" : "DOWN",
00160          stack->blocked);
00161    } else {
00162       buf[0]=0;
00163    }
00164 }
00165 
00166 
00167 static int nt_err_cnt =0 ;
00168 
00169 enum global_states {
00170    MISDN_INITIALIZING,
00171    MISDN_INITIALIZED
00172 } ;
00173 
00174 static enum global_states  global_state=MISDN_INITIALIZING;
00175 
00176 
00177 #include <mISDNuser/net_l2.h>
00178 #include <mISDNuser/tone.h>
00179 #include <unistd.h>
00180 #include <semaphore.h>
00181 #include <pthread.h>
00182 #include <signal.h>
00183 
00184 #include "isdn_lib.h"
00185 
00186 
00187 struct misdn_lib {
00188    /*! \brief mISDN device handle returned by mISDN_open() */
00189    int midev;
00190    int midev_nt;  /* Not used */
00191 
00192    pthread_t event_thread;
00193    pthread_t event_handler_thread;
00194 
00195    void *user_data;
00196 
00197    msg_queue_t upqueue;
00198    msg_queue_t activatequeue; 
00199   
00200    sem_t new_msg;
00201   
00202    struct misdn_stack *stack_list;
00203 } ;
00204 
00205 #ifndef ECHOCAN_ON
00206 #define ECHOCAN_ON 123
00207 #define ECHOCAN_OFF 124
00208 #endif
00209 
00210 #define MISDN_DEBUG 0
00211 
00212 void misdn_tx_jitter(struct misdn_bchannel *bc, int len);
00213 
00214 struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id);
00215 
00216 struct misdn_bchannel *find_bc_by_confid(unsigned long confid);
00217 
00218 struct misdn_bchannel *stack_holder_find_bychan(struct misdn_stack *stack, int chan);
00219 
00220 int setup_bc(struct misdn_bchannel *bc);
00221 
00222 int manager_isdn_handler(iframe_t *frm ,msg_t *msg);
00223 
00224 int misdn_lib_port_restart(int port);
00225 int misdn_lib_pid_restart(int pid);
00226 
00227 extern struct isdn_msg msgs_g[]; 
00228 
00229 #define ISDN_PID_L3_B_USER 0x430000ff
00230 #define ISDN_PID_L4_B_USER 0x440000ff
00231 
00232 /* #define MISDN_IBUF_SIZE 1024 */
00233 #define MISDN_IBUF_SIZE 512
00234 
00235 /*  Fine Tuning of Inband  Signalling time */
00236 #define TONE_ALERT_CNT 41 /*  1 Sec  */
00237 #define TONE_ALERT_SILENCE_CNT 200 /*  4 Sec */
00238 
00239 #define TONE_BUSY_CNT 20 /*  ? */
00240 #define TONE_BUSY_SILENCE_CNT 48 /*  ? */
00241 
00242 static int  entity;
00243 
00244 static struct misdn_lib *glob_mgr;
00245 
00246 char tone_425_flip[TONE_425_SIZE];
00247 char tone_silence_flip[TONE_SILENCE_SIZE];
00248 
00249 static void misdn_lib_isdn_event_catcher(void *arg);
00250 static int handle_event_nt(void *dat, void *arg);
00251 
00252 
00253 void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder);
00254 void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder);
00255 struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned long l3id);
00256 
00257 /* from isdn_lib.h */
00258    /* user iface */
00259 int te_lib_init( void ) ; /* returns midev */
00260 void te_lib_destroy(int midev) ;
00261 struct misdn_bchannel *manager_find_bc_by_pid(int pid);
00262 struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc);
00263 void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len);
00264 void manager_clean_bc(struct misdn_bchannel *bc );
00265 void manager_bchannel_setup (struct misdn_bchannel *bc);
00266 void manager_bchannel_cleanup (struct misdn_bchannel *bc);
00267 
00268 void ec_chunk( struct misdn_bchannel *bc, unsigned char *rxchunk, unsigned char *txchunk, int chunk_size);
00269    /* end */
00270 int bchdev_echocancel_activate(struct misdn_bchannel* dev);
00271 void bchdev_echocancel_deactivate(struct misdn_bchannel* dev);
00272 /* end */
00273 
00274 
00275 static char *bearer2str(int cap) {
00276    static char *bearers[]={
00277       "Speech",
00278       "Audio 3.1k",
00279       "Unres Digital",
00280       "Res Digital",
00281       "Unknown Bearer"
00282    };
00283    
00284    switch (cap) {
00285    case INFO_CAPABILITY_SPEECH:
00286       return bearers[0];
00287       break;
00288    case INFO_CAPABILITY_AUDIO_3_1K:
00289       return bearers[1];
00290       break;
00291    case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00292       return bearers[2];
00293       break;
00294    case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00295       return bearers[3];
00296       break;
00297    default:
00298       return bearers[4];
00299       break;
00300    }
00301 }
00302 
00303 
00304 static char flip_table[256];
00305 
00306 static void init_flip_bits(void)
00307 {
00308    int i,k;
00309    
00310    for (i = 0 ; i < 256 ; i++) {
00311       unsigned char sample = 0 ;
00312       for (k = 0; k<8; k++) {
00313          if ( i & 1 << k ) sample |= 0x80 >>  k;
00314       }
00315       flip_table[i] = sample;
00316    }
00317 }
00318 
00319 static char * flip_buf_bits ( char * buf , int len)
00320 {
00321    int i;
00322    char * start = buf;
00323    
00324    for (i = 0 ; i < len; i++) {
00325       buf[i] = flip_table[(unsigned char)buf[i]];
00326    }
00327    
00328    return start;
00329 }
00330 
00331 
00332 
00333 
00334 static msg_t *create_l2msg(int prim, int dinfo, int size) /* NT only */
00335 {
00336    int i = 0;
00337    msg_t *dmsg;
00338   
00339    while(i < 10)
00340    {
00341       dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
00342       if (dmsg)
00343          return(dmsg);
00344       
00345       if (!i)
00346          printf("cannot allocate memory, trying again...\n");
00347       i++;
00348       usleep(300000);
00349    }
00350    printf("cannot allocate memory, system overloaded.\n");
00351    exit(-1);
00352 }
00353 
00354 
00355 
00356 msg_t *create_l3msg(int prim, int mt, int dinfo, int size, int ntmode)
00357 {
00358    int i = 0;
00359    msg_t *dmsg;
00360    Q931_info_t *qi;
00361    iframe_t *frm;
00362   
00363    if (!ntmode)
00364       size = sizeof(Q931_info_t)+2;
00365   
00366    while(i < 10) {
00367       if (ntmode) {
00368          dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
00369          if (dmsg) {
00370             return(dmsg);
00371          }
00372       } else {
00373          dmsg = alloc_msg(size+256+mISDN_HEADER_LEN+DEFAULT_HEADROOM);
00374          if (dmsg)
00375          {
00376             memset(msg_put(dmsg,size+mISDN_HEADER_LEN), 0, size+mISDN_HEADER_LEN);
00377             frm = (iframe_t *)dmsg->data;
00378             frm->prim = prim;
00379             frm->dinfo = dinfo;
00380             qi = (Q931_info_t *)(dmsg->data + mISDN_HEADER_LEN);
00381             qi->type = mt;
00382             return(dmsg);
00383          }
00384       }
00385     
00386       if (!i) printf("cannot allocate memory, trying again...\n");
00387       i++;
00388       usleep(300000);
00389    }
00390    printf("cannot allocate memory, system overloaded.\n");
00391    exit(-1);
00392 }
00393 
00394 
00395 static int send_msg (int midev, struct misdn_bchannel *bc, msg_t *dmsg)
00396 {
00397    iframe_t *frm = (iframe_t *)dmsg->data;
00398    struct misdn_stack *stack=get_stack_by_bc(bc);
00399 
00400    if (!stack) {
00401       cb_log(0,bc->port,"send_msg: IEK!! no stack\n ");
00402       return -1;
00403    }
00404    
00405    frm->addr = (stack->upper_id | FLG_MSG_DOWN);
00406    frm->dinfo = bc->l3_id;
00407    frm->len = (dmsg->len) - mISDN_HEADER_LEN;
00408             
00409    cb_log(4,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo);
00410 
00411    mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC);
00412    free_msg(dmsg);
00413 
00414    return 0;
00415 }
00416 
00417 
00418 static int mypid=1;
00419 
00420 
00421 int misdn_cap_is_speech(int cap)
00422 /** Poor mans version **/
00423 {
00424    if ( (cap != INFO_CAPABILITY_DIGITAL_UNRESTRICTED) &&
00425         (cap != INFO_CAPABILITY_DIGITAL_RESTRICTED) ) return 1;
00426    return 0;
00427 }
00428 
00429 int misdn_inband_avail(struct misdn_bchannel *bc)
00430 {
00431 
00432    if (!bc->early_bconnect) {
00433       /* We have opted to never receive any available inband recorded messages */
00434       return 0;
00435    }
00436    
00437    switch (bc->progress_indicator) {
00438    case INFO_PI_INBAND_AVAILABLE:
00439    case INFO_PI_CALL_NOT_E2E_ISDN:
00440    case INFO_PI_CALLED_NOT_ISDN:
00441       return 1;
00442    default:
00443       return 0;
00444    }
00445    return 0;
00446 }
00447 
00448 
00449 static void dump_chan_list(struct misdn_stack *stack)
00450 {
00451    int i;
00452 
00453    for (i=0; i <= stack->b_num; i++) {
00454       cb_log(6, stack->port, "Idx:%d stack->cchan:%d in_use:%d Chan:%d\n",i,stack->channels[i], stack->bc[i].in_use, i+1);
00455    }
00456 }
00457 
00458 
00459 void misdn_dump_chanlist()
00460 {
00461    struct misdn_stack *stack=get_misdn_stack();
00462    for ( ; stack; stack=stack->next) {
00463       dump_chan_list(stack);
00464    }
00465 
00466 }
00467 
00468 int set_chan_in_stack(struct misdn_stack *stack, int channel)
00469 {
00470 
00471    cb_log(4,stack->port,"set_chan_in_stack: %d\n",channel);
00472    dump_chan_list(stack);
00473    if (channel >=1 && channel <= MAX_BCHANS) {
00474       if (!stack->channels[channel-1])
00475          stack->channels[channel-1] = 1;
00476       else {
00477          cb_log(4,stack->port,"channel already in use:%d\n", channel );
00478          return -1;
00479       }
00480    } else {
00481       cb_log(0,stack->port,"couldn't set channel %d in\n", channel );
00482       return -1;
00483    }
00484   
00485    return 0;
00486 }
00487 
00488 
00489 
00490 static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchannel *bc, int channel, int dec)
00491 {
00492    int i;
00493    int chan=0;
00494    int bnums = stack->pri ? stack->b_num : stack->b_num - 1;
00495 
00496    if (bc->channel_found)  
00497       return 0;
00498    
00499    bc->channel_found=1;
00500 
00501    cb_log(5,stack->port,"find_free_chan: req_chan:%d\n",channel);
00502 
00503    if (channel < 0 || channel > MAX_BCHANS) {
00504       cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
00505       return 0;
00506    }
00507    
00508    channel--;
00509 
00510    if (dec) {
00511       for (i = bnums; i >=0; i--) {
00512          if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */
00513             if (!stack->channels[i]) {
00514                cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
00515                chan=i+1;
00516                break;
00517             }
00518          }
00519       }
00520    } else {
00521       for (i = 0; i <= bnums; i++) {
00522          if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */
00523             if (!stack->channels[i]) {
00524                cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
00525                chan=i+1;
00526                break;
00527             }
00528          }
00529       }
00530    }
00531 
00532    if (!chan) {
00533       cb_log (1, stack->port, " !! NO FREE CHAN IN STACK\n");
00534       dump_chan_list(stack);
00535       bc->out_cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
00536       return -1;
00537    }  
00538 
00539    if (set_chan_in_stack(stack, chan)<0) {
00540       cb_log (0, stack->port, "Channel Already in use:%d\n", chan);
00541       bc->out_cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
00542       return -1;
00543    }
00544 
00545    bc->channel=chan;
00546    return 0;
00547 }
00548 
00549 static int empty_chan_in_stack(struct misdn_stack *stack, int channel)
00550 {
00551    if (channel<=0 || channel>MAX_BCHANS) {
00552       cb_log(0,stack?stack->port:0, "empty_chan_in_stack: cannot empty channel %d\n",channel);
00553       return -1;
00554    }
00555    
00556    cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel); 
00557    stack->channels[channel-1] = 0;
00558    dump_chan_list(stack);
00559    return 0;
00560 }
00561 
00562 char *bc_state2str(enum bchannel_state state) {
00563    int i;
00564    
00565    struct bchan_state_s {
00566       char *n;
00567       enum bchannel_state s;
00568    } states[] = {
00569       {"BCHAN_CLEANED", BCHAN_CLEANED },
00570       {"BCHAN_EMPTY", BCHAN_EMPTY},
00571       {"BCHAN_SETUP", BCHAN_SETUP},
00572       {"BCHAN_SETUPED", BCHAN_SETUPED},
00573       {"BCHAN_ACTIVE", BCHAN_ACTIVE},
00574       {"BCHAN_ACTIVATED", BCHAN_ACTIVATED},
00575       {"BCHAN_BRIDGE",  BCHAN_BRIDGE},
00576       {"BCHAN_BRIDGED", BCHAN_BRIDGED},
00577       {"BCHAN_RELEASE", BCHAN_RELEASE},
00578       {"BCHAN_RELEASED", BCHAN_RELEASED},
00579       {"BCHAN_CLEAN", BCHAN_CLEAN},
00580       {"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST},
00581       {"BCHAN_ERROR", BCHAN_ERROR}
00582    };
00583    
00584    for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++)
00585       if ( states[i].s == state)
00586          return states[i].n;
00587 
00588    return "UNKNOWN";
00589 }
00590 
00591 void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state)
00592 {
00593    cb_log(5,bc->port,"BC_STATE_CHANGE: l3id:%x from:%s to:%s\n",
00594       bc->l3_id,
00595           bc_state2str(bc->bc_state),
00596           bc_state2str(state) );
00597    
00598    switch (state) {
00599       case BCHAN_ACTIVATED:
00600          if (bc->next_bc_state ==  BCHAN_BRIDGED) {
00601             misdn_join_conf(bc, bc->conf_id);
00602             bc->next_bc_state = BCHAN_EMPTY;
00603             return;
00604          }
00605       default:
00606          bc->bc_state=state;
00607          break;
00608    }
00609 }
00610 
00611 static void bc_next_state_change(struct misdn_bchannel *bc, enum bchannel_state state)
00612 {
00613    cb_log(5,bc->port,"BC_NEXT_STATE_CHANGE: from:%s to:%s\n",
00614           bc_state2str(bc->next_bc_state),
00615           bc_state2str(state) );
00616 
00617    bc->next_bc_state=state;
00618 }
00619 
00620 
00621 static void empty_bc(struct misdn_bchannel *bc)
00622 {
00623    bc->dummy=0;
00624 
00625    bc->bframe_len=0;
00626 
00627    bc->cw= 0;
00628 
00629    bc->dec=0;
00630    bc->channel = 0;
00631 
00632    bc->sending_complete = 0;
00633 
00634    bc->restart_channel=0;
00635    
00636    bc->conf_id = 0;
00637 
00638    bc->need_more_infos = 0;
00639    
00640    bc->send_dtmf=0;
00641    bc->nodsp=0;
00642    bc->nojitter=0;
00643 
00644    bc->time_usec=0;
00645    
00646    bc->rxgain=0;
00647    bc->txgain=0;
00648 
00649    bc->crypt=0;
00650    bc->curptx=0; bc->curprx=0;
00651    
00652    bc->crypt_key[0] = 0;
00653    
00654    bc->generate_tone=0;
00655    bc->tone_cnt=0;
00656   
00657    bc->dnumplan=NUMPLAN_UNKNOWN;
00658    bc->onumplan=NUMPLAN_UNKNOWN;
00659    bc->rnumplan=NUMPLAN_UNKNOWN;
00660    bc->cpnnumplan=NUMPLAN_UNKNOWN;
00661    
00662 
00663    bc->active = 0;
00664 
00665    bc->early_bconnect = 1;
00666    
00667 #ifdef MISDN_1_2
00668    *bc->pipeline = 0;
00669 #else
00670    bc->ec_enable = 0;
00671    bc->ec_deftaps = 128;
00672 #endif
00673 
00674    bc->orig=0;
00675   
00676    bc->cause = AST_CAUSE_NORMAL_CLEARING;
00677    bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
00678    bc->pres = 0;  /* allowed */
00679    
00680    bc->evq=EVENT_NOTHING;
00681 
00682    bc->progress_coding=0;
00683    bc->progress_location=0;
00684    bc->progress_indicator=0;
00685    
00686 /** Set Default Bearer Caps **/
00687    bc->capability=INFO_CAPABILITY_SPEECH;
00688    bc->law=INFO_CODEC_ALAW;
00689    bc->mode=0;
00690    bc->rate=0x10;
00691    bc->user1=0;
00692    bc->urate=0;
00693    
00694    bc->hdlc=0;
00695    
00696    
00697    bc->info_dad[0] = 0;
00698    bc->display[0] = 0;
00699    bc->infos_pending[0] = 0;
00700    bc->cad[0] = 0;
00701    bc->oad[0] = 0;
00702    bc->dad[0] = 0;
00703    bc->rad[0] = 0;
00704    bc->orig_dad[0] = 0;
00705    bc->uu[0]=0;
00706    bc->uulen=0;
00707    
00708    bc->fac_in.Function = Fac_None;
00709    bc->fac_out.Function = Fac_None;
00710    
00711    bc->te_choose_channel = 0;
00712    bc->channel_found= 0;
00713 
00714    gettimeofday(&bc->last_used, NULL);
00715 }
00716 
00717 
00718 static int clean_up_bc(struct misdn_bchannel *bc)
00719 {
00720    int ret=0;
00721    unsigned char buff[32];
00722    struct misdn_stack * stack;
00723 
00724    cb_log(3, bc?bc->port:0, "$$$ CLEANUP CALLED pid:%d\n", bc?bc->pid:-1);
00725    
00726    if (!bc  ) return -1;
00727    stack=get_stack_by_bc(bc);
00728    
00729    if (!stack) return -1;
00730    
00731    switch (bc->bc_state ) {
00732    case BCHAN_CLEANED:
00733       cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid);
00734       return -1;
00735       
00736    default:
00737       break;
00738    }
00739    
00740    cb_log(2, stack->port, "$$$ Cleaning up bc with stid :%x pid:%d\n", bc->b_stid, bc->pid);
00741    
00742    manager_ec_disable(bc);
00743 
00744    manager_bchannel_deactivate(bc);
00745 
00746    mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_TARGET|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
00747    
00748    bc->b_stid = 0;
00749    bc_state_change(bc, BCHAN_CLEANED);
00750    
00751    return ret;
00752 }
00753 
00754 
00755 
00756 static void clear_l3(struct misdn_stack *stack)
00757 {
00758    int i;
00759 
00760    for (i=0; i<=stack->b_num; i++) {
00761       if (global_state == MISDN_INITIALIZED)  {
00762          cb_event(EVENT_CLEANUP, &stack->bc[i], NULL); 
00763          empty_chan_in_stack(stack,i+1);
00764          empty_bc(&stack->bc[i]);
00765          clean_up_bc(&stack->bc[i]);
00766          stack->bc[i].in_use = 0;
00767       }
00768       
00769    } 
00770 }
00771 
00772 static int newteid=0;
00773 
00774 #define MAXPROCS 0x100
00775 
00776 static int misdn_lib_get_l1_down(struct misdn_stack *stack)
00777 {
00778    /* Pull Up L1 */ 
00779    iframe_t act;
00780    act.prim = PH_DEACTIVATE | REQUEST; 
00781    act.addr = stack->lower_id|FLG_MSG_DOWN;
00782    act.dinfo = 0;
00783    act.len = 0;
00784 
00785    cb_log(1, stack->port, "SENDING PH_DEACTIVATE | REQ\n");
00786    return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00787 }
00788 
00789 
00790 static int misdn_lib_get_l2_down(struct misdn_stack *stack)
00791 {
00792    
00793    if (stack->ptp && (stack->nt) ) {
00794       msg_t *dmsg;
00795       /* L2 */
00796       dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
00797       
00798       if (stack->nst.manager_l3(&stack->nst, dmsg))
00799          free_msg(dmsg);
00800       
00801    } else {
00802       iframe_t act;
00803       
00804       act.prim = DL_RELEASE| REQUEST;
00805       act.addr = (stack->upper_id |FLG_MSG_DOWN)  ;
00806       
00807       act.dinfo = 0;
00808       act.len = 0;
00809       return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00810    }
00811    
00812    return 0;
00813 }
00814 
00815 
00816 static int misdn_lib_get_l1_up(struct misdn_stack *stack)
00817 {
00818    /* Pull Up L1 */ 
00819    iframe_t act;
00820    act.prim = PH_ACTIVATE | REQUEST; 
00821    act.addr = (stack->upper_id | FLG_MSG_DOWN)  ;
00822 
00823    
00824    act.dinfo = 0;
00825    act.len = 0;
00826 
00827    return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00828 
00829 }
00830 
00831 int misdn_lib_get_l2_up(struct misdn_stack *stack)
00832 {
00833    
00834    if (stack->ptp && (stack->nt) ) {
00835       msg_t *dmsg;
00836       /* L2 */
00837       dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
00838       
00839       if (stack->nst.manager_l3(&stack->nst, dmsg))
00840          free_msg(dmsg);
00841       
00842    } else {
00843       iframe_t act;
00844       
00845       act.prim = DL_ESTABLISH | REQUEST;
00846       act.addr = (stack->upper_id |FLG_MSG_DOWN)  ;
00847       
00848       act.dinfo = 0;
00849       act.len = 0;
00850       return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00851    }
00852    
00853    return 0;
00854 }
00855 
00856 #if 0
00857 static int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack)
00858 {
00859    iframe_t act;
00860       
00861    act.prim = DL_ESTABLISH | REQUEST;
00862    act.addr = (stack->upper_id  & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
00863       
00864    act.dinfo = 0;
00865    act.len = 0;
00866    return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00867    return 0;
00868 }
00869 #endif
00870 
00871 static int misdn_lib_get_short_status(struct misdn_stack *stack)
00872 {
00873    iframe_t act;
00874    
00875    
00876    act.prim = MGR_SHORTSTATUS | REQUEST; 
00877    
00878    act.addr = (stack->upper_id | MSG_BROADCAST)  ;
00879 
00880    act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
00881    
00882    act.len = 0;
00883    return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
00884 }
00885 
00886 
00887 
00888 static int create_process (int midev, struct misdn_bchannel *bc) {
00889    iframe_t ncr;
00890    int l3_id;
00891    int i;
00892    struct misdn_stack *stack=get_stack_by_bc(bc);
00893   
00894    if (stack->nt) {
00895       if (find_free_chan_in_stack(stack, bc, bc->channel_preselected?bc->channel:0, 0)<0) return -1;
00896       cb_log(4,stack->port, " -->  found channel: %d\n",bc->channel);
00897     
00898       for (i=0; i <= MAXPROCS; i++)
00899          if (stack->procids[i]==0) break;
00900     
00901       if (i== MAXPROCS) {
00902          cb_log(0, stack->port, "Couldn't Create New ProcId.\n");
00903          return -1;
00904       }
00905       stack->procids[i]=1;
00906 
00907       l3_id = 0xff00 | i;
00908     
00909       ncr.prim = CC_NEW_CR | REQUEST; 
00910 
00911       ncr.addr = (stack->upper_id | FLG_MSG_DOWN)  ;
00912 
00913       ncr.dinfo = l3_id;
00914       ncr.len = 0;
00915 
00916       bc->l3_id = l3_id;
00917       cb_log(3, stack->port, " --> new_l3id %x\n",l3_id);
00918     
00919    } else { 
00920       if (stack->ptp || bc->te_choose_channel) {
00921          /* we know exactly which channels are in use */
00922          if (find_free_chan_in_stack(stack, bc, bc->channel_preselected?bc->channel:0, bc->dec)<0) return -1;
00923          cb_log(2,stack->port, " -->  found channel: %d\n",bc->channel);
00924       } else {
00925          /* other phones could have made a call also on this port (ptmp) */
00926          bc->channel=0xff;
00927       }
00928     
00929     
00930       /* if we are in te-mode, we need to create a process first */
00931       if (newteid++ > 0xffff)
00932          newteid = 0x0001;
00933     
00934       l3_id = (entity<<16) | newteid;
00935       /* preparing message */
00936       ncr.prim = CC_NEW_CR | REQUEST; 
00937 
00938       ncr.addr = (stack->upper_id | FLG_MSG_DOWN)  ;
00939 
00940       ncr.dinfo =l3_id;
00941       ncr.len = 0;
00942       /* send message */
00943 
00944       bc->l3_id = l3_id;
00945       cb_log(3, stack->port, "--> new_l3id %x\n",l3_id);
00946     
00947       mISDN_write(midev, &ncr, mISDN_HEADER_LEN+ncr.len, TIMEOUT_1SEC);
00948    }
00949   
00950    return l3_id;
00951 }
00952 
00953 
00954 void misdn_lib_setup_bc(struct misdn_bchannel *bc)
00955 {
00956    clean_up_bc(bc);
00957    setup_bc(bc);
00958 }
00959 
00960 
00961 int setup_bc(struct misdn_bchannel *bc)
00962 {
00963    unsigned char buff[1025];
00964    int midev;
00965    int channel;
00966    int b_stid;
00967    int i;
00968    mISDN_pid_t pid;
00969    int ret;
00970 
00971    struct misdn_stack *stack=get_stack_by_bc(bc);
00972 
00973    if (!stack) {
00974       cb_log(0, bc->port, "setup_bc: NO STACK FOUND!!\n");
00975       return -1;
00976    }
00977    
00978    midev = stack->midev;
00979    channel = bc->channel - 1 - (bc->channel > 16);
00980    b_stid = stack->b_stids[channel >= 0 ? channel : 0];
00981 
00982    switch (bc->bc_state) {
00983       case BCHAN_CLEANED:
00984          break;
00985       default:
00986          cb_log(4, stack->port, "$$$ bc already setup stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) );
00987          return -1;
00988    }
00989    
00990    cb_log(5, stack->port, "$$$ Setting up bc with stid :%x\n", b_stid);
00991    
00992    /*check if the b_stid is already initialized*/
00993    for (i=0; i <= stack->b_num; i++) {
00994       if (stack->bc[i].b_stid == b_stid) {
00995          cb_log(0, bc->port, "setup_bc: b_stid:%x already in use !!!\n", b_stid);
00996          return -1;
00997       }
00998    }
00999    
01000    if (b_stid <= 0) {
01001       cb_log(0, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel);
01002       
01003       bc_state_change(bc,BCHAN_ERROR);
01004       return 1;
01005    }
01006 
01007    bc->b_stid = b_stid;
01008 
01009    {
01010       layer_info_t li;
01011       memset(&li, 0, sizeof(li));
01012     
01013       li.object_id = -1;
01014       li.extentions = 0;
01015       
01016       li.st = bc->b_stid; /*  given idx */
01017 
01018 
01019 #define MISDN_DSP
01020 #ifndef MISDN_DSP
01021       bc->nodsp=1;
01022 #endif
01023       if ( bc->hdlc || bc->nodsp) {
01024          cb_log(4, stack->port,"setup_bc: without dsp\n");
01025          { 
01026             int l = sizeof(li.name);
01027             strncpy(li.name, "B L3", l);
01028             li.name[l-1] = 0;
01029          }
01030          li.pid.layermask = ISDN_LAYER((3));
01031          li.pid.protocol[3] = ISDN_PID_L3_B_USER;
01032          
01033          bc->layer=3;
01034       } else {
01035          cb_log(4, stack->port,"setup_bc: with dsp\n");
01036          { 
01037             int l = sizeof(li.name);
01038             strncpy(li.name, "B L4", l);
01039             li.name[l-1] = 0;
01040          }
01041          li.pid.layermask = ISDN_LAYER((4));
01042          li.pid.protocol[4] = ISDN_PID_L4_B_USER;
01043 
01044          bc->layer=4;
01045       }  
01046       
01047       ret = mISDN_new_layer(midev, &li);
01048       if (ret ) {
01049          cb_log(0, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno));
01050 
01051          bc_state_change(bc,BCHAN_ERROR);
01052          return(-EINVAL);
01053       }
01054       
01055       bc->layer_id = li.id;
01056    }
01057    
01058    memset(&pid, 0, sizeof(pid));
01059    
01060    
01061    
01062    cb_log(4, stack->port," --> Channel is %d\n", bc->channel);
01063    
01064    if (bc->nodsp) {
01065       cb_log(2, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n");
01066       pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
01067       pid.protocol[2] = ISDN_PID_L2_B_TRANS;
01068       pid.protocol[3] = ISDN_PID_L3_B_USER;
01069       pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3));
01070       
01071    } else if ( bc->hdlc ) {
01072       cb_log(2, stack->port," --> HDLC Mode\n");
01073       pid.protocol[1] = ISDN_PID_L1_B_64HDLC ;
01074       pid.protocol[2] = ISDN_PID_L2_B_TRANS  ;
01075       pid.protocol[3] = ISDN_PID_L3_B_USER;
01076       pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) ;
01077    } else {
01078       cb_log(2, stack->port," --> TRANSPARENT Mode\n");
01079       pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
01080       pid.protocol[2] = ISDN_PID_L2_B_TRANS;
01081       pid.protocol[3] = ISDN_PID_L3_B_DSP;
01082       pid.protocol[4] =