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

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