Thu Jul 9 13:40:27 2009

Asterisk developer's documentation


chan_misdn.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  * 
00004  * Copyright (C) 2004 - 2006, Christian Richter
00005  *
00006  * Christian Richter <crich@beronet.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  *
00018  */
00019 
00020 /*!
00021  * \file
00022  *
00023  * \brief the chan_misdn channel driver for Asterisk
00024  *
00025  * \author Christian Richter <crich@beronet.com>
00026  *
00027  * \extref MISDN http://www.misdn.org/
00028  *
00029  * \ingroup channel_drivers
00030  */
00031 
00032 /*** MODULEINFO
00033    <depend>isdnnet</depend>
00034    <depend>misdn</depend>
00035    <depend>suppserv</depend>
00036  ***/
00037 #include "asterisk.h"
00038 
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 196118 $")
00040 
00041 #include <pthread.h>
00042 #include <sys/socket.h>
00043 #include <sys/time.h>
00044 #include <arpa/inet.h>
00045 #include <fcntl.h>
00046 #include <sys/ioctl.h>
00047 #include <signal.h>
00048 #include <sys/file.h>
00049 #include <semaphore.h>
00050 
00051 #include "asterisk/channel.h"
00052 #include "asterisk/config.h"
00053 #include "asterisk/module.h"
00054 #include "asterisk/pbx.h"
00055 #include "asterisk/io.h"
00056 #include "asterisk/frame.h"
00057 #include "asterisk/translate.h"
00058 #include "asterisk/cli.h"
00059 #include "asterisk/musiconhold.h"
00060 #include "asterisk/dsp.h"
00061 #include "asterisk/file.h"
00062 #include "asterisk/callerid.h"
00063 #include "asterisk/indications.h"
00064 #include "asterisk/app.h"
00065 #include "asterisk/features.h"
00066 #include "asterisk/term.h"
00067 #include "asterisk/sched.h"
00068 #include "asterisk/stringfields.h"
00069 #include "asterisk/abstract_jb.h"
00070 #include "asterisk/causes.h"
00071 
00072 #include "chan_misdn_config.h"
00073 #include "isdn_lib.h"
00074 
00075 char global_tracefile[BUFFERSIZE + 1];
00076 
00077 static int g_config_initialized = 0;
00078 
00079 struct misdn_jb{
00080    int size;
00081    int upper_threshold;
00082    char *samples, *ok;
00083    int wp,rp;
00084    int state_empty;
00085    int state_full;
00086    int state_buffer;
00087    int bytes_wrote;
00088    ast_mutex_t mutexjb;
00089 };
00090 
00091 
00092 
00093 /*! \brief allocates the jb-structure and initialize the elements */
00094 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
00095 
00096 /*! \brief frees the data and destroys the given jitterbuffer struct */
00097 void misdn_jb_destroy(struct misdn_jb *jb);
00098 
00099 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
00100 error (buffer overrun). */
00101 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
00102 
00103 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
00104 available data is returned and the return value indicates the number
00105 of data. */
00106 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
00107 
00108 static char *complete_ch(struct ast_cli_args *a);
00109 static char *complete_debug_port(struct ast_cli_args *a);
00110 static char *complete_show_config(struct ast_cli_args *a);
00111 
00112 /* BEGIN: chan_misdn.h */
00113 
00114 ast_mutex_t release_lock;
00115 
00116 enum misdn_chan_state {
00117    MISDN_NOTHING=0,  /*!< at beginning */
00118    MISDN_WAITING4DIGS, /*!<  when waiting for infos */
00119    MISDN_EXTCANTMATCH, /*!<  when asterisk couldn't match our ext */
00120    MISDN_INCOMING_SETUP, /*!<  for incoming setups*/
00121    MISDN_DIALING, /*!<  when pbx_start */
00122    MISDN_PROGRESS, /*!<  we got a progress */
00123    MISDN_PROCEEDING, /*!<  we got a progress */
00124    MISDN_CALLING, /*!<  when misdn_call is called */
00125    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
00126    MISDN_ALERTING, /*!<  when Alerting */
00127    MISDN_BUSY, /*!<  when BUSY */
00128    MISDN_CONNECTED, /*!<  when connected */
00129    MISDN_PRECONNECTED, /*!<  when connected */
00130    MISDN_DISCONNECTED, /*!<  when connected */
00131    MISDN_RELEASED, /*!<  when connected */
00132    MISDN_BRIDGED, /*!<  when bridged */
00133    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00134    MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  came from misdn */
00135    MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
00136    MISDN_HOLDED, /*!< if this chan is holded */
00137    MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
00138   
00139 };
00140 
00141 #define ORG_AST 1
00142 #define ORG_MISDN 2
00143 
00144 struct hold_info {
00145    /*!
00146     * \brief Logical port the channel call record is HOLDED on 
00147     * because the B channel is no longer associated. 
00148     */
00149    int port;
00150 
00151    /*!
00152     * \brief Original B channel number the HOLDED call was using. 
00153     * \note Used only for debug display messages.
00154     */
00155    int channel;
00156 };
00157 
00158 /*!
00159  * \brief Channel call record structure
00160  */
00161 struct chan_list {
00162    /*! 
00163     * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
00164     */
00165    char allowed_bearers[BUFFERSIZE + 1];
00166    
00167    /*! 
00168     * \brief State of the channel
00169     */
00170    enum misdn_chan_state state;
00171 
00172    /*! 
00173     * \brief TRUE if a hangup needs to be queued 
00174     * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
00175     */
00176    int need_queue_hangup;
00177 
00178    /*!
00179     * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
00180     */
00181    int need_hangup;
00182 
00183    /*!
00184     * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
00185     */
00186    int need_busy;
00187    
00188    /*!
00189     * \brief Who originally created this channel. ORG_AST or ORG_MISDN
00190     */
00191    int originator;
00192 
00193    /*! 
00194     * \brief TRUE of we are not to respond immediately to a SETUP message.  Check the dialplan first.
00195     * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
00196     */
00197    int noautorespond_on_setup;
00198    
00199    int norxtone;  /* Boolean assigned values but the value is not used. */
00200 
00201    /*!
00202     * \brief TRUE if we are not to generate tones (Playtones)
00203     */
00204    int notxtone; 
00205 
00206    /*!
00207     * \brief TRUE if echo canceller is enabled.  Value is toggled.
00208     */
00209    int toggle_ec;
00210    
00211    /*!
00212     * \brief TRUE if you want to send Tone Indications to an incoming
00213     * ISDN channel on a TE Port.
00214     * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
00215     */
00216    int incoming_early_audio;
00217 
00218    /*!
00219     * \brief TRUE if DTMF digits are to be passed inband only.
00220     * \note It is settable by the misdn_set_opt() application.
00221     */
00222    int ignore_dtmf;
00223 
00224    /*!
00225     * \brief Pipe file descriptor handles array. 
00226     * Read from pipe[0], write to pipe[1] 
00227     */
00228    int pipe[2];
00229 
00230    /*!
00231     * \brief Read buffer for inbound audio from pipe[0]
00232     */
00233    char ast_rd_buf[4096];
00234 
00235    /*!
00236     * \brief Inbound audio frame returned by misdn_read().
00237     */
00238    struct ast_frame frame;
00239 
00240    /*!
00241     * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
00242     * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
00243     * \note It is settable by the misdn_set_opt() application.
00244     */
00245    int faxdetect;
00246 
00247    /*!
00248     * \brief Number of seconds to detect a Fax machine when detection enabled.
00249     * \note 0 disables the timeout.
00250     * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
00251     */
00252    int faxdetect_timeout;
00253 
00254    /*!
00255     * \brief Starting time of fax detection with timeout when nonzero.
00256     */
00257    struct timeval faxdetect_tv;
00258 
00259    /*!
00260     * \brief TRUE if a fax has been detected.
00261     */
00262    int faxhandled;
00263 
00264    /*!
00265     * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
00266     * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
00267     */
00268    int ast_dsp;
00269 
00270    /*!
00271     * \brief Jitterbuffer length
00272     * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
00273     */
00274    int jb_len;
00275 
00276    /*!
00277     * \brief Jitterbuffer upper threshold
00278     * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
00279     */
00280    int jb_upper_threshold;
00281 
00282    /*!
00283     * \brief Allocated jitterbuffer controller
00284     * \note misdn_jb_init() creates the jitterbuffer.
00285     * \note Must use misdn_jb_destroy() to clean up. 
00286     */
00287    struct misdn_jb *jb;
00288    
00289    /*!
00290     * \brief Allocated DSP controller
00291     * \note ast_dsp_new() creates the DSP controller.
00292     * \note Must use ast_dsp_free() to clean up. 
00293     */
00294    struct ast_dsp *dsp;
00295 
00296    /*!
00297     * \brief Allocated audio frame sample translator
00298     * \note ast_translator_build_path() creates the translator path.
00299     * \note Must use ast_translator_free_path() to clean up. 
00300     */
00301    struct ast_trans_pvt *trans;
00302   
00303    /*!
00304     * \brief Associated Asterisk channel structure.
00305     */
00306    struct ast_channel * ast;
00307 
00308    //int dummy;   /* Not used */
00309   
00310    /*!
00311     * \brief Associated B channel structure.
00312     */
00313    struct misdn_bchannel *bc;
00314 
00315    /*!
00316     * \brief HOLDED channel information
00317     */
00318    struct hold_info hold_info;
00319 
00320    /*! 
00321     * \brief From associated B channel: Layer 3 process ID 
00322     * \note Used to find the HOLDED channel call record when retrieving a call. 
00323     */
00324    unsigned int l3id;
00325 
00326    /*! 
00327     * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
00328     * \note Used only for debug display messages.
00329     */
00330    int addr;
00331 
00332    /*!
00333     * \brief Incoming call dialplan context identifier.
00334     * \note The "context" string read in from /etc/asterisk/misdn.conf
00335     */
00336    char context[AST_MAX_CONTEXT];
00337 
00338    /*!
00339     * \brief The configured music-on-hold class to use for this call.
00340     * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
00341     */
00342    char mohinterpret[MAX_MUSICCLASS];
00343 
00344    //int zero_read_cnt; /* Not used */
00345 
00346    /*!
00347     * \brief Number of outgoing audio frames dropped since last debug gripe message.
00348     */
00349    int dropped_frame_cnt;
00350 
00351    /*!
00352     * \brief TRUE if we must do the ringback tones.
00353     * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
00354     */
00355    int far_alerting;
00356 
00357    /*!
00358     * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
00359     * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
00360     */
00361    int nttimeout;
00362 
00363    /*!
00364     * \brief Other channel call record PID 
00365     * \note Value imported from Asterisk environment variable MISDN_PID 
00366     */
00367    int other_pid;
00368 
00369    /*!
00370     * \brief Bridged other channel call record
00371     * \note Pointer set when other_pid imported from Asterisk environment 
00372     * variable MISDN_PID by either side.
00373     */
00374    struct chan_list *other_ch;
00375 
00376    /*!
00377     * \brief Tone zone sound used for dialtone generation.
00378     * \note Used as a boolean.  Non-NULL to prod generation if enabled. 
00379     */
00380    const struct tone_zone_sound *ts;
00381    
00382    /*!
00383     * \brief Enables overlap dialing for the set amount of seconds.  (0 = Disabled)
00384     * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
00385     */
00386    int overlap_dial;
00387 
00388    /*!
00389     * \brief Overlap dialing timeout Task ID.  -1 if not running.
00390     */
00391    int overlap_dial_task;
00392 
00393    /*!
00394     * \brief overlap_tv access lock.
00395     */
00396    ast_mutex_t overlap_tv_lock;
00397 
00398    /*!
00399     * \brief Overlap timer start time.  Timer restarted for every digit received.
00400     */
00401    struct timeval overlap_tv;
00402   
00403    //struct chan_list *peer;  /* Not used */
00404 
00405    /*!
00406     * \brief Next channel call record in the list.
00407     */
00408    struct chan_list *next;
00409    //struct chan_list *prev;     /* Not used */
00410    //struct chan_list *first; /* Not used */
00411 };
00412 
00413 
00414 
00415 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
00416 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
00417 
00418 struct robin_list {
00419    char *group;
00420    int port;
00421    int channel;
00422    struct robin_list *next;
00423    struct robin_list *prev;
00424 };
00425 static struct robin_list *robin = NULL;
00426 
00427 
00428 
00429 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
00430 
00431 
00432 
00433 static inline void free_robin_list_r (struct robin_list *r)
00434 {
00435    if (r) {
00436       if (r->next)
00437          free_robin_list_r(r->next);
00438       if (r->group)
00439          ast_free(r->group);
00440       ast_free(r);
00441    }
00442 }
00443 
00444 static void free_robin_list ( void )
00445 {
00446    free_robin_list_r(robin);
00447    robin = NULL;
00448 }
00449 
00450 static struct robin_list* get_robin_position (char *group) 
00451 {
00452    struct robin_list *new;
00453    struct robin_list *iter = robin;
00454    for (; iter; iter = iter->next) {
00455       if (!strcasecmp(iter->group, group))
00456          return iter;
00457    }
00458    new = ast_calloc(1, sizeof(*new));
00459    new->group = strndup(group, strlen(group));
00460    new->channel = 1;
00461    if (robin) {
00462       new->next = robin;
00463       robin->prev = new;
00464    }
00465    robin = new;
00466    return robin;
00467 }
00468 
00469 
00470 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
00471 static struct sched_context *misdn_tasks = NULL;
00472 static pthread_t misdn_tasks_thread;
00473 
00474 static int *misdn_ports;
00475 
00476 static void chan_misdn_log(int level, int port, char *tmpl, ...)
00477    __attribute__((format(printf, 3, 4)));
00478 
00479 static struct ast_channel *misdn_new(struct chan_list *cl, int state,  char *exten, char *callerid, int format, int port, int c);
00480 static void send_digit_to_chan(struct chan_list *cl, char digit );
00481 
00482 static void hangup_chan(struct chan_list *ch);
00483 static int pbx_start_chan(struct chan_list *ch);
00484 
00485 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
00486 #define MISDN_ASTERISK_PVT(ast) 1
00487 
00488 #include "asterisk/strings.h"
00489 
00490 /* #define MISDN_DEBUG 1 */
00491 
00492 static const char misdn_type[] = "mISDN";
00493 
00494 static int tracing = 0 ;
00495 
00496 /*! \brief Only alaw and mulaw is allowed for now */
00497 static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
00498 
00499 static int *misdn_debug;
00500 static int *misdn_debug_only;
00501 static int max_ports;
00502 
00503 static int *misdn_in_calls;
00504 static int *misdn_out_calls;
00505 
00506 
00507 struct chan_list dummy_cl;
00508 
00509 /*!
00510  * \brief Global channel call record list head.
00511  */
00512 struct chan_list *cl_te=NULL;
00513 ast_mutex_t cl_te_lock;
00514 
00515 static enum event_response_e
00516 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
00517 
00518 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
00519 
00520 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
00521 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
00522 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
00523 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
00524 
00525 
00526 
00527 static int dialtone_indicate(struct chan_list *cl);
00528 static int hanguptone_indicate(struct chan_list *cl);
00529 static int stop_indicate(struct chan_list *cl);
00530 
00531 static int start_bc_tones(struct chan_list *cl);
00532 static int stop_bc_tones(struct chan_list *cl);
00533 static void release_chan(struct misdn_bchannel *bc);
00534 
00535 static int misdn_check_l2l1(struct ast_channel *chan, void *data);
00536 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
00537 static int misdn_facility_exec(struct ast_channel *chan, void *data);
00538 
00539 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
00540 
00541 
00542 void debug_numplan(int port, int numplan, char *type);
00543 
00544 
00545 int add_out_calls(int port);
00546 int add_in_calls(int port);
00547 
00548 
00549 #ifdef MISDN_1_2
00550 static int update_pipeline_config(struct misdn_bchannel *bc);
00551 #else
00552 static int update_ec_config(struct misdn_bchannel *bc);
00553 #endif
00554 
00555 
00556 
00557 /*************** Helpers *****************/
00558 
00559 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
00560 {
00561    struct chan_list *tmp;
00562   
00563    for (tmp=cl_te; tmp; tmp = tmp->next) {
00564       if ( tmp->ast == ast ) return tmp;
00565    }
00566   
00567    return NULL;
00568 }
00569 
00570 static struct chan_list * get_chan_by_ast_name(char *name)
00571 {
00572    struct chan_list *tmp;
00573   
00574    for (tmp=cl_te; tmp; tmp = tmp->next) {
00575       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
00576    }
00577   
00578    return NULL;
00579 }
00580 
00581 
00582 
00583 struct allowed_bearers {
00584    int cap;
00585    int val;
00586    char *name;
00587    int deprecated;
00588 };
00589 
00590 static struct allowed_bearers allowed_bearers_array[]= {
00591    {INFO_CAPABILITY_SPEECH,1,"speech"},
00592    {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
00593    {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
00594    {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restricted"},
00595    {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced", 1}, /* Allow misspelling for backwards compatibility */
00596    {INFO_CAPABILITY_VIDEO,16,"video"}
00597 };
00598 
00599 static char *bearer2str(int cap) {
00600    static char *bearers[]={
00601       "Speech",
00602       "Audio 3.1k",
00603       "Unres Digital",
00604       "Res Digital",
00605       "Video",
00606       "Unknown Bearer"
00607    };
00608    
00609    switch (cap) {
00610    case INFO_CAPABILITY_SPEECH:
00611       return bearers[0];
00612       break;
00613    case INFO_CAPABILITY_AUDIO_3_1K:
00614       return bearers[1];
00615       break;
00616    case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00617       return bearers[2];
00618       break;
00619    case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00620       return bearers[3];
00621       break;
00622    case INFO_CAPABILITY_VIDEO:
00623       return bearers[4];
00624       break;
00625    default:
00626       return bearers[5];
00627       break;
00628    }
00629 }
00630 
00631 
00632 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
00633 {
00634    switch (fac->Function) {
00635 #ifdef HAVE_MISDN_FAC_RESULT
00636    case Fac_RESULT:
00637       chan_misdn_log(0, bc->port," --> Received RESULT Operation\n");
00638       break;
00639 #endif
00640 #ifdef HAVE_MISDN_FAC_ERROR
00641    case Fac_ERROR:
00642       chan_misdn_log(0, bc->port," --> Received Error Operation\n");
00643       chan_misdn_log(0, bc->port," --> Value:%d Error:%s\n",fac->u.ERROR.errorValue, fac->u.ERROR.error);
00644       break;
00645 #endif
00646    case Fac_CD:
00647       chan_misdn_log(1,bc->port," --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
00648          fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
00649       break;
00650    case Fac_AOCDCurrency:
00651       if (fac->u.AOCDcur.chargeNotAvailable)
00652          chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
00653       else if (fac->u.AOCDcur.freeOfCharge)
00654          chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
00655       else if (fac->u.AOCDchu.billingId >= 0)
00656          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
00657             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00658             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
00659       else
00660          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
00661             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00662             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
00663       break;
00664    case Fac_AOCDChargingUnit:
00665       if (fac->u.AOCDchu.chargeNotAvailable)
00666          chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
00667       else if (fac->u.AOCDchu.freeOfCharge)
00668          chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
00669       else if (fac->u.AOCDchu.billingId >= 0)
00670          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
00671             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
00672       else
00673          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
00674             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
00675       break;
00676    case Fac_None:
00677    default:
00678       chan_misdn_log(1,bc->port," --> unknown facility\n");
00679       break;
00680    }
00681 }
00682 
00683 static void print_bearer(struct misdn_bchannel *bc) 
00684 {
00685    
00686    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00687    
00688    switch(bc->law) {
00689    case INFO_CODEC_ALAW:
00690       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00691       break;
00692    case INFO_CODEC_ULAW:
00693       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00694       break;
00695    }
00696 }
00697 
00698 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
00699 {
00700    char buf[128];
00701 
00702    if (!bc->AOCD_need_export || !ast)
00703       return;
00704 
00705    if (originator == ORG_AST) {
00706       ast = ast_bridged_channel(ast);
00707       if (!ast)
00708          return;
00709    }
00710 
00711    switch (bc->AOCDtype) {
00712    case Fac_AOCDCurrency:
00713       pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
00714       if (bc->AOCD.currency.chargeNotAvailable)
00715          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00716       else {
00717          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00718          if (bc->AOCD.currency.freeOfCharge)
00719             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00720          else {
00721             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00722             if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
00723                pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
00724                if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
00725                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00726             }
00727          }
00728       }
00729       break;
00730    case Fac_AOCDChargingUnit:
00731       pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
00732       if (bc->AOCD.chargingUnit.chargeNotAvailable)
00733          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00734       else {
00735          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00736          if (bc->AOCD.chargingUnit.freeOfCharge)
00737             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00738          else {
00739             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00740             if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
00741                pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
00742                if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
00743                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00744             }
00745          }
00746       }
00747       break;
00748    default:
00749       break;
00750    }
00751    
00752    bc->AOCD_need_export = 0;
00753 }
00754 
00755 /*************** Helpers END *************/
00756 
00757 static void sighandler(int sig)
00758 {}
00759 
00760 static void* misdn_tasks_thread_func (void *data)
00761 {
00762    int wait;
00763    struct sigaction sa;
00764 
00765    sa.sa_handler = sighandler;
00766    sa.sa_flags = SA_NODEFER;
00767    sigemptyset(&sa.sa_mask);
00768    sigaddset(&sa.sa_mask, SIGUSR1);
00769    sigaction(SIGUSR1, &sa, NULL);
00770    
00771    sem_post((sem_t *)data);
00772 
00773    while (1) {
00774       wait = ast_sched_wait(misdn_tasks);
00775       if (wait < 0)
00776          wait = 8000;
00777       if (poll(NULL, 0, wait) < 0)
00778          chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
00779       ast_sched_runq(misdn_tasks);
00780    }
00781    return NULL;
00782 }
00783 
00784 static void misdn_tasks_init (void)
00785 {
00786    sem_t blocker;
00787    int i = 5;
00788 
00789    if (sem_init(&blocker, 0, 0)) {
00790       perror("chan_misdn: Failed to initialize semaphore!");
00791       exit(1);
00792    }
00793 
00794    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
00795    
00796    misdn_tasks = sched_context_create();
00797    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
00798 
00799    while (sem_wait(&blocker) && --i);
00800    sem_destroy(&blocker);
00801 }
00802 
00803 static void misdn_tasks_destroy (void)
00804 {
00805    if (misdn_tasks) {
00806       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
00807       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
00808          cb_log(4, 0, "Joining misdn_tasks thread\n");
00809          pthread_join(misdn_tasks_thread, NULL);
00810       }
00811       sched_context_destroy(misdn_tasks);
00812    }
00813 }
00814 
00815 static inline void misdn_tasks_wakeup (void)
00816 {
00817    pthread_kill(misdn_tasks_thread, SIGUSR1);
00818 }
00819 
00820 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
00821 {
00822    int task_id;
00823 
00824    if (!misdn_tasks) {
00825       misdn_tasks_init();
00826    }
00827    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00828    misdn_tasks_wakeup();
00829 
00830    return task_id;
00831 }
00832 
00833 static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data)
00834 {
00835    return _misdn_tasks_add_variable(timeout, callback, data, 0);
00836 }
00837 
00838 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data)
00839 {
00840    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00841 }
00842 
00843 static void misdn_tasks_remove (int task_id)
00844 {
00845    AST_SCHED_DEL(misdn_tasks, task_id);
00846 }
00847 
00848 static int misdn_l1_task (const void *data)
00849 {
00850    misdn_lib_isdn_l1watcher(*(int *)data);
00851    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00852    return 1;
00853 }
00854 
00855 static int misdn_overlap_dial_task (const void *data)
00856 {
00857    struct timeval tv_end, tv_now;
00858    int diff;
00859    struct chan_list *ch = (struct chan_list *)data;
00860 
00861    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
00862 
00863    if (ch->state != MISDN_WAITING4DIGS) {
00864       ch->overlap_dial_task = -1;
00865       return 0;
00866    }
00867    
00868    ast_mutex_lock(&ch->overlap_tv_lock);
00869    tv_end = ch->overlap_tv;
00870    ast_mutex_unlock(&ch->overlap_tv_lock);
00871    
00872    tv_end.tv_sec += ch->overlap_dial;
00873    tv_now = ast_tvnow();
00874 
00875    diff = ast_tvdiff_ms(tv_end, tv_now);
00876 
00877    if (diff <= 100) {
00878       char *dad=ch->bc->dad, sexten[]="s";
00879       /* if we are 100ms near the timeout, we are satisfied.. */
00880       stop_indicate(ch);
00881       
00882       if (ast_strlen_zero(ch->bc->dad)) {
00883          dad=sexten;
00884          strcpy(ch->ast->exten, sexten);
00885       }
00886 
00887       if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
00888          ch->state=MISDN_DIALING;
00889          if (pbx_start_chan(ch) < 0) {
00890             chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
00891             goto misdn_overlap_dial_task_disconnect;
00892          }
00893       } else {
00894 misdn_overlap_dial_task_disconnect:
00895          hanguptone_indicate(ch);
00896          ch->bc->out_cause=1;
00897          ch->state=MISDN_CLEANING;
00898          misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
00899       }
00900       ch->overlap_dial_task = -1;
00901       return 0;
00902    } else
00903       return diff;
00904 }
00905 
00906 static void send_digit_to_chan(struct chan_list *cl, char digit )
00907 {
00908    static const char* dtmf_tones[] = {
00909       "!941+1336/100,!0/100", /* 0 */
00910       "!697+1209/100,!0/100", /* 1 */
00911       "!697+1336/100,!0/100", /* 2 */
00912       "!697+1477/100,!0/100", /* 3 */
00913       "!770+1209/100,!0/100", /* 4 */
00914       "!770+1336/100,!0/100", /* 5 */
00915       "!770+1477/100,!0/100", /* 6 */
00916       "!852+1209/100,!0/100", /* 7 */
00917       "!852+1336/100,!0/100", /* 8 */
00918       "!852+1477/100,!0/100", /* 9 */
00919       "!697+1633/100,!0/100", /* A */
00920       "!770+1633/100,!0/100", /* B */
00921       "!852+1633/100,!0/100", /* C */
00922       "!941+1633/100,!0/100", /* D */
00923       "!941+1209/100,!0/100", /* * */
00924       "!941+1477/100,!0/100" };  /* # */
00925    struct ast_channel *chan=cl->ast; 
00926   
00927    if (digit >= '0' && digit <='9')
00928       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00929    else if (digit >= 'A' && digit <= 'D')
00930       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00931    else if (digit == '*')
00932       ast_playtones_start(chan,0,dtmf_tones[14], 0);
00933    else if (digit == '#')
00934       ast_playtones_start(chan,0,dtmf_tones[15], 0);
00935    else {
00936       /* not handled */
00937       ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00938    }
00939 }
00940 
00941 /*** CLI HANDLING ***/
00942 static char *handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00943 {
00944    int level;
00945 
00946    switch (cmd) {
00947    case CLI_INIT:
00948       e->command = "misdn set debug";
00949       e->usage =
00950          "Usage: misdn set debug <level> [only] | [port <port> [only]]\n"
00951          "       Set the debug level of the mISDN channel.\n";
00952       return NULL;
00953    case CLI_GENERATE:
00954       return complete_debug_port(a);
00955    }
00956 
00957    if (a->argc < 4 || a->argc > 7)
00958       return CLI_SHOWUSAGE;
00959 
00960    level = atoi(a->argv[3]);
00961 
00962    switch (a->argc) {
00963    case 4:  
00964    case 5:
00965       {
00966          int only = 0, i;
00967          if (a->argc == 5) {
00968             if (strncasecmp(a->argv[4], "only", strlen(a->argv[4])))
00969                return CLI_SHOWUSAGE;
00970             else
00971                only = 1;
00972          }
00973    
00974          for (i = 0; i <= max_ports; i++) {
00975             misdn_debug[i] = level;
00976             misdn_debug_only[i] = only;
00977          }
00978          ast_cli(a->fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00979       }
00980       break;
00981    case 6: 
00982    case 7:
00983       {
00984          int port;
00985          if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
00986             return CLI_SHOWUSAGE;
00987          port = atoi(a->argv[5]);
00988          if (port <= 0 || port > max_ports) {
00989             switch (max_ports) {
00990             case 0:
00991                ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00992                break;
00993             case 1:
00994                ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
00995                break;
00996             default:
00997                ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00998             }
00999             return 0;
01000          }
01001          if (a->argc == 7) {
01002             if (strncasecmp(a->argv[6], "only", strlen(a->argv[6])))
01003                return CLI_SHOWUSAGE;
01004             else
01005                misdn_debug_only[port] = 1;
01006          } else
01007             misdn_debug_only[port] = 0;
01008          misdn_debug[port] = level;
01009          ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
01010       }
01011    }
01012 
01013    return CLI_SUCCESS;
01014 }
01015 
01016 static char *handle_cli_misdn_set_crypt_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01017 {
01018    switch (cmd) {
01019    case CLI_INIT:
01020       e->command = "misdn set crypt debug";
01021       e->usage =
01022          "Usage: misdn set crypt debug <level>\n"
01023          "       Set the crypt debug level of the mISDN channel. Level\n"
01024          "       must be 1 or 2.\n";
01025       return NULL;
01026    case CLI_GENERATE:
01027       return NULL;
01028    }
01029 
01030    if (a->argc != 5)
01031       return CLI_SHOWUSAGE;
01032 
01033    /* Is this supposed to not do anything? */
01034 
01035    return CLI_SUCCESS;
01036 }
01037 
01038 static char *handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01039 {
01040    switch (cmd) {
01041    case CLI_INIT:
01042       e->command = "misdn port block";
01043       e->usage =
01044          "Usage: misdn port block <port>\n"
01045          "       Block the specified port by <port>.\n";
01046       return NULL;
01047    case CLI_GENERATE:
01048       return NULL;
01049    }
01050 
01051    if (a->argc != 4)
01052       return CLI_SHOWUSAGE;
01053 
01054    misdn_lib_port_block(atoi(a->argv[3]));
01055 
01056    return CLI_SUCCESS;
01057 }
01058 
01059 static char *handle_cli_misdn_port_unblock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01060 {
01061    switch (cmd) {
01062    case CLI_INIT:
01063       e->command = "misdn port unblock";
01064       e->usage =
01065          "Usage: misdn port unblock <port>\n"
01066          "       Unblock the port specified by <port>.\n";
01067       return NULL;
01068    case CLI_GENERATE:
01069       return NULL;
01070    }
01071 
01072    if (a->argc != 4)
01073       return CLI_SHOWUSAGE;
01074 
01075    misdn_lib_port_unblock(atoi(a->argv[3]));
01076 
01077    return CLI_SUCCESS;
01078 }
01079 
01080 static char *handle_cli_misdn_restart_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01081 {
01082    switch (cmd) {
01083    case CLI_INIT:
01084       e->command = "misdn restart port";
01085       e->usage =
01086          "Usage: misdn restart port <port>\n"
01087          "       Restart the given port.\n";
01088       return NULL;
01089    case CLI_GENERATE:
01090       return NULL;
01091    }
01092 
01093    if (a->argc != 4)
01094       return CLI_SHOWUSAGE;
01095 
01096    misdn_lib_port_restart(atoi(a->argv[3]));
01097 
01098    return CLI_SUCCESS;
01099 }
01100 
01101 static char *handle_cli_misdn_restart_pid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01102 {
01103    switch (cmd) {
01104    case CLI_INIT:
01105       e->command = "misdn restart pid";
01106       e->usage =
01107          "Usage: misdn restart pid <pid>\n"
01108          "       Restart the given pid\n";
01109       return NULL;
01110    case CLI_GENERATE:
01111       return NULL;
01112    }
01113 
01114    if (a->argc != 4)
01115       return CLI_SHOWUSAGE;
01116 
01117    misdn_lib_pid_restart(atoi(a->argv[3]));
01118 
01119    return CLI_SUCCESS;
01120 }
01121 
01122 static char *handle_cli_misdn_port_up(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01123 {
01124    switch (cmd) {
01125    case CLI_INIT:
01126       e->command = "misdn port up";
01127       e->usage =
01128          "Usage: misdn port up <port>\n"
01129          "       Try to establish L1 on the given port.\n";
01130       return NULL;
01131    case CLI_GENERATE:
01132       return NULL;
01133    }
01134 
01135    if (a->argc != 4)
01136       return CLI_SHOWUSAGE;
01137 
01138    misdn_lib_get_port_up(atoi(a->argv[3]));
01139 
01140    return CLI_SUCCESS;
01141 }
01142 
01143 static char *handle_cli_misdn_port_down(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01144 {
01145    switch (cmd) {
01146    case CLI_INIT:
01147       e->command = "misdn port down";
01148       e->usage =
01149          "Usage: misdn port down <port>\n"
01150          "       Try to deactivate the L1 on the given port.\n";
01151       return NULL;
01152    case CLI_GENERATE:
01153       return NULL;
01154    }
01155 
01156    if (a->argc != 4)
01157       return CLI_SHOWUSAGE;
01158 
01159    misdn_lib_get_port_down(atoi(a->argv[3]));
01160 
01161    return CLI_SUCCESS;
01162 }
01163 
01164 static inline void show_config_description(int fd, enum misdn_cfg_elements elem)
01165 {
01166    char section[BUFFERSIZE];
01167    char name[BUFFERSIZE];
01168    char desc[BUFFERSIZE];
01169    char def[BUFFERSIZE];
01170    char tmp[BUFFERSIZE];
01171 
01172    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
01173    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
01174    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
01175 
01176    if (elem < MISDN_CFG_LAST)
01177       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
01178    else
01179       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
01180 
01181    if (*def)
01182       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
01183    else
01184       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
01185 
01186    return;
01187 }
01188 
01189 static char *handle_cli_misdn_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01190 {
01191    char buffer[BUFFERSIZE];
01192    enum misdn_cfg_elements elem;
01193    int linebreak;
01194    int onlyport = -1;
01195    int ok = 0;
01196 
01197    switch (cmd) {
01198    case CLI_INIT:
01199       e->command = "misdn show config";
01200       e->usage =
01201          "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
01202          "       Use 0 for <port> to only print the general config.\n";
01203       return NULL;
01204    case CLI_GENERATE:
01205       return complete_show_config(a);
01206    }
01207 
01208    if (a->argc >= 4) {
01209       if (!strcmp(a->argv[3], "description")) {
01210          if (a->argc == 5) {
01211             enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
01212             if (elem == MISDN_CFG_FIRST)
01213                ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
01214             else
01215                show_config_description(a->fd, elem);
01216             return CLI_SUCCESS;
01217          }
01218          return CLI_SHOWUSAGE;
01219       } else if (!strcmp(a->argv[3], "descriptions")) {
01220          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
01221             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01222                show_config_description(a->fd, elem);
01223                ast_cli(a->fd, "\n");
01224             }
01225             ok = 1;
01226          }
01227          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
01228             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
01229                show_config_description(a->fd, elem);
01230                ast_cli(a->fd, "\n");
01231             }
01232             ok = 1;
01233          }
01234          return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
01235       } else if (!sscanf(a->argv[3], "%d", &onlyport) || onlyport < 0) {
01236          ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
01237          return CLI_SHOWUSAGE;
01238       }
01239    } else if (a->argc == 3 || onlyport == 0) {
01240       ast_cli(a->fd, "mISDN General-Config:\n");
01241       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
01242          misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
01243          ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01244       }
01245       ast_cli(a->fd, "\n");
01246    }
01247 
01248    if (onlyport < 0) {
01249       int port = misdn_cfg_get_next_port(0);
01250       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
01251          ast_cli(a->fd, "\n[PORT %d]\n", port);
01252          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01253             misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
01254             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01255          }  
01256          ast_cli(a->fd, "\n");
01257       }
01258    }
01259    
01260    if (onlyport > 0) {
01261       if (misdn_cfg_is_port_valid(onlyport)) {
01262          ast_cli(a->fd, "[PORT %d]\n", onlyport);
01263          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01264             misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
01265             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01266          }  
01267          ast_cli(a->fd, "\n");
01268       } else {
01269          ast_cli(a->fd, "Port %d is not active!\n", onlyport);
01270       }
01271    }
01272 
01273    return CLI_SUCCESS;
01274 }
01275 
01276 struct state_struct {
01277    enum misdn_chan_state state;
01278    char txt[255];
01279 };
01280 
01281 static struct state_struct state_array[] = {
01282    {MISDN_NOTHING,"NOTHING"}, /* at beginning */
01283    {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /*  when waiting for infos */
01284    {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldn't match our ext */
01285    {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /*  when pbx_start */
01286    {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
01287    {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
01288    {MISDN_PROCEEDING,"PROCEEDING"}, /*  when pbx_start */
01289    {MISDN_CALLING,"CALLING"}, /*  when misdn_call is called */
01290    {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /*  when misdn_call is called */
01291    {MISDN_ALERTING,"ALERTING"}, /*  when Alerting */
01292    {MISDN_BUSY,"BUSY"}, /*  when BUSY */
01293    {MISDN_CONNECTED,"CONNECTED"}, /*  when connected */
01294    {MISDN_PRECONNECTED,"PRECONNECTED"}, /*  when connected */
01295    {MISDN_DISCONNECTED,"DISCONNECTED"}, /*  when connected */
01296    {MISDN_RELEASED,"RELEASED"}, /*  when connected */
01297    {MISDN_BRIDGED,"BRIDGED"}, /*  when bridged */
01298    {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
01299    {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  came from misdn */
01300    {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  came from misdn */
01301    {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  came from misdn */
01302    {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
01303 };
01304 
01305 static const char *misdn_get_ch_state(struct chan_list *p) 
01306 {
01307    int i;
01308    static char state[8];
01309    
01310    if( !p) return NULL;
01311   
01312    for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
01313       if (state_array[i].state == p->state)
01314          return state_array[i].txt; 
01315    }
01316 
01317    snprintf(state, sizeof(state), "%d", p->state) ;
01318 
01319    return state;
01320 }
01321 
01322 
01323 
01324 static void reload_config(void)
01325 {
01326    int i, cfg_debug;
01327 
01328    if (!g_config_initialized) {
01329       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
01330       return ;
01331    }
01332    
01333    free_robin_list();
01334    misdn_cfg_reload();
01335    misdn_cfg_update_ptp();
01336    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
01337    misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
01338 
01339    for (i = 0;  i <= max_ports; i++) {
01340       misdn_debug[i] = cfg_debug;
01341       misdn_debug_only[i] = 0;
01342    }
01343 }
01344 
01345 static char *handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01346 {
01347    switch (cmd) {
01348    case CLI_INIT:
01349       e->command = "misdn reload";
01350       e->usage =
01351          "Usage: misdn reload\n"
01352          "       Reload internal mISDN config, read from the config\n"
01353          "       file.\n";
01354       return NULL;
01355    case CLI_GENERATE:
01356       return NULL;
01357    }
01358 
01359    if (a->argc != 2)
01360       return CLI_SHOWUSAGE;
01361 
01362    ast_cli(a->fd, "Reloading mISDN configuration\n");
01363    reload_config();
01364    return CLI_SUCCESS;
01365 }
01366 
01367 static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
01368 {
01369    struct ast_channel *ast = help->ast;
01370    ast_cli(fd,
01371       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
01372 
01373       bc->pid, bc->port, bc->channel,
01374       bc->nt ? "NT" : "TE",
01375       help->originator == ORG_AST ? "*" : "I",
01376       ast ? ast->exten : NULL,
01377       ast ? ast->cid.cid_num : NULL,
01378       bc->rad,
01379       ast ? ast->context : NULL,
01380       misdn_get_ch_state(help)
01381       );
01382    if (misdn_debug[bc->port] > 0)
01383       ast_cli(fd,
01384          "  --> astname: %s\n"
01385          "  --> ch_l3id: %x\n"
01386          "  --> ch_addr: %x\n"
01387          "  --> bc_addr: %x\n"
01388          "  --> bc_l3id: %x\n"
01389          "  --> display: %s\n"
01390          "  --> activated: %d\n"
01391          "  --> state: %s\n"
01392          "  --> capability: %s\n"
01393 #ifdef MISDN_1_2
01394          "  --> pipeline: %s\n"
01395 #else
01396          "  --> echo_cancel: %d\n"
01397 #endif
01398          "  --> notone : rx %d tx:%d\n"
01399          "  --> bc_hold: %d\n",
01400          help->ast->name,
01401          help->l3id,
01402          help->addr,
01403          bc->addr,
01404          bc ? bc->l3_id : -1,
01405          bc->display,
01406          
01407          bc->active,
01408          bc_state2str(bc->bc_state),
01409          bearer2str(bc->capability),
01410 #ifdef MISDN_1_2
01411          bc->pipeline,
01412 #else
01413          bc->ec_enable,
01414 #endif
01415 
01416          help->norxtone, help->notxtone,
01417          bc->holded
01418          );
01419 
01420 }
01421 
01422 static char *handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01423 {
01424    struct chan_list *help = NULL;
01425 
01426    switch (cmd) {
01427    case CLI_INIT:
01428       e->command = "misdn show channels";
01429       e->usage =
01430          "Usage: misdn show channels\n"
01431          "       Show the internal mISDN channel list\n";
01432       return NULL;
01433    case CLI_GENERATE:
01434       return NULL;
01435    }
01436 
01437    if (a->argc != 3)
01438       return CLI_SHOWUSAGE;
01439 
01440    help = cl_te;
01441   
01442    ast_cli(a->fd, "Channel List: %p\n", cl_te); 
01443 
01444    for (; help; help = help->next) {
01445       struct misdn_bchannel *bc = help->bc;   
01446       struct ast_channel *ast = help->ast;
01447       if (!ast) {
01448          if (!bc) {
01449             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
01450             continue;
01451          }
01452          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
01453          continue;
01454       }
01455 
01456       if (misdn_debug[0] > 2)
01457          ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
01458       if (bc) {
01459          print_bc_info(a->fd, help, bc);
01460       } else {
01461          if (help->state == MISDN_HOLDED) {
01462             ast_cli(a->fd, "ITS A HOLDED BC:\n");
01463             ast_cli(a->fd, " --> l3_id: %x\n"
01464                   " --> dad:%s oad:%s\n"
01465                   " --> hold_port: %d\n"
01466                   " --> hold_channel: %d\n",
01467                   help->l3id,
01468                   ast->exten,
01469                   ast->cid.cid_num,
01470                   help->hold_info.port,
01471                   help->hold_info.channel
01472                   );
01473          } else {
01474             ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
01475          }
01476       }
01477    }
01478 
01479    misdn_dump_chanlist();
01480 
01481    return CLI_SUCCESS;
01482 }
01483 
01484 static char *handle_cli_misdn_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01485 {
01486    struct chan_list *help = NULL;
01487 
01488    switch (cmd) {
01489    case CLI_INIT:
01490       e->command = "misdn show channel";
01491       e->usage =
01492          "Usage: misdn show channel <channel>\n"
01493          "       Show an internal mISDN channel\n.";
01494       return NULL;
01495    case CLI_GENERATE:
01496       return complete_ch(a);
01497    }
01498 
01499    if (a->argc != 4)
01500       return CLI_SHOWUSAGE;
01501 
01502    help = cl_te;
01503 
01504    for (; help; help = help->next) {
01505       struct misdn_bchannel *bc = help->bc;   
01506       struct ast_channel *ast = help->ast;
01507     
01508       if (bc && ast) {
01509          if (!strcasecmp(ast->name, a->argv[3])) {
01510             print_bc_info(a->fd, help, bc);
01511             break; 
01512          }
01513       } 
01514    }
01515 
01516    return CLI_SUCCESS;
01517 }
01518 
01519 ast_mutex_t lock;
01520 int MAXTICS = 8;
01521 
01522 static char *handle_cli_misdn_set_tics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01523 {
01524    switch (cmd) {
01525    case CLI_INIT:
01526       e->command = "misdn set tics";
01527       e->usage =
01528          "Usage: misdn set tics <value>\n";
01529       return NULL;
01530    case CLI_GENERATE:
01531       return NULL;
01532    }
01533 
01534    if (a->argc != 4)
01535       return CLI_SHOWUSAGE;
01536 
01537    MAXTICS = atoi(a->argv[3]);
01538 
01539    return CLI_SUCCESS;
01540 }
01541 
01542 static char *handle_cli_misdn_show_stacks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01543 {
01544    int port;
01545 
01546    switch (cmd) {
01547    case CLI_INIT:
01548       e->command = "misdn show stacks";
01549       e->usage =
01550          "Usage: misdn show stacks\n"
01551          "       Show internal mISDN stack_list.\n";
01552       return NULL;
01553    case CLI_GENERATE:
01554       return NULL;
01555    }
01556 
01557    if (a->argc != 3)
01558       return CLI_SHOWUSAGE;
01559 
01560    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01561    for (port = misdn_cfg_get_next_port(0); port > 0;
01562         port = misdn_cfg_get_next_port(port)) {
01563       char buf[128];
01564       get_show_stack_details(port, buf);
01565       ast_cli(a->fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01566    }
01567 
01568    return CLI_SUCCESS;
01569 }
01570 
01571 static char *handle_cli_misdn_show_ports_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01572 {
01573    int port;
01574 
01575    switch (cmd) {
01576    case CLI_INIT:
01577       e->command = "misdn show ports stats";
01578       e->usage =
01579          "Usage: misdn show ports stats\n"
01580          "       Show mISDNs channel's call statistics per port.\n";
01581       return NULL;
01582    case CLI_GENERATE:
01583       return NULL;
01584    }
01585 
01586    if (a->argc != 4)
01587       return CLI_SHOWUSAGE;
01588 
01589    ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
01590    for (port = misdn_cfg_get_next_port(0); port > 0;
01591         port = misdn_cfg_get_next_port(port)) {
01592       ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
01593    }
01594    ast_cli(a->fd, "\n");
01595 
01596    return CLI_SUCCESS;
01597 }
01598 
01599 static char *handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01600 {
01601    int port;
01602    char buf[128];
01603 
01604    switch (cmd) {
01605    case CLI_INIT:
01606       e->command = "misdn show port";
01607       e->usage =
01608          "Usage: misdn show port <port>\n"
01609          "       Show detailed information for given port.\n";
01610       return NULL;
01611    case CLI_GENERATE:
01612       return NULL;
01613    }
01614 
01615    if (a->argc != 4)
01616       return CLI_SHOWUSAGE;
01617 
01618    port = atoi(a->argv[3]);
01619   
01620    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01621    get_show_stack_details(port, buf);
01622    ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01623 
01624    return CLI_SUCCESS;
01625 }
01626 
01627 static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01628 {
01629    char *channame; 
01630    char *nr;
01631    struct chan_list *tmp;
01632    int port; 
01633    char *served_nr;
01634    struct misdn_bchannel dummy, *bc=&dummy;
01635  
01636    switch (cmd) {
01637    case CLI_INIT:
01638       e->command = "misdn send facility";
01639       e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
01640       "\t type is one of:\n"
01641       "\t - calldeflect\n"
01642       "\t - CFActivate\n"
01643       "\t - CFDeactivate\n";
01644 
01645       return NULL;
01646    case CLI_GENERATE:
01647       return complete_ch(a);
01648    }
01649 
01650    if (a->argc < 5)
01651       return CLI_SHOWUSAGE;
01652  
01653    if (strstr(a->argv[3], "calldeflect")) {
01654       if (a->argc < 6) {
01655          ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
01656          return 0;
01657       }
01658       channame = a->argv[4];
01659       nr = a->argv[5];
01660 
01661       ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
01662       tmp = get_chan_by_ast_name(channame);
01663       if (!tmp) {
01664          ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
01665          return 0; 
01666       }
01667 
01668       if (strlen(nr) >= 15) {
01669          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
01670          return 0; 
01671       }
01672       tmp->bc->fac_out.Function = Fac_CD;
01673       ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
01674       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
01675    } else if (strstr(a->argv[3],"CFActivate")) {
01676       if (a->argc < 7) {
01677          ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
01678          return 0;
01679       }
01680       port = atoi(a->argv[4]);
01681       served_nr = a->argv[5];
01682       nr = a->argv[6];
01683 
01684       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01685 
01686       ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
01687 
01688       bc->fac_out.Function = Fac_CFActivate;
01689       bc->fac_out.u.CFActivate.BasicService = 0; //All Services
01690       bc->fac_out.u.CFActivate.Procedure = 0; //Unconditional
01691       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01692       ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
01693 
01694       misdn_lib_send_event(bc, EVENT_FACILITY);
01695    } else if (strstr(a->argv[3],"CFDeactivate")) {
01696 
01697       if (a->argc < 6) {
01698          ast_verbose("CFActivate requires 1 arg: FromNumber\n\n");
01699          return 0;
01700       }
01701       port = atoi(a->argv[4]);
01702       served_nr = a->argv[5];
01703       
01704       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01705       ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
01706 
01707       bc->fac_out.Function = Fac_CFDeactivate;
01708       bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
01709       bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
01710       
01711       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01712       misdn_lib_send_event(bc, EVENT_FACILITY);
01713    }
01714 
01715    return CLI_SUCCESS;
01716 }
01717 
01718 static char *handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01719 {
01720    switch (cmd) {
01721    case CLI_INIT:
01722       e->command = "misdn send restart";
01723       e->usage =
01724          "Usage: misdn send restart [port [channel]]\n"
01725          "       Send a restart for every bchannel on the given port.\n";
01726       return NULL;
01727    case CLI_GENERATE:
01728       return NULL;
01729    }
01730 
01731    if (a->argc < 4 || a->argc > 5)
01732       return CLI_SHOWUSAGE;
01733 
01734    if (a->argc == 5)
01735       misdn_lib_send_restart(atoi(a->argv[3]), atoi(a->argv[4]));
01736    else
01737       misdn_lib_send_restart(atoi(a->argv[3]), -1);
01738 
01739    return CLI_SUCCESS;
01740 }
01741 
01742 static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01743 {
01744    char *channame; 
01745    char *msg; 
01746    struct chan_list *tmp;
01747    int i, msglen;
01748 
01749    switch (cmd) {
01750    case CLI_INIT:
01751       e->command = "misdn send digit";
01752       e->usage =
01753          "Usage: misdn send digit <channel> \"<msg>\" \n"
01754          "       Send <digit> to <channel> as DTMF Tone\n"
01755          "       when channel is a mISDN channel\n";
01756       return NULL;
01757    case CLI_GENERATE:
01758       return complete_ch(a);
01759    }
01760 
01761    if (a->argc != 5)
01762       return CLI_SHOWUSAGE;
01763 
01764    channame = a->argv[3];
01765    msg = a->argv[4];
01766    msglen = strlen(msg);
01767 
01768    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01769 
01770    tmp = get_chan_by_ast_name(channame);
01771    if (!tmp) {
01772       ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
01773       return CLI_SUCCESS; 
01774    }
01775 #if 1
01776    for (i = 0; i < msglen; i++) {
01777       ast_cli(a->fd, "Sending: %c\n", msg[i]);
01778       send_digit_to_chan(tmp, msg[i]);
01779       /* res = ast_safe_sleep(tmp->ast, 250); */
01780       usleep(250000);
01781       /* res = ast_waitfor(tmp->ast,100); */
01782    }
01783 #else
01784    ast_dtmf_stream(tmp->ast, NULL, msg, 250);
01785 #endif
01786 
01787    return CLI_SUCCESS;
01788 }
01789 
01790 static char *handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01791 {
01792    char *channame;
01793    struct chan_list *tmp;
01794 
01795    switch (cmd) {
01796    case CLI_INIT:
01797       e->command = "misdn toggle echocancel";
01798       e->usage =
01799          "Usage: misdn toggle echocancel <channel>\n"
01800          "       Toggle EchoCancel on mISDN Channel.\n";
01801       return NULL;
01802    case CLI_GENERATE:
01803       return complete_ch(a);
01804    }
01805 
01806    if (a->argc != 4)
01807       return CLI_SHOWUSAGE;
01808 
01809    channame = a->argv[3];
01810   
01811    ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
01812   
01813    tmp = get_chan_by_ast_name(channame);
01814    if (!tmp) {
01815       ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
01816       return CLI_SUCCESS;
01817    }
01818 
01819    tmp->toggle_ec = tmp->toggle_ec?0:1;
01820 
01821    if (tmp->toggle_ec) {
01822 #ifdef MISDN_1_2
01823       update_pipeline_config(tmp->bc);
01824 #else
01825       update_ec_config(tmp->bc);
01826 #endif
01827       manager_ec_enable(tmp->bc);
01828    } else {
01829       manager_ec_disable(tmp->bc);
01830    }
01831 
01832    return CLI_SUCCESS;
01833 }
01834 
01835 static char *handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01836 {
01837    char *channame;
01838    char *msg;
01839    struct chan_list *tmp;
01840 
01841    switch (cmd) {
01842    case CLI_INIT:
01843       e->command = "misdn send display";
01844       e->usage =
01845          "Usage: misdn send display <channel> \"<msg>\" \n"
01846          "       Send <msg> to <channel> as Display Message\n"
01847          "       when channel is a mISDN channel\n";
01848       return NULL;
01849    case CLI_GENERATE:
01850       return complete_ch(a);
01851    }
01852 
01853    if (a->argc != 5)
01854       return CLI_SHOWUSAGE;
01855 
01856    channame = a->argv[3];
01857    msg = a->argv[4];
01858 
01859    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01860    tmp = get_chan_by_ast_name(channame);
01861     
01862    if (tmp && tmp->bc) {
01863       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01864       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01865    } else {
01866       ast_cli(a->fd, "No such channel %s\n", channame);
01867       return CLI_SUCCESS;
01868    }
01869 
01870    return CLI_SUCCESS;
01871 }
01872 
01873 static char *complete_ch(struct ast_cli_args *a)
01874 {
01875    return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
01876 }
01877 
01878 static char *complete_debug_port (struct ast_cli_args *a)
01879 {
01880    if (a->n)
01881       return NULL;
01882 
01883    switch (a->pos) {
01884    case 4:
01885       if (a->word[0] == 'p')
01886          return ast_strdup("port");
01887       else if (a->word[0] == 'o')
01888          return ast_strdup("only");
01889       break;
01890    case 6:
01891       if (a->word[0] == 'o')
01892          return ast_strdup("only");
01893       break;
01894    }
01895    return NULL;
01896 }
01897 
01898 static char *complete_show_config(struct ast_cli_args *a)
01899 {
01900    char buffer[BUFFERSIZE];
01901    enum misdn_cfg_elements elem;
01902    int wordlen = strlen(a->word);
01903    int which = 0;
01904    int port = 0;
01905 
01906    switch (a->pos) {
01907    case 3:
01908       if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n))
01909          return ast_strdup("description");
01910       if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n))
01911          return ast_strdup("descriptions");
01912       if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n))
01913          return ast_strdup("0");
01914       while ((port = misdn_cfg_get_next_port(port)) != -1) {
01915          snprintf(buffer, sizeof(buffer), "%d", port);
01916          if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
01917             return ast_strdup(buffer);
01918          }
01919       }
01920       break;
01921    case 4:
01922       if (strstr(a->line, "description ")) {
01923          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01924             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
01925                continue;
01926             misdn_cfg_get_name(elem, buffer, sizeof(buffer));
01927             if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
01928                if (++which > a->n)
01929                   return ast_strdup(buffer);
01930             }
01931          }
01932       } else if (strstr(a->line, "descriptions ")) {
01933          if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n))
01934             return ast_strdup("general");
01935          if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n))
01936             return ast_strdup("ports");
01937       }
01938       break;
01939    }
01940    return NULL;
01941 }
01942 
01943 static struct ast_cli_entry chan_misdn_clis[] = {
01944    AST_CLI_DEFINE(handle_cli_misdn_port_block,        "Block the given port"),
01945    AST_CLI_DEFINE(handle_cli_misdn_port_down,         "Try to deactivate the L1 on the given port"),
01946    AST_CLI_DEFINE(handle_cli_misdn_port_unblock,      "Unblock the given port"),
01947    AST_CLI_DEFINE(handle_cli_misdn_port_up,           "Try to establish L1 on the given port"),
01948    AST_CLI_DEFINE(handle_cli_misdn_reload,            "Reload internal mISDN config, read from the config file"),
01949    AST_CLI_DEFINE(handle_cli_misdn_restart_pid,       "Restart the given pid"),
01950    AST_CLI_DEFINE(handle_cli_misdn_restart_port,      "Restart the given port"),
01951    AST_CLI_DEFINE(handle_cli_misdn_show_channel,      "Show an internal mISDN channel"),
01952    AST_CLI_DEFINE(handle_cli_misdn_show_channels,     "Show the internal mISDN channel list"),
01953    AST_CLI_DEFINE(handle_cli_misdn_show_config,       "Show internal mISDN config, read from the config file"),
01954    AST_CLI_DEFINE(handle_cli_misdn_show_port,         "Show detailed information for given port"),
01955    AST_CLI_DEFINE(handle_cli_misdn_show_ports_stats,  "Show mISDNs channel's call statistics per port"),
01956    AST_CLI_DEFINE(handle_cli_misdn_show_stacks,       "Show internal mISDN stack_list"),
01957    AST_CLI_DEFINE(handle_cli_misdn_send_facility,     "Sends a Facility Message to the mISDN Channel"),
01958    AST_CLI_DEFINE(handle_cli_misdn_send_digit,        "Send DTMF digit to mISDN Channel"),
01959    AST_CLI_DEFINE(handle_cli_misdn_send_display,      "Send Text to mISDN Channel"),
01960    AST_CLI_DEFINE(handle_cli_misdn_send_restart,      "Send a restart for every bchannel on the given port"),
01961    AST_CLI_DEFINE(handle_cli_misdn_set_crypt_debug,   "Set CryptDebuglevel of chan_misdn, at the moment, level={1,2}"),
01962    AST_CLI_DEFINE(handle_cli_misdn_set_debug,         "Set Debuglevel of chan_misdn"),
01963    AST_CLI_DEFINE(handle_cli_misdn_set_tics,          "???"),
01964    AST_CLI_DEFINE(handle_cli_misdn_toggle_echocancel, "Toggle EchoCancel on mISDN Channel"),
01965 };
01966 
01967 /*! \brief Updates caller ID information from config */
01968 static int update_config(struct chan_list *ch, int orig) 
01969 {
01970    struct ast_channel *ast;
01971    struct misdn_bchannel *bc;
01972    int port, hdlc = 0;
01973    int pres, screen;
01974 
01975    if (!ch) {
01976       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01977       return -1;
01978    }
01979 
01980    ast = ch->ast;
01981    bc = ch->bc;
01982    if (! ast || ! bc) {
01983       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01984       return -1;
01985    }
01986 
01987    port = bc->port;
01988 
01989    chan_misdn_log(7, port, "update_config: Getting Config\n");
01990 
01991    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01992    
01993    if (hdlc) {
01994       switch (bc->capability) {
01995       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01996       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01997          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
01998          bc->hdlc = 1;
01999          break;
02000       }
02001    }
02002 
02003 
02004    misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
02005    misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
02006    chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
02007       
02008    if ( (pres + screen) < 0 ) {
02009 
02010       chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
02011          
02012       switch (ast->cid.cid_pres & 0x60) {
02013             
02014       case AST_PRES_RESTRICTED:
02015          bc->pres = 1;
02016          chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
02017          break;
02018       case AST_PRES_UNAVAILABLE:
02019          bc->pres = 2;
02020          chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
02021          break;
02022       default:
02023          bc->pres = 0;
02024          chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
02025       }
02026          
02027       switch (ast->cid.cid_pres & 0x3) {
02028 
02029       case AST_PRES_USER_NUMBER_UNSCREENED:
02030          bc->screen = 0;
02031          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
02032          break;
02033       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02034          bc->screen = 1;
02035          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
02036          break;
02037       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02038          bc->screen = 2;
02039          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
02040          break;
02041       case AST_PRES_NETWORK_NUMBER:
02042          bc->screen = 3;
02043          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
02044          break;
02045       default:
02046          bc->screen = 0;
02047          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
02048       }
02049    } else {
02050       bc->screen = screen;
02051       bc->pres = pres;
02052    }
02053 
02054    return 0;
02055 }
02056 
02057 
02058 static void config_jitterbuffer(struct chan_list *ch)
02059 {
02060    struct misdn_bchannel *bc = ch->bc;
02061    int len = ch->jb_len, threshold = ch->jb_upper_threshold;
02062    
02063    chan_misdn_log(5, bc->port, "config_jb: Called\n");
02064    
02065    if (! len) {
02066       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
02067       bc->nojitter=1;
02068    } else {
02069       if (len <= 100 || len > 8000) {
02070          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
02071          len = 1000;
02072       }
02073 
02074       if ( threshold > len ) {
02075          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
02076       }
02077 
02078       if ( ch->jb) {
02079          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
02080          misdn_jb_destroy(ch->jb);
02081          ch->jb = NULL;
02082       }
02083 
02084       ch->jb=misdn_jb_init(len, threshold);
02085 
02086       if (!ch->jb ) 
02087          bc->nojitter = 1;
02088    }
02089 }
02090 
02091 
02092 void debug_numplan(int port, int numplan, char *type)
02093 {
02094    switch (numplan) {
02095    case NUMPLAN_INTERNATIONAL:
02096       chan_misdn_log(2, port, " --> %s: International\n", type);
02097       break;
02098    case NUMPLAN_NATIONAL:
02099       chan_misdn_log(2, port, " --> %s: National\n", type);
02100       break;
02101    case NUMPLAN_SUBSCRIBER:
02102       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
02103       break;
02104    case NUMPLAN_UNKNOWN:
02105       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
02106       break;
02107       /* Maybe we should cut off the prefix if present ? */
02108    default:
02109       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
02110       break;
02111    }
02112 }
02113 
02114 
02115 #ifdef MISDN_1_2
02116 static int update_pipeline_config(struct misdn_bchannel *bc)
02117 {
02118    int ec;
02119 
02120    misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
02121 
02122    if (*bc->pipeline)
02123       return 0;
02124 
02125    misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
02126    if (ec == 1)
02127       ast_copy_string(bc->pipeline, "mg2ec", sizeof(bc->pipeline));
02128    else if (ec > 1)
02129       snprintf(bc->pipeline, sizeof(bc->pipeline), "mg2ec(deftaps=%d)", ec);
02130 
02131    return 0;
02132 }
02133 #else
02134 static int update_ec_config(struct misdn_bchannel *bc)
02135 {
02136    int ec;
02137    int port = bc->port;
02138 
02139    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
02140 
02141    if (ec == 1) {
02142       bc->ec_enable = 1;
02143    } else if (ec > 1) {
02144       bc->ec_enable = 1;
02145       bc->ec_deftaps = ec;
02146    }
02147 
02148    return 0;
02149 }
02150 #endif
02151 
02152 
02153 static int read_config(struct chan_list *ch, int orig)
02154 {
02155    struct ast_channel *ast;
02156    struct misdn_bchannel *bc;
02157    int port;
02158    int hdlc = 0;
02159    char lang[BUFFERSIZE + 1];
02160    char faxdetect[BUFFERSIZE + 1];
02161    char buf[256];
02162    char buf2[256];
02163    ast_group_t pg;
02164    ast_group_t cg;
02165 
02166    if (!ch) {
02167       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
02168       return -1;
02169    }
02170 
02171    ast = ch->ast;
02172    bc = ch->bc;
02173    if (! ast || ! bc) {
02174       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
02175       return -1;
02176    }
02177    
02178    port = bc->port;
02179    chan_misdn_log(1, port, "read_config: Getting Config\n");
02180 
02181    misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
02182    ast_string_field_set(ast, language, lang);
02183 
02184    misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
02185 
02186    misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
02187    misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
02188 
02189    misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
02190 
02191    misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
02192    
02193    misdn_cfg_get( port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
02194 
02195    if (ch->ast_dsp) {
02196       ch->ignore_dtmf=1;
02197    }
02198 
02199    misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
02200    misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
02201 
02202    misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
02203 
02204    misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
02205 
02206    misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
02207 
02208    misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
02209 
02210    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
02211 
02212    if (hdlc) {
02213       switch (bc->capability) {
02214       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02215       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
02216          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
02217          bc->hdlc = 1;
02218          break;
02219       }
02220       
02221    }
02222    /*Initialize new Jitterbuffer*/
02223    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
02224    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
02225 
02226    config_jitterbuffer(ch);
02227 
02228    misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
02229 
02230    ast_copy_string(ast->context, ch->context, sizeof(ast->context));
02231 
02232 #ifdef MISDN_1_2
02233    update_pipeline_config(bc);
02234 #else
02235    update_ec_config(bc);
02236 #endif
02237 
02238    misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
02239 
02240    misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02241    misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02242 
02243    chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
02244    ast->pickupgroup = pg;
02245    ast->callgroup = cg;
02246    
02247    if (orig == ORG_AST) {
02248       char callerid[BUFFERSIZE + 1];
02249 
02250       /* ORIGINATOR Asterisk (outgoing call) */
02251 
02252       misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
02253 
02254       if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
02255          if (strstr(faxdetect, "nojump"))
02256             ch->faxdetect = 2;
02257          else
02258             ch->faxdetect = 1;
02259       }
02260 
02261       misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
02262       if ( ! ast_strlen_zero(callerid) ) {
02263          chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
02264          ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
02265       }
02266 
02267       misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
02268       misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
02269       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02270       debug_numplan(port, bc->dnumplan, "TON");
02271       debug_numplan(port, bc->onumplan, "LTON");
02272       debug_numplan(port, bc->cpnnumplan, "CTON");
02273 
02274       ch->overlap_dial = 0;
02275    } else {
02276       /* ORIGINATOR MISDN (incoming call) */
02277       char prefix[BUFFERSIZE + 1] = "";
02278 
02279       if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
02280          if (strstr(faxdetect, "nojump"))
02281             ch->faxdetect = 2;
02282          else
02283             ch->faxdetect = 1;
02284       }
02285 
02286       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02287       debug_numplan(port, bc->cpnnumplan, "CTON");
02288 
02289       switch (bc->onumplan) {
02290       case NUMPLAN_INTERNATIONAL:
02291          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02292          break;
02293 
02294       case NUMPLAN_NATIONAL:
02295          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02296          break;
02297       default:
02298          break;
02299       }
02300 
02301       ast_copy_string(buf, bc->oad, sizeof(buf));
02302       snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
02303 
02304       if (!ast_strlen_zero(bc->dad)) {
02305          ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
02306       }
02307 
02308       if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02309          ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
02310       }
02311 
02312       prefix[0] = 0;
02313 
02314       switch (bc->dnumplan) {
02315       case NUMPLAN_INTERNATIONAL:
02316          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02317          break;
02318       case NUMPLAN_NATIONAL:
02319          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02320          break;
02321       default:
02322          break;
02323       }
02324 
02325       ast_copy_string(buf, bc->dad, sizeof(buf));
02326       snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
02327 
02328       if (strcmp(bc->dad, ast->exten)) {
02329          ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
02330       }
02331 
02332       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
02333 
02334       if ( !ast_strlen_zero(bc->rad) ) {
02335          if (ast->cid.cid_rdnis)
02336             ast_free(ast->cid.cid_rdnis);
02337          ast->cid.cid_rdnis = ast_strdup(bc->rad);
02338       }
02339    
02340       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
02341       ast_mutex_init(&ch->overlap_tv_lock);
02342    } /* ORIG MISDN END */
02343 
02344    ch->overlap_dial_task = -1;
02345    
02346    if (ch->faxdetect  || ch->ast_dsp) {
02347       misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
02348       if (!ch->dsp)
02349          ch->dsp = ast_dsp_new();
02350       if (ch->dsp) {
02351          if (ch->faxdetect) 
02352             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
02353          else 
02354             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT );
02355       }
02356       if (!ch->trans)
02357          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
02358    }
02359 
02360    /* AOCD initialization */
02361    bc->AOCDtype = Fac_None;
02362 
02363    return 0;
02364 }
02365 
02366 
02367 /*****************************/
02368 /*** AST Indications Start ***/
02369 /*****************************/
02370 
02371 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
02372 {
02373    int port = 0;
02374    int r;
02375    int exceed;
02376    int bridging;
02377    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(ast);
02378    struct misdn_bchannel *newbc;
02379    char *opts = NULL, *ext, *tokb;
02380    char *dest_cp = ast_strdupa(dest);
02381 
02382    ext = strtok_r(dest_cp, "/", &tokb);
02383 
02384    if (ext) {
02385       ext = strtok_r(NULL, "/", &tokb);
02386       if (ext) {
02387          opts = strtok_r(NULL, "/", &tokb);
02388       } else {
02389          chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
02390          return -1;
02391       }
02392    }
02393 
02394    if (!ast) {
02395       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
02396       return -1;
02397    }
02398 
02399    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
02400       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02401       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02402       ast_setstate(ast, AST_STATE_DOWN);
02403       return -1;
02404    }
02405 
02406    if (!ch) {
02407       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02408       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02409       ast_setstate(ast, AST_STATE_DOWN);
02410       return -1;
02411    }
02412    
02413    newbc = ch->bc;
02414    
02415    if (!newbc) {
02416       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02417       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02418       ast_setstate(ast, AST_STATE_DOWN);
02419       return -1;
02420    }
02421    
02422    port = newbc->port;
02423 
02424    if ((exceed = add_out_calls(port))) {
02425       char tmp[16];
02426       snprintf(tmp, sizeof(tmp), "%d", exceed);
02427       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
02428       return -1;
02429    }
02430    
02431    chan_misdn_log(1, port, "* CALL: %s\n", dest);
02432    
02433    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
02434    
02435    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
02436    if (ast->exten) {
02437       ast_copy_string(ast->exten, ext, sizeof(ast->exten));
02438       ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
02439    }
02440 
02441    ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
02442 
02443    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
02444    if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
02445       ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
02446    }
02447 
02448    newbc->capability = ast->transfercapability;
02449    pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
02450    if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
02451       chan_misdn_log(2, port, " --> * Call with flag Digital\n");
02452    }
02453 
02454    /* update screening and presentation */ 
02455    update_config(ch, ORG_AST);
02456       
02457    /* fill in some ies from channel vary*/
02458    import_ch(ast, newbc, ch);
02459 
02460    /* Finally The Options Override Everything */
02461    if (opts)
02462       misdn_set_opt_exec(ast, opts);
02463    else
02464       chan_misdn_log(2, port, "NO OPTS GIVEN\n");
02465 
02466    /*check for bridging*/
02467    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
02468    if (bridging && ch->other_ch) {
02469 #ifdef MISDN_1_2
02470       chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
02471       *ch->bc->pipeline = 0;
02472       *ch->other_ch->bc->pipeline = 0;
02473 #else
02474       chan_misdn_log(1, port, "Disabling EC on both Sides\n");
02475       ch->bc->ec_enable = 0;
02476       ch->other_ch->bc->ec_enable = 0;
02477 #endif
02478    }
02479 
02480    r = misdn_lib_send_event( newbc, EVENT_SETUP );
02481 
02482    /** we should have l3id after sending setup **/
02483    ch->l3id = newbc->l3_id;
02484 
02485    if ( r == -ENOCHAN  ) {
02486       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
02487       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
02488       ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
02489       ast_setstate(ast, AST_STATE_DOWN);
02490       return -1;
02491    }
02492    
02493    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
02494 
02495    ast_setstate(ast, AST_STATE_DIALING);
02496    ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
02497    
02498    if (newbc->nt)
02499       stop_bc_tones(ch);
02500 
02501    ch->state = MISDN_CALLING;
02502    
02503    return 0; 
02504 }
02505 
02506 
02507 static int misdn_answer(struct ast_channel *ast)
02508 {
02509    struct chan_list *p;
02510    const char *tmp;
02511 
02512    if (!ast || ! (p = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02513    
02514    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
02515    
02516    if (!p) {
02517       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02518       ast_queue_hangup(ast);
02519    }
02520 
02521    if (!p->bc) {
02522       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
02523 
02524       ast_queue_hangup(ast);
02525    }
02526 
02527    tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
02528 
02529    if (!ast_strlen_zero(tmp)) {
02530       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02531       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
02532    } else {
02533       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02534    }
02535 
02536    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02537    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
02538       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02539       p->bc->nodsp = 1;
02540       p->bc->hdlc = 0;
02541       p->bc->nojitter = 1;
02542    }
02543 
02544    p->state = MISDN_CONNECTED;
02545    stop_indicate(p);
02546 
02547    if ( ast_strlen_zero(p->bc->cad) ) {
02548       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
02549       ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
02550    }
02551 
02552    misdn_lib_send_event( p->bc, EVENT_CONNECT);
02553    start_bc_tones(p);
02554 
02555    return 0;
02556 }
02557 
02558 static int misdn_digit_begin(struct ast_channel *chan, char digit)
02559 {
02560    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02561    return 0;
02562 }
02563 
02564 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
02565 {
02566    struct chan_list *p;
02567    struct misdn_bchannel *bc;
02568    char buf[2] = { digit, 0 };
02569    
02570    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02571 
02572    bc = p->bc;
02573    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
02574    
02575    if (!bc) {
02576       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
02577       return -1;
02578    }
02579    
02580    switch (p->state ) {
02581    case MISDN_CALLING:
02582       if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1)
02583          strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
02584       break;
02585    case MISDN_CALLING_ACKNOWLEDGE:
02586       ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
02587       if (strlen(bc->dad) < sizeof(bc->dad) - 1)
02588          strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
02589       ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
02590       misdn_lib_send_event( bc, EVENT_INFORMATION);
02591       break;
02592    default: 
02593          /* Do not send Digits in CONNECTED State, when
02594           * the other side is too mISDN. */
02595          if (p->other_ch ) 
02596             return 0;
02597 
02598          if ( bc->send_dtmf ) 
02599             send_digit_to_chan(p,digit);
02600       break;
02601 }
02602 
02603    return 0;
02604 }
02605 
02606 
02607 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
02608 {
02609    struct chan_list *p;
02610 
02611    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02612 
02613    chan_misdn_log(1, p->bc ? p->bc->port : 0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
02614 
02615    p->ast = ast;
02616 
02617    return 0;
02618 }
02619 
02620 
02621 
02622 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
02623 {
02624    struct chan_list *p;
02625 
02626    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02627       ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
02628       return -1;
02629    }
02630    
02631    if (!p->bc ) {
02632       chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast->exten);
02633       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02634       return -1;
02635    }
02636    
02637    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n", cond, ast->exten);
02638    
02639    switch (cond) {
02640    case AST_CONTROL_BUSY:
02641       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
02642       ast_setstate(ast, AST_STATE_BUSY);
02643 
02644       p->bc->out_cause = AST_CAUSE_USER_BUSY;
02645       if (p->state != MISDN_CONNECTED) {
02646          start_bc_tones(p);
02647          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02648       } else {
02649          chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
02650       }
02651       return -1;
02652    case AST_CONTROL_RING:
02653       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02654       return -1;
02655    case AST_CONTROL_RINGING:
02656       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02657       switch (p->state) {
02658       case MISDN_ALERTING:
02659          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc ? p->bc->pid : -1);
02660          break;
02661       case MISDN_CONNECTED:
02662          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc ? p->bc->pid : -1);
02663          return -1;
02664       default:
02665          p->state = MISDN_ALERTING;
02666          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02667          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02668          
02669          if (p->other_ch && p->other_ch->bc) {
02670             if (misdn_inband_avail(p->other_ch->bc)) {
02671                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02672                break;
02673             }
02674 
02675             if (!p->other_ch->bc->nt) {
02676                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02677                break;
02678             }
02679          }
02680 
02681          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02682          ast_setstate(ast, AST_STATE_RING);
02683          
02684          if ( !p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio ) 
02685             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02686          else 
02687             return -1;
02688       }
02689       break;
02690    case AST_CONTROL_ANSWER:
02691       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02692       start_bc_tones(p);
02693       break;
02694    case AST_CONTROL_TAKEOFFHOOK:
02695       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02696       return -1;
02697    case AST_CONTROL_OFFHOOK:
02698       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02699       return -1;
02700    case AST_CONTROL_FLASH:
02701       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02702       break;
02703    case AST_CONTROL_PROGRESS:
02704       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02705       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02706       break;
02707    case AST_CONTROL_PROCEEDING:
02708       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02709       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02710       break;
02711    case AST_CONTROL_CONGESTION:
02712       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02713 
02714       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02715       start_bc_tones(p);
02716       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02717 
02718       if (p->bc->nt) {
02719          hanguptone_indicate(p);
02720       }
02721       break;
02722    case -1 :
02723       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02724 
02725       stop_indicate(p);
02726 
02727       if (p->state == MISDN_CONNECTED) 
02728          start_bc_tones(p);
02729       break;
02730    case AST_CONTROL_HOLD:
02731       ast_moh_start(ast, data, p->mohinterpret); 
02732       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02733       break;
02734    case AST_CONTROL_UNHOLD:
02735       ast_moh_stop(ast);
02736       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02737       break;
02738    default:
02739       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02740    }
02741   
02742    return 0;
02743 }
02744 
02745 static int misdn_hangup(struct ast_channel *ast)
02746 {
02747    struct chan_list *p;
02748    struct misdn_bchannel *bc = NULL;
02749    const char *varcause = NULL;
02750 
02751    ast_debug(1, "misdn_hangup(%s)\n", ast->name);
02752 
02753    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
02754 
02755    if (!p) {
02756       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
02757       return 0 ;
02758    }
02759 
02760    bc = p->bc;
02761 
02762    if (bc) {
02763       const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
02764       if (tmp) {
02765          ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
02766          strcpy(bc->uu, tmp);
02767          bc->uulen=strlen(bc->uu);
02768       }
02769    }
02770 
02771    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02772    p->ast = NULL;
02773 
02774    if (ast->_state == AST_STATE_RESERVED || 
02775       p->state == MISDN_NOTHING || 
02776       p->state == MISDN_HOLDED || 
02777       p->state == MISDN_HOLD_DISCONNECT ) {
02778 
02779       CLEAN_CH:
02780       /* between request and call */
02781       ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
02782       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02783    
02784       ast_mutex_lock(&release_lock);
02785       cl_dequeue_chan(&cl_te, p);
02786       close(p->pipe[0]);
02787       close(p->pipe[1]);
02788       ast_free(p);
02789       ast_mutex_unlock(&release_lock);
02790       
02791       if (bc)
02792          misdn_lib_release(bc);
02793       
02794       return 0;
02795    }
02796 
02797    if (!bc) {
02798       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02799       goto CLEAN_CH;
02800    }
02801 
02802 
02803    p->need_hangup = 0;
02804    p->need_queue_hangup = 0;
02805    p->need_busy = 0;
02806 
02807 
02808    if (!p->bc->nt) 
02809       stop_bc_tones(p);
02810 
02811    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02812       
02813    if ( (varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02814         (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02815       int tmpcause = atoi(varcause);
02816       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02817    }
02818     
02819    chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n", p->bc ? p->bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
02820    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02821    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02822    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02823    chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02824 
02825    switch (p->state) {
02826    case MISDN_INCOMING_SETUP:
02827       p->state = MISDN_CLEANING;
02828       /* This is the only place in misdn_hangup, where we 
02829        * can call release_chan, else it might create lot's of trouble
02830        * */
02831       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02832       release_chan(bc);
02833       misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02834       break;
02835    case MISDN_HOLDED:
02836    case MISDN_DIALING:
02837       start_bc_tones(p);
02838       hanguptone_indicate(p);
02839       
02840       p->state=MISDN_CLEANING;
02841       if (bc->need_disconnect)
02842          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02843       break;
02844    case MISDN_CALLING_ACKNOWLEDGE:
02845       start_bc_tones(p);
02846       hanguptone_indicate(p);
02847       
02848       if (bc->need_disconnect)
02849          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02850       break;
02851       
02852    case MISDN_CALLING:
02853    case MISDN_ALERTING:
02854    case MISDN_PROGRESS:
02855    case MISDN_PROCEEDING:
02856       if (p->originator != ORG_AST) 
02857          hanguptone_indicate(p);
02858       
02859       /*p->state=MISDN_CLEANING;*/
02860       if (bc->need_disconnect)
02861          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02862       break;
02863    case MISDN_CONNECTED:
02864    case MISDN_PRECONNECTED:
02865       /*  Alerting or Disconnect */
02866       if (p->bc->nt) {
02867          start_bc_tones(p);
02868          hanguptone_indicate(p);
02869          p->bc->progress_indicator = 8;
02870       }
02871       if (bc->need_disconnect)
02872          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02873 
02874       /*p->state=MISDN_CLEANING;*/
02875       break;
02876    case MISDN_DISCONNECTED:
02877       if (bc->need_release)
02878          misdn_lib_send_event( bc, EVENT_RELEASE);
02879       p->state = MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
02880       break;
02881 
02882    case MISDN_RELEASED:
02883    case MISDN_CLEANING:
02884       p->state = MISDN_CLEANING;
02885       break;
02886 
02887    case MISDN_BUSY:
02888       break;
02889       
02890    case MISDN_HOLD_DISCONNECT:
02891       /* need to send release here */
02892       chan_misdn_log(1, bc->port, " --> cause %d\n", bc->cause);
02893       chan_misdn_log(1, bc->port, " --> out_cause %d\n", bc->out_cause);
02894 
02895       bc->out_cause = -1;
02896       if (bc->need_release)
02897          misdn_lib_send_event(bc, EVENT_RELEASE);
02898       p->state = MISDN_CLEANING;
02899       break;
02900    default:
02901       if (bc->nt) {
02902          bc->out_cause = -1;
02903          if (bc->need_release)
02904             misdn_lib_send_event(bc, EVENT_RELEASE);
02905          p->state = MISDN_CLEANING; 
02906       } else {
02907          if (bc->need_disconnect)
02908             misdn_lib_send_event(bc, EVENT_DISCONNECT);
02909       }
02910    }
02911 
02912    p->state = MISDN_CLEANING;
02913     
02914    chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
02915 
02916    return 0;
02917 }
02918 
02919 
02920 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
02921 {
02922    struct ast_frame *f,*f2;
02923  
02924    if (tmp->trans) {
02925       f2 = ast_translate(tmp->trans, frame, 0);
02926       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02927    } else {
02928       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02929       return NULL;
02930    }
02931 
02932    if (!f || (f->frametype != AST_FRAME_DTMF))
02933       return frame;
02934  
02935    ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
02936  
02937    if (tmp->faxdetect && (f->subclass == 'f')) {
02938       /* Fax tone -- Handle and return NULL */
02939       if (!tmp->faxhandled) {
02940          struct ast_channel *ast = tmp->ast;
02941          tmp->faxhandled++;
02942          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02943          tmp->bc->rxgain = 0;
02944          isdn_lib_update_rxgain(tmp->bc);
02945          tmp->bc->txgain = 0;
02946          isdn_lib_update_txgain(tmp->bc);
02947 #ifdef MISDN_1_2
02948          *tmp->bc->pipeline = 0;
02949 #else
02950          tmp->bc->ec_enable = 0;
02951 #endif
02952          isdn_lib_update_ec(tmp->bc);
02953          isdn_lib_stop_dtmf(tmp->bc);
02954          switch (tmp->faxdetect) {
02955          case 1:
02956             if (strcmp(ast->exten, "fax")) {
02957                char *context;
02958                char context_tmp[BUFFERSIZE];
02959                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02960                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02961                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02962                   ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02963                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02964                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02965                   if (ast_async_goto(ast, context, "fax", 1))
02966                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02967                } else
02968                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02969             } else {
02970                ast_debug(1, "Already in a fax extension, not redirecting\n");
02971             }
02972             break;
02973          case 2:
02974             ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02975             break;
02976          }
02977       } else {
02978          ast_debug(1, "Fax already handled\n");
02979       }
02980    }
02981    
02982    if (tmp->ast_dsp && (f->subclass != 'f')) {
02983       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02984    }
02985 
02986    return f;
02987 }
02988 
02989 
02990 static struct ast_frame *misdn_read(struct ast_channel *ast)
02991 {
02992    struct chan_list *tmp;
02993    fd_set rrfs;
02994    struct timeval tv;
02995    int len, t;
02996 
02997    if (!ast) {
02998       chan_misdn_log(1, 0, "misdn_read called without ast\n");
02999       return NULL;
03000    }
03001    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
03002       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
03003       return NULL;
03004    }
03005 
03006    if (!tmp->bc && !(tmp->state == MISDN_HOLDED)) {
03007       chan_misdn_log(1, 0, "misdn_read called without bc\n");
03008       return NULL;
03009    }
03010 
03011    tv.tv_sec=0;
03012    tv.tv_usec=20000;
03013 
03014    FD_ZERO(&rrfs);
03015    FD_SET(tmp->pipe[0],&rrfs);
03016 
03017    t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
03018 
03019    if (!t) {
03020       chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
03021       len=160;
03022    }
03023 
03024    if (t<0) {
03025       chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
03026       return NULL;
03027    }
03028 
03029    if (FD_ISSET(tmp->pipe[0],&rrfs)) {
03030       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
03031 
03032       if (len<=0) {
03033          /* we hangup here, since our pipe is closed */
03034          chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
03035          return NULL;
03036       }
03037 
03038    } else {
03039       return NULL;
03040    }
03041 
03042    tmp->frame.frametype = AST_FRAME_VOICE;
03043    tmp->frame.subclass = AST_FORMAT_ALAW;
03044    tmp->frame.datalen = len;
03045    tmp->frame.samples = len;
03046    tmp->frame.mallocd = 0;
03047    tmp->frame.offset = 0;
03048    tmp->frame.delivery = ast_tv(0,0);
03049    tmp->frame.src = NULL;
03050    tmp->frame.data = tmp->ast_rd_buf;
03051 
03052    if (tmp->faxdetect && !tmp->faxhandled) {
03053       if (tmp->faxdetect_timeout) {
03054          if (ast_tvzero(tmp->faxdetect_tv)) {
03055             tmp->faxdetect_tv = ast_tvnow();
03056             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
03057             return process_ast_dsp(tmp, &tmp->frame);
03058          } else {
03059             struct timeval tv_now = ast_tvnow();
03060             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
03061             if (diff <= (tmp->faxdetect_timeout * 1000)) {
03062                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
03063                return process_ast_dsp(tmp, &tmp->frame);
03064             } else {
03065                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
03066                tmp->faxdetect = 0;
03067                return &tmp->frame;
03068             }
03069          }
03070       } else {
03071          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
03072          return process_ast_dsp(tmp, &tmp->frame);
03073       }
03074    } else {
03075       if (tmp->ast_dsp)
03076          return process_ast_dsp(tmp, &tmp->frame);
03077       else
03078          return &tmp->frame;
03079    }
03080 }
03081 
03082 
03083 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
03084 {
03085    struct chan_list *ch;
03086    int i  = 0;
03087    
03088    if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
03089 
03090    if (ch->state == MISDN_HOLDED) {
03091       chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
03092       return 0;
03093    }
03094    
03095    if (!ch->bc ) {
03096       ast_log(LOG_WARNING, "private but no bc\n");
03097       return -1;
03098    }
03099    
03100    if (ch->notxtone) {
03101       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
03102       return 0;
03103    }
03104 
03105 
03106    if (!frame->subclass) {
03107       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
03108       return 0;
03109    }
03110    
03111    if (!(frame->subclass & prefformat)) {
03112       
03113       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
03114       return 0;
03115    }
03116    
03117 
03118    if (!frame->samples ) {
03119       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
03120       
03121       if (!strcmp(frame->src,"ast_prod")) {
03122          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
03123 
03124          if (ch->ts) {
03125             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
03126             misdn_lib_tone_generator_start(ch->bc);
03127          }
03128          return 0;
03129       }
03130 
03131       return -1;
03132    }
03133 
03134    if ( ! ch->bc->addr ) {
03135       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
03136       return 0;
03137    }
03138    
03139 #ifdef MISDN_DEBUG
03140    {
03141       int i, max = 5 > frame->samples ? frame->samples : 5;
03142 
03143       ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
03144 
03145       for (i = 0; i < max ; i++)
03146          ast_debug(1, "%2.2x ", ((char*) frame->data)[i]);
03147    }
03148 #endif
03149 
03150    switch (ch->bc->bc_state) {
03151    case BCHAN_ACTIVATED:
03152    case BCHAN_BRIDGED:
03153       break;
03154    default:
03155       if (!ch->dropped_frame_cnt)
03156          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n", frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
03157       
03158       ch->dropped_frame_cnt++;
03159       if (ch->dropped_frame_cnt > 100) {
03160          ch->dropped_frame_cnt = 0;
03161          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x  dropped > 100 frames!\n", frame->samples, ch->bc->addr);
03162       }
03163 
03164       return 0;
03165    }
03166 
03167    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n", frame->samples);
03168    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
03169       /* Buffered Transmit (triggered by read from isdn side)*/
03170       if (misdn_jb_fill(ch->jb, frame->data, frame->samples) < 0) {
03171          if (ch->bc->active)
03172             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
03173       }
03174       
03175    } else {
03176       /*transmit without jitterbuffer*/
03177       i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
03178    }
03179 
03180    return 0;
03181 }
03182 
03183 
03184 
03185 
03186 static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
03187                   struct ast_channel *c1, int flags,
03188                   struct ast_frame **fo,
03189                   struct ast_channel **rc,
03190                   int timeoutms)
03191 
03192 {
03193    struct chan_list *ch1, *ch2;
03194    struct ast_channel *carr[2], *who;
03195    int to = -1;
03196    struct ast_frame *f;
03197    int p1_b, p2_b;
03198    int bridging;
03199   
03200    ch1 = get_chan_by_ast(c0);
03201    ch2 = get_chan_by_ast(c1);
03202 
03203    carr[0] = c0;
03204    carr[1] = c1;
03205   
03206    if (!(ch1 && ch2))
03207       return -1;
03208 
03209    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
03210    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
03211 
03212    if (! p1_b || ! p2_b) {
03213       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03214       return AST_BRIDGE_FAILED;
03215    }
03216 
03217    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03218    if (bridging) {
03219       /* trying to make a mISDN_dsp conference */
03220       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03221       misdn_lib_bridge(ch1->bc, ch2->bc);
03222    }
03223 
03224    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03225 
03226    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03227  
03228    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
03229       ch1->ignore_dtmf = 1;
03230 
03231    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
03232       ch2->ignore_dtmf = 1;
03233 
03234    for (;/*ever*/;) {
03235       to = -1;
03236       who = ast_waitfor_n(carr, 2, &to);
03237 
03238       if (!who) {
03239          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03240          break;
03241       }
03242       f = ast_read(who);
03243 
03244       if (!f || f->frametype == AST_FRAME_CONTROL) {
03245          /* got hangup .. */
03246 
03247          if (!f) 
03248             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03249          else
03250             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03251 
03252          *fo = f;
03253          *rc = who;
03254          break;
03255       }
03256       
03257       if ( f->frametype == AST_FRAME_DTMF ) {
03258          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03259 
03260          *fo = f;
03261          *rc = who;
03262          break;
03263       }
03264    
03265 #if 0
03266       if (f->frametype == AST_FRAME_VOICE) {
03267          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03268    
03269          continue;
03270       }
03271 #endif
03272 
03273       if (who == c0) {
03274          ast_write(c1, f);
03275       }
03276       else {
03277          ast_write(c0, f);
03278       }
03279    }
03280 
03281    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03282 
03283    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03284 
03285    return AST_BRIDGE_COMPLETE;
03286 }
03287 
03288 /** AST INDICATIONS END **/
03289 
03290 static int dialtone_indicate(struct chan_list *cl)
03291 {
03292    const struct tone_zone_sound *ts = NULL;
03293    struct ast_channel *ast = cl->ast;
03294    int nd = 0;
03295 
03296    if (!ast) {
03297       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03298       return -1;
03299    }
03300 
03301    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03302 
03303    if (nd) {
03304       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03305       return 0;
03306    }
03307    
03308    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03309    ts = ast_get_indication_tone(ast->zone, "dial");
03310    cl->ts = ts;   
03311    
03312    if (ts) {
03313       cl->notxtone = 0;
03314       cl->norxtone = 0;
03315       /* This prods us in misdn_write */
03316       ast_playtones_start(ast, 0, ts->data, 0);
03317    }
03318 
03319    return 0;
03320 }
03321 
03322 static int hanguptone_indicate(struct chan_list *cl)
03323 {
03324    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03325    return 0;
03326 }
03327 
03328 static int stop_indicate(struct chan_list *cl)
03329 {
03330    struct ast_channel *ast = cl->ast;
03331 
03332    if (!ast) {
03333       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03334       return -1;
03335    }
03336 
03337    chan_misdn_log(3, cl->bc->port, " --> None\n");
03338    misdn_lib_tone_generator_stop(cl->bc);
03339    ast_playtones_stop(ast);
03340 
03341    cl->ts = NULL;
03342    /*ast_deactivate_generator(ast);*/
03343 
03344    return 0;
03345 }
03346 
03347 
03348 static int start_bc_tones(struct chan_list* cl)
03349 {
03350    misdn_lib_tone_generator_stop(cl->bc);
03351    cl->notxtone = 0;
03352    cl->norxtone = 0;
03353    return 0;
03354 }
03355 
03356 static int stop_bc_tones(struct chan_list *cl)
03357 {
03358    if (!cl) return -1;
03359 
03360    cl->notxtone = 1;
03361    cl->norxtone = 1;
03362    
03363    return 0;
03364 }
03365 
03366 
03367 static struct chan_list *init_chan_list(int orig)
03368 {
03369    struct chan_list *cl;
03370 
03371    cl = ast_calloc(1, sizeof(*cl));
03372 
03373    if (!cl) {
03374       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03375       return NULL;
03376    }
03377    
03378    cl->originator = orig;
03379    cl->need_queue_hangup = 1;
03380    cl->need_hangup = 1;
03381    cl->need_busy = 1;
03382    cl->overlap_dial_task = -1;
03383 
03384    return cl;
03385 }
03386 
03387 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
03388 {
03389    struct ast_channel *tmp = NULL;
03390    char group[BUFFERSIZE + 1] = "";
03391    char buf[128];
03392    char *buf2 = ast_strdupa(data), *ext = NULL, *port_str;
03393    char *tokb = NULL, *p = NULL;
03394    int channel = 0, port = 0;
03395    struct misdn_bchannel *newbc = NULL;
03396    int dec = 0;
03397 
03398    struct chan_list *cl = init_chan_list(ORG_AST);
03399 
03400    snprintf(buf, sizeof(buf), "%s/%s", misdn_type, (char*)data);
03401 
03402    port_str = strtok_r(buf2, "/", &tokb);
03403 
03404    ext = strtok_r(NULL, "/", &tokb);
03405 
03406    if (port_str) {
03407       if (port_str[0] == 'g' && port_str[1] == ':' ) {
03408          /* We make a group call lets checkout which ports are in my group */
03409          port_str += 2;
03410          ast_copy_string(group, port_str, sizeof(group));
03411          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03412       } else if ((p = strchr(port_str, ':'))) {
03413          /* we have a preselected channel */
03414          *p = 0;
03415          channel = atoi(++p);
03416          port = atoi(port_str);
03417          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03418       } else {
03419          port = atoi(port_str);
03420       }
03421    } else {
03422       ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extensions.conf\n", ext);
03423       return NULL;
03424    }
03425 
03426    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03427       chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
03428       dec = 1;
03429    }
03430 
03431    if (!ast_strlen_zero(group)) {
03432       char cfg_group[BUFFERSIZE + 1];
03433       struct robin_list *rr = NULL;
03434 
03435       /* Group dial */
03436 
03437       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03438          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03439          rr = get_robin_position(group);
03440       }
03441 
03442       if (rr) {
03443          int robin_channel = rr->channel;
03444          int port_start;
03445          int next_chan = 1;
03446 
03447          do {
03448             port_start = 0;
03449             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
03450                 port = misdn_cfg_get_next_port_spin(port)) {
03451 
03452                if (!port_start)
03453                   port_start = port;
03454 
03455                if (port >= port_start)
03456                   next_chan = 1;
03457                
03458                if (port <= port_start && next_chan) {
03459                   int maxbchans=misdn_lib_get_maxchans(port);
03460                   if (++robin_channel >= maxbchans) {
03461                      robin_channel = 1;
03462                   }
03463                   next_chan = 0;
03464                }
03465 
03466                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03467 
03468                if (!strcasecmp(cfg_group, group)) {
03469                   int port_up;
03470                   int check;
03471                   misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03472                   port_up = misdn_lib_port_up(port, check);
03473 
03474                   if (check && !port_up) 
03475                      chan_misdn_log(1, port, "L1 is not Up on this Port\n");
03476                   
03477                   if (check && port_up < 0) {
03478                      ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
03479                   }
03480 
03481                   if (port_up > 0)  {
03482                      newbc = misdn_lib_get_free_bc(port, robin_channel, 0, 0);
03483                      if (newbc) {
03484                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03485                         if (port_up)
03486                            chan_misdn_log(4, port, "portup:%d\n",  port_up);
03487                         rr->port = newbc->port;
03488                         rr->channel = newbc->channel;
03489                         break;
03490                      }
03491                   }
03492                }
03493             }
03494          } while (!newbc && robin_channel != rr->channel);
03495          
03496       } else {    
03497          for (port = misdn_cfg_get_next_port(0); port > 0;
03498              port = misdn_cfg_get_next_port(port)) {
03499 
03500             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03501 
03502             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03503             if (!strcasecmp(cfg_group, group)) {
03504                int port_up;
03505                int check;
03506                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03507                port_up = misdn_lib_port_up(port, check);
03508 
03509                chan_misdn_log(4, port, "portup:%d\n", port_up);
03510 
03511                if (port_up > 0) {
03512                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03513                   if (newbc)
03514                      break;
03515                }
03516             }
03517          }
03518       }
03519       
03520       /* Group dial failed ?*/
03521       if (!newbc) {
03522          ast_log(LOG_WARNING, 
03523                "Could not Dial out on group '%s'.\n"
03524                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03525                "\tOr there was no free channel on none of the ports\n\n"
03526                , group);
03527          return NULL;
03528       }
03529    } else {
03530       /* 'Normal' Port dial * Port dial */
03531       if (channel)
03532          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03533       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03534 
03535       if (!newbc) {
03536          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03537          return NULL;
03538       }
03539    }
03540    
03541 
03542    /* create ast_channel and link all the objects together */
03543    cl->bc = newbc;
03544    
03545    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03546    if (!tmp) {
03547       ast_log(LOG_ERROR,"Could not create Asterisk object\n");
03548       return NULL;
03549    }
03550 
03551    cl->ast=tmp;
03552    
03553    /* register chan in local list */
03554    cl_queue_chan(&cl_te, cl) ;
03555    
03556    /* fill in the config into the objects */
03557    read_config(cl, ORG_AST);
03558 
03559    /* important */
03560    cl->need_hangup = 0;
03561    
03562    return tmp;
03563 }
03564 
03565 
03566 static int misdn_send_text(struct ast_channel *chan, const char *text)
03567 {
03568    struct chan_list *tmp = chan->tech_pvt;
03569    
03570    if (tmp && tmp->bc) {
03571       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03572       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03573    } else {
03574       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03575       return -1;
03576    }
03577    
03578    return 0;
03579 }
03580 
03581 static struct ast_channel_tech misdn_tech = {
03582    .type = "mISDN",
03583    .description = "Channel driver for mISDN Support (Bri/Pri)",
03584    .capabilities = AST_FORMAT_ALAW ,
03585    .requester = misdn_request,
03586    .send_digit_begin = misdn_digit_begin,
03587    .send_digit_end = misdn_digit_end,
03588    .call = misdn_call,
03589    .bridge = misdn_bridge, 
03590    .hangup = misdn_hangup,
03591    .answer = misdn_answer,
03592    .read = misdn_read,
03593    .write = misdn_write,
03594    .indicate = misdn_indication,
03595    .fixup = misdn_fixup,
03596    .send_text = misdn_send_text,
03597    .properties = 0
03598 };
03599 
03600 static struct ast_channel_tech misdn_tech_wo_bridge = {
03601    .type = "mISDN",
03602    .description = "Channel driver for mISDN Support (Bri/Pri)",
03603    .capabilities = AST_FORMAT_ALAW ,
03604    .requester = misdn_request,
03605    .send_digit_begin = misdn_digit_begin,
03606    .send_digit_end = misdn_digit_end,
03607    .call = misdn_call,
03608    .hangup = misdn_hangup,
03609    .answer = misdn_answer,
03610    .read = misdn_read,
03611    .write = misdn_write,
03612    .indicate = misdn_indication,
03613    .fixup = misdn_fixup,
03614    .send_text = misdn_send_text,
03615    .properties = 0
03616 };
03617 
03618 
03619 static int glob_channel = 0;
03620 
03621 static void update_name(struct ast_channel *tmp, int port, int c) 
03622 {
03623    int chan_offset = 0;
03624    int tmp_port = misdn_cfg_get_next_port(0);
03625    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03626       if (tmp_port == port)
03627          break;
03628       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03629    }
03630    if (c < 0)
03631       c = 0;
03632 
03633    ast_string_field_build(tmp, name, "%s/%d-u%d",
03634              misdn_type, chan_offset+c, glob_channel++);
03635 
03636    chan_misdn_log(3 , port, " --> updating channel name to [%s]\n", tmp->name);
03637 }
03638 
03639 static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char *exten, char *callerid, int format, int port, int c)
03640 {
03641    struct ast_channel *tmp;
03642    char *cid_name = 0, *cid_num = 0;
03643    int chan_offset = 0;
03644    int tmp_port = misdn_cfg_get_next_port(0);
03645    int bridging;
03646 
03647    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03648       if (tmp_port == port)
03649          break;
03650       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03651    }
03652    if (c < 0)
03653       c = 0;
03654 
03655    if (callerid) 
03656       ast_callerid_parse(callerid, &cid_name, &cid_num);
03657 
03658    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03659 
03660    if (tmp) {
03661       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03662 
03663       tmp->nativeformats = prefformat;
03664 
03665       tmp->readformat = format;
03666       tmp->rawreadformat = format;
03667       tmp->writeformat = format;
03668       tmp->rawwriteformat = format;
03669     
03670       tmp->tech_pvt = chlist;
03671 
03672       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03673 
03674       if (bridging)
03675          tmp->tech = &misdn_tech;
03676       else
03677          tmp->tech = &misdn_tech_wo_bridge;
03678 
03679       tmp->writeformat = format;
03680       tmp->readformat = format;
03681       tmp->priority=1;
03682 
03683       if (exten) 
03684          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03685       else
03686          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03687 
03688       if (callerid)
03689          /* Don't use ast_set_callerid() here because it will
03690           * generate a needless NewCallerID event */
03691          tmp->cid.cid_ani = ast_strdup(cid_num);
03692 
03693       if (pipe(chlist->pipe) < 0)
03694          ast_log(LOG_ERROR, "Pipe failed\n");
03695 
03696       ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
03697 
03698       if (state == AST_STATE_RING)
03699          tmp->rings = 1;
03700       else
03701          tmp->rings = 0;
03702       
03703            ast_jb_configure(tmp, misdn_get_global_jbconf());
03704    } else {
03705       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03706    }
03707    
03708    return tmp;
03709 }
03710 
03711 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
03712 {
03713    struct chan_list *help = list;
03714    for (; help; help = help->next) {
03715       if (help->bc == bc) return help;
03716    }
03717 
03718    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03719 
03720    return NULL;
03721 }
03722 
03723 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
03724 {
03725    struct chan_list *help = list;
03726    for (; help; help = help->next) {
03727       if ( help->bc && (help->bc->pid == pid) ) return help;
03728    }
03729 
03730    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03731 
03732    return NULL;
03733 }
03734 
03735 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
03736 {
03737    struct chan_list *help = list;
03738 
03739    if (bc->pri) return NULL;
03740 
03741    chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03742    for (;help; help = help->next) {
03743       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state==MISDN_HOLDED, help->hold_info.channel);
03744       if (  (help->state == MISDN_HOLDED) && 
03745          (help->hold_info.port == bc->port) ) 
03746          return help;
03747    }
03748    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03749 
03750    return NULL;
03751 }
03752 
03753 
03754 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w) 
03755 {
03756    struct chan_list *help = list;
03757 
03758    for (; help; help = help->next) {
03759       if ( (help->state == MISDN_HOLDED) &&
03760           (help->l3id == l3_id)   
03761          ) 
03762          return help;
03763    }
03764 
03765    return NULL;
03766 }
03767 
03768 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
03769 {
03770    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03771   
03772    ast_mutex_lock(&cl_te_lock);
03773    if (!*list) {
03774       *list = chan;
03775    } else {
03776       struct chan_list *help = *list;
03777       for (; help->next; help = help->next); 
03778       help->next = chan;
03779    }
03780    chan->next = NULL;
03781    ast_mutex_unlock(&cl_te_lock);
03782 }
03783 
03784 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
03785 {
03786    struct chan_list *help;
03787 
03788    if (chan->dsp) 
03789       ast_dsp_free(chan->dsp);
03790    if (chan->trans)
03791       ast_translator_free_path(chan->trans);
03792 
03793    ast_mutex_lock(&cl_te_lock);
03794    if (!*list) {
03795       ast_mutex_unlock(&cl_te_lock);
03796       return;
03797    }
03798   
03799    if (*list == chan) {
03800       *list = (*list)->next;
03801       ast_mutex_unlock(&cl_te_lock);
03802       return;
03803    }
03804   
03805    for (help = *list; help->next; help = help->next) {
03806       if (help->next == chan) {
03807          help->next = help->next->next;
03808          ast_mutex_unlock(&cl_te_lock);
03809          return;
03810       }
03811    }
03812    
03813    ast_mutex_unlock(&cl_te_lock);
03814 }
03815 
03816 /** Channel Queue End **/
03817 
03818 
03819 static int pbx_start_chan(struct chan_list *ch)
03820 {
03821    int ret = ast_pbx_start(ch->ast);   
03822 
03823    if (ret >= 0) 
03824       ch->need_hangup = 0;
03825    else
03826       ch->need_hangup = 1;
03827 
03828    return ret;
03829 }
03830 
03831 static void hangup_chan(struct chan_list *ch)
03832 {
03833    int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
03834    if (!ch) {
03835       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03836       return;
03837    }
03838 
03839    cb_log(5, port, "hangup_chan called\n");
03840 
03841    if (ch->need_hangup) {
03842       cb_log(2, port, " --> hangup\n");
03843       send_cause2ast(ch->ast, ch->bc, ch);
03844       ch->need_hangup = 0;
03845       ch->need_queue_hangup = 0;
03846       if (ch->ast)
03847          ast_hangup(ch->ast);
03848       return;
03849    }
03850 
03851    if (!ch->need_queue_hangup) {
03852       cb_log(2, port, " --> No need to queue hangup\n");
03853    }
03854 
03855    ch->need_queue_hangup = 0;
03856    if (ch->ast) {
03857       send_cause2ast(ch->ast, ch->bc, ch);
03858 
03859       if (ch->ast)
03860          ast_queue_hangup(ch->ast);
03861       cb_log(2, port, " --> queue_hangup\n");
03862    } else {
03863       cb_log(1, port, "Cannot hangup chan, no ast\n");
03864    }
03865 }
03866 
03867 /** Isdn asks us to release channel, pendant to misdn_hangup **/
03868 static void release_chan(struct misdn_bchannel *bc) {
03869    struct ast_channel *ast=NULL;
03870 
03871    ast_mutex_lock(&release_lock);
03872    {
03873       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03874       if (!ch)  {
03875          chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03876          ast_mutex_unlock(&release_lock);
03877          return;
03878       }
03879 
03880       if (ch->ast) {
03881          ast = ch->ast;
03882       } 
03883 
03884       chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
03885 
03886       /*releasing jitterbuffer*/
03887       if (ch->jb ) {
03888          misdn_jb_destroy(ch->jb);
03889          ch->jb = NULL;
03890       } else {
03891          if (!bc->nojitter)
03892             chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03893       }
03894 
03895       if (ch->overlap_dial) {
03896          if (ch->overlap_dial_task != -1) {
03897             misdn_tasks_remove(ch->overlap_dial_task);
03898             ch->overlap_dial_task = -1;
03899          }
03900          ast_mutex_destroy(&ch->overlap_tv_lock);
03901       }
03902 
03903       if (ch->originator == ORG_AST) {
03904          misdn_out_calls[bc->port]--;
03905       } else {
03906          misdn_in_calls[bc->port]--;
03907       }
03908 
03909       if (ch) {
03910          close(ch->pipe[0]);
03911          close(ch->pipe[1]);
03912 
03913          if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03914             chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n", bc ? bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch));
03915             chan_misdn_log(3, bc->port, " --> * State Down\n");
03916             MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03917 
03918             if (ast->_state != AST_STATE_RESERVED) {
03919                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03920                ast_setstate(ast, AST_STATE_DOWN);
03921             }
03922          }
03923 
03924          ch->state = MISDN_CLEANING;
03925          cl_dequeue_chan(&cl_te, ch);
03926 
03927          ast_free(ch);
03928       } else {
03929          /* chan is already cleaned, so exiting  */
03930       }
03931 
03932       ast_mutex_unlock(&release_lock);
03933    }
03934 /*** release end **/
03935 }
03936 
03937 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
03938 {
03939    chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
03940 
03941    tmp_ch->state = MISDN_HOLD_DISCONNECT;
03942 
03943    ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03944 
03945    holded_chan->state=MISDN_CONNECTED;
03946    /* misdn_lib_transfer(holded_chan->bc); */
03947    ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03948 }
03949 
03950 
03951 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
03952 {
03953    char *predial;
03954    struct ast_frame fr;
03955 
03956    predial = ast_strdupa(ast->exten);
03957 
03958    ch->state = MISDN_DIALING;
03959 
03960    if (!ch->noautorespond_on_setup) {
03961       if (bc->nt) {
03962          int ret; 
03963          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03964       } else {
03965          int ret;
03966          if ( misdn_lib_is_ptp(bc->port)) {
03967             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03968          } else {
03969             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03970          }
03971       }
03972    } else {
03973       ch->state = MISDN_INCOMING_SETUP;
03974    }
03975 
03976    chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, ast->cid.cid_num);
03977   
03978    strncpy(ast->exten, "s", 2);
03979   
03980    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03981       ast = NULL;
03982       bc->out_cause = AST_CAUSE_UNALLOCATED;
03983       hangup_chan(ch);
03984       hanguptone_indicate(ch);
03985 
03986       if (bc->nt)
03987          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03988       else
03989          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03990    }
03991   
03992   
03993    while (!ast_strlen_zero(predial) ) {
03994       fr.frametype = AST_FRAME_DTMF;
03995       fr.subclass = *predial;
03996       fr.src = NULL;
03997       fr.data = NULL;
03998       fr.datalen = 0;
03999       fr.samples = 0;
04000       fr.mallocd = 0;
04001       fr.offset = 0;
04002       fr.delivery = ast_tv(0,0);
04003 
04004       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04005          ast_queue_frame(ch->ast, &fr);
04006       }
04007       predial++;
04008    }
04009 }
04010 
04011 
04012 
04013 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) {
04014    if (!ast) {
04015       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
04016       return;
04017    }
04018    if (!bc) {
04019       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
04020       return;
04021    }
04022    if (!ch) {
04023       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
04024       return;
04025    }
04026 
04027    ast->hangupcause = bc->cause;
04028 
04029    switch (bc->cause) {
04030 
04031    case 1: /** Congestion Cases **/
04032    case 2:
04033    case 3:
04034    case 4:
04035    case 22:
04036    case 27:
04037       /*
04038        * Not Queueing the Congestion anymore, since we want to hear
04039        * the inband message
04040        *
04041       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
04042       ch->state = MISDN_BUSY;
04043       
04044       ast_queue_control(ast, AST_CONTROL_CONGESTION);
04045       */
04046       break;
04047 
04048    case 21:
04049    case 17: /* user busy */
04050 
04051       ch->state = MISDN_BUSY;
04052 
04053       if (!ch->need_busy) {
04054          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
04055          break;
04056       }
04057 
04058       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04059       
04060       ast_queue_control(ast, AST_CONTROL_BUSY);
04061       
04062       ch->need_busy = 0;
04063       
04064       break;
04065    }
04066 }
04067 
04068 
04069 /*! \brief Import parameters from the dialplan environment variables */
04070 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
04071 {
04072    const char *tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04073    if (tmp) {
04074       ch->other_pid = atoi(tmp);
04075       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04076       if (ch->other_pid > 0) {
04077          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04078          if (ch->other_ch)
04079             ch->other_ch->other_ch = ch;
04080       }
04081    }
04082 
04083    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04084    if (tmp && (atoi(tmp) == 1)) {
04085       bc->sending_complete = 1;
04086    }
04087 
04088    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04089    if (tmp) {
04090       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04091       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04092       bc->uulen = strlen(bc->uu);
04093    }
04094 
04095    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04096    if (tmp)
04097       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04098 }
04099 
04100 /*! \brief Export parameters to the dialplan environment variables */
04101 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
04102 {
04103    char tmp[32];
04104    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04105    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04106    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04107 
04108    if (bc->sending_complete) {
04109       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04110       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04111    }
04112 
04113    if (bc->urate) {
04114       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04115       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04116    }
04117 
04118    if (bc->uulen)
04119       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04120 
04121    if (!ast_strlen_zero(bc->keypad)) 
04122       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04123 }
04124 
04125 int add_in_calls(int port)
04126 {
04127    int max_in_calls;
04128    
04129    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04130    misdn_in_calls[port]++;
04131 
04132    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04133       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04134       return misdn_in_calls[port] - max_in_calls;
04135    }
04136    
04137    return 0;
04138 }
04139 
04140 int add_out_calls(int port)
04141 {
04142    int max_out_calls;
04143    
04144    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04145 
04146    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04147       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04148       return (misdn_out_calls[port] + 1) - max_out_calls;
04149    }
04150 
04151    misdn_out_calls[port]++;
04152    
04153    return 0;
04154 }
04155 
04156 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
04157    if (pbx_start_chan(ch) < 0) {
04158       hangup_chan(ch);
04159       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04160       if (bc->nt) {
04161          hanguptone_indicate(ch);
04162          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04163       } else
04164          misdn_lib_send_event(bc, EVENT_RELEASE);
04165    }
04166 }
04167 
04168 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
04169    ch->state=MISDN_WAITING4DIGS;
04170    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04171    if (bc->nt && !bc->dad[0])
04172       dialtone_indicate(ch);
04173 }
04174 
04175 
04176 /************************************************************/
04177 /*  Receive Events from isdn_lib  here                     */
04178 /************************************************************/
04179 static enum event_response_e
04180 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
04181 {
04182    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04183    
04184    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
04185       int debuglevel = 1;
04186       if ( event == EVENT_CLEANUP && !user_data)
04187          debuglevel = 5;
04188 
04189       chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch ? misdn_get_ch_state(ch) : "none");
04190       if (debuglevel == 1) {
04191          misdn_lib_log_ies(bc);
04192          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04193       }
04194    }
04195    
04196    if (!ch) {
04197       switch(event) {
04198       case EVENT_SETUP:
04199       case EVENT_DISCONNECT:
04200       case EVENT_PORT_ALARM:
04201       case EVENT_RETRIEVE:
04202       case EVENT_NEW_BC:
04203       case EVENT_FACILITY:
04204          break;
04205       case EVENT_RELEASE_COMPLETE:
04206          chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
04207          break;
04208       case EVENT_CLEANUP:
04209       case EVENT_TONE_GENERATE:
04210       case EVENT_BCHAN_DATA:
04211          return -1;
04212       default:
04213          chan_misdn_log(1, bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n", bc->l3_id, bc, manager_isdn_get_info(event), bc->port, bc->channel);
04214          return -1;
04215       }
04216    }
04217    
04218    if (ch) {
04219       switch (event) {
04220       case EVENT_TONE_GENERATE:
04221          break;
04222       case EVENT_DISCONNECT:
04223       case EVENT_RELEASE:
04224       case EVENT_RELEASE_COMPLETE:
04225       case EVENT_CLEANUP:
04226       case EVENT_TIMEOUT:
04227          if (!ch->ast)
04228             chan_misdn_log(3, bc->port, "ast_hangup already called, so we have no ast ptr anymore in event(%s)\n", manager_isdn_get_info(event));
04229          break;
04230       default:
04231          if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04232             if (event != EVENT_BCHAN_DATA)
04233                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04234             return -1;
04235          }
04236       }
04237    }
04238    
04239    
04240    switch (event) {
04241    case EVENT_PORT_ALARM:
04242       {
04243          int boa = 0;
04244          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
04245          if (boa) {
04246             cb_log(1, bc->port, " --> blocking\n");
04247             misdn_lib_port_block(bc->port); 
04248          }
04249       }
04250       break;
04251    case EVENT_BCHAN_ACTIVATED:
04252       break;
04253       
04254    case EVENT_NEW_CHANNEL:
04255       update_name(ch->ast,bc->port,bc->channel);
04256       break;
04257       
04258    case EVENT_NEW_L3ID:
04259       ch->l3id=bc->l3_id;
04260       ch->addr=bc->addr;
04261       break;
04262 
04263    case EVENT_NEW_BC:
04264       if (!ch) {
04265          ch = find_holded(cl_te,bc);
04266       }
04267       
04268       if (!ch) {
04269          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04270          break;
04271       }
04272 
04273       if (bc)
04274          ch->bc = (struct misdn_bchannel *)user_data;
04275       break;
04276       
04277    case EVENT_DTMF_TONE:
04278    {
04279       /*  sending INFOS as DTMF-Frames :) */
04280       struct ast_frame fr = { 0, };
04281       fr.frametype = AST_FRAME_DTMF;
04282       fr.subclass = bc->dtmf ;
04283       fr.src = NULL;
04284       fr.data = NULL;
04285       fr.datalen = 0;
04286       fr.samples = 0;
04287       fr.mallocd = 0;
04288       fr.offset = 0;
04289       fr.delivery = ast_tv(0,0);
04290       
04291       if (!ch->ignore_dtmf) {
04292          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04293          ast_queue_frame(ch->ast, &fr);
04294       } else {
04295          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04296       }
04297    }
04298       break;
04299    case EVENT_STATUS:
04300       break;
04301     
04302    case EVENT_INFORMATION:
04303    {
04304       if ( ch->state != MISDN_CONNECTED ) 
04305          stop_indicate(ch);
04306    
04307       if (!ch->ast)
04308          break;
04309 
04310       if (ch->state == MISDN_WAITING4DIGS ) {
04311          /*  Ok, incomplete Setup, waiting till extension exists */
04312          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04313             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04314             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04315          }
04316 
04317          strncat(bc->dad,bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04318          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04319 
04320          /* Check for Pickup Request first */
04321          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04322             if (ast_pickup_call(ch->ast)) {
04323                hangup_chan(ch);
04324             } else {
04325                struct ast_channel *chan = ch->ast;
04326                ch->state = MISDN_CALLING_ACKNOWLEDGE;
04327                ast_setstate(chan, AST_STATE_DOWN);
04328                hangup_chan(ch);
04329                ch->ast = NULL;
04330                break;
04331             }
04332          }
04333          
04334          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04335             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04336                ast_log(LOG_WARNING,
04337                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04338                   bc->dad, ch->context, bc->port);
04339                strcpy(ch->ast->exten, "i");
04340 
04341                ch->state = MISDN_DIALING;
04342                start_pbx(ch, bc, ch->ast);
04343                break;
04344             }
04345 
04346             ast_log(LOG_WARNING,
04347                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04348                "\tMaybe you want to add an 'i' extension to catch this case.\n",
04349                bc->dad, ch->context, bc->port);
04350 
04351             if (bc->nt)
04352                hanguptone_indicate(ch);
04353             ch->state = MISDN_EXTCANTMATCH;
04354             bc->out_cause = 1;
04355 
04356             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04357             break;
04358          }
04359 
04360          if (ch->overlap_dial) {
04361             ast_mutex_lock(&ch->overlap_tv_lock);
04362             ch->overlap_tv = ast_tvnow();
04363             ast_mutex_unlock(&ch->overlap_tv_lock);
04364             if (ch->overlap_dial_task == -1) {
04365                ch->overlap_dial_task = 
04366                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04367             }
04368             break;
04369          }
04370 
04371          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04372             
04373             ch->state = MISDN_DIALING;
04374             start_pbx(ch, bc, ch->ast);
04375          }
04376       } else {
04377          /*  sending INFOS as DTMF-Frames :) */
04378          struct ast_frame fr;
04379          int digits;
04380          memset(&fr, 0, sizeof(fr));
04381          fr.frametype = AST_FRAME_DTMF;
04382          fr.subclass = bc->info_dad[0] ;
04383          fr.src = NULL;
04384          fr.data = NULL;
04385          fr.datalen = 0;
04386          fr.samples = 0;
04387          fr.mallocd = 0;
04388          fr.offset = 0;
04389          fr.delivery = ast_tv(0,0);
04390 
04391          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
04392          if (ch->state != MISDN_CONNECTED ) {
04393             if (digits) {
04394                strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04395                ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04396                ast_cdr_update(ch->ast);
04397             }
04398             
04399             ast_queue_frame(ch->ast, &fr);
04400          }
04401       }
04402    }
04403       break;
04404    case EVENT_SETUP:
04405    {
04406       struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04407       int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04408       struct ast_channel *chan;
04409       int exceed;
04410       int pres,screen;
04411       int ai;
04412       int im;
04413 
04414       if (ch) {
04415          switch (ch->state) {
04416          case MISDN_NOTHING:
04417             ch = NULL;
04418             break;
04419          default:
04420             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04421             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
04422          }
04423       }
04424 
04425       if (!bc->nt && ! msn_valid) {
04426          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04427          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04428       }
04429 
04430       if (bc->cw) {
04431          int cause;
04432          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04433          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04434          bc->out_cause = cause ? cause : 16;
04435          return RESPONSE_RELEASE_SETUP;
04436       }
04437 
04438       print_bearer(bc);
04439     
04440       if (!bc->nt && ! msn_valid) {
04441          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04442          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04443       }
04444 
04445       if (bc->cw) {
04446          int cause;
04447          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04448          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04449          bc->out_cause = cause ? cause : 16;
04450          return RESPONSE_RELEASE_SETUP;
04451       }
04452 
04453       print_bearer(bc);
04454 
04455       ch = init_chan_list(ORG_MISDN);
04456 
04457       if (!ch) {
04458          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
04459          return 0;
04460       }
04461 
04462       ch->bc = bc;
04463       ch->l3id = bc->l3_id;
04464       ch->addr = bc->addr;
04465       ch->originator = ORG_MISDN;
04466 
04467       chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04468 
04469       if (!chan) {
04470          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04471          ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); 
04472          return 0;
04473       }
04474 
04475       ch->ast = chan;
04476 
04477       if ((exceed = add_in_calls(bc->port))) {
04478          char tmp[16];
04479          snprintf(tmp, sizeof(tmp), "%d", exceed);
04480          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
04481       }
04482 
04483       read_config(ch, ORG_MISDN);
04484 
04485       export_ch(chan, bc, ch);
04486 
04487       ch->ast->rings = 1;
04488       ast_setstate(ch->ast, AST_STATE_RINGING);
04489 
04490       switch (bc->pres) {
04491       case 1:
04492          pres = AST_PRES_RESTRICTED;
04493          chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
04494          break;
04495       case 2:
04496          pres = AST_PRES_UNAVAILABLE;
04497          chan_misdn_log(2, bc->port, " --> PRES: Restricted (2)\n");
04498          break;
04499       default:
04500          pres = AST_PRES_ALLOWED;
04501          chan_misdn_log(2, bc->port, " --> PRES: Restricted (%d)\n", bc->pres);
04502       }
04503 
04504       switch (bc->screen) {
04505       case 0:
04506          screen = AST_PRES_USER_NUMBER_UNSCREENED;
04507          chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (0)\n");
04508          break;
04509       case 1:
04510          screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
04511          chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
04512          break;
04513       case 2:
04514          screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
04515          chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
04516          break;
04517       case 3:
04518          screen = AST_PRES_NETWORK_NUMBER;
04519          chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
04520          break;
04521       default:
04522          screen = AST_PRES_USER_NUMBER_UNSCREENED;
04523          chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
04524       }
04525 
04526       chan->cid.cid_pres = pres + screen;
04527 
04528       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04529       chan->transfercapability = bc->capability;
04530 
04531       switch (bc->capability) {
04532       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04533          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
04534          break;
04535       default:
04536          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
04537       }
04538 
04539       /** queue new chan **/
04540       cl_queue_chan(&cl_te, ch);
04541 
04542       if (!strstr(ch->allowed_bearers, "all")) {
04543          int i;
04544 
04545          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
04546             if (allowed_bearers_array[i].cap == bc->capability) {
04547                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
04548                   /* The bearer capability is allowed */
04549                   if (allowed_bearers_array[i].deprecated) {
04550                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
04551                         allowed_bearers_array[i].name);
04552                   }
04553                   break;
04554                }
04555             }
04556          }  /* end for */
04557          if (i == ARRAY_LEN(allowed_bearers_array)) {
04558             /* We did not find the bearer capability */
04559             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
04560                bearer2str(bc->capability), bc->capability);
04561             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
04562 
04563             ch->state = MISDN_EXTCANTMATCH;
04564             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04565             return RESPONSE_OK;
04566          }
04567       }
04568 
04569       /* Check for Pickup Request first */
04570       if (!strcmp(chan->exten, ast_pickup_ext())) {
04571          if (!ch->noautorespond_on_setup) {
04572             int ret;/** Sending SETUP_ACK**/
04573             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04574          } else {
04575             ch->state = MISDN_INCOMING_SETUP;
04576          }
04577          if (ast_pickup_call(chan)) {
04578             hangup_chan(ch);
04579          } else {
04580             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04581             ast_setstate(chan, AST_STATE_DOWN);
04582             hangup_chan(ch);
04583             ch->ast = NULL;
04584             break;
04585          }
04586       }
04587 
04588       /*
04589        * added support for s extension hope it will help those poor cretains
04590        * which haven't overlap dial.
04591        */
04592       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04593       if (ai) {
04594          do_immediate_setup(bc, ch, chan);
04595          break;
04596       }
04597 
04598       /* check if we should jump into s when we have no dad */
04599       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04600       if (im && ast_strlen_zero(bc->dad)) {
04601          do_immediate_setup(bc, ch, chan);
04602          break;
04603       }
04604 
04605       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
04606       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04607          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04608             ast_log(LOG_WARNING,
04609                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04610                bc->dad, ch->context, bc->port);
04611             strcpy(ch->ast->exten, "i");
04612             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04613             ch->state = MISDN_DIALING;
04614             start_pbx(ch, bc, chan);
04615             break;
04616          }
04617 
04618          ast_log(LOG_WARNING,
04619             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04620             "\tMaybe you want to add an 'i' extension to catch this case.\n",
04621             bc->dad, ch->context, bc->port);
04622          if (bc->nt)
04623             hanguptone_indicate(ch);
04624 
04625          ch->state = MISDN_EXTCANTMATCH;
04626          bc->out_cause = AST_CAUSE_UNALLOCATED;
04627 
04628          if (bc->nt)
04629             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04630          else
04631             misdn_lib_send_event(bc, EVENT_RELEASE );
04632 
04633          break;
04634       }
04635 
04636       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
04637        * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
04638        * will be used by Asterisk automatically. */
04639       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04640          if (!ch->noautorespond_on_setup) {
04641             ch->state=MISDN_DIALING;
04642             misdn_lib_send_event(bc, EVENT_PROCEEDING );
04643          } else {
04644             ch->state = MISDN_INCOMING_SETUP;
04645          }
04646          start_pbx(ch, bc, chan);
04647          break;
04648       }
04649 
04650 
04651       /*
04652        * When we are NT and overlapdial is set and if 
04653        * the number is empty, we wait for the ISDN timeout
04654        * instead of our own timer.
04655        */
04656       if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04657          wait_for_digits(ch, bc, chan);
04658          break;
04659       }
04660 
04661       /* 
04662        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
04663        * Infos with a Interdigit Timeout.
04664        * */
04665       if (ch->overlap_dial) {
04666          ast_mutex_lock(&ch->overlap_tv_lock);
04667          ch->overlap_tv = ast_tvnow();
04668          ast_mutex_unlock(&ch->overlap_tv_lock);
04669 
04670          wait_for_digits(ch, bc, chan);
04671          if (ch->overlap_dial_task == -1) 
04672             ch->overlap_dial_task = 
04673                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04674 
04675          break;
04676       }
04677 
04678       /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
04679        * without interdigit timeout.
04680        * */
04681       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04682          wait_for_digits(ch, bc, chan);
04683          break;
04684       }
04685 
04686       /*
04687        * If the extension exists let's just jump into it.
04688        * */
04689       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04690          if (bc->need_more_infos)
04691             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04692          else
04693             misdn_lib_send_event(bc, EVENT_PROCEEDING);
04694 
04695          ch->state = MISDN_DIALING;
04696          start_pbx(ch, bc, chan);
04697          break;
04698       }
04699    }
04700    break;
04701 
04702    case EVENT_SETUP_ACKNOWLEDGE:
04703    {
04704       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04705 
04706       if (bc->channel) 
04707          update_name(ch->ast,bc->port,bc->channel);
04708       
04709       if (!ast_strlen_zero(bc->infos_pending)) {
04710          /* TX Pending Infos */
04711          strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04712 
04713          if (!ch->ast)
04714             break;
04715          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04716          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04717          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04718 
04719          misdn_lib_send_event(bc, EVENT_INFORMATION);
04720       }
04721    }
04722    break;
04723    case EVENT_PROCEEDING:
04724    {
04725       
04726       if (misdn_cap_is_speech(bc->capability) &&
04727            misdn_inband_avail(bc) ) {
04728          start_bc_tones(ch);
04729       }
04730 
04731       ch->state = MISDN_PROCEEDING;
04732       
04733       if (!ch->ast)
04734          break;
04735 
04736       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04737    }
04738    break;
04739    case EVENT_PROGRESS:
04740 
04741       if (bc->channel) 
04742          update_name(ch->ast, bc->port, bc->channel);
04743 
04744       if (!bc->nt ) {
04745          if ( misdn_cap_is_speech(bc->capability) &&
04746               misdn_inband_avail(bc)
04747             ) {
04748             start_bc_tones(ch);
04749          }
04750          
04751          ch->state = MISDN_PROGRESS;
04752 
04753          if (!ch->ast)
04754             break;
04755          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04756       }
04757       break;
04758       
04759       
04760    case EVENT_ALERTING:
04761    {
04762       ch->state = MISDN_ALERTING;
04763       
04764       if (!ch->ast)
04765          break;
04766 
04767       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04768       ast_setstate(ch->ast, AST_STATE_RINGING);
04769       
04770       cb_log(7, bc->port, " --> Set State Ringing\n");
04771       
04772       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04773          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04774          start_bc_tones(ch);
04775       } else {
04776          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04777          if (ch->far_alerting) {
04778             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04779             start_bc_tones(ch);
04780             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04781          }
04782       }
04783    }
04784    break;
04785    case EVENT_CONNECT:
04786    {
04787       struct ast_channel *bridged;
04788 
04789       /*we answer when we've got our very new L3 ID from the NT stack */
04790       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04791 
04792       if (!ch->ast)
04793          break;
04794 
04795       bridged = ast_bridged_channel(ch->ast);
04796       stop_indicate(ch);
04797 
04798       if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04799          struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04800 
04801          chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04802          if (bridged_ch) {
04803             bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04804             ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04805          }
04806       }
04807    }
04808    ch->l3id=bc->l3_id;
04809    ch->addr=bc->addr;
04810 
04811    start_bc_tones(ch);
04812    
04813    ch->state = MISDN_CONNECTED;
04814    
04815    ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04816    break;
04817    case EVENT_CONNECT_ACKNOWLEDGE:
04818    {
04819       ch->l3id = bc->l3_id;
04820       ch->addr = bc->addr;
04821 
04822       start_bc_tones(ch);
04823 
04824       ch->state = MISDN_CONNECTED;
04825    }
04826    break;
04827    case EVENT_DISCONNECT:
04828       /*we might not have an ch->ast ptr here anymore*/
04829       if (ch) {
04830          struct chan_list *holded_ch = find_holded(cl_te, bc);
04831 
04832          chan_misdn_log(3, bc->port, " --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
04833          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04834             /* If there's inband information available (e.g. a
04835                recorded message saying what was wrong with the
04836                dialled number, or perhaps even giving an
04837                alternative number, then play it instead of
04838                immediately releasing the call */
04839             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04840       
04841             ch->state = MISDN_DISCONNECTED;
04842             start_bc_tones(ch);
04843 
04844             if (ch->ast) {
04845                ch->ast->hangupcause = bc->cause;
04846                if (bc->cause == AST_CAUSE_USER_BUSY)
04847                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04848             }
04849             ch->need_busy = 0;
04850             break;
04851          }
04852 
04853          /*Check for holded channel, to implement transfer*/
04854          if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
04855             cb_log(1, bc->port, " --> found holded ch\n");
04856             misdn_transfer_bc(ch, holded_ch) ;
04857          }
04858 
04859          bc->need_disconnect = 0;
04860 
04861          stop_bc_tones(ch);
04862          hangup_chan(ch);
04863 #if 0
04864       } else {
04865          ch = find_holded_l3(cl_te, bc->l3_id,1);
04866          if (ch) {
04867             hangup_chan(ch);
04868          }
04869 #endif
04870       }
04871       bc->out_cause = -1;
04872       if (bc->need_release)
04873          misdn_lib_send_event(bc, EVENT_RELEASE);
04874       break;
04875    
04876    case EVENT_RELEASE:
04877       {
04878          bc->need_disconnect = 0;
04879          bc->need_release = 0;
04880 
04881          hangup_chan(ch);
04882          release_chan(bc);
04883       }
04884       break;
04885    case EVENT_RELEASE_COMPLETE:
04886    {
04887       bc->need_disconnect = 0;
04888       bc->need_release = 0;
04889       bc->need_release_complete = 0;
04890 
04891       stop_bc_tones(ch);
04892       hangup_chan(ch);
04893 
04894       if (ch)
04895          ch->state = MISDN_CLEANING;
04896 
04897       release_chan(bc);
04898    }
04899    break;
04900    case EVENT_BCHAN_ERROR:
04901    case EVENT_CLEANUP:
04902    {
04903       stop_bc_tones(ch);
04904       
04905       switch (ch->state) {
04906       case MISDN_CALLING:
04907          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04908          break;
04909       default:
04910          break;
04911       }
04912       
04913       hangup_chan(ch);
04914       release_chan(bc);
04915    }
04916    break;
04917 
04918    case EVENT_TONE_GENERATE:
04919    {
04920       int tone_len = bc->tone_cnt;
04921       struct ast_channel *ast = ch->ast;
04922       void *tmp;
04923       int res;
04924       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04925 
04926       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
04927 
04928       if (!ast)
04929          break;
04930 
04931       if (!ast->generator)
04932          break;
04933 
04934       tmp = ast->generatordata;
04935       ast->generatordata = NULL;
04936       generate = ast->generator->generate;
04937 
04938       if (tone_len < 0 || tone_len > 512 ) {
04939          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
04940          tone_len = 128;
04941       }
04942 
04943       res = generate(ast, tmp, tone_len, tone_len);
04944       ast->generatordata = tmp;
04945       
04946       if (res) {
04947          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04948          ast_deactivate_generator(ast);
04949       } else {
04950          bc->tone_cnt = 0;
04951       }
04952    }
04953    break;
04954 
04955    case EVENT_BCHAN_DATA:
04956    {
04957       if (ch->bc->AOCD_need_export)
04958          export_aoc_vars(ch->originator, ch->ast, ch->bc);
04959       if (!misdn_cap_is_speech(ch->bc->capability) ) {
04960          struct ast_frame frame;
04961          /*In Data Modes we queue frames*/
04962          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
04963          frame.subclass = AST_FORMAT_ALAW;
04964          frame.datalen = bc->bframe_len;
04965          frame.samples = bc->bframe_len;
04966          frame.mallocd = 0;
04967          frame.offset = 0;
04968          frame.delivery = ast_tv(0,0);
04969          frame.src = NULL;
04970          frame.data = bc->bframe;
04971 
04972          if (ch->ast) 
04973             ast_queue_frame(ch->ast, &frame);
04974       } else {
04975          fd_set wrfs;
04976          struct timeval tv = { 0, 0 };
04977          int t;
04978 
04979          FD_ZERO(&wrfs);
04980          FD_SET(ch->pipe[1], &wrfs);
04981 
04982          t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
04983 
04984          if (!t) {
04985             chan_misdn_log(9, bc->port, "Select Timed out\n");
04986             break;
04987          }
04988          
04989          if (t < 0) {
04990             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
04991             break;
04992          }
04993          
04994          if (FD_ISSET(ch->pipe[1], &wrfs)) {
04995             chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n", bc->bframe_len);
04996             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
04997                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
04998 
04999                stop_bc_tones(ch);
05000                hangup_chan(ch);
05001                release_chan(bc);
05002             }
05003          } else {
05004             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
05005          }
05006       }
05007    }
05008    break;
05009    case EVENT_TIMEOUT:
05010       {
05011       if (ch && bc)
05012          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
05013 
05014       switch (ch->state) {
05015       case MISDN_DIALING:
05016       case MISDN_PROGRESS:
05017          if (bc->nt && !ch->nttimeout)
05018             break;
05019          
05020       case MISDN_CALLING:
05021       case MISDN_ALERTING:
05022       case MISDN_PROCEEDING:
05023       case MISDN_CALLING_ACKNOWLEDGE:
05024          if (bc->nt) {
05025             bc->progress_indicator = 8;
05026             hanguptone_indicate(ch);
05027          }
05028             
05029          bc->out_cause = AST_CAUSE_UNALLOCATED;
05030          misdn_lib_send_event(bc, EVENT_DISCONNECT);
05031          break;
05032 
05033       case MISDN_WAITING4DIGS:
05034          if (bc->nt) {
05035             bc->progress_indicator = 8;
05036             bc->out_cause = AST_CAUSE_UNALLOCATED;
05037             hanguptone_indicate(ch);
05038             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05039          } else {
05040             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
05041             misdn_lib_send_event(bc, EVENT_RELEASE);
05042          }
05043             
05044          break;
05045 
05046       case MISDN_CLEANING: 
05047          chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
05048          break;
05049 
05050       default:
05051          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
05052       }
05053    }
05054    break;
05055 
05056     
05057    /****************************/
05058    /** Supplementary Services **/
05059    /****************************/
05060    case EVENT_RETRIEVE:
05061    {
05062       struct ast_channel *hold_ast;
05063 
05064       if (!ch) {
05065          chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
05066          ch = find_holded_l3(cl_te, bc->l3_id, 1);
05067       }
05068 
05069       if (!ch) {
05070          ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
05071          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05072          break;
05073       }
05074 
05075       /*remember the channel again*/
05076       ch->bc = bc;
05077       ch->state = MISDN_CONNECTED;
05078 
05079       ch->hold_info.port = 0;
05080       ch->hold_info.channel = 0;
05081 
05082       hold_ast = ast_bridged_channel(ch->ast);
05083 
05084       if (hold_ast) {
05085          ast_moh_stop(hold_ast);
05086       }
05087    
05088       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
05089          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
05090          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05091       }
05092    }
05093    break;
05094     
05095    case EVENT_HOLD:
05096    {
05097       int hold_allowed;
05098       struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05099 
05100       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
05101 
05102       if (!hold_allowed) {
05103 
05104          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
05105          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05106          break;
05107       }
05108 
05109       if (bridged) {
05110          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
05111          ch->state = MISDN_HOLDED;
05112          ch->l3id = bc->l3_id;
05113          
05114          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
05115 
05116          /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
05117           * instead of starting moh on the bridged channel directly */
05118          ast_moh_start(bridged, NULL, NULL);
05119 
05120          /*forget the channel now*/
05121          ch->bc = NULL;
05122          ch->hold_info.port = bc->port;
05123          ch->hold_info.channel = bc->channel;
05124 
05125       } else {
05126          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05127          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
05128       }
05129    } 
05130    break;
05131    
05132    case EVENT_FACILITY:
05133       print_facility(&(bc->fac_in), bc);
05134       
05135       switch (bc->fac_in.Function) {
05136 #ifdef HAVE_MISDN_FAC_RESULT
05137       case Fac_RESULT:
05138       break;
05139 #endif
05140       case Fac_CD:
05141          if (ch) {
05142             struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05143             struct chan_list *ch_br;
05144             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
05145                ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
05146                /*ch->state = MISDN_FACILITY_DEFLECTED;*/
05147                if (ch_br->bc) {
05148                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
05149                      ch_br->state = MISDN_DIALING;
05150                      if (pbx_start_chan(ch_br) < 0) {
05151                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
05152                      }
05153                   }
05154                }
05155             }
05156             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05157          } 
05158          break;
05159       case Fac_AOCDCurrency:
05160          if (ch) {
05161             bc->AOCDtype = Fac_AOCDCurrency;
05162             memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
05163             bc->AOCD_need_export = 1;
05164             export_aoc_vars(ch->originator, ch->ast, bc);
05165          }
05166          break;
05167       case Fac_AOCDChargingUnit:
05168          if (ch) {
05169             bc->AOCDtype = Fac_AOCDChargingUnit;
05170             memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
05171             bc->AOCD_need_export = 1;
05172             export_aoc_vars(ch->originator, ch->ast, bc);
05173          }
05174          break;
05175       case Fac_None:
05176 #ifdef HAVE_MISDN_FAC_ERROR
05177       case Fac_ERROR:
05178 #endif
05179       break;
05180       default:
05181          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
05182       }
05183       
05184       break;
05185 
05186    case EVENT_RESTART:
05187 
05188       if (!bc->dummy) {
05189          stop_bc_tones(ch);
05190          release_chan(bc);
05191       }
05192       break;
05193 
05194    default:
05195       chan_misdn_log(1, 0, "Got Unknown Event\n");
05196       break;
05197    }
05198    
05199    return RESPONSE_OK;
05200 }
05201 
05202 /** TE STUFF END **/
05203 
05204 /******************************************
05205  *
05206  *   Asterisk Channel Endpoint END
05207  *
05208  *
05209  *******************************************/
05210 
05211 
05212 
05213 static int unload_module(void)
05214 {
05215    /* First, take us out of the channel loop */
05216    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05217 
05218    misdn_tasks_destroy();
05219    
05220    if (!g_config_initialized)
05221       return 0;
05222    
05223    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05224    
05225    /* ast_unregister_application("misdn_crypt"); */
05226    ast_unregister_application("misdn_set_opt");
05227    ast_unregister_application("misdn_facility");
05228    ast_unregister_application("misdn_check_l2l1");
05229   
05230    ast_channel_unregister(&misdn_tech);
05231 
05232    free_robin_list();
05233    misdn_cfg_destroy();
05234    misdn_lib_destroy();
05235   
05236    if (misdn_debug)
05237       ast_free(misdn_debug);
05238    if (misdn_debug_only)
05239       ast_free(misdn_debug_only);
05240    ast_free(misdn_ports);
05241    
05242    return 0;
05243 }
05244 
05245 static int load_module(void)
05246 {
05247    int i, port;
05248    int ntflags = 0, ntkc = 0;
05249    char ports[256] = "";
05250    char tempbuf[BUFFERSIZE + 1];
05251    char ntfile[BUFFERSIZE + 1];
05252    struct misdn_lib_iface iface = {
05253       .cb_event = cb_events,
05254       .cb_log = chan_misdn_log,
05255       .cb_jb_empty = chan_misdn_jb_empty,
05256    };
05257 
05258    max_ports = misdn_lib_maxports_get();
05259    
05260    if (max_ports <= 0) {
05261       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05262       return AST_MODULE_LOAD_DECLINE;
05263    }
05264    
05265    if (misdn_cfg_init(max_ports, 0)) {
05266       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05267       return AST_MODULE_LOAD_DECLINE;
05268    }
05269    g_config_initialized = 1;
05270    
05271    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
05272    if (!misdn_debug) {
05273       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05274       return AST_MODULE_LOAD_DECLINE;
05275    }
05276    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
05277    if (!misdn_ports) {
05278       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05279       return AST_MODULE_LOAD_DECLINE;
05280    }
05281    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
05282    for (i = 1; i <= max_ports; i++) {
05283       misdn_debug[i] = misdn_debug[0];
05284       misdn_ports[i] = i;
05285    }
05286    *misdn_ports = 0;
05287    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
05288 
05289    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
05290    if (!ast_strlen_zero(tempbuf))
05291       tracing = 1;
05292 
05293    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05294    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05295 
05296    for (i = 1; i <= max_ports; i++) {
05297       misdn_in_calls[i] = 0;
05298       misdn_out_calls[i] = 0;
05299    }
05300 
05301    ast_mutex_init(&cl_te_lock);
05302    ast_mutex_init(&release_lock);
05303 
05304    misdn_cfg_update_ptp();
05305    misdn_cfg_get_ports_string(ports);
05306 
05307    if (!ast_strlen_zero(ports))
05308       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05309    if (misdn_lib_init(ports, &iface, NULL))
05310       chan_misdn_log(0, 0, "No te ports initialized\n");
05311 
05312    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
05313    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
05314    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
05315 
05316    misdn_lib_nt_keepcalls(ntkc);
05317    misdn_lib_nt_debug_init(ntflags, ntfile);
05318 
05319    if (ast_channel_register(&misdn_tech)) {
05320       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05321       unload_module();
05322       return AST_MODULE_LOAD_DECLINE;
05323    }
05324   
05325    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05326 
05327    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05328       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05329       "Sets mISDN opts. and optargs\n"
05330       "\n"
05331       "The available options are:\n"
05332       "    a - Have Asterisk detect DTMF tones on called channel\n"
05333       "    c - Make crypted outgoing call, optarg is keyindex\n"
05334       "    d - Send display text to called phone, text is the optarg\n"
05335       "    e - Perform echo cancelation on this channel,\n"
05336       "        takes taps as optarg (32,64,128,256)\n"
05337       "   e! - Disable echo cancelation on this channel\n"
05338       "    f - Enable fax detection\n"
05339       "    h - Make digital outgoing call\n"
05340       "   h1 - Make HDLC mode digital outgoing call\n"
05341       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05342       "        they will be transported inband.\n"
05343       "   jb - Set jitter buffer length, optarg is length\n"
05344       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05345       "   jn - Disable jitter buffer\n"
05346       "    n - Disable mISDN DSP on channel.\n"
05347       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05348       "    p - Caller ID presentation,\n"
05349       "        optarg is either 'allowed' or 'restricted'\n"
05350       "    s - Send Non-inband DTMF as inband\n"
05351       "   vr - Rx gain control, optarg is gain\n"
05352       "   vt - Tx gain control, optarg is gain\n"
05353       );
05354 
05355    
05356    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05357              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05358              "Sends the Facility Message FACILITY_TYPE with \n"
05359              "the given Arguments to the current ISDN Channel\n"
05360              "Supported Facilities are:\n"
05361              "\n"
05362              "type=calldeflect args=Nr where to deflect\n"
05363       );
05364 
05365 
05366    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05367              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05368              "Checks if the L2 and L1 are up on either the given <port> or\n"
05369              "on the ports in the group with <groupname>\n"
05370              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05371              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05372              "\n"
05373              "This application, ensures the L1/L2 state of the Ports in a group\n"
05374              "it is intended to make the pmp_l1_check option redundant and to\n"
05375              "fix a buggy switch config from your provider\n"
05376              "\n"
05377              "a sample dialplan would look like:\n\n"
05378              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05379              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05380              "\n"
05381       );
05382 
05383 
05384    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
05385 
05386    /* start the l1 watchers */
05387    
05388    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05389       int l1timeout;
05390       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05391       if (l1timeout) {
05392          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05393          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05394       }
05395    }
05396 
05397    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05398 
05399    return 0;
05400 }
05401 
05402 
05403 
05404 static int reload(void)
05405 {
05406    reload_config();
05407 
05408    return 0;
05409 }
05410 
05411 /*** SOME APPS ;)***/
05412 
05413 static int misdn_facility_exec(struct ast_channel *chan, void *data)
05414 {
05415    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05416    char *parse, *tok, *tokb;
05417 
05418    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05419    
05420    if (strcasecmp(chan->tech->type, "mISDN")) {
05421       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05422       return -1;
05423    }
05424    
05425    if (ast_strlen_zero((char *)data)) {
05426       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05427       return -1;
05428    }
05429 
05430    parse = ast_strdupa(data);
05431    tok = strtok_r(parse, "|", &tokb) ;
05432 
05433    if (!tok) {
05434       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05435       return -1;
05436    }
05437 
05438    if (!strcasecmp(tok, "calldeflect")) {
05439       tok = strtok_r(NULL, "|", &tokb) ;
05440       
05441       if (!tok) {
05442          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05443       }
05444 
05445       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05446          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05447          return 0; 
05448       }
05449       ch->bc->fac_out.Function = Fac_CD;
05450       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05451       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05452    } else {
05453       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05454    }
05455 
05456    return 0;
05457 }
05458 
05459 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
05460 {
05461    char *parse;
05462    char group[BUFFERSIZE + 1];
05463    char *port_str;
05464    int port = 0;
05465    int timeout;
05466    int dowait = 0;
05467    int port_up;
05468 
05469    AST_DECLARE_APP_ARGS(args,
05470          AST_APP_ARG(grouppar);
05471          AST_APP_ARG(timeout);
05472    );
05473 
05474    if (ast_strlen_zero((char *)data)) {
05475       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05476       return -1;
05477    }
05478 
05479    parse = ast_strdupa(data);
05480    AST_STANDARD_APP_ARGS(args, parse);
05481 
05482    if (args.argc != 2) {
05483       ast_log(LOG_WARNING, "Wrong argument count\n");
05484       return 0;
05485    }
05486 
05487    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05488    timeout = atoi(args.timeout);
05489    port_str = args.grouppar;
05490 
05491    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05492       /* We make a group call lets checkout which ports are in my group */
05493       port_str += 2;
05494       ast_copy_string(group, port_str, sizeof(group));
05495       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05496 
05497       for ( port = misdn_cfg_get_next_port(port); 
05498          port > 0;
05499          port = misdn_cfg_get_next_port(port)) {
05500          char cfg_group[BUFFERSIZE + 1];
05501 
05502          chan_misdn_log(2, 0, "trying port %d\n", port);
05503 
05504          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
05505 
05506          if (!strcasecmp(cfg_group, group)) {
05507             port_up = misdn_lib_port_up(port, 1);
05508 
05509             if (!port_up) {
05510                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05511                misdn_lib_get_port_up(port);
05512                dowait = 1;
05513             }
05514          }
05515       }
05516 
05517    } else {
05518       port = atoi(port_str);
05519       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05520       port_up = misdn_lib_port_up(port, 1);
05521       if (!port_up) {
05522          misdn_lib_get_port_up(port);
05523          dowait = 1;
05524       }
05525    }
05526 
05527    if (dowait) {
05528       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05529       ast_safe_sleep(chan, timeout * 1000);
05530    }
05531 
05532    return 0;
05533 }
05534 
05535 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
05536 {
05537    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05538    char *tok, *tokb, *parse;
05539    int  keyidx = 0;
05540    int rxgain = 0;
05541    int txgain = 0;
05542    int change_jitter = 0;
05543 
05544    if (strcasecmp(chan->tech->type, "mISDN")) {
05545       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05546       return -1;
05547    }
05548    
05549    if (ast_strlen_zero((char *)data)) {
05550       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05551       return -1;
05552    }
05553 
05554    parse = ast_strdupa(data);
05555    for (tok = strtok_r(parse, ":", &tokb);
05556         tok;
05557         tok = strtok_r(NULL, ":", &tokb) ) {
05558       int neglect = 0;
05559 
05560       if (tok[0] == '!' ) {
05561          neglect = 1;
05562          tok++;
05563       }
05564       
05565       switch(tok[0]) {
05566          
05567       case 'd' :
05568          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05569          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05570          break;
05571          
05572       case 'n':
05573          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05574          ch->bc->nodsp = 1;
05575          break;
05576 
05577       case 'j':
05578          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05579          tok++;
05580          change_jitter = 1;
05581 
05582          switch ( tok[0] ) {
05583          case 'b':
05584             ch->jb_len = atoi(++tok);
05585             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05586             break;
05587          case 't' :
05588             ch->jb_upper_threshold = atoi(++tok);
05589             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05590             break;
05591          case 'n':
05592             ch->bc->nojitter = 1;
05593             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05594             break;
05595          default:
05596             ch->jb_len = 4000;
05597             ch->jb_upper_threshold = 0;
05598             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05599             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05600          }
05601          break;
05602       case 'v':
05603          tok++;
05604 
05605          switch (tok[0]) {
05606          case 'r' :
05607             rxgain = atoi(++tok);
05608             if (rxgain < -8)
05609                rxgain = -8;
05610             if (rxgain > 8)
05611                rxgain = 8;
05612             ch->bc->rxgain = rxgain;
05613             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05614             break;
05615          case 't':
05616             txgain = atoi(++tok);
05617             if (txgain < -8)
05618                txgain = -8;
05619             if (txgain > 8)
05620                txgain = 8;
05621             ch->bc->txgain = txgain;
05622             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05623             break;
05624          }
05625          break;
05626       
05627       case 'c':
05628          keyidx = atoi(++tok);
05629          {
05630             char keys[4096];
05631             char *key = NULL, *tmp = keys;
05632             int i;
05633             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05634 
05635             for (i = 0; i < keyidx; i++) {
05636                key = strsep(&tmp, ",");
05637             }
05638 
05639             if (key) {
05640                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05641             }
05642 
05643             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05644             break;
05645          }
05646       case 'e':
05647          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05648          
05649          if (neglect) {
05650             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05651 #ifdef MISDN_1_2
05652             *ch->bc->pipeline = 0;
05653 #else
05654             ch->bc->ec_enable = 0;
05655 #endif
05656          } else {
05657 #ifdef MISDN_1_2
05658             update_pipeline_config(ch->bc);
05659 #else
05660             ch->bc->ec_enable = 1;
05661             ch->bc->orig = ch->originator;
05662             tok++;
05663             if (*tok) {
05664                ch->bc->ec_deftaps = atoi(tok);
05665             }
05666 #endif
05667          }
05668          
05669          break;
05670       case 'h':
05671          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05672          
05673          if (strlen(tok) > 1 && tok[1] == '1') {
05674             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05675             if (!ch->bc->hdlc) {
05676                ch->bc->hdlc = 1;
05677             }
05678          }
05679          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05680          break;
05681             
05682       case 's':
05683          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05684          ch->bc->send_dtmf = 1;
05685          break;
05686          
05687       case 'f':
05688          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05689          ch->faxdetect = 1;
05690          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05691          break;
05692 
05693       case 'a':
05694          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05695          ch->ast_dsp = 1;
05696          break;
05697 
05698       case 'p':
05699          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05700          /* CRICH: callingpres!!! */
05701          if (strstr(tok,"allowed")) {
05702             ch->bc->pres = 0;
05703          } else if (strstr(tok, "not_screened")) {
05704             ch->bc->pres = 1;
05705          }
05706          break;
05707       case 'i' :
05708          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05709          ch->ignore_dtmf=1;
05710          break;
05711       default:
05712          break;
05713       }
05714    }
05715 
05716    if (change_jitter)
05717       config_jitterbuffer(ch);
05718 
05719    if (ch->faxdetect || ch->ast_dsp) {
05720       if (!ch->dsp)
05721          ch->dsp = ast_dsp_new();
05722       if (ch->dsp)
05723          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
05724       if (!ch->trans)
05725          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05726    }
05727 
05728    if (ch->ast_dsp) {
05729       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05730       ch->bc->nodsp = 1;
05731    }
05732    
05733    return 0;
05734 }
05735 
05736 
05737 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len) 
05738 {
05739    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05740    
05741    if (ch && ch->jb) {
05742       return misdn_jb_empty(ch->jb, buf, len);
05743    }
05744    
05745    return -1;
05746 }
05747 
05748 
05749 
05750 /*******************************************************/
05751 /***************** JITTERBUFFER ************************/
05752 /*******************************************************/
05753 
05754 
05755 /* allocates the jb-structure and initialize the elements*/
05756 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
05757 {
05758    int i;
05759    struct misdn_jb *jb;
05760 
05761    jb = ast_malloc(sizeof(*jb));
05762    if (!jb) {
05763        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05764        return NULL;
05765    }
05766    jb->size = size;
05767    jb->upper_threshold = upper_threshold;
05768    jb->wp = 0;
05769    jb->rp = 0;
05770    jb->state_full = 0;
05771    jb->state_empty = 0;
05772    jb->bytes_wrote = 0;
05773    jb->samples = ast_malloc(size * sizeof(char));
05774 
05775    if (!jb->samples) {
05776       ast_free(jb);
05777       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05778       return NULL;
05779    }
05780    
05781    jb->ok = ast_malloc(size * sizeof(char));
05782 
05783    if (!jb->ok) {
05784       ast_free(jb->samples);
05785       ast_free(jb);
05786       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05787       return NULL;
05788    }
05789 
05790    for (i = 0; i < size; i++)
05791       jb->ok[i] = 0;
05792 
05793    ast_mutex_init(&jb->mutexjb);
05794 
05795    return jb;
05796 }
05797 
05798 /* frees the data and destroys the given jitterbuffer struct */
05799 void misdn_jb_destroy(struct misdn_jb *jb)
05800 {
05801    ast_mutex_destroy(&jb->mutexjb);
05802    
05803    ast_free(jb->ok);
05804    ast_free(jb->samples);
05805    ast_free(jb);
05806 }
05807 
05808 /* fills the jitterbuffer with len data returns < 0 if there was an
05809    error (buffer overflow). */
05810 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
05811 {
05812    int i, j, rp, wp;
05813 
05814    if (!jb || ! data)
05815       return 0;
05816 
05817    ast_mutex_lock(&jb->mutexjb);
05818    
05819    wp = jb->wp;
05820    rp = jb->rp;
05821    
05822    for (i = 0; i < len; i++) {
05823       jb->samples[wp] = data[i];
05824       jb->ok[wp] = 1;
05825       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05826 
05827       if (wp == jb->rp)
05828          jb->state_full = 1;
05829    }
05830 
05831    if (wp >= rp)
05832       jb->state_buffer = wp - rp;
05833    else
05834       jb->state_buffer = jb->size - rp + wp;
05835    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05836 
05837    if (jb->state_full) {
05838       jb->wp = wp;
05839 
05840       rp = wp;
05841       for (j = 0; j < jb->upper_threshold; j++)
05842          rp = rp != 0 ? rp - 1 : jb->size - 1;
05843       jb->rp = rp;
05844       jb->state_full = 0;
05845       jb->state_empty = 1;
05846 
05847       ast_mutex_unlock(&jb->mutexjb);
05848 
05849       return -1;
05850    }
05851 
05852    if (!jb->state_empty) {
05853       jb->bytes_wrote += len;
05854       if (jb->bytes_wrote >= jb->upper_threshold) {
05855          jb->state_empty = 1;
05856          jb->bytes_wrote = 0;
05857       }
05858    }
05859    jb->wp = wp;
05860 
05861    ast_mutex_unlock(&jb->mutexjb);
05862    
05863    return 0;
05864 }
05865 
05866 /* gets len bytes out of the jitterbuffer if available, else only the
05867 available data is returned and the return value indicates the number
05868 of data. */
05869 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
05870 {
05871    int i, wp, rp, read = 0;
05872 
05873    ast_mutex_lock(&jb->mutexjb);
05874 
05875    rp = jb->rp;
05876    wp = jb->wp;
05877 
05878    if (jb->state_empty) {  
05879       for (i = 0; i < len; i++) {
05880          if (wp == rp) {
05881             jb->rp = rp;
05882             jb->state_empty = 0;
05883 
05884             ast_mutex_unlock(&jb->mutexjb);
05885 
05886             return read;
05887          } else {
05888             if (jb->ok[rp] == 1) {
05889                data[i] = jb->samples[rp];
05890                jb->ok[rp] = 0;
05891                rp = (rp != jb->size - 1) ? rp + 1 : 0;
05892                read += 1;
05893             }
05894          }
05895       }
05896 
05897       if (wp >= rp)
05898          jb->state_buffer = wp - rp;
05899       else
05900          jb->state_buffer = jb->size - rp + wp;
05901       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05902 
05903       jb->rp = rp;
05904    } else
05905       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05906 
05907    ast_mutex_unlock(&jb->mutexjb);
05908 
05909    return read;
05910 }
05911 
05912 
05913 
05914 
05915 /*******************************************************/
05916 /*************** JITTERBUFFER  END *********************/
05917 /*******************************************************/
05918 
05919 
05920 
05921 
05922 static void chan_misdn_log(int level, int port, char *tmpl, ...)
05923 {
05924    va_list ap;
05925    char buf[1024];
05926    char port_buf[8];
05927 
05928    if (! ((0 <= port) && (port <= max_ports))) {
05929       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05930       port = 0;
05931       level = -1;
05932    }
05933 
05934    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05935 
05936    va_start(ap, tmpl);
05937    vsnprintf(buf, sizeof(buf), tmpl, ap);
05938    va_end(ap);
05939 
05940    if (level == -1)
05941       ast_log(LOG_WARNING, "%s", buf);
05942 
05943    else if (misdn_debug_only[port] ? 
05944          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
05945        : level <= misdn_debug[port]) {
05946       
05947       ast_console_puts(port_buf);
05948       ast_console_puts(buf);
05949    }
05950    
05951    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05952       char ctimebuf[30];
05953       time_t tm = time(NULL);
05954       char *tmp = ctime_r(&tm, ctimebuf), *p;
05955 
05956       FILE *fp = fopen(global_tracefile, "a+");
05957 
05958       p = strchr(tmp, '\n');
05959       if (p)
05960          *p = ':';
05961       
05962       if (!fp) {
05963          ast_console_puts("Error opening Tracefile: [ ");
05964          ast_console_puts(global_tracefile);
05965          ast_console_puts(" ] ");
05966          
05967          ast_console_puts(strerror(errno));
05968          ast_console_puts("\n");
05969          return ;
05970       }
05971       
05972       fputs(tmp, fp);
05973       fputs(" ", fp);
05974       fputs(port_buf, fp);
05975       fputs(" ", fp);
05976       fputs(buf, fp);
05977 
05978       fclose(fp);
05979    }
05980 }
05981 
05982 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
05983    .load = load_module,
05984    .unload = unload_module,
05985    .reload = reload,
05986 );

Generated on Thu Jul 9 13:40:28 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7