Thu Apr 28 2011 16:56:43

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: 284593 $")
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    int len, t;
03037    struct pollfd pfd = { .fd = -1, .events = POLLIN };
03038 
03039    if (!ast) {
03040       chan_misdn_log(1, 0, "misdn_read called without ast\n");
03041       return NULL;
03042    }
03043    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
03044       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
03045       return NULL;
03046    }
03047 
03048    if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
03049       chan_misdn_log(1, 0, "misdn_read called without bc\n");
03050       return NULL;
03051    }
03052 
03053    pfd.fd = tmp->pipe[0];
03054    t = ast_poll(&pfd, 1, 20);
03055 
03056    if (t < 0) {
03057       chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
03058       return NULL;
03059    }
03060 
03061    if (!t) {
03062       chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
03063       len = 160;
03064    } else if (pfd.revents & POLLIN) {
03065       len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
03066 
03067       if (len <= 0) {
03068          /* we hangup here, since our pipe is closed */
03069          chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
03070          return NULL;
03071       }
03072 
03073    } else {
03074       return NULL;
03075    }
03076 
03077    tmp->frame.frametype = AST_FRAME_VOICE;
03078    tmp->frame.subclass = AST_FORMAT_ALAW;
03079    tmp->frame.datalen = len;
03080    tmp->frame.samples = len;
03081    tmp->frame.mallocd = 0;
03082    tmp->frame.offset = 0;
03083    tmp->frame.delivery = ast_tv(0, 0);
03084    tmp->frame.src = NULL;
03085    tmp->frame.data.ptr = tmp->ast_rd_buf;
03086 
03087    if (tmp->faxdetect && !tmp->faxhandled) {
03088       if (tmp->faxdetect_timeout) {
03089          if (ast_tvzero(tmp->faxdetect_tv)) {
03090             tmp->faxdetect_tv = ast_tvnow();
03091             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
03092             return process_ast_dsp(tmp, &tmp->frame);
03093          } else {
03094             struct timeval tv_now = ast_tvnow();
03095             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
03096             if (diff <= (tmp->faxdetect_timeout * 1000)) {
03097                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
03098                return process_ast_dsp(tmp, &tmp->frame);
03099             } else {
03100                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
03101                tmp->faxdetect = 0;
03102                return &tmp->frame;
03103             }
03104          }
03105       } else {
03106          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
03107          return process_ast_dsp(tmp, &tmp->frame);
03108       }
03109    } else {
03110       if (tmp->ast_dsp) {
03111          return process_ast_dsp(tmp, &tmp->frame);
03112       } else {
03113          return &tmp->frame;
03114       }
03115    }
03116 }
03117 
03118 
03119 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
03120 {
03121    struct chan_list *ch;
03122    int i  = 0;
03123    
03124    if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
03125       return -1;
03126    }
03127 
03128    if (ch->hold.state != MISDN_HOLD_IDLE) {
03129       chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
03130       return 0;
03131    }
03132    
03133    if (!ch->bc ) {
03134       ast_log(LOG_WARNING, "private but no bc\n");
03135       return -1;
03136    }
03137    
03138    if (ch->notxtone) {
03139       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
03140       return 0;
03141    }
03142 
03143 
03144    if (!frame->subclass) {
03145       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
03146       return 0;
03147    }
03148    
03149    if (!(frame->subclass & prefformat)) {
03150       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
03151       return 0;
03152    }
03153    
03154 
03155    if (!frame->samples ) {
03156       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
03157       
03158       if (!strcmp(frame->src,"ast_prod")) {
03159          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
03160 
03161          if (ch->ts) {
03162             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
03163             misdn_lib_tone_generator_start(ch->bc);
03164          }
03165          return 0;
03166       }
03167 
03168       return -1;
03169    }
03170 
03171    if (!ch->bc->addr) {
03172       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
03173       return 0;
03174    }
03175    
03176 #ifdef MISDN_DEBUG
03177    {
03178       int i, max = 5 > frame->samples ? frame->samples : 5;
03179 
03180       ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
03181 
03182       for (i = 0; i < max; i++) {
03183          ast_debug(1, "%2.2x ", ((char *) frame->data.ptr)[i]);
03184       }
03185    }
03186 #endif
03187 
03188    switch (ch->bc->bc_state) {
03189    case BCHAN_ACTIVATED:
03190    case BCHAN_BRIDGED:
03191       break;
03192    default:
03193       if (!ch->dropped_frame_cnt) {
03194          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);
03195       }
03196       
03197       if (++ch->dropped_frame_cnt > 100) {
03198          ch->dropped_frame_cnt = 0;
03199          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);
03200       }
03201 
03202       return 0;
03203    }
03204 
03205    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
03206    if (!ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability)) {
03207       /* Buffered Transmit (triggered by read from isdn side)*/
03208       if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
03209          if (ch->bc->active) {
03210             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
03211          }
03212       }
03213       
03214    } else {
03215       /*transmit without jitterbuffer*/
03216       i = misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
03217    }
03218 
03219    return 0;
03220 }
03221 
03222 
03223 
03224 
03225 static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
03226                   struct ast_channel *c1, int flags,
03227                   struct ast_frame **fo,
03228                   struct ast_channel **rc,
03229                   int timeoutms)
03230 
03231 {
03232    struct chan_list *ch1, *ch2;
03233    struct ast_channel *carr[2], *who;
03234    int to = -1;
03235    struct ast_frame *f;
03236    int p1_b, p2_b;
03237    int bridging;
03238   
03239    ch1 = get_chan_by_ast(c0);
03240    ch2 = get_chan_by_ast(c1);
03241 
03242    carr[0] = c0;
03243    carr[1] = c1;
03244   
03245    if (!(ch1 && ch2)) {
03246       return -1;
03247    }
03248 
03249    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
03250    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
03251 
03252    if (! p1_b || ! p2_b) {
03253       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03254       return AST_BRIDGE_FAILED;
03255    }
03256 
03257    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03258    if (bridging) {
03259       /* trying to make a mISDN_dsp conference */
03260       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03261       misdn_lib_bridge(ch1->bc, ch2->bc);
03262    }
03263 
03264    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03265 
03266    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03267  
03268    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) ) {
03269       ch1->ignore_dtmf = 1;
03270    }
03271 
03272    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) ) {
03273       ch2->ignore_dtmf = 1;
03274    }
03275 
03276    for (;/*ever*/;) {
03277       to = -1;
03278       who = ast_waitfor_n(carr, 2, &to);
03279 
03280       if (!who) {
03281          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03282          break;
03283       }
03284       f = ast_read(who);
03285 
03286       if (!f || f->frametype == AST_FRAME_CONTROL) {
03287          /* got hangup .. */
03288 
03289          if (!f) 
03290             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03291          else
03292             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03293 
03294          *fo = f;
03295          *rc = who;
03296          break;
03297       }
03298       
03299       if ( f->frametype == AST_FRAME_DTMF ) {
03300          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03301 
03302          *fo = f;
03303          *rc = who;
03304          break;
03305       }
03306    
03307 #if 0
03308       if (f->frametype == AST_FRAME_VOICE) {
03309          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03310    
03311          continue;
03312       }
03313 #endif
03314 
03315       ast_write(who == c0 ? c1 : c0, f);
03316    }
03317 
03318    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03319 
03320    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03321 
03322    return AST_BRIDGE_COMPLETE;
03323 }
03324 
03325 /** AST INDICATIONS END **/
03326 
03327 static int dialtone_indicate(struct chan_list *cl)
03328 {
03329    struct ast_channel *ast = cl->ast;
03330    int nd = 0;
03331 
03332    if (!ast) {
03333       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03334       return -1;
03335    }
03336 
03337    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03338 
03339    if (nd) {
03340       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03341       return 0;
03342    }
03343    
03344    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03345 
03346    cl->ts = ast_get_indication_tone(ast->zone, "dial");
03347    
03348    if (cl->ts) {
03349       cl->notxtone = 0;
03350       cl->norxtone = 0;
03351       /* This prods us in misdn_write */
03352       ast_playtones_start(ast, 0, cl->ts->data, 0);
03353    }
03354 
03355    return 0;
03356 }
03357 
03358 static void hanguptone_indicate(struct chan_list *cl)
03359 {
03360    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03361 }
03362 
03363 static int stop_indicate(struct chan_list *cl)
03364 {
03365    struct ast_channel *ast = cl->ast;
03366 
03367    if (!ast) {
03368       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03369       return -1;
03370    }
03371 
03372    chan_misdn_log(3, cl->bc->port, " --> None\n");
03373    misdn_lib_tone_generator_stop(cl->bc);
03374    ast_playtones_stop(ast);
03375 
03376    if (cl->ts) {
03377       cl->ts = ast_tone_zone_sound_unref(cl->ts);
03378    }
03379 
03380    return 0;
03381 }
03382 
03383 
03384 static int start_bc_tones(struct chan_list* cl)
03385 {
03386    misdn_lib_tone_generator_stop(cl->bc);
03387    cl->notxtone = 0;
03388    cl->norxtone = 0;
03389    return 0;
03390 }
03391 
03392 static int stop_bc_tones(struct chan_list *cl)
03393 {
03394    if (!cl) {
03395       return -1;
03396    }
03397 
03398    cl->notxtone = 1;
03399    cl->norxtone = 1;
03400    
03401    return 0;
03402 }
03403 
03404 
03405 static struct chan_list *init_chan_list(int orig)
03406 {
03407    struct chan_list *cl;
03408 
03409    if (!(cl = ast_calloc(1, sizeof(*cl)))) {
03410       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03411       return NULL;
03412    }
03413    
03414    cl->originator = orig;
03415    cl->need_queue_hangup = 1;
03416    cl->need_hangup = 1;
03417    cl->need_busy = 1;
03418    cl->overlap_dial_task = -1;
03419 
03420    return cl;
03421 }
03422 
03423 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
03424 {
03425    struct ast_channel *tmp = NULL;
03426    char group[BUFFERSIZE + 1] = "";
03427    char dial_str[128];
03428    char *buf2 = ast_strdupa(data);
03429    char *ext;
03430    char *port_str;
03431    char *p = NULL;
03432    int channel = 0;
03433    int port = 0;
03434    struct misdn_bchannel *newbc = NULL;
03435    int dec = 0;
03436    struct chan_list *cl;
03437 
03438    snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
03439 
03440    /*
03441     * data is ---v
03442     * Dial(mISDN/g:group_name[/extension[/options]])
03443     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
03444     *
03445     * The dial extension could be empty if you are using MISDN_KEYPAD
03446     * to control ISDN provider features.
03447     */
03448    port_str = strsep(&buf2, "/");
03449    if (!ast_strlen_zero(port_str)) {
03450       if (port_str[0] == 'g' && port_str[1] == ':' ) {
03451          /* We make a group call lets checkout which ports are in my group */
03452          port_str += 2;
03453          ast_copy_string(group, port_str, sizeof(group));
03454          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03455       } else if ((p = strchr(port_str, ':'))) {
03456          /* we have a preselected channel */
03457          *p = 0;
03458          channel = atoi(++p);
03459          port = atoi(port_str);
03460          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03461       } else {
03462          port = atoi(port_str);
03463       }
03464    } else {
03465       ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
03466       return NULL;
03467    }
03468 
03469    ext = strsep(&buf2, "/");
03470    if (!ext) {
03471       ext = "";
03472    }
03473 
03474    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03475       chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
03476       dec = 1;
03477    }
03478 
03479    if (!ast_strlen_zero(group)) {
03480       char cfg_group[BUFFERSIZE + 1];
03481       struct robin_list *rr = NULL;
03482 
03483       /* Group dial */
03484 
03485       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03486          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03487          rr = get_robin_position(group);
03488       }
03489 
03490       if (rr) {
03491          int robin_channel = rr->channel;
03492          int port_start;
03493          int next_chan = 1;
03494 
03495          do {
03496             port_start = 0;
03497             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
03498                 port = misdn_cfg_get_next_port_spin(port)) {
03499 
03500                if (!port_start) {
03501                   port_start = port;
03502                }
03503 
03504                if (port >= port_start) {
03505                   next_chan = 1;
03506                }
03507                
03508                if (port <= port_start && next_chan) {
03509                   int maxbchans=misdn_lib_get_maxchans(port);
03510                   if (++robin_channel >= maxbchans) {
03511                      robin_channel = 1;
03512                   }
03513                   next_chan = 0;
03514                }
03515 
03516                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03517 
03518                if (!strcasecmp(cfg_group, group)) {
03519                   int port_up;
03520                   int check;
03521                   misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03522                   port_up = misdn_lib_port_up(port, check);
03523 
03524                   if (check && !port_up) {
03525                      chan_misdn_log(1, port, "L1 is not Up on this Port\n");
03526                   }
03527                   
03528                   if (check && port_up < 0) {
03529                      ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
03530                   }
03531 
03532                   if (port_up > 0)  {
03533                      newbc = misdn_lib_get_free_bc(port, robin_channel, 0, 0);
03534                      if (newbc) {
03535                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03536                         if (port_up) {
03537                            chan_misdn_log(4, port, "portup:%d\n",  port_up);
03538                         }
03539                         rr->port = newbc->port;
03540                         rr->channel = newbc->channel;
03541                         break;
03542                      }
03543                   }
03544                }
03545             }
03546          } while (!newbc && robin_channel != rr->channel);
03547       } else {    
03548          for (port = misdn_cfg_get_next_port(0); port > 0;
03549              port = misdn_cfg_get_next_port(port)) {
03550 
03551             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03552 
03553             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03554             if (!strcasecmp(cfg_group, group)) {
03555                int port_up;
03556                int check;
03557                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03558                port_up = misdn_lib_port_up(port, check);
03559 
03560                chan_misdn_log(4, port, "portup:%d\n", port_up);
03561 
03562                if (port_up > 0) {
03563                   if ((newbc = misdn_lib_get_free_bc(port, 0, 0, dec))) {
03564                      break;
03565                   }
03566                }
03567             }
03568          }
03569       }
03570       
03571       /* Group dial failed ?*/
03572       if (!newbc) {
03573          ast_log(LOG_WARNING, 
03574                "Could not Dial out on group '%s'.\n"
03575                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03576                "\tOr there was no free channel on none of the ports\n\n"
03577                , group);
03578          return NULL;
03579       }
03580    } else {
03581       /* 'Normal' Port dial * Port dial */
03582       if (channel) {
03583          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03584       }
03585       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03586 
03587       if (!newbc) {
03588          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03589          return NULL;
03590       }
03591    }
03592    
03593 
03594    /* create ast_channel and link all the objects together */
03595    cl = init_chan_list(ORG_AST);
03596    if (!cl) {
03597       ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
03598       return NULL;
03599    }
03600    cl->bc = newbc;
03601    
03602    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03603    if (!tmp) {
03604       ast_free(cl);
03605       ast_log(LOG_ERROR, "Could not create Asterisk object\n");
03606       return NULL;
03607    }
03608 
03609    cl->ast = tmp;
03610    
03611    /* register chan in local list */
03612    cl_queue_chan(&cl_te, cl);
03613    
03614    /* fill in the config into the objects */
03615    read_config(cl, ORG_AST);
03616 
03617    /* important */
03618    cl->need_hangup = 0;
03619    
03620    return tmp;
03621 }
03622 
03623 
03624 static int misdn_send_text(struct ast_channel *chan, const char *text)
03625 {
03626    struct chan_list *tmp = chan->tech_pvt;
03627    
03628    if (tmp && tmp->bc) {
03629       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03630       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03631    } else {
03632       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03633       return -1;
03634    }
03635    
03636    return 0;
03637 }
03638 
03639 static struct ast_channel_tech misdn_tech = {
03640    .type = "mISDN",
03641    .description = "Channel driver for mISDN Support (Bri/Pri)",
03642    .capabilities = AST_FORMAT_ALAW ,
03643    .requester = misdn_request,
03644    .send_digit_begin = misdn_digit_begin,
03645    .send_digit_end = misdn_digit_end,
03646    .call = misdn_call,
03647    .bridge = misdn_bridge, 
03648    .hangup = misdn_hangup,
03649    .answer = misdn_answer,
03650    .read = misdn_read,
03651    .write = misdn_write,
03652    .indicate = misdn_indication,
03653    .fixup = misdn_fixup,
03654    .send_text = misdn_send_text,
03655    .properties = 0,
03656 };
03657 
03658 static struct ast_channel_tech misdn_tech_wo_bridge = {
03659    .type = "mISDN",
03660    .description = "Channel driver for mISDN Support (Bri/Pri)",
03661    .capabilities = AST_FORMAT_ALAW ,
03662    .requester = misdn_request,
03663    .send_digit_begin = misdn_digit_begin,
03664    .send_digit_end = misdn_digit_end,
03665    .call = misdn_call,
03666    .hangup = misdn_hangup,
03667    .answer = misdn_answer,
03668    .read = misdn_read,
03669    .write = misdn_write,
03670    .indicate = misdn_indication,
03671    .fixup = misdn_fixup,
03672    .send_text = misdn_send_text,
03673    .properties = 0,
03674 };
03675 
03676 
03677 static int glob_channel = 0;
03678 
03679 static void update_name(struct ast_channel *tmp, int port, int c) 
03680 {
03681    int chan_offset = 0;
03682    int tmp_port = misdn_cfg_get_next_port(0);
03683    char newname[255];
03684    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03685       if (tmp_port == port) {
03686          break;
03687       }
03688       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03689    }
03690    if (c < 0) {
03691       c = 0;
03692    }
03693 
03694    snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
03695    if (strncmp(tmp->name, newname, strlen(newname))) {
03696       snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03697       ast_change_name(tmp, newname);
03698       chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03699    }
03700 }
03701 
03702 static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char *exten, char *callerid, int format, int port, int c)
03703 {
03704    struct ast_channel *tmp;
03705    char *cid_name = 0, *cid_num = 0;
03706    int chan_offset = 0;
03707    int tmp_port = misdn_cfg_get_next_port(0);
03708    int bridging;
03709 
03710    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03711       if (tmp_port == port) {
03712          break;
03713       }
03714       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03715    }
03716    if (c < 0) {
03717       c = 0;
03718    }
03719 
03720    if (callerid) {
03721       ast_callerid_parse(callerid, &cid_name, &cid_num);
03722    }
03723 
03724    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++);
03725    if (tmp) {
03726       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03727 
03728       tmp->nativeformats = prefformat;
03729 
03730       tmp->readformat = format;
03731       tmp->rawreadformat = format;
03732       tmp->writeformat = format;
03733       tmp->rawwriteformat = format;
03734     
03735       tmp->tech_pvt = chlist;
03736 
03737       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03738 
03739       tmp->tech = bridging ? &misdn_tech : &misdn_tech_wo_bridge;
03740 
03741       tmp->writeformat = format;
03742       tmp->readformat = format;
03743       tmp->priority = 1;
03744 
03745       if (exten) {
03746          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03747       } else {
03748          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03749       }
03750 
03751       if (callerid) {
03752          /* Don't use ast_set_callerid() here because it will
03753           * generate a needless NewCallerID event */
03754          tmp->cid.cid_ani = ast_strdup(cid_num);
03755       }
03756 
03757       if (pipe(chlist->pipe) < 0) {
03758          ast_log(LOG_ERROR, "Pipe failed\n");
03759       }
03760       ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
03761 
03762       tmp->rings = (state == AST_STATE_RING) ? 1 : 0;
03763 
03764       ast_jb_configure(tmp, misdn_get_global_jbconf());
03765    } else {
03766       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03767    }
03768    
03769    return tmp;
03770 }
03771 
03772 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
03773 {
03774    struct chan_list *help = list;
03775    for (; help; help = help->next) {
03776       if (help->bc == bc) {
03777          return help;
03778       }
03779    }
03780 
03781    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03782 
03783    return NULL;
03784 }
03785 
03786 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
03787 {
03788    struct chan_list *help = list;
03789    for (; help; help = help->next) {
03790       if (help->bc && (help->bc->pid == pid)) {
03791          return help;
03792       }
03793    }
03794 
03795    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03796 
03797    return NULL;
03798 }
03799 
03800 static struct chan_list *find_hold_call(struct chan_list *list, struct misdn_bchannel *bc)
03801 {
03802    struct chan_list *help = list;
03803 
03804    if (bc->pri) {
03805       return NULL;
03806    }
03807 
03808    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03809    for (;help; help = help->next) {
03810       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
03811       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
03812          return help;
03813       }
03814    }
03815    chan_misdn_log(6, bc->port, "$$$ find_hold_call: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03816 
03817    return NULL;
03818 }
03819 
03820 
03821 static struct chan_list *find_hold_call_l3(struct chan_list *list, unsigned long l3_id)
03822 {
03823    struct chan_list *help = list;
03824 
03825    for (; help; help = help->next) {
03826       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
03827          return help;
03828       }
03829    }
03830 
03831    return NULL;
03832 }
03833 
03834 #define TRANSFER_ON_HELD_CALL_HANGUP 1
03835 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
03836 /*!
03837  * \internal
03838  * \brief Find a suitable active call to go with a held call so we could try a transfer.
03839  *
03840  * \param list Channel list.
03841  * \param bc B channel record.
03842  *
03843  * \return Found call record or NULL.
03844  *
03845  * \note There could be a possibility where we find the wrong active call to transfer.
03846  * This concern is mitigated by the fact that there could be at most one other call
03847  * on a PTMP BRI link to another device.  Maybe the l3_id could help in locating an
03848  * active call on the same TEI?
03849  */
03850 static struct chan_list *find_hold_active_call(struct chan_list *list, struct misdn_bchannel *bc)
03851 {
03852    for (; list; list = list->next) {
03853       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
03854          && list->ast) {
03855          switch (list->state) {
03856          case MISDN_PROCEEDING:
03857          case MISDN_PROGRESS:
03858          case MISDN_ALERTING:
03859          case MISDN_CONNECTED:
03860             return list;
03861          default:
03862             break;
03863          }
03864       }
03865    }
03866    return NULL;
03867 }
03868 #endif   /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
03869 
03870 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
03871 {
03872    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03873   
03874    ast_mutex_lock(&cl_te_lock);
03875    if (!*list) {
03876       *list = chan;
03877    } else {
03878       struct chan_list *help = *list;
03879       for (; help->next; help = help->next); 
03880       help->next = chan;
03881    }
03882    chan->next = NULL;
03883    ast_mutex_unlock(&cl_te_lock);
03884 }
03885 
03886 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
03887 {
03888    struct chan_list *help;
03889 
03890    if (chan->dsp) {
03891       ast_dsp_free(chan->dsp);
03892    }
03893 
03894    ast_mutex_lock(&cl_te_lock);
03895    if (!*list) {
03896       ast_mutex_unlock(&cl_te_lock);
03897       return;
03898    }
03899   
03900    if (*list == chan) {
03901       *list = (*list)->next;
03902       ast_mutex_unlock(&cl_te_lock);
03903       return;
03904    }
03905   
03906    for (help = *list; help->next; help = help->next) {
03907       if (help->next == chan) {
03908          help->next = help->next->next;
03909          ast_mutex_unlock(&cl_te_lock);
03910          return;
03911       }
03912    }
03913    
03914    ast_mutex_unlock(&cl_te_lock);
03915 }
03916 
03917 /** Channel Queue End **/
03918 
03919 
03920 static int pbx_start_chan(struct chan_list *ch)
03921 {
03922    int ret = ast_pbx_start(ch->ast);   
03923 
03924    ch->need_hangup = (ret >= 0) ? 0 : 1;
03925 
03926    return ret;
03927 }
03928 
03929 static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
03930 {
03931    int port;
03932 
03933    if (!ch) {
03934       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03935       return;
03936    }
03937 
03938    port = bc->port;
03939    cb_log(5, port, "hangup_chan called\n");
03940 
03941    if (ch->need_hangup) {
03942       cb_log(2, port, " --> hangup\n");
03943       ch->need_hangup = 0;
03944       ch->need_queue_hangup = 0;
03945       if (ch->ast) {
03946          send_cause2ast(ch->ast, bc, ch);
03947          ast_hangup(ch->ast);
03948       }
03949       return;
03950    }
03951 
03952    if (!ch->need_queue_hangup) {
03953       cb_log(2, port, " --> No need to queue hangup\n");
03954    }
03955 
03956    ch->need_queue_hangup = 0;
03957    if (ch->ast) {
03958       send_cause2ast(ch->ast, bc, ch);
03959       ast_queue_hangup_with_cause(ch->ast, bc->cause);
03960       cb_log(2, port, " --> queue_hangup\n");
03961    } else {
03962       cb_log(1, port, "Cannot hangup chan, no ast\n");
03963    }
03964 }
03965 
03966 /*!
03967  * \internal
03968  * \brief ISDN asked us to release channel, pendant to misdn_hangup.
03969  *
03970  * \param ch Call channel record to release.
03971  * \param bc Current B channel record associated with ch.
03972  *
03973  * \return Nothing
03974  *
03975  * \note ch must not be referenced after calling.
03976  */
03977 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
03978 {
03979    struct ast_channel *ast;
03980 
03981    ch->state = MISDN_CLEANING;
03982 
03983    ast_mutex_lock(&release_lock);
03984 
03985    cl_dequeue_chan(&cl_te, ch);
03986 
03987    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
03988 
03989    /* releasing jitterbuffer */
03990    if (ch->jb) {
03991       misdn_jb_destroy(ch->jb);
03992       ch->jb = NULL;
03993    } else {
03994       if (!bc->nojitter) {
03995          chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03996       }
03997    }
03998 
03999    if (ch->overlap_dial) {
04000       if (ch->overlap_dial_task != -1) {
04001          misdn_tasks_remove(ch->overlap_dial_task);
04002          ch->overlap_dial_task = -1;
04003       }
04004       ast_mutex_destroy(&ch->overlap_tv_lock);
04005    }
04006 
04007    if (ch->originator == ORG_AST) {
04008       --misdn_out_calls[bc->port];
04009    } else {
04010       --misdn_in_calls[bc->port];
04011    }
04012 
04013    close(ch->pipe[0]);
04014    close(ch->pipe[1]);
04015 
04016    ast = ch->ast;
04017    if (ast) {
04018       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
04019       chan_misdn_log(1, bc->port,
04020          "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s\n",
04021          bc->pid,
04022          ast->context,
04023          ast->exten,
04024          ast->cid.cid_num);
04025 
04026       if (ast->_state != AST_STATE_RESERVED) {
04027          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
04028          ast_setstate(ast, AST_STATE_DOWN);
04029       }
04030    }
04031 
04032    ast_free(ch);
04033 
04034    ast_mutex_unlock(&release_lock);
04035 }
04036 
04037 /*!
04038  * \internal
04039  * \brief Do everything in release_chan() that makes sense without a bc.
04040  *
04041  * \param ch Call channel record to release.
04042  *
04043  * \return Nothing
04044  *
04045  * \note ch must not be referenced after calling.
04046  */
04047 static void release_chan_early(struct chan_list *ch)
04048 {
04049    struct ast_channel *ast;
04050 
04051    ch->state = MISDN_CLEANING;
04052 
04053    ast_mutex_lock(&release_lock);
04054 
04055    cl_dequeue_chan(&cl_te, ch);
04056 
04057    /* releasing jitterbuffer */
04058    if (ch->jb) {
04059       misdn_jb_destroy(ch->jb);
04060       ch->jb = NULL;
04061    }
04062 
04063    if (ch->overlap_dial) {
04064       if (ch->overlap_dial_task != -1) {
04065          misdn_tasks_remove(ch->overlap_dial_task);
04066          ch->overlap_dial_task = -1;
04067       }
04068       ast_mutex_destroy(&ch->overlap_tv_lock);
04069    }
04070 
04071    if (ch->hold.state != MISDN_HOLD_IDLE) {
04072       if (ch->originator == ORG_AST) {
04073          --misdn_out_calls[ch->hold.port];
04074       } else {
04075          --misdn_in_calls[ch->hold.port];
04076       }
04077    }
04078 
04079    close(ch->pipe[0]);
04080    close(ch->pipe[1]);
04081 
04082    ast = ch->ast;
04083    if (ast) {
04084       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
04085       if (ast->_state != AST_STATE_RESERVED) {
04086          ast_setstate(ast, AST_STATE_DOWN);
04087       }
04088    }
04089 
04090    ast_free(ch);
04091 
04092    ast_mutex_unlock(&release_lock);
04093 }
04094 
04095 /*!
04096  * \internal
04097  * \brief Attempt to transfer the active channel party to the held channel party.
04098  *
04099  * \param active_ch Channel currently connected.
04100  * \param held_ch Channel currently on hold.
04101  *
04102  * \retval 0 on success.
04103  * \retval -1 on error.
04104  */
04105 static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list *held_ch)
04106 {
04107    int retval;
04108    struct ast_channel *bridged;
04109 
04110    switch (active_ch->state) {
04111    case MISDN_PROCEEDING:
04112    case MISDN_PROGRESS:
04113    case MISDN_ALERTING:
04114    case MISDN_CONNECTED:
04115       break;
04116    default:
04117       return -1;
04118    }
04119 
04120    bridged = ast_bridged_channel(held_ch->ast);
04121    if (bridged) {
04122       ast_queue_control(held_ch->ast, AST_CONTROL_UNHOLD);
04123       held_ch->hold.state = MISDN_HOLD_TRANSFER;
04124 
04125       chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
04126          held_ch->ast->name, active_ch->ast->name);
04127       retval = ast_channel_masquerade(active_ch->ast, bridged);
04128    } else {
04129       /*
04130        * Could not transfer.  Held channel is not bridged anymore.
04131        * Held party probably got tired of waiting and hung up.
04132        */
04133       retval = -1;
04134    }
04135 
04136    return retval;
04137 }
04138 
04139 
04140 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
04141 {
04142    char *predial;
04143    struct ast_frame fr;
04144 
04145    predial = ast_strdupa(ast->exten);
04146 
04147    ch->state = MISDN_DIALING;
04148 
04149    if (!ch->noautorespond_on_setup) {
04150       if (bc->nt) {
04151          int ret; 
04152          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04153       } else {
04154          int ret;
04155          if ( misdn_lib_is_ptp(bc->port)) {
04156             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04157          } else {
04158             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
04159          }
04160       }
04161    } else {
04162       ch->state = MISDN_INCOMING_SETUP;
04163    }
04164 
04165    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);
04166   
04167    strcpy(ast->exten, "s");
04168   
04169    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
04170       ast = NULL;
04171       bc->out_cause = AST_CAUSE_UNALLOCATED;
04172       hangup_chan(ch, bc);
04173       hanguptone_indicate(ch);
04174 
04175       misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
04176    }
04177   
04178   
04179    while (!ast_strlen_zero(predial) ) {
04180       fr.frametype = AST_FRAME_DTMF;
04181       fr.subclass = *predial;
04182       fr.src = NULL;
04183       fr.data.ptr = NULL;
04184       fr.datalen = 0;
04185       fr.samples = 0;
04186       fr.mallocd = 0;
04187       fr.offset = 0;
04188       fr.delivery = ast_tv(0,0);
04189 
04190       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04191          ast_queue_frame(ch->ast, &fr);
04192       }
04193       predial++;
04194    }
04195 }
04196 
04197 
04198 
04199 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) {
04200    if (!ast) {
04201       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
04202       return;
04203    }
04204    if (!bc) {
04205       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
04206       return;
04207    }
04208    if (!ch) {
04209       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
04210       return;
04211    }
04212 
04213    ast->hangupcause = bc->cause;
04214 
04215    switch (bc->cause) {
04216 
04217    case AST_CAUSE_UNALLOCATED:
04218    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
04219    case AST_CAUSE_NO_ROUTE_DESTINATION:
04220    case 4:  /* Send special information tone */
04221    case AST_CAUSE_NUMBER_CHANGED:
04222    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04223       /* Congestion Cases */
04224       /*
04225        * Not Queueing the Congestion anymore, since we want to hear
04226        * the inband message
04227        *
04228       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
04229       ch->state = MISDN_BUSY;
04230       
04231       ast_queue_control(ast, AST_CONTROL_CONGESTION);
04232       */
04233       break;
04234 
04235    case AST_CAUSE_CALL_REJECTED:
04236    case AST_CAUSE_USER_BUSY:
04237       ch->state = MISDN_BUSY;
04238 
04239       if (!ch->need_busy) {
04240          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
04241          break;
04242       }
04243 
04244       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04245       
04246       ast_queue_control(ast, AST_CONTROL_BUSY);
04247       
04248       ch->need_busy = 0;
04249       
04250       break;
04251    }
04252 }
04253 
04254 
04255 /*! \brief Import parameters from the dialplan environment variables */
04256 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
04257 {
04258    const char *tmp;
04259 
04260    ast_channel_lock(chan);
04261    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04262    if (tmp) {
04263       ch->other_pid = atoi(tmp);
04264       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04265       if (ch->other_pid > 0) {
04266          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04267          if (ch->other_ch) {
04268             ch->other_ch->other_ch = ch;
04269          }
04270       }
04271    }
04272 
04273    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04274    if (tmp && (atoi(tmp) == 1)) {
04275       bc->sending_complete = 1;
04276    }
04277 
04278    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04279    if (tmp) {
04280       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04281       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04282       bc->uulen = strlen(bc->uu);
04283    }
04284 
04285    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04286    if (tmp) {
04287       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04288    }
04289    ast_channel_unlock(chan);
04290 }
04291 
04292 /*! \brief Export parameters to the dialplan environment variables */
04293 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
04294 {
04295    char tmp[32];
04296    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04297    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04298    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04299 
04300    if (bc->sending_complete) {
04301       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04302       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04303    }
04304 
04305    if (bc->urate) {
04306       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04307       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04308    }
04309 
04310    if (bc->uulen) {
04311       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04312    }
04313 
04314    if (!ast_strlen_zero(bc->keypad)) {
04315       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04316    }
04317 }
04318 
04319 int add_in_calls(int port)
04320 {
04321    int max_in_calls;
04322    
04323    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04324    misdn_in_calls[port]++;
04325 
04326    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04327       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04328       return misdn_in_calls[port] - max_in_calls;
04329    }
04330    
04331    return 0;
04332 }
04333 
04334 int add_out_calls(int port)
04335 {
04336    int max_out_calls;
04337    
04338    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04339 
04340    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04341       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04342       return (misdn_out_calls[port] + 1) - max_out_calls;
04343    }
04344 
04345    misdn_out_calls[port]++;
04346    
04347    return 0;
04348 }
04349 
04350 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
04351    if (pbx_start_chan(ch) < 0) {
04352       hangup_chan(ch, bc);
04353       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04354       if (bc->nt) {
04355          hanguptone_indicate(ch);
04356          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04357       } else {
04358          misdn_lib_send_event(bc, EVENT_RELEASE);
04359       }
04360    }
04361 }
04362 
04363 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
04364    ch->state = MISDN_WAITING4DIGS;
04365    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04366    if (bc->nt && !bc->dad[0]) {
04367       dialtone_indicate(ch);
04368    }
04369 }
04370 
04371 
04372 /************************************************************/
04373 /*  Receive Events from isdn_lib  here                     */
04374 /************************************************************/
04375 static enum event_response_e
04376 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
04377 {
04378    int msn_valid;
04379    struct chan_list *held_ch;
04380    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04381    
04382    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
04383       int debuglevel = 1;
04384       if ( event == EVENT_CLEANUP && !user_data) {
04385          debuglevel = 5;
04386       }
04387 
04388       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");
04389       if (debuglevel == 1) {
04390          misdn_lib_log_ies(bc);
04391          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04392       }
04393    }
04394    
04395    if (!ch) {
04396       switch(event) {
04397       case EVENT_SETUP:
04398       case EVENT_DISCONNECT:
04399       case EVENT_RELEASE:
04400       case EVENT_RELEASE_COMPLETE:
04401       case EVENT_PORT_ALARM:
04402       case EVENT_RETRIEVE:
04403       case EVENT_NEW_BC:
04404       case EVENT_FACILITY:
04405          break;
04406       case EVENT_CLEANUP:
04407       case EVENT_TONE_GENERATE:
04408       case EVENT_BCHAN_DATA:
04409          return -1;
04410       default:
04411          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);
04412          return -1;
04413       }
04414    }
04415    
04416    if (ch) {
04417       switch (event) {
04418       case EVENT_TONE_GENERATE:
04419          break;
04420       case EVENT_DISCONNECT:
04421       case EVENT_RELEASE:
04422       case EVENT_RELEASE_COMPLETE:
04423       case EVENT_CLEANUP:
04424       case EVENT_TIMEOUT:
04425          if (!ch->ast) {
04426             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));
04427          }
04428          break;
04429       default:
04430          if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04431             if (event != EVENT_BCHAN_DATA) {
04432                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04433             }
04434             return -1;
04435          }
04436       }
04437    }
04438    
04439    
04440    switch (event) {
04441    case EVENT_PORT_ALARM:
04442       {
04443          int boa = 0;
04444          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
04445          if (boa) {
04446             cb_log(1, bc->port, " --> blocking\n");
04447             misdn_lib_port_block(bc->port); 
04448          }
04449       }
04450       break;
04451    case EVENT_BCHAN_ACTIVATED:
04452       break;
04453       
04454    case EVENT_NEW_CHANNEL:
04455       update_name(ch->ast,bc->port,bc->channel);
04456       break;
04457       
04458    case EVENT_NEW_L3ID:
04459       ch->l3id=bc->l3_id;
04460       ch->addr=bc->addr;
04461       break;
04462 
04463    case EVENT_NEW_BC:
04464       if (!ch) {
04465          ch = find_hold_call(cl_te,bc);
04466       }
04467       
04468       if (!ch) {
04469          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04470          break;
04471       }
04472 
04473       if (bc) {
04474          ch->bc = (struct misdn_bchannel *)user_data;
04475       }
04476       break;
04477       
04478    case EVENT_DTMF_TONE:
04479    {
04480       /*  sending INFOS as DTMF-Frames :) */
04481       struct ast_frame fr;
04482 
04483       memset(&fr, 0, sizeof(fr));
04484       fr.frametype = AST_FRAME_DTMF;
04485       fr.subclass = bc->dtmf ;
04486       fr.src = NULL;
04487       fr.data.ptr = NULL;
04488       fr.datalen = 0;
04489       fr.samples = 0;
04490       fr.mallocd = 0;
04491       fr.offset = 0;
04492       fr.delivery = ast_tv(0,0);
04493       
04494       if (!ch->ignore_dtmf) {
04495          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04496          ast_queue_frame(ch->ast, &fr);
04497       } else {
04498          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04499       }
04500    }
04501       break;
04502    case EVENT_STATUS:
04503       break;
04504     
04505    case EVENT_INFORMATION:
04506       if (ch->state != MISDN_CONNECTED) {
04507          stop_indicate(ch);
04508       }
04509    
04510       if (!ch->ast) {
04511          break;
04512       }
04513 
04514       if (ch->state == MISDN_WAITING4DIGS ) {
04515          /*  Ok, incomplete Setup, waiting till extension exists */
04516          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04517             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04518             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04519          }
04520 
04521          strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04522          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04523 
04524          /* Check for Pickup Request first */
04525          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04526             if (ast_pickup_call(ch->ast)) {
04527                hangup_chan(ch, bc);
04528             } else {
04529                struct ast_channel *chan = ch->ast;
04530                ch->state = MISDN_CALLING_ACKNOWLEDGE;
04531                ast_setstate(chan, AST_STATE_DOWN);
04532                hangup_chan(ch, bc);
04533                ch->ast = NULL;
04534                break;
04535             }
04536          }
04537          
04538          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04539             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04540                ast_log(LOG_WARNING,
04541                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04542                   bc->dad, ch->context, bc->port);
04543                strcpy(ch->ast->exten, "i");
04544 
04545                ch->state = MISDN_DIALING;
04546                start_pbx(ch, bc, ch->ast);
04547                break;
04548             }
04549 
04550             ast_log(LOG_WARNING,
04551                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04552                "\tMaybe you want to add an 'i' extension to catch this case.\n",
04553                bc->dad, ch->context, bc->port);
04554 
04555             if (bc->nt) {
04556                hanguptone_indicate(ch);
04557             }
04558             ch->state = MISDN_EXTCANTMATCH;
04559             bc->out_cause = AST_CAUSE_UNALLOCATED;
04560 
04561             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04562             break;
04563          }
04564 
04565          if (ch->overlap_dial) {
04566             ast_mutex_lock(&ch->overlap_tv_lock);
04567             ch->overlap_tv = ast_tvnow();
04568             ast_mutex_unlock(&ch->overlap_tv_lock);
04569             if (ch->overlap_dial_task == -1) {
04570                ch->overlap_dial_task = 
04571                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04572             }
04573             break;
04574          }
04575 
04576          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04577             ch->state = MISDN_DIALING;
04578             start_pbx(ch, bc, ch->ast);
04579          }
04580       } else {
04581          /*  sending INFOS as DTMF-Frames :) */
04582          struct ast_frame fr;
04583          int digits;
04584 
04585          memset(&fr, 0, sizeof(fr));
04586          fr.frametype = AST_FRAME_DTMF;
04587          fr.subclass = bc->info_dad[0] ;
04588          fr.src = NULL;
04589          fr.data.ptr = NULL;
04590          fr.datalen = 0;
04591          fr.samples = 0;
04592          fr.mallocd = 0;
04593          fr.offset = 0;
04594          fr.delivery = ast_tv(0,0);
04595 
04596          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
04597          if (ch->state != MISDN_CONNECTED ) {
04598             if (digits) {
04599                strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04600                ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04601                ast_cdr_update(ch->ast);
04602             }
04603             
04604             ast_queue_frame(ch->ast, &fr);
04605          }
04606       }
04607       break;
04608    case EVENT_SETUP:
04609    {
04610       struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04611       struct ast_channel *chan;
04612       int exceed;
04613       int pres, screen;
04614       int ai;
04615       int im;
04616 
04617       if (ch) {
04618          switch (ch->state) {
04619          case MISDN_NOTHING:
04620             ch = NULL;
04621             break;
04622          default:
04623             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04624             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
04625          }
04626       }
04627 
04628       msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04629       if (!bc->nt && ! msn_valid) {
04630          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04631          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04632       }
04633 
04634       if (bc->cw) {
04635          int cause;
04636          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04637          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04638          bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
04639          return RESPONSE_RELEASE_SETUP;
04640       }
04641 
04642       print_bearer(bc);
04643 
04644       ch = init_chan_list(ORG_MISDN);
04645 
04646       if (!ch) {
04647          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
04648          return 0;
04649       }
04650 
04651       ch->bc = bc;
04652       ch->l3id = bc->l3_id;
04653       ch->addr = bc->addr;
04654       ch->originator = ORG_MISDN;
04655 
04656       chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04657       if (!chan) {
04658          ast_free(ch);
04659          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04660          ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); 
04661          return 0;
04662       }
04663 
04664       ch->ast = chan;
04665 
04666       if ((exceed = add_in_calls(bc->port))) {
04667          char tmp[16];
04668          snprintf(tmp, sizeof(tmp), "%d", exceed);
04669          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
04670       }
04671 
04672       read_config(ch, ORG_MISDN);
04673 
04674       export_ch(chan, bc, ch);
04675 
04676       ch->ast->rings = 1;
04677       ast_setstate(ch->ast, AST_STATE_RINGING);
04678 
04679       switch (bc->pres) {
04680       case 1:
04681          pres = AST_PRES_RESTRICTED;
04682          chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
04683          break;
04684       case 2:
04685          pres = AST_PRES_UNAVAILABLE;
04686          chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
04687          break;
04688       default:
04689          pres = AST_PRES_ALLOWED;
04690          chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
04691          break;
04692       }
04693 
04694       switch (bc->screen) {
04695       default:
04696       case 0:
04697          screen = AST_PRES_USER_NUMBER_UNSCREENED;
04698          chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
04699          break;
04700       case 1:
04701          screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
04702          chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
04703          break;
04704       case 2:
04705          screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
04706          chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
04707          break;
04708       case 3:
04709          screen = AST_PRES_NETWORK_NUMBER;
04710          chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
04711          break;
04712       }
04713 
04714       chan->cid.cid_pres = pres | screen;
04715 
04716       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04717       chan->transfercapability = bc->capability;
04718 
04719       switch (bc->capability) {
04720       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04721          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
04722          break;
04723       default:
04724          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
04725       }
04726 
04727       /** queue new chan **/
04728       cl_queue_chan(&cl_te, ch);
04729 
04730       if (!strstr(ch->allowed_bearers, "all")) {
04731          int i;
04732 
04733          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
04734             if (allowed_bearers_array[i].cap == bc->capability) {
04735                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
04736                   /* The bearer capability is allowed */
04737                   if (allowed_bearers_array[i].deprecated) {
04738                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
04739                         allowed_bearers_array[i].name);
04740                   }
04741                   break;
04742                }
04743             }
04744          }  /* end for */
04745          if (i == ARRAY_LEN(allowed_bearers_array)) {
04746             /* We did not find the bearer capability */
04747             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
04748                bearer2str(bc->capability), bc->capability);
04749             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
04750 
04751             ch->state = MISDN_EXTCANTMATCH;
04752             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04753             return RESPONSE_OK;
04754          }
04755       }
04756 
04757       /* Check for Pickup Request first */
04758       if (!strcmp(chan->exten, ast_pickup_ext())) {
04759          if (!ch->noautorespond_on_setup) {
04760             int ret;/** Sending SETUP_ACK**/
04761             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04762          } else {
04763             ch->state = MISDN_INCOMING_SETUP;
04764          }
04765          if (ast_pickup_call(chan)) {
04766             hangup_chan(ch, bc);
04767          } else {
04768             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04769             ast_setstate(chan, AST_STATE_DOWN);
04770             hangup_chan(ch, bc);
04771             ch->ast = NULL;
04772             break;
04773          }
04774       }
04775 
04776       /*
04777        * added support for s extension hope it will help those poor cretains
04778        * which haven't overlap dial.
04779        */
04780       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04781       if (ai) {
04782          do_immediate_setup(bc, ch, chan);
04783          break;
04784       }
04785 
04786       /* check if we should jump into s when we have no dad */
04787       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04788       if (im && ast_strlen_zero(bc->dad)) {
04789          do_immediate_setup(bc, ch, chan);
04790          break;
04791       }
04792 
04793       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
04794       if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04795          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04796             ast_log(LOG_WARNING,
04797                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04798                bc->dad, ch->context, bc->port);
04799             strcpy(ch->ast->exten, "i");
04800             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04801             ch->state = MISDN_DIALING;
04802             start_pbx(ch, bc, chan);
04803             break;
04804          }
04805 
04806          ast_log(LOG_WARNING,
04807             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04808             "\tMaybe you want to add an 'i' extension to catch this case.\n",
04809             bc->dad, ch->context, bc->port);
04810          if (bc->nt) {
04811             hanguptone_indicate(ch);
04812          }
04813 
04814          ch->state = MISDN_EXTCANTMATCH;
04815          bc->out_cause = AST_CAUSE_UNALLOCATED;
04816 
04817          misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_RELEASE);
04818 
04819          break;
04820       }
04821 
04822       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
04823        * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
04824        * will be used by Asterisk automatically. */
04825       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04826          if (!ch->noautorespond_on_setup) {
04827             ch->state=MISDN_DIALING;
04828             misdn_lib_send_event(bc, EVENT_PROCEEDING );
04829          } else {
04830             ch->state = MISDN_INCOMING_SETUP;
04831          }
04832          start_pbx(ch, bc, chan);
04833          break;
04834       }
04835 
04836 
04837       /*
04838        * When we are NT and overlapdial is set and if 
04839        * the number is empty, we wait for the ISDN timeout
04840        * instead of our own timer.
04841        */
04842       if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04843          wait_for_digits(ch, bc, chan);
04844          break;
04845       }
04846 
04847       /* 
04848        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
04849        * Infos with a Interdigit Timeout.
04850        * */
04851       if (ch->overlap_dial) {
04852          ast_mutex_lock(&ch->overlap_tv_lock);
04853          ch->overlap_tv = ast_tvnow();
04854          ast_mutex_unlock(&ch->overlap_tv_lock);
04855 
04856          wait_for_digits(ch, bc, chan);
04857          if (ch->overlap_dial_task == -1) {
04858             ch->overlap_dial_task = 
04859                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04860          }
04861          break;
04862       }
04863 
04864       /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
04865        * without interdigit timeout.
04866        * */
04867       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04868          wait_for_digits(ch, bc, chan);
04869          break;
04870       }
04871 
04872       /*
04873        * If the extension exists let's just jump into it.
04874        * */
04875       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04876          misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
04877          ch->state = MISDN_DIALING;
04878          start_pbx(ch, bc, chan);
04879          break;
04880       }
04881    }
04882       break;
04883 
04884    case EVENT_SETUP_ACKNOWLEDGE:
04885       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04886 
04887       if (bc->channel) 
04888          update_name(ch->ast,bc->port,bc->channel);
04889       
04890       if (!ast_strlen_zero(bc->infos_pending)) {
04891          /* TX Pending Infos */
04892          strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04893 
04894          if (!ch->ast) {
04895             break;
04896          }
04897          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04898          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04899          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04900 
04901          misdn_lib_send_event(bc, EVENT_INFORMATION);
04902       }
04903       break;
04904    case EVENT_PROCEEDING:
04905       if (misdn_cap_is_speech(bc->capability) &&
04906            misdn_inband_avail(bc) ) {
04907          start_bc_tones(ch);
04908       }
04909 
04910       ch->state = MISDN_PROCEEDING;
04911       
04912       if (!ch->ast) {
04913          break;
04914       }
04915 
04916       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04917       break;
04918    case EVENT_PROGRESS:
04919       if (bc->channel) {
04920          update_name(ch->ast, bc->port, bc->channel);
04921       }
04922 
04923       if (!bc->nt ) {
04924          if (misdn_cap_is_speech(bc->capability) &&
04925             misdn_inband_avail(bc)) {
04926             start_bc_tones(ch);
04927          }
04928          
04929          ch->state = MISDN_PROGRESS;
04930 
04931          if (!ch->ast) {
04932             break;
04933          }
04934          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04935       }
04936       break;
04937    case EVENT_ALERTING:
04938       ch->state = MISDN_ALERTING;
04939       
04940       if (!ch->ast) {
04941          break;
04942       }
04943 
04944       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04945       ast_setstate(ch->ast, AST_STATE_RINGING);
04946       
04947       cb_log(7, bc->port, " --> Set State Ringing\n");
04948       
04949       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04950          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04951          start_bc_tones(ch);
04952       } else {
04953          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04954          if (ch->far_alerting) {
04955             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04956             start_bc_tones(ch);
04957             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04958          }
04959       }
04960       break;
04961    case EVENT_CONNECT:
04962       {
04963          struct ast_channel *bridged;
04964 
04965          /*we answer when we've got our very new L3 ID from the NT stack */
04966          misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04967 
04968          if (!ch->ast) {
04969             break;
04970          }
04971 
04972          bridged = ast_bridged_channel(ch->ast);
04973          stop_indicate(ch);
04974 
04975          if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04976             struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04977 
04978             chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04979             if (bridged_ch) {
04980                bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04981                ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04982             }
04983          }
04984       }
04985       ch->l3id = bc->l3_id;
04986       ch->addr = bc->addr;
04987 
04988       start_bc_tones(ch);
04989    
04990       ch->state = MISDN_CONNECTED;
04991    
04992       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04993       break;
04994    case EVENT_CONNECT_ACKNOWLEDGE:
04995       ch->l3id = bc->l3_id;
04996       ch->addr = bc->addr;
04997 
04998       start_bc_tones(ch);
04999 
05000       ch->state = MISDN_CONNECTED;
05001       break;
05002    case EVENT_DISCONNECT:
05003       /* we might not have an ch->ast ptr here anymore */
05004       if (ch) {
05005          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);
05006          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
05007             /* If there's inband information available (e.g. a
05008                recorded message saying what was wrong with the
05009                dialled number, or perhaps even giving an
05010                alternative number, then play it instead of
05011                immediately releasing the call */
05012             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
05013       
05014             ch->state = MISDN_DISCONNECTED;
05015             start_bc_tones(ch);
05016 
05017             if (ch->ast) {
05018                ch->ast->hangupcause = bc->cause;
05019                if (bc->cause == AST_CAUSE_USER_BUSY) {
05020                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
05021                }
05022             }
05023             ch->need_busy = 0;
05024             break;
05025          }
05026 
05027          bc->need_disconnect = 0;
05028          stop_bc_tones(ch);
05029 
05030          /* Check for held channel, to implement transfer */
05031          held_ch = find_hold_call(cl_te, bc);
05032          if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
05033             hangup_chan(ch, bc);
05034          }
05035       } else {
05036          held_ch = find_hold_call_l3(cl_te, bc->l3_id);
05037          if (held_ch && held_ch->hold.state == MISDN_HOLD_ACTIVE) {
05038             bc->need_disconnect = 0;
05039 
05040 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
05041             /*
05042              * Some phones disconnect the held call and the active call at the
05043              * same time to do the transfer.  Unfortunately, either call could
05044              * be disconnected first.
05045              */
05046             ch = find_hold_active_call(cl_te, bc);
05047             if (!ch || misdn_attempt_transfer(ch, held_ch)) {
05048                held_ch->hold.state = MISDN_HOLD_DISCONNECT;
05049                hangup_chan(held_ch, bc);
05050             }
05051 #else
05052             hangup_chan(held_ch, bc);
05053 #endif   /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
05054          }
05055       }
05056       bc->out_cause = -1;
05057       if (bc->need_release) {
05058          misdn_lib_send_event(bc, EVENT_RELEASE);
05059       }
05060       break;
05061    case EVENT_RELEASE:
05062       if (!ch) {
05063          ch = find_hold_call_l3(cl_te, bc->l3_id);
05064          if (!ch) {
05065             chan_misdn_log(1, bc->port,
05066                " --> no Ch, so we've already released. (%s)\n",
05067                manager_isdn_get_info(event));
05068             return -1;
05069          }
05070       }
05071 
05072       bc->need_disconnect = 0;
05073       bc->need_release = 0;
05074 
05075       hangup_chan(ch, bc);
05076       release_chan(ch, bc);
05077       break;
05078    case EVENT_RELEASE_COMPLETE:
05079       if (!ch) {
05080          ch = find_hold_call_l3(cl_te, bc->l3_id);
05081          if (!ch) {
05082             chan_misdn_log(1, bc->port,
05083                " --> no Ch, so we've already released. (%s)\n",
05084                manager_isdn_get_info(event));
05085             break;
05086          }
05087       }
05088 
05089       bc->need_disconnect = 0;
05090       bc->need_release = 0;
05091       bc->need_release_complete = 0;
05092 
05093       stop_bc_tones(ch);
05094       hangup_chan(ch, bc);
05095       release_chan(ch, bc);
05096       break;
05097    case EVENT_BCHAN_ERROR:
05098    case EVENT_CLEANUP:
05099       stop_bc_tones(ch);
05100       
05101       switch (ch->state) {
05102       case MISDN_CALLING:
05103          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
05104          break;
05105       default:
05106          break;
05107       }
05108       
05109       hangup_chan(ch, bc);
05110       release_chan(ch, bc);
05111       break;
05112    case EVENT_TONE_GENERATE:
05113    {
05114       int tone_len = bc->tone_cnt;
05115       struct ast_channel *ast = ch->ast;
05116       void *tmp;
05117       int res;
05118       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
05119 
05120       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
05121 
05122       if (!ast) {
05123          break;
05124       }
05125 
05126       if (!ast->generator) {
05127          break;
05128       }
05129 
05130       tmp = ast->generatordata;
05131       ast->generatordata = NULL;
05132       generate = ast->generator->generate;
05133 
05134       if (tone_len < 0 || tone_len > 512 ) {
05135          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
05136          tone_len = 128;
05137       }
05138 
05139       res = generate(ast, tmp, tone_len, tone_len);
05140       ast->generatordata = tmp;
05141       
05142       if (res) {
05143          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
05144          ast_deactivate_generator(ast);
05145       } else {
05146          bc->tone_cnt = 0;
05147       }
05148    }
05149       break;
05150 
05151    case EVENT_BCHAN_DATA:
05152       if (ch->bc->AOCD_need_export) {
05153          export_aoc_vars(ch->originator, ch->ast, ch->bc);
05154       }
05155       if (!misdn_cap_is_speech(ch->bc->capability)) {
05156          struct ast_frame frame;
05157          /*In Data Modes we queue frames*/
05158          memset(&frame, 0, sizeof(frame));
05159          frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
05160          frame.subclass = AST_FORMAT_ALAW;
05161          frame.datalen = bc->bframe_len;
05162          frame.samples = bc->bframe_len;
05163          frame.mallocd = 0;
05164          frame.offset = 0;
05165          frame.delivery = ast_tv(0, 0);
05166          frame.src = NULL;
05167          frame.data.ptr = bc->bframe;
05168 
05169          if (ch->ast) 
05170             ast_queue_frame(ch->ast, &frame);
05171       } else {
05172          struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
05173          int t;
05174 
05175          t = ast_poll(&pfd, 1, 0);
05176 
05177          if (t < 0) {
05178             chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
05179             break;
05180          }
05181 
05182          if (!t) {
05183             chan_misdn_log(9, bc->port, "poll() timed out\n");
05184             break;
05185          }
05186 
05187          if (pfd.revents & POLLOUT) {
05188             chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
05189             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
05190                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
05191 
05192                stop_bc_tones(ch);
05193                hangup_chan(ch, bc);
05194                release_chan(ch, bc);
05195             }
05196          } else {
05197             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
05198          }
05199       }
05200       break;
05201    case EVENT_TIMEOUT:
05202       if (ch && bc) {
05203          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
05204       }
05205 
05206       switch (ch->state) {
05207       case MISDN_DIALING:
05208       case MISDN_PROGRESS:
05209          if (bc->nt && !ch->nttimeout) {
05210             break;
05211          }
05212          /* fall-through */
05213       case MISDN_CALLING:
05214       case MISDN_ALERTING:
05215       case MISDN_PROCEEDING:
05216       case MISDN_CALLING_ACKNOWLEDGE:
05217          if (bc->nt) {
05218             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
05219             hanguptone_indicate(ch);
05220          }
05221 
05222          bc->out_cause = AST_CAUSE_UNALLOCATED;
05223          misdn_lib_send_event(bc, EVENT_DISCONNECT);
05224          break;
05225       case MISDN_WAITING4DIGS:
05226          if (bc->nt) {
05227             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
05228             bc->out_cause = AST_CAUSE_UNALLOCATED;
05229             hanguptone_indicate(ch);
05230             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05231          } else {
05232             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
05233             misdn_lib_send_event(bc, EVENT_RELEASE);
05234          }
05235          break;
05236       case MISDN_CLEANING: 
05237          chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
05238          break;
05239       default:
05240          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
05241       }
05242       break;
05243 
05244    /****************************/
05245    /** Supplementary Services **/
05246    /****************************/
05247    case EVENT_RETRIEVE:
05248       if (!ch) {
05249          chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
05250          ch = find_hold_call_l3(cl_te, bc->l3_id);
05251          if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
05252             ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
05253             misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05254             break;
05255          }
05256       }
05257 
05258       /* remember the channel again */
05259       ch->bc = bc;
05260 
05261       ch->hold.state = MISDN_HOLD_IDLE;
05262       ch->hold.port = 0;
05263       ch->hold.channel = 0;
05264 
05265       ast_queue_control(ch->ast, AST_CONTROL_UNHOLD);
05266    
05267       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
05268          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
05269          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05270       }
05271       break;
05272    case EVENT_HOLD:
05273    {
05274       int hold_allowed;
05275       struct ast_channel *bridged;
05276 
05277       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
05278       if (!hold_allowed) {
05279          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
05280          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05281          break;
05282       }
05283 
05284       bridged = ast_bridged_channel(ch->ast);
05285       if (bridged) {
05286          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
05287          ch->l3id = bc->l3_id;
05288 
05289          /* forget the channel now */
05290          ch->bc = NULL;
05291          ch->hold.state = MISDN_HOLD_ACTIVE;
05292          ch->hold.port = bc->port;
05293          ch->hold.channel = bc->channel;
05294 
05295          ast_queue_control(ch->ast, AST_CONTROL_HOLD);
05296          
05297          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
05298       } else {
05299          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05300          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
05301       }
05302    } 
05303       break;
05304    case EVENT_FACILITY:
05305       print_facility(&(bc->fac_in), bc);
05306       
05307       switch (bc->fac_in.Function) {
05308 #ifdef HAVE_MISDN_FAC_RESULT
05309       case Fac_RESULT:
05310          break;
05311 #endif
05312       case Fac_CD:
05313          if (ch) {
05314             struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05315             struct chan_list *ch_br;
05316             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
05317                ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
05318                /*ch->state = MISDN_FACILITY_DEFLECTED;*/
05319                if (ch_br->bc) {
05320                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
05321                      ch_br->state = MISDN_DIALING;
05322                      if (pbx_start_chan(ch_br) < 0) {
05323                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
05324                      }
05325                   }
05326                }
05327             }
05328             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05329          } 
05330          break;
05331       case Fac_AOCDCurrency:
05332          if (ch) {
05333             bc->AOCDtype = Fac_AOCDCurrency;
05334             memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
05335             bc->AOCD_need_export = 1;
05336             export_aoc_vars(ch->originator, ch->ast, bc);
05337          }
05338          break;
05339       case Fac_AOCDChargingUnit:
05340          if (ch) {
05341             bc->AOCDtype = Fac_AOCDChargingUnit;
05342             memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
05343             bc->AOCD_need_export = 1;
05344             export_aoc_vars(ch->originator, ch->ast, bc);
05345          }
05346          break;
05347       case Fac_None:
05348 #ifdef HAVE_MISDN_FAC_ERROR
05349       case Fac_ERROR:
05350 #endif
05351          break;
05352       default:
05353          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
05354       }
05355       
05356       break;
05357    case EVENT_RESTART:
05358       if (!bc->dummy) {
05359          stop_bc_tones(ch);
05360          release_chan(ch, bc);
05361       }
05362       break;
05363    default:
05364       chan_misdn_log(1, 0, "Got Unknown Event\n");
05365       break;
05366    }
05367    
05368    return RESPONSE_OK;
05369 }
05370 
05371 /** TE STUFF END **/
05372 
05373 /******************************************
05374  *
05375  *   Asterisk Channel Endpoint END
05376  *
05377  *
05378  *******************************************/
05379 
05380 
05381 
05382 static int unload_module(void)
05383 {
05384    /* First, take us out of the channel loop */
05385    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05386 
05387    misdn_tasks_destroy();
05388    
05389    if (!g_config_initialized) {
05390       return 0;
05391    }
05392    
05393    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05394 
05395    /* ast_unregister_application("misdn_crypt"); */
05396    ast_unregister_application("misdn_set_opt");
05397    ast_unregister_application("misdn_facility");
05398    ast_unregister_application("misdn_check_l2l1");
05399 
05400    ast_channel_unregister(&misdn_tech);
05401 
05402    free_robin_list();
05403    misdn_cfg_destroy();
05404    misdn_lib_destroy();
05405   
05406    ast_free(misdn_out_calls);
05407    ast_free(misdn_in_calls);
05408    ast_free(misdn_debug_only);
05409    ast_free(misdn_ports);
05410    ast_free(misdn_debug);
05411    
05412    return 0;
05413 }
05414 
05415 static int load_module(void)
05416 {
05417    int i, port;
05418    int ntflags = 0, ntkc = 0;
05419    char ports[256] = "";
05420    char tempbuf[BUFFERSIZE + 1];
05421    char ntfile[BUFFERSIZE + 1];
05422    struct misdn_lib_iface iface = {
05423       .cb_event = cb_events,
05424       .cb_log = chan_misdn_log,
05425       .cb_jb_empty = chan_misdn_jb_empty,
05426    };
05427 
05428    max_ports = misdn_lib_maxports_get();
05429    
05430    if (max_ports <= 0) {
05431       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05432       return AST_MODULE_LOAD_DECLINE;
05433    }
05434    
05435    if (misdn_cfg_init(max_ports, 0)) {
05436       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05437       return AST_MODULE_LOAD_DECLINE;
05438    }
05439    g_config_initialized = 1;
05440    
05441    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
05442    if (!misdn_debug) {
05443       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05444       return AST_MODULE_LOAD_DECLINE;
05445    }
05446    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
05447    if (!misdn_ports) {
05448       ast_free(misdn_debug);
05449       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05450       return AST_MODULE_LOAD_DECLINE;
05451    }
05452    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
05453    for (i = 1; i <= max_ports; i++) {
05454       misdn_debug[i] = misdn_debug[0];
05455       misdn_ports[i] = i;
05456    }
05457    *misdn_ports = 0;
05458    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
05459    if (!misdn_debug_only) {
05460       ast_free(misdn_ports);
05461       ast_free(misdn_debug);
05462       ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
05463       return AST_MODULE_LOAD_DECLINE;
05464    }
05465 
05466    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
05467    if (!ast_strlen_zero(tempbuf)) {
05468       tracing = 1;
05469    }
05470 
05471    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05472    if (!misdn_in_calls) {
05473       ast_free(misdn_debug_only);
05474       ast_free(misdn_ports);
05475       ast_free(misdn_debug);
05476       ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
05477       return AST_MODULE_LOAD_DECLINE;
05478    }
05479    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05480    if (!misdn_out_calls) {
05481       ast_free(misdn_in_calls);
05482       ast_free(misdn_debug_only);
05483       ast_free(misdn_ports);
05484       ast_free(misdn_debug);
05485       ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
05486       return AST_MODULE_LOAD_DECLINE;
05487    }
05488 
05489    for (i = 1; i <= max_ports; i++) {
05490       misdn_in_calls[i] = 0;
05491       misdn_out_calls[i] = 0;
05492    }
05493 
05494    ast_mutex_init(&cl_te_lock);
05495    ast_mutex_init(&release_lock);
05496 
05497    misdn_cfg_update_ptp();
05498    misdn_cfg_get_ports_string(ports);
05499 
05500    if (!ast_strlen_zero(ports)) {
05501       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05502    }
05503    if (misdn_lib_init(ports, &iface, NULL)) {
05504       chan_misdn_log(0, 0, "No te ports initialized\n");
05505    }
05506 
05507    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
05508    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
05509    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
05510 
05511    misdn_lib_nt_keepcalls(ntkc);
05512    misdn_lib_nt_debug_init(ntflags, ntfile);
05513 
05514    if (ast_channel_register(&misdn_tech)) {
05515       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05516       unload_module();
05517       return AST_MODULE_LOAD_DECLINE;
05518    }
05519   
05520    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05521 
05522    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05523       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05524       "Sets mISDN opts. and optargs\n"
05525       "\n"
05526       "The available options are:\n"
05527       "    a - Have Asterisk detect DTMF tones on called channel\n"
05528       "    c - Make crypted outgoing call, optarg is keyindex\n"
05529       "    d - Send display text to called phone, text is the optarg\n"
05530       "    e - Perform echo cancelation on this channel,\n"
05531       "        takes taps as optarg (32,64,128,256)\n"
05532       "   e! - Disable echo cancelation on this channel\n"
05533       "    f - Enable fax detection\n"
05534       "    h - Make digital outgoing call\n"
05535       "   h1 - Make HDLC mode digital outgoing call\n"
05536       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05537       "        they will be transported inband.\n"
05538       "   jb - Set jitter buffer length, optarg is length\n"
05539       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05540       "   jn - Disable jitter buffer\n"
05541       "    n - Disable mISDN DSP on channel.\n"
05542       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05543       "    p - Caller ID presentation,\n"
05544       "        optarg is either 'allowed' or 'restricted'\n"
05545       "    s - Send Non-inband DTMF as inband\n"
05546       "   vr - Rx gain control, optarg is gain\n"
05547       "   vt - Tx gain control, optarg is gain\n"
05548       );
05549 
05550    
05551    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05552              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05553              "Sends the Facility Message FACILITY_TYPE with \n"
05554              "the given Arguments to the current ISDN Channel\n"
05555              "Supported Facilities are:\n"
05556              "\n"
05557              "type=calldeflect args=Nr where to deflect\n"
05558       );
05559 
05560 
05561    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05562              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05563              "Checks if the L2 and L1 are up on either the given <port> or\n"
05564              "on the ports in the group with <groupname>\n"
05565              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05566              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05567              "\n"
05568              "This application, ensures the L1/L2 state of the Ports in a group\n"
05569              "it is intended to make the pmp_l1_check option redundant and to\n"
05570              "fix a buggy switch config from your provider\n"
05571              "\n"
05572              "a sample dialplan would look like:\n\n"
05573              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05574              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05575              "\n"
05576       );
05577 
05578 
05579    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
05580 
05581    /* start the l1 watchers */
05582    
05583    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05584       int l1timeout;
05585       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05586       if (l1timeout) {
05587          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05588          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05589       }
05590    }
05591 
05592    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05593 
05594    return 0;
05595 }
05596 
05597 
05598 
05599 static int reload(void)
05600 {
05601    reload_config();
05602 
05603    return 0;
05604 }
05605 
05606 /*** SOME APPS ;)***/
05607 
05608 static int misdn_facility_exec(struct ast_channel *chan, void *data)
05609 {
05610    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05611    char *parse;
05612    AST_DECLARE_APP_ARGS(args,
05613       AST_APP_ARG(facility_type);
05614       AST_APP_ARG(arg)[99];
05615    );
05616 
05617    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05618    
05619    if (strcasecmp(chan->tech->type, "mISDN")) {
05620       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05621       return -1;
05622    }
05623    
05624    if (ast_strlen_zero((char *)data)) {
05625       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
05626       return -1;
05627    }
05628 
05629    parse = ast_strdupa(data);
05630    AST_STANDARD_APP_ARGS(args, parse);
05631 
05632    if (ast_strlen_zero(args.facility_type)) {
05633       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
05634       return -1;
05635    }
05636 
05637    if (!strcasecmp(args.facility_type, "calldeflect")) {
05638       if (ast_strlen_zero(args.arg[0])) {
05639          ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
05640       }
05641 
05642       if (strlen(args.arg[0]) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05643          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));
05644          return 0;
05645       }
05646       ch->bc->fac_out.Function = Fac_CD;
05647       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0], sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05648       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05649    } else {
05650       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
05651    }
05652 
05653    return 0;
05654 }
05655 
05656 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
05657 {
05658    char *parse;
05659    char group[BUFFERSIZE + 1];
05660    char *port_str;
05661    int port = 0;
05662    int timeout;
05663    int dowait = 0;
05664    int port_up;
05665 
05666    AST_DECLARE_APP_ARGS(args,
05667          AST_APP_ARG(grouppar);
05668          AST_APP_ARG(timeout);
05669    );
05670 
05671    if (ast_strlen_zero((char *)data)) {
05672       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05673       return -1;
05674    }
05675 
05676    parse = ast_strdupa(data);
05677    AST_STANDARD_APP_ARGS(args, parse);
05678 
05679    if (args.argc != 2) {
05680       ast_log(LOG_WARNING, "Wrong argument count\n");
05681       return 0;
05682    }
05683 
05684    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05685    timeout = atoi(args.timeout);
05686    port_str = args.grouppar;
05687 
05688    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05689       /* We make a group call lets checkout which ports are in my group */
05690       port_str += 2;
05691       ast_copy_string(group, port_str, sizeof(group));
05692       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05693 
05694       for ( port = misdn_cfg_get_next_port(port); 
05695          port > 0;
05696          port = misdn_cfg_get_next_port(port)) {
05697          char cfg_group[BUFFERSIZE + 1];
05698 
05699          chan_misdn_log(2, 0, "trying port %d\n", port);
05700 
05701          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
05702 
05703          if (!strcasecmp(cfg_group, group)) {
05704             port_up = misdn_lib_port_up(port, 1);
05705 
05706             if (!port_up) {
05707                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05708                misdn_lib_get_port_up(port);
05709                dowait = 1;
05710             }
05711          }
05712       }
05713 
05714    } else {
05715       port = atoi(port_str);
05716       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05717       port_up = misdn_lib_port_up(port, 1);
05718       if (!port_up) {
05719          misdn_lib_get_port_up(port);
05720          dowait = 1;
05721       }
05722    }
05723 
05724    if (dowait) {
05725       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05726       ast_safe_sleep(chan, timeout * 1000);
05727    }
05728 
05729    return 0;
05730 }
05731 
05732 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
05733 {
05734    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05735    char *tok, *tokb, *parse;
05736    int  keyidx = 0;
05737    int rxgain = 0;
05738    int txgain = 0;
05739    int change_jitter = 0;
05740 
05741    if (strcasecmp(chan->tech->type, "mISDN")) {
05742       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05743       return -1;
05744    }
05745    
05746    if (ast_strlen_zero((char *)data)) {
05747       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05748       return -1;
05749    }
05750 
05751    parse = ast_strdupa(data);
05752    for (tok = strtok_r(parse, ":", &tokb);
05753         tok;
05754         tok = strtok_r(NULL, ":", &tokb) ) {
05755       int neglect = 0;
05756 
05757       if (tok[0] == '!' ) {
05758          neglect = 1;
05759          tok++;
05760       }
05761       
05762       switch(tok[0]) {
05763          
05764       case 'd' :
05765          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05766          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05767          break;
05768          
05769       case 'n':
05770          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05771          ch->bc->nodsp = 1;
05772          break;
05773 
05774       case 'j':
05775          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05776          tok++;
05777          change_jitter = 1;
05778 
05779          switch ( tok[0] ) {
05780          case 'b':
05781             ch->jb_len = atoi(++tok);
05782             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05783             break;
05784          case 't' :
05785             ch->jb_upper_threshold = atoi(++tok);
05786             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05787             break;
05788          case 'n':
05789             ch->bc->nojitter = 1;
05790             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05791             break;
05792          default:
05793             ch->jb_len = 4000;
05794             ch->jb_upper_threshold = 0;
05795             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05796             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05797          }
05798          break;
05799       case 'v':
05800          tok++;
05801 
05802          switch (tok[0]) {
05803          case 'r' :
05804             rxgain = atoi(++tok);
05805             if (rxgain < -8) {
05806                rxgain = -8;
05807             }
05808             if (rxgain > 8) {
05809                rxgain = 8;
05810             }
05811             ch->bc->rxgain = rxgain;
05812             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05813             break;
05814          case 't':
05815             txgain = atoi(++tok);
05816             if (txgain < -8) {
05817                txgain = -8;
05818             }
05819             if (txgain > 8) {
05820                txgain = 8;
05821             }
05822             ch->bc->txgain = txgain;
05823             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05824             break;
05825          }
05826          break;
05827       
05828       case 'c':
05829          keyidx = atoi(++tok);
05830          {
05831             char keys[4096];
05832             char *key = NULL, *tmp = keys;
05833             int i;
05834             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05835 
05836             for (i = 0; i < keyidx; i++) {
05837                key = strsep(&tmp, ",");
05838             }
05839 
05840             if (key) {
05841                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05842             }
05843 
05844             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05845             break;
05846          }
05847       case 'e':
05848          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05849          
05850          if (neglect) {
05851             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05852 #ifdef MISDN_1_2
05853             *ch->bc->pipeline = 0;
05854 #else
05855             ch->bc->ec_enable = 0;
05856 #endif
05857          } else {
05858 #ifdef MISDN_1_2
05859             update_pipeline_config(ch->bc);
05860 #else
05861             ch->bc->ec_enable = 1;
05862             ch->bc->orig = ch->originator;
05863             tok++;
05864             if (*tok) {
05865                ch->bc->ec_deftaps = atoi(tok);
05866             }
05867 #endif
05868          }
05869          
05870          break;
05871       case 'h':
05872          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05873          
05874          if (strlen(tok) > 1 && tok[1] == '1') {
05875             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05876             if (!ch->bc->hdlc) {
05877                ch->bc->hdlc = 1;
05878             }
05879          }
05880          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05881          break;
05882             
05883       case 's':
05884          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05885          ch->bc->send_dtmf = 1;
05886          break;
05887          
05888       case 'f':
05889          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05890          ch->faxdetect = 1;
05891          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05892          break;
05893 
05894       case 'a':
05895          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05896          ch->ast_dsp = 1;
05897          break;
05898 
05899       case 'p':
05900          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05901          /* CRICH: callingpres!!! */
05902          if (strstr(tok, "allowed")) {
05903             ch->bc->pres = 0;
05904          } else if (strstr(tok, "restricted")) {
05905             ch->bc->pres = 1;
05906          } else if (strstr(tok, "not_screened")) {
05907             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05908             ch->bc->pres = 1;
05909          }
05910          break;
05911       case 'i' :
05912          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05913          ch->ignore_dtmf=1;
05914          break;
05915       default:
05916          break;
05917       }
05918    }
05919 
05920    if (change_jitter) {
05921       config_jitterbuffer(ch);
05922    }
05923 
05924    if (ch->faxdetect || ch->ast_dsp) {
05925       if (!ch->dsp) {
05926          ch->dsp = ast_dsp_new();
05927       }
05928       if (ch->dsp) {
05929          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
05930       }
05931    }
05932 
05933    if (ch->ast_dsp) {
05934       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05935       ch->bc->nodsp = 1;
05936    }
05937    
05938    return 0;
05939 }
05940 
05941 
05942 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len) 
05943 {
05944    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05945    
05946    if (ch && ch->jb) {
05947       return misdn_jb_empty(ch->jb, buf, len);
05948    }
05949    
05950    return -1;
05951 }
05952 
05953 
05954 
05955 /*******************************************************/
05956 /***************** JITTERBUFFER ************************/
05957 /*******************************************************/
05958 
05959 
05960 /* allocates the jb-structure and initialize the elements*/
05961 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
05962 {
05963    int i;
05964    struct misdn_jb *jb;
05965 
05966    jb = ast_malloc(sizeof(*jb));
05967    if (!jb) {
05968        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05969        return NULL;
05970    }
05971    jb->size = size;
05972    jb->upper_threshold = upper_threshold;
05973    jb->wp = 0;
05974    jb->rp = 0;
05975    jb->state_full = 0;
05976    jb->state_empty = 0;
05977    jb->bytes_wrote = 0;
05978    jb->samples = ast_malloc(size * sizeof(char));
05979    if (!jb->samples) {
05980       ast_free(jb);
05981       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05982       return NULL;
05983    }
05984 
05985    jb->ok = ast_malloc(size * sizeof(char));
05986    if (!jb->ok) {
05987       ast_free(jb->samples);
05988       ast_free(jb);
05989       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05990       return NULL;
05991    }
05992 
05993    for (i = 0; i < size; i++) {
05994       jb->ok[i] = 0;
05995    }
05996 
05997    ast_mutex_init(&jb->mutexjb);
05998 
05999    return jb;
06000 }
06001 
06002 /* frees the data and destroys the given jitterbuffer struct */
06003 void misdn_jb_destroy(struct misdn_jb *jb)
06004 {
06005    ast_mutex_destroy(&jb->mutexjb);
06006    
06007    ast_free(jb->ok);
06008    ast_free(jb->samples);
06009    ast_free(jb);
06010 }
06011 
06012 /* fills the jitterbuffer with len data returns < 0 if there was an
06013    error (buffer overflow). */
06014 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
06015 {
06016    int i, j, rp, wp;
06017 
06018    if (!jb || ! data) {
06019       return 0;
06020    }
06021 
06022    ast_mutex_lock(&jb->mutexjb);
06023    
06024    wp = jb->wp;
06025    rp = jb->rp;
06026    
06027    for (i = 0; i < len; i++) {
06028       jb->samples[wp] = data[i];
06029       jb->ok[wp] = 1;
06030       wp = (wp != jb->size - 1) ? wp + 1 : 0;
06031 
06032       if (wp == jb->rp) {
06033          jb->state_full = 1;
06034       }
06035    }
06036 
06037    if (wp >= rp) {
06038       jb->state_buffer = wp - rp;
06039    } else {
06040       jb->state_buffer = jb->size - rp + wp;
06041    }
06042    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
06043 
06044    if (jb->state_full) {
06045       jb->wp = wp;
06046 
06047       rp = wp;
06048       for (j = 0; j < jb->upper_threshold; j++) {
06049          rp = (rp != 0) ? rp - 1 : jb->size - 1;
06050       }
06051       jb->rp = rp;
06052       jb->state_full = 0;
06053       jb->state_empty = 1;
06054 
06055       ast_mutex_unlock(&jb->mutexjb);
06056 
06057       return -1;
06058    }
06059 
06060    if (!jb->state_empty) {
06061       jb->bytes_wrote += len;
06062       if (jb->bytes_wrote >= jb->upper_threshold) {
06063          jb->state_empty = 1;
06064          jb->bytes_wrote = 0;
06065       }
06066    }
06067    jb->wp = wp;
06068 
06069    ast_mutex_unlock(&jb->mutexjb);
06070    
06071    return 0;
06072 }
06073 
06074 /* gets len bytes out of the jitterbuffer if available, else only the
06075 available data is returned and the return value indicates the number
06076 of data. */
06077 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
06078 {
06079    int i, wp, rp, read = 0;
06080 
06081    ast_mutex_lock(&jb->mutexjb);
06082 
06083    rp = jb->rp;
06084    wp = jb->wp;
06085 
06086    if (jb->state_empty) {  
06087       for (i = 0; i < len; i++) {
06088          if (wp == rp) {
06089             jb->rp = rp;
06090             jb->state_empty = 0;
06091 
06092             ast_mutex_unlock(&jb->mutexjb);
06093 
06094             return read;
06095          } else {
06096             if (jb->ok[rp] == 1) {
06097                data[i] = jb->samples[rp];
06098                jb->ok[rp] = 0;
06099                rp = (rp != jb->size - 1) ? rp + 1 : 0;
06100                read += 1;
06101             }
06102          }
06103       }
06104 
06105       if (wp >= rp) {
06106          jb->state_buffer = wp - rp;
06107       } else {
06108          jb->state_buffer = jb->size - rp + wp;
06109       }
06110       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
06111 
06112       jb->rp = rp;
06113    } else {
06114       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
06115    }
06116 
06117    ast_mutex_unlock(&jb->mutexjb);
06118 
06119    return read;
06120 }
06121 
06122 
06123 
06124 
06125 /*******************************************************/
06126 /*************** JITTERBUFFER  END *********************/
06127 /*******************************************************/
06128 
06129 
06130 
06131 
06132 static void chan_misdn_log(int level, int port, char *tmpl, ...)
06133 {
06134    va_list ap;
06135    char buf[1024];
06136    char port_buf[8];
06137 
06138    if (! ((0 <= port) && (port <= max_ports))) {
06139       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
06140       port = 0;
06141       level = -1;
06142    }
06143 
06144    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
06145 
06146    va_start(ap, tmpl);
06147    vsnprintf(buf, sizeof(buf), tmpl, ap);
06148    va_end(ap);
06149 
06150    if (level == -1) {
06151       ast_log(LOG_WARNING, "%s", buf);
06152 
06153    } else if (misdn_debug_only[port] ? 
06154          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
06155        : level <= misdn_debug[port]) {
06156       
06157       ast_console_puts(port_buf);
06158       ast_console_puts(buf);
06159    }
06160    
06161    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
06162       char ctimebuf[30];
06163       time_t tm = time(NULL);
06164       char *tmp = ctime_r(&tm, ctimebuf), *p;
06165 
06166       FILE *fp = fopen(global_tracefile, "a+");
06167 
06168       if ((p = strchr(tmp, '\n'))) {
06169          *p = ':';
06170       }
06171       
06172       if (!fp) {
06173          ast_console_puts("Error opening Tracefile: [ ");
06174          ast_console_puts(global_tracefile);
06175          ast_console_puts(" ] ");
06176          
06177          ast_console_puts(strerror(errno));
06178          ast_console_puts("\n");
06179          return ;
06180       }
06181       
06182       fputs(tmp, fp);
06183       fputs(" ", fp);
06184       fputs(port_buf, fp);
06185       fputs(" ", fp);
06186       fputs(buf, fp);
06187 
06188       fclose(fp);
06189    }
06190 }
06191 
06192 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
06193    .load = load_module,
06194    .unload = unload_module,
06195    .reload = reload,
06196 );