Tue Aug 24 2010 19:41:28

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