Wed Mar 3 22:36:19 2010

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

Generated on 3 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1