Thu Dec 17 13:33:29 2009

Asterisk developer's documentation


chan_dahdi.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.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 /*! \file
00020  *
00021  * \brief DAHDI Pseudo TDM interface 
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  * 
00025  * Connects to the DAHDI telephony library as well as 
00026  * libpri. Libpri is optional and needed only if you are
00027  * going to use ISDN connections.
00028  *
00029  * You need to install libraries before you attempt to compile
00030  * and install the DAHDI channel.
00031  *
00032  * \par See also
00033  * \arg \ref Config_dahdi
00034  *
00035  * \ingroup channel_drivers
00036  *
00037  * \todo Deprecate the "musiconhold" configuration option post 1.4
00038  */
00039 
00040 /*** MODULEINFO
00041    <depend>res_smdi</depend>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <depend>res_features</depend>
00045    <use>pri</use>
00046    <use>openr2</use>
00047  ***/
00048 
00049 #include "asterisk.h"
00050 
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 227275 $")
00052 
00053 #include <stdio.h>
00054 #include <string.h>
00055 #ifdef __NetBSD__
00056 #include <pthread.h>
00057 #include <signal.h>
00058 #else
00059 #include <sys/signal.h>
00060 #endif
00061 #include <errno.h>
00062 #include <stdlib.h>
00063 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00064 #include <stdint.h>
00065 #endif
00066 #include <unistd.h>
00067 #include <sys/ioctl.h>
00068 #include <math.h>
00069 #include <ctype.h>
00070 
00071 #ifdef HAVE_PRI
00072 #include <libpri.h>
00073 #endif
00074 
00075 #ifdef HAVE_OPENR2
00076 #include <openr2.h>
00077 #endif
00078 
00079 #include "asterisk/lock.h"
00080 #include "asterisk/channel.h"
00081 #include "asterisk/config.h"
00082 #include "asterisk/logger.h"
00083 #include "asterisk/module.h"
00084 #include "asterisk/pbx.h"
00085 #include "asterisk/options.h"
00086 #include "asterisk/file.h"
00087 #include "asterisk/ulaw.h"
00088 #include "asterisk/alaw.h"
00089 #include "asterisk/callerid.h"
00090 #include "asterisk/adsi.h"
00091 #include "asterisk/cli.h"
00092 #include "asterisk/cdr.h"
00093 #include "asterisk/features.h"
00094 #include "asterisk/musiconhold.h"
00095 #include "asterisk/say.h"
00096 #include "asterisk/tdd.h"
00097 #include "asterisk/app.h"
00098 #include "asterisk/dsp.h"
00099 #include "asterisk/astdb.h"
00100 #include "asterisk/manager.h"
00101 #include "asterisk/causes.h"
00102 #include "asterisk/term.h"
00103 #include "asterisk/utils.h"
00104 #include "asterisk/transcap.h"
00105 #include "asterisk/stringfields.h"
00106 #include "asterisk/abstract_jb.h"
00107 #include "asterisk/smdi.h"
00108 #include "asterisk/astobj.h"
00109 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00110 
00111 #include "asterisk/dahdi_compat.h"
00112 #include "asterisk/tonezone_compat.h"
00113 
00114 /*! Global jitterbuffer configuration - by default, jb is disabled */
00115 static struct ast_jb_conf default_jbconf =
00116 {
00117    .flags = 0,
00118    .max_size = -1,
00119    .resync_threshold = -1,
00120    .impl = ""
00121 };
00122 static struct ast_jb_conf global_jbconf;
00123 
00124 #ifndef DAHDI_TONEDETECT
00125 /* Work around older code with no tone detect */
00126 #define DAHDI_EVENT_DTMFDOWN 0
00127 #define DAHDI_EVENT_DTMFUP 0
00128 #endif
00129 
00130 /* define this to send PRI user-user information elements */
00131 #undef SUPPORT_USERUSER
00132 
00133 /*! 
00134  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00135  * the user hangs up to reset the state machine so ring works properly.
00136  * This is used to be able to support kewlstart by putting the zhone in
00137  * groundstart mode since their forward disconnect supervision is entirely
00138  * broken even though their documentation says it isn't and their support
00139  * is entirely unwilling to provide any assistance with their channel banks
00140  * even though their web site says they support their products for life.
00141  */
00142 /* #define ZHONE_HACK */
00143 
00144 /*! \note
00145  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00146  * before dialing on it.  Certain FXO interfaces always think they're out of
00147  * service with this method however.
00148  */
00149 /* #define DAHDI_CHECK_HOOKSTATE */
00150 
00151 /*! \brief Typically, how many rings before we should send Caller*ID */
00152 #define DEFAULT_CIDRINGS 1
00153 
00154 #define CHANNEL_PSEUDO -12
00155 
00156 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00157 
00158 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00159 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) 
00160 
00161 static const char tdesc[] = "DAHDI Telephony Driver"
00162 #ifdef HAVE_PRI
00163                " w/PRI"
00164 #endif
00165 #ifdef HAVE_OPENR2
00166           " w/OPENR2"
00167 #endif
00168 ;
00169 
00170 #define SIG_EM    DAHDI_SIG_EM
00171 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00175 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00178 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI      DAHDI_SIG_CLEAR
00186 #define SIG_MFCR2 DAHDI_SIG_CAS
00187 #define  SIG_SF      DAHDI_SIG_SF
00188 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00189 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00190 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00191 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00192 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00193 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00194 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00195 
00196 #define NUM_SPANS       32
00197 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00198 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00199 
00200 #define CHAN_PSEUDO  -2
00201 
00202 #define DCHAN_PROVISIONED (1 << 0)
00203 #define DCHAN_NOTINALARM  (1 << 1)
00204 #define DCHAN_UP          (1 << 2)
00205 
00206 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00207 
00208 /* Overlap dialing option types */
00209 #define DAHDI_OVERLAPDIAL_NONE 0
00210 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00211 #define DAHDI_OVERLAPDIAL_INCOMING 2
00212 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00213 
00214 static char defaultcic[64] = "";
00215 static char defaultozz[64] = "";
00216 
00217 static char progzone[10] = "";
00218 
00219 static int distinctiveringaftercid = 0;
00220 
00221 static int numbufs = 4;
00222 
00223 #ifdef HAVE_PRI
00224 static struct ast_channel inuse;
00225 #ifdef PRI_GETSET_TIMERS
00226 static int pritimers[PRI_MAX_TIMERS];
00227 #endif
00228 static int pridebugfd = -1;
00229 static char pridebugfilename[1024] = "";
00230 #endif
00231 
00232 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00233 static int firstdigittimeout = 16000;
00234 
00235 /*! \brief How long to wait for following digits (FXO logic) */
00236 static int gendigittimeout = 8000;
00237 
00238 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00239 static int matchdigittimeout = 3000;
00240 
00241 /*! \brief Protect the interface list (of dahdi_pvt's) */
00242 AST_MUTEX_DEFINE_STATIC(iflock);
00243 
00244 
00245 static int ifcount = 0;
00246 
00247 #ifdef HAVE_PRI
00248 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00249 #endif
00250 
00251 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00252    when it's doing something critical. */
00253 AST_MUTEX_DEFINE_STATIC(monlock);
00254 
00255 /*! \brief This is the thread for the monitor which checks for input on the channels
00256    which are not currently in use. */
00257 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00258 static ast_cond_t ss_thread_complete;
00259 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00260 AST_MUTEX_DEFINE_STATIC(restart_lock);
00261 static int ss_thread_count = 0;
00262 static int num_restart_pending = 0;
00263 
00264 static int restart_monitor(void);
00265 
00266 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00267 
00268 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00269 
00270 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00271 static inline int dahdi_get_event(int fd)
00272 {
00273    int j;
00274    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00275       return -1;
00276    return j;
00277 }
00278 
00279 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00280 static inline int dahdi_wait_event(int fd)
00281 {
00282    int i, j = 0;
00283    i = DAHDI_IOMUX_SIGEVENT;
00284    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00285       return -1;
00286    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00287       return -1;
00288    return j;
00289 }
00290 
00291 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00292 #define READ_SIZE 160
00293 
00294 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00295 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00296 
00297 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00298 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00299 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00300 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00301 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00302 
00303 struct dahdi_pvt;
00304 
00305 /*!
00306  * \brief Configured ring timeout base.
00307  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00308  */
00309 static int ringt_base = DEFAULT_RINGT;
00310 
00311 #ifdef HAVE_OPENR2
00312 
00313 struct dahdi_mfcr2 {
00314    pthread_t master;           /*!< Thread of master */
00315    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */ 
00316    struct dahdi_pvt *pvts[MAX_CHANNELS];     /*!< Member channel pvt structs */
00317    int numchans;                          /*!< Number of channels in this R2 block */
00318 };
00319 
00320 static struct dahdi_mfcr2 r2links[NUM_SPANS];
00321 static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN;
00322 static int mfcr2_cur_mfback_timeout = -1;
00323 static int mfcr2_cur_metering_pulse_timeout = -1;
00324 static int mfcr2_cur_max_ani = 10;
00325 static int mfcr2_cur_max_dnis = 4;
00326 static int mfcr2_cur_get_ani_first = -1;
00327 static int mfcr2_cur_skip_category = -1;
00328 static int mfcr2_cur_context_index = 0;
00329 static int mfcr2_cur_call_files = 0;
00330 static int mfcr2_cur_allow_collect_calls = 0;
00331 static int mfcr2_cur_accept_on_offer = 1;
00332 static int mfcr2_cur_charge_calls = 1;
00333 static int mfcr2_cur_forced_release = 0;
00334 static int mfcr2_cur_double_answer = 0;
00335 static int mfcr2_cur_immediate_accept = -1;
00336 /* starting with openr2 interface 3 we have DTMF support */
00337 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00338 static int mfcr2_cur_dtmf_dialing = -1;
00339 static int mfcr2_cur_dtmf_detection = -1;
00340 static int mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
00341 static int mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
00342 #endif
00343 static char mfcr2_cur_logdir[OR2_MAX_PATH];
00344 static char mfcr2_cur_r2proto_file[OR2_MAX_PATH];
00345 static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
00346 static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
00347 
00348 #endif /* HAVE_OPENR2 */
00349 
00350 #ifdef HAVE_PRI
00351 
00352 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00353 #define PRI_CHANNEL(p) ((p) & 0xff)
00354 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00355 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00356 
00357 struct dahdi_pri {
00358    pthread_t master;                /*!< Thread of master */
00359    ast_mutex_t lock;                /*!< Mutex */
00360    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00361    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00362    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00363    int minunused;                   /*!< Min # of channels to keep empty */
00364    int minidle;                     /*!< Min # of "idling" calls to keep active */
00365    int nodetype;                    /*!< Node type */
00366    int switchtype;                     /*!< Type of switch to emulate */
00367    int nsf;                   /*!< Network-Specific Facilities */
00368    int dialplan;                    /*!< Dialing plan */
00369    int localdialplan;                  /*!< Local dialing plan */
00370    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00371    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00372    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00373    char privateprefix[20];                /*!< for private dialplans */
00374    char unknownprefix[20];                /*!< for unknown dialplans */
00375    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00376    int trunkgroup;                     /*!< What our trunkgroup is */
00377    int mastertrunkgroup;                  /*!< What trunk group is our master */
00378    int prilogicalspan;                 /*!< Logical span number within trunk group */
00379    int numchans;                    /*!< Num of channels we represent */
00380    int overlapdial;                 /*!< In overlap dialing mode */
00381    int facilityenable;                 /*!< Enable facility IEs */
00382    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00383    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00384    struct pri *pri;                 /*!< Currently active D-channel */
00385    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00386    int debug;
00387    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00388    /*! \brief Value set but not used */
00389    int offset;
00390    /*! \brief Span number put into user output messages */
00391    int span;
00392    /*! \brief TRUE if span is being reset/restarted */
00393    int resetting;
00394    /*! \brief Current position during a reset (-1 if not started) */
00395    int resetpos;
00396 #ifdef HAVE_PRI_INBANDDISCONNECT
00397    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00398 #endif
00399    time_t lastreset;                /*!< time when unused channels were last reset */
00400    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00401    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00402    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00403    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00404 };
00405 
00406 
00407 static struct dahdi_pri pris[NUM_SPANS];
00408 
00409 #if 0
00410 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00411 #else
00412 #define DEFAULT_PRI_DEBUG 0
00413 #endif
00414 
00415 static inline void pri_rel(struct dahdi_pri *pri)
00416 {
00417    ast_mutex_unlock(&pri->lock);
00418 }
00419 
00420 #else
00421 /*! Shut up the compiler */
00422 struct dahdi_pri;
00423 #endif
00424 
00425 #define SUB_REAL  0        /*!< Active call */
00426 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00427 #define SUB_THREEWAY 2        /*!< Three-way call */
00428 
00429 /* Polarity states */
00430 #define POLARITY_IDLE   0
00431 #define POLARITY_REV    1
00432 
00433 
00434 static struct dahdi_distRings drings;
00435 
00436 struct distRingData {
00437    int ring[3];
00438 };
00439 struct ringContextData {
00440    char contextData[AST_MAX_CONTEXT];
00441 };
00442 struct dahdi_distRings {
00443    struct distRingData ringnum[3];
00444    struct ringContextData ringContext[3];
00445 };
00446 
00447 static char *subnames[] = {
00448    "Real",
00449    "Callwait",
00450    "Threeway"
00451 };
00452 
00453 struct dahdi_subchannel {
00454    int dfd;
00455    struct ast_channel *owner;
00456    int chan;
00457    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00458    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00459    unsigned int needringing:1;
00460    unsigned int needbusy:1;
00461    unsigned int needcongestion:1;
00462    unsigned int needcallerid:1;
00463    unsigned int needanswer:1;
00464    unsigned int needflash:1;
00465    unsigned int needhold:1;
00466    unsigned int needunhold:1;
00467    unsigned int linear:1;
00468    unsigned int inthreeway:1;
00469    struct dahdi_confinfo curconf;
00470 };
00471 
00472 #define CONF_USER_REAL     (1 << 0)
00473 #define CONF_USER_THIRDCALL   (1 << 1)
00474 
00475 #define MAX_SLAVES   4
00476 
00477 static struct dahdi_pvt {
00478    ast_mutex_t lock;
00479    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00480                      /*!< Up to three channels can be associated with this call */
00481       
00482    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00483    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00484    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00485 
00486    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00487    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00488    int inconference;          /*!< If our real should be in the conference */
00489    
00490    int buf_no;             /*!< Number of buffers */
00491    int buf_policy;            /*!< Buffer policy */
00492    int sig;             /*!< Signalling style */
00493    /*!
00494     * \brief Nonzero if the signaling type is sent over a radio.
00495     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00496     */
00497    int radio;
00498    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00499    int oprmode;               /*!< "Operator Services" mode */
00500    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00501    /*! \brief Rx gain set by chan_dahdi.conf */
00502    float rxgain;
00503    /*! \brief Tx gain set by chan_dahdi.conf */
00504    float txgain;
00505    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00506    struct dahdi_pvt *next;          /*!< Next channel in list */
00507    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00508 
00509    /* flags */
00510 
00511    /*!
00512     * \brief TRUE if ADSI (Analog Display Services Interface) available
00513     * \note Set from the "adsi" value read in from chan_dahdi.conf
00514     */
00515    unsigned int adsi:1;
00516    /*!
00517     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00518     * call is answered by the remote party.
00519     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00520     */
00521    unsigned int answeronpolarityswitch:1;
00522    /*!
00523     * \brief TRUE if busy detection is enabled.
00524     * (Listens for the beep-beep busy pattern.)
00525     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00526     */
00527    unsigned int busydetect:1;
00528    /*!
00529     * \brief TRUE if call return is enabled.
00530     * (*69, if your dialplan doesn't catch this first)
00531     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00532     */
00533    unsigned int callreturn:1;
00534    /*!
00535     * \brief TRUE if busy extensions will hear the call-waiting tone
00536     * and can use hook-flash to switch between callers.
00537     * \note Can be disabled by dialing *70.
00538     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00539     */
00540    unsigned int callwaiting:1;
00541    /*!
00542     * \brief TRUE if send caller ID for Call Waiting
00543     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00544     */
00545    unsigned int callwaitingcallerid:1;
00546    /*!
00547     * \brief TRUE if support for call forwarding enabled.
00548     * Dial *72 to enable call forwarding.
00549     * Dial *73 to disable call forwarding.
00550     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00551     */
00552    unsigned int cancallforward:1;
00553    /*!
00554     * \brief TRUE if support for call parking is enabled.
00555     * \note Set from the "canpark" value read in from chan_dahdi.conf
00556     */
00557    unsigned int canpark:1;
00558    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00559    unsigned int confirmanswer:1;
00560    /*!
00561     * \brief TRUE if the channel is to be destroyed on hangup.
00562     * (Used by pseudo channels.)
00563     */
00564    unsigned int destroy:1;
00565    unsigned int didtdd:1;           /*!< flag to say its done it once */
00566    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00567    unsigned int dialednone:1;
00568    /*! \brief TRUE if in the process of dialing digits or sending something. */
00569    unsigned int dialing:1;
00570    /*! \brief TRUE if the transfer capability of the call is digital. */
00571    unsigned int digital:1;
00572    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00573    unsigned int dnd:1;
00574    /*! \brief XXX BOOLEAN Purpose??? */
00575    unsigned int echobreak:1;
00576    /*!
00577     * \brief TRUE if echo cancellation enabled when bridged.
00578     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00579     * \note Disabled if the echo canceller is not setup.
00580     */
00581    unsigned int echocanbridged:1;
00582    /*! \brief TRUE if echo cancellation is turned on. */
00583    unsigned int echocanon:1;
00584    /*! \brief TRUE if a fax tone has already been handled. */
00585    unsigned int faxhandled:1;
00586    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00587    unsigned int firstradio:1;
00588    /*!
00589     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00590     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00591     */
00592    unsigned int hanguponpolarityswitch:1;
00593    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00594    unsigned int hardwaredtmf:1;
00595    /*!
00596     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00597     * \note Caller ID can be disabled by dialing *67.
00598     * \note Caller ID can be enabled by dialing *82.
00599     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00600     */
00601    unsigned int hidecallerid:1;
00602    /*!
00603     * \brief TRUE if hide just the name not the number for legacy PBX use.
00604     * \note Only applies to PRI channels.
00605     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00606     */
00607    unsigned int hidecalleridname:1;
00608    /*! \brief TRUE if DTMF detection is disabled. */
00609    unsigned int ignoredtmf:1;
00610    /*!
00611     * \brief TRUE if the channel should be answered immediately
00612     * without attempting to gather any digits.
00613     * \note Set from the "immediate" value read in from chan_dahdi.conf
00614     */
00615    unsigned int immediate:1;
00616    /*! \brief TRUE if in an alarm condition. */
00617    unsigned int inalarm:1;
00618    unsigned int unknown_alarm:1;
00619    /*! \brief TRUE if TDD in MATE mode */
00620    unsigned int mate:1;
00621    /*! \brief TRUE if we originated the call leg. */
00622    unsigned int outgoing:1;
00623    /* unsigned int overlapdial:1;         unused and potentially confusing */
00624    /*!
00625     * \brief TRUE if busy extensions will hear the call-waiting tone
00626     * and can use hook-flash to switch between callers.
00627     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00628     */
00629    unsigned int permcallwaiting:1;
00630    /*!
00631     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00632     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00633     */
00634    unsigned int permhidecallerid:1;
00635    /*!
00636     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00637     * \note Set from the "priindication" value read in from chan_dahdi.conf
00638     */
00639    unsigned int priindication_oob:1;
00640    /*!
00641     * \brief TRUE if PRI B channels are always exclusively selected.
00642     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00643     */
00644    unsigned int priexclusive:1;
00645    /*!
00646     * \brief TRUE if we will pulse dial.
00647     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00648     */
00649    unsigned int pulse:1;
00650    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00651    unsigned int pulsedial:1;
00652    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00653    /*!
00654     * \brief TRUE if caller ID is restricted.
00655     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00656     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00657     */
00658    unsigned int restrictcid:1;
00659    /*!
00660     * \brief TRUE if three way calling is enabled
00661     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00662     */
00663    unsigned int threewaycalling:1;
00664    /*!
00665     * \brief TRUE if call transfer is enabled
00666     * \note For FXS ports (either direct analog or over T1/E1):
00667     *   Support flash-hook call transfer
00668     * \note For digital ports using ISDN PRI protocols:
00669     *   Support switch-side transfer (called 2BCT, RLT or other names)
00670     * \note Set from the "transfer" value read in from chan_dahdi.conf
00671     */
00672    unsigned int transfer:1;
00673    /*!
00674     * \brief TRUE if caller ID is used on this channel.
00675     * \note PRI spans will save caller ID from the networking peer.
00676     * \note FXS ports will generate the caller ID spill.
00677     * \note FXO ports will listen for the caller ID spill.
00678     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00679     */
00680    unsigned int use_callerid:1;
00681    /*!
00682     * \brief TRUE if we will use the calling presentation setting
00683     * from the Asterisk channel for outgoing calls.
00684     * \note Only applies to PRI channels.
00685     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00686     */
00687    unsigned int use_callingpres:1;
00688    /*!
00689     * \brief TRUE if distinctive rings are to be detected.
00690     * \note For FXO lines
00691     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00692     */
00693    unsigned int usedistinctiveringdetection:1;
00694    /*!
00695     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00696     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00697     */
00698    unsigned int dahditrcallerid:1;
00699    /*!
00700     * \brief TRUE if allowed to flash-transfer to busy channels.
00701     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00702     */
00703    unsigned int transfertobusy:1;
00704 #if defined(HAVE_PRI)
00705    /*! \brief TRUE if channel is alerting/ringing */
00706    unsigned int alerting:1;
00707    /*! \brief TRUE if the call has already gone/hungup */
00708    unsigned int alreadyhungup:1;
00709    /*!
00710     * \brief TRUE if this is an idle call
00711     * \note Applies to PRI channels.
00712     */
00713    unsigned int isidlecall:1;
00714    /*!
00715     * \brief TRUE if call is in a proceeding state.
00716     * The call has started working its way through the network.
00717     */
00718    unsigned int proceeding:1;
00719    /*! \brief TRUE if the call has seen progress through the network. */
00720    unsigned int progress:1;
00721    /*!
00722     * \brief TRUE if this channel is being reset/restarted
00723     * \note Applies to PRI channels.
00724     */
00725    unsigned int resetting:1;
00726    /*!
00727     * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
00728     * \note Applies to PRI channels.
00729     */
00730    unsigned int setup_ack:1;
00731 #endif
00732    /*!
00733     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00734     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00735     */
00736    unsigned int use_smdi:1;
00737    /*! \brief The serial port to listen for SMDI data on */
00738    struct ast_smdi_interface *smdi_iface;
00739 
00740    /*! \brief Distinctive Ring data */
00741    struct dahdi_distRings drings;
00742 
00743    /*!
00744     * \brief The configured context for incoming calls.
00745     * \note The "context" string read in from chan_dahdi.conf
00746     */
00747    char context[AST_MAX_CONTEXT];
00748    /*!
00749     * \brief Saved context string.
00750     */
00751    char defcontext[AST_MAX_CONTEXT];
00752    /*! \brief Extension to use in the dialplan. */
00753    char exten[AST_MAX_EXTENSION];
00754    /*!
00755     * \brief Language configured for calls.
00756     * \note The "language" string read in from chan_dahdi.conf
00757     */
00758    char language[MAX_LANGUAGE];
00759    /*!
00760     * \brief The configured music-on-hold class to use for calls.
00761     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00762     */
00763    char mohinterpret[MAX_MUSICCLASS];
00764    /*!
00765     * \brief Sugggested music-on-hold class for peer channel to use for calls.
00766     * \note The "mohsuggest" string read in from chan_dahdi.conf
00767     */
00768    char mohsuggest[MAX_MUSICCLASS];
00769 #ifdef PRI_ANI
00770    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
00771    char cid_ani[AST_MAX_EXTENSION];
00772 #endif
00773    /*! \brief Caller ID number from an incoming call. */
00774    char cid_num[AST_MAX_EXTENSION];
00775    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
00776    int cid_ton;
00777    /*! \brief Caller ID name from an incoming call. */
00778    char cid_name[AST_MAX_EXTENSION];
00779    /*! \brief Last Caller ID number from an incoming call. */
00780    char lastcid_num[AST_MAX_EXTENSION];
00781    /*! \brief Last Caller ID name from an incoming call. */
00782    char lastcid_name[AST_MAX_EXTENSION];
00783    char *origcid_num;            /*!< malloced original callerid */
00784    char *origcid_name;           /*!< malloced original callerid */
00785    /*! \brief Call waiting number. */
00786    char callwait_num[AST_MAX_EXTENSION];
00787    /*! \brief Call waiting name. */
00788    char callwait_name[AST_MAX_EXTENSION];
00789    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
00790    char rdnis[AST_MAX_EXTENSION];
00791    /*! \brief Dialed Number Identifier */
00792    char dnid[AST_MAX_EXTENSION];
00793    /*!
00794     * \brief Bitmapped groups this belongs to.
00795     * \note The "group" bitmapped group string read in from chan_dahdi.conf
00796     */
00797    ast_group_t group;
00798    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
00799    int law;
00800    int confno;             /*!< Our conference */
00801    int confusers;             /*!< Who is using our conference */
00802    int propconfno;               /*!< Propagated conference number */
00803    /*!
00804     * \brief Bitmapped call groups this belongs to.
00805     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
00806     */
00807    ast_group_t callgroup;
00808    /*!
00809     * \brief Bitmapped pickup groups this belongs to.
00810     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
00811     */
00812    ast_group_t pickupgroup;
00813    int channel;               /*!< Channel Number or CRV */
00814    int span;               /*!< Span number */
00815    time_t guardtime;          /*!< Must wait this much time before using for new call */
00816    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
00817    int cid_start;             /*!< CID start indicator, polarity or ring */
00818    int callingpres;           /*!< The value of callling presentation that we're going to use when placing a PRI call */
00819    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
00820    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
00821    /*! \brief Analog caller ID waveform sample buffer */
00822    unsigned char *cidspill;
00823    /*! \brief Position in the cidspill buffer to send out next. */
00824    int cidpos;
00825    /*! \brief Length of the cidspill buffer containing samples. */
00826    int cidlen;
00827    /*! \brief Ring timeout timer?? */
00828    int ringt;
00829    /*!
00830     * \brief Ring timeout base.
00831     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
00832     */
00833    int ringt_base;
00834    /*!
00835     * \brief Number of most significant digits/characters to strip from the dialed number.
00836     * \note Feature is deprecated.  Use dialplan logic.
00837     * \note The characters are stripped before the PRI TON/NPI prefix
00838     * characters are processed.
00839     */
00840    int stripmsd;
00841    /*! \brief BOOLEAN. XXX Meaning what?? */
00842    int callwaitcas;
00843    /*! \brief Number of call waiting rings. */
00844    int callwaitrings;
00845    /*! \brief Number of echo cancel taps.  0 if echo canceller not requested. */
00846    int echocancel;
00847    /*!
00848     * \brief Echo training time. 0 = disabled
00849     * \note Set from the "echotraining" value read in from chan_dahdi.conf
00850     */
00851    int echotraining;
00852    /*! \brief Filled with 'w'.  XXX Purpose?? */
00853    char echorest[20];
00854    /*!
00855     * \brief Number of times to see "busy" tone before hanging up.
00856     * \note Set from the "busycount" value read in from chan_dahdi.conf
00857     */
00858    int busycount;
00859    /*!
00860     * \brief If your country has a busy tone with the same length tone and silence (as many countries do), consider using this option in order to compare tone and silence lengths
00861     * \note Set from the "busycompare" value read in from chan_dahdi.conf
00862     */
00863    int busycompare;
00864    /*!
00865     * \brief Lenght of "tone" in ms.
00866     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00867     */
00868    int busytonelength;
00869    /*!
00870     * \brief Lenght of "silence" in ms.
00871     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00872     */
00873    int busyquietlength;
00874    /*!
00875     * \brief  Maximun percentage difference allowed between measured and actual pattern
00876     * \note Set from the "busyfuzziness" value read in from chan_dahdi.conf
00877     */
00878    int busyfuzziness;
00879    /*!
00880     * \brief Maximun signal average level considered as silence in this channel
00881     * \note Set from the "silencethreshold" value read in from chan_dahdi.conf
00882     */
00883    int silencethreshold;
00884    /*!
00885     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
00886     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
00887     */
00888    int callprogress;
00889    struct timeval flashtime;        /*!< Last flash-hook time */
00890    /*! \brief Opaque DSP configuration structure. */
00891    struct ast_dsp *dsp;
00892    //int cref;             /*!< Call reference number (Not used) */
00893    /*! \brief DAHDI dial operation command struct for ioctl() call. */
00894    struct dahdi_dialoperation dop;
00895    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
00896    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
00897    char finaldial[64];
00898    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
00899    int amaflags;              /*!< AMA Flags */
00900    struct tdd_state *tdd;           /*!< TDD flag */
00901    /*! \brief Accumulated call forwarding number. */
00902    char call_forward[AST_MAX_EXTENSION];
00903    /*!
00904     * \brief Voice mailbox location.
00905     * \note Set from the "mailbox" string read in from chan_dahdi.conf
00906     */
00907    char mailbox[AST_MAX_EXTENSION];
00908    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
00909    char dialdest[256];
00910    /*! \brief Time the interface went on-hook. */
00911    int onhooktime;
00912    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
00913    int msgstate;
00914    int distinctivering;          /*!< Which distinctivering to use */
00915    int cidrings;              /*!< Which ring to deliver CID on */
00916    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
00917    /*! \brief Holding place for event injected from outside normal operation. */
00918    int fake_event;
00919    /*!
00920     * \brief Minimal time period (ms) between the answer polarity
00921     * switch and hangup polarity switch.
00922     */
00923    int polarityonanswerdelay;
00924    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
00925    struct timeval polaritydelaytv;
00926    /*!
00927     * \brief Send caller ID after this many rings.
00928     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
00929     */
00930    int sendcalleridafter;
00931 #ifdef HAVE_PRI
00932    /*! \brief DAHDI PRI control parameters */
00933    struct dahdi_pri *pri;
00934    /*! \brief XXX Purpose??? */
00935    struct dahdi_pvt *bearer;
00936    /*! \brief XXX Purpose??? */
00937    struct dahdi_pvt *realcall;
00938    /*! \brief Opaque libpri call control structure */
00939    q931_call *call;
00940    /*! \brief Channel number in span. */
00941    int prioffset;
00942    /*! \brief Logical span number within trunk group */
00943    int logicalspan;
00944 #endif   
00945 #ifdef HAVE_OPENR2
00946    int mfcr2call;
00947    int mfcr2block;
00948    struct dahdi_mfcr2 *mfcr2;
00949    openr2_chan_t *r2chan;
00950    openr2_calling_party_category_t mfcr2_recvd_category;
00951    openr2_calling_party_category_t mfcr2_category;
00952    int mfcr2_accept_on_offer;
00953    int mfcr2_charge_calls;
00954    int mfcr2_allow_collect_calls;
00955    int mfcr2_forced_release;
00956    int mfcr2_dnis_index;
00957    int mfcr2_ani_index;
00958    int mfcr2_dnis_matched;
00959    int mfcr2_call_accepted;
00960 #endif
00961    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
00962    int polarity;
00963    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
00964    int dsp_features;
00965    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
00966    char begindigit;
00967 } *iflist = NULL, *ifend = NULL;
00968 
00969 /*! \brief Channel configuration from chan_dahdi.conf .
00970  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
00971  * Generally there is a field here for every possible configuration item.
00972  *
00973  * The state of fields is saved along the parsing and whenever a 'channel'
00974  * statement is reached, the current dahdi_chan_conf is used to configure the 
00975  * channel (struct dahdi_pvt)
00976  *
00977  * @seealso dahdi_chan_init for the default values.
00978  */
00979 struct dahdi_chan_conf {
00980    struct dahdi_pvt chan;
00981 #ifdef HAVE_PRI
00982    struct dahdi_pri pri;
00983 #endif
00984    struct dahdi_params timing;
00985 
00986    /*!
00987     * \brief The serial port to listen for SMDI data on
00988     * \note Set from the "smdiport" string read in from chan_dahdi.conf
00989     */
00990    char smdi_port[SMDI_MAX_FILENAME_LEN];
00991 };
00992 
00993 /** returns a new dahdi_chan_conf with default values (by-value) */
00994 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00995    /* recall that if a field is not included here it is initialized
00996     * to 0 or equivalent
00997     */
00998    struct dahdi_chan_conf conf = {
00999 #ifdef HAVE_PRI
01000       .pri = {
01001          .nsf = PRI_NSF_NONE,
01002          .switchtype = PRI_SWITCH_NI2,
01003          .dialplan = PRI_NATIONAL_ISDN + 1,
01004          .localdialplan = PRI_NATIONAL_ISDN + 1,
01005          .nodetype = PRI_CPE,
01006 
01007          .minunused = 2,
01008          .idleext = "",
01009          .idledial = "",
01010          .internationalprefix = "",
01011          .nationalprefix = "",
01012          .localprefix = "",
01013          .privateprefix = "",
01014          .unknownprefix = "",
01015 
01016          .resetinterval = 3600
01017       },
01018 #endif
01019       .chan = {
01020          .context = "default",
01021          .cid_num = "",
01022          .cid_name = "",
01023          .mohinterpret = "default",
01024          .mohsuggest = "",
01025          .transfertobusy = 1,
01026 
01027          .cid_signalling = CID_SIG_BELL,
01028          .cid_start = CID_START_RING,
01029          .dahditrcallerid = 0,
01030          .use_callerid = 1,
01031          .sig = -1,
01032          .outsigmod = -1,
01033 
01034          .tonezone = -1,
01035 
01036          .echocancel = 1,
01037 
01038          .busycount = 3,
01039          .busycompare = 0,
01040          .busytonelength = 0,
01041          .busyquietlength = 0,
01042          .busyfuzziness = 0,
01043          .silencethreshold = 0,
01044 
01045          .accountcode = "",
01046 
01047          .mailbox = "",
01048 
01049 
01050          .polarityonanswerdelay = 600,
01051 
01052          .sendcalleridafter = DEFAULT_CIDRINGS,
01053 
01054          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01055          .buf_no = numbufs
01056       },
01057       .timing = {
01058          .prewinktime = -1,
01059          .preflashtime = -1,
01060          .winktime = -1,
01061          .flashtime = -1,
01062          .starttime = -1,
01063          .rxwinktime = -1,
01064          .rxflashtime = -1,
01065          .debouncetime = -1
01066       },
01067       .smdi_port = "/dev/ttyS0",
01068    };
01069 
01070    return conf;
01071 }
01072 
01073 
01074 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01075 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01076 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01077 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01078 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01079 static int dahdi_hangup(struct ast_channel *ast);
01080 static int dahdi_answer(struct ast_channel *ast);
01081 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01082 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01083 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01084 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01085 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01086 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01087 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
01088 
01089 static const struct ast_channel_tech dahdi_tech = {
01090    .type = "DAHDI",
01091    .description = tdesc,
01092    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01093    .requester = dahdi_request,
01094    .send_digit_begin = dahdi_digit_begin,
01095    .send_digit_end = dahdi_digit_end,
01096    .send_text = dahdi_sendtext,
01097    .call = dahdi_call,
01098    .hangup = dahdi_hangup,
01099    .answer = dahdi_answer,
01100    .read = dahdi_read,
01101    .write = dahdi_write,
01102    .bridge = dahdi_bridge,
01103    .exception = dahdi_exception,
01104    .indicate = dahdi_indicate,
01105    .fixup = dahdi_fixup,
01106    .setoption = dahdi_setoption,
01107    .func_channel_read = dahdi_func_read,
01108 };
01109 
01110 static const struct ast_channel_tech zap_tech = {
01111    .type = "Zap",
01112    .description = tdesc,
01113    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01114    .requester = dahdi_request,
01115    .send_digit_begin = dahdi_digit_begin,
01116    .send_digit_end = dahdi_digit_end,
01117    .send_text = dahdi_sendtext,
01118    .call = dahdi_call,
01119    .hangup = dahdi_hangup,
01120    .answer = dahdi_answer,
01121    .read = dahdi_read,
01122    .write = dahdi_write,
01123    .bridge = dahdi_bridge,
01124    .exception = dahdi_exception,
01125    .indicate = dahdi_indicate,
01126    .fixup = dahdi_fixup,
01127    .setoption = dahdi_setoption,
01128    .func_channel_read = dahdi_func_read,
01129 };
01130 
01131 static const struct ast_channel_tech *chan_tech;
01132 
01133 #ifdef HAVE_PRI
01134 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01135 #else
01136 #define GET_CHANNEL(p) ((p)->channel)
01137 #endif
01138 
01139 struct dahdi_pvt *round_robin[32];
01140 
01141 #ifdef HAVE_PRI
01142 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01143 {
01144    int res;
01145    /* Grab the lock first */
01146    do {
01147       res = ast_mutex_trylock(&pri->lock);
01148       if (res) {
01149          DEADLOCK_AVOIDANCE(&pvt->lock);
01150       }
01151    } while (res);
01152    /* Then break the poll */
01153    if (pri->master != AST_PTHREADT_NULL)
01154       pthread_kill(pri->master, SIGURG);
01155    return 0;
01156 }
01157 #endif
01158 
01159 #define NUM_CADENCE_MAX 25
01160 static int num_cadence = 4;
01161 static int user_has_defined_cadences = 0;
01162 
01163 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01164    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01165    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01166    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01167    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01168 };
01169 
01170 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01171  * is 1, the second pause is 2 and so on.
01172  */
01173 
01174 static int cidrings[NUM_CADENCE_MAX] = {
01175    2,                            /*!< Right after first long ring */
01176    4,                            /*!< Right after long part */
01177    3,                            /*!< After third chirp */
01178    2,                            /*!< Second spell */
01179 };
01180 
01181 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01182          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01183 
01184 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01185 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01186 
01187 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01188 {
01189    int res;
01190    if (p->subs[SUB_REAL].owner == ast)
01191       res = 0;
01192    else if (p->subs[SUB_CALLWAIT].owner == ast)
01193       res = 1;
01194    else if (p->subs[SUB_THREEWAY].owner == ast)
01195       res = 2;
01196    else {
01197       res = -1;
01198       if (!nullok)
01199          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01200    }
01201    return res;
01202 }
01203 
01204 #ifdef HAVE_PRI
01205 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01206 #else
01207 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01208 #endif
01209 {
01210 #ifdef HAVE_PRI
01211    if (pri)
01212       ast_mutex_unlock(&pri->lock);
01213 #endif         
01214    for (;;) {
01215       if (p->subs[a].owner) {
01216          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01217             DEADLOCK_AVOIDANCE(&p->lock);
01218          } else {
01219             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01220             ast_mutex_unlock(&p->subs[a].owner->lock);
01221             break;
01222          }
01223       } else
01224          break;
01225    }
01226 #ifdef HAVE_PRI
01227    if (pri)
01228       ast_mutex_lock(&pri->lock);
01229 #endif         
01230 }
01231 
01232 #ifdef HAVE_PRI
01233 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01234 #else
01235 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01236 #endif
01237 {
01238    /* We must unlock the PRI to avoid the possibility of a deadlock */
01239 #ifdef HAVE_PRI
01240    if (pri)
01241       ast_mutex_unlock(&pri->lock);
01242 #endif      
01243    for (;;) {
01244       if (p->owner) {
01245          if (ast_mutex_trylock(&p->owner->lock)) {
01246             DEADLOCK_AVOIDANCE(&p->lock);
01247          } else {
01248             ast_queue_frame(p->owner, f);
01249             ast_mutex_unlock(&p->owner->lock);
01250             break;
01251          }
01252       } else
01253          break;
01254    }
01255 #ifdef HAVE_PRI
01256    if (pri)
01257       ast_mutex_lock(&pri->lock);
01258 #endif      
01259 }
01260 
01261 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability);
01262 #ifdef HAVE_OPENR2
01263 static void init_mfcr2_globals(void)
01264 {
01265    int r;
01266    mfcr2_cur_context_index = 0;
01267    mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01268    mfcr2_cur_mfback_timeout = -1;
01269    mfcr2_cur_metering_pulse_timeout = -1;
01270    mfcr2_cur_max_ani = 10;
01271    mfcr2_cur_max_dnis = 4;
01272    mfcr2_cur_get_ani_first = -1;
01273 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01274    mfcr2_cur_dtmf_dialing = -1;
01275    mfcr2_cur_dtmf_detection = -1;
01276    mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01277    mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01278 #endif
01279    mfcr2_cur_skip_category = -1;
01280    mfcr2_cur_call_files = 0;
01281    mfcr2_cur_allow_collect_calls = 0;
01282    mfcr2_cur_forced_release = 0;
01283    mfcr2_cur_double_answer = 0;
01284    mfcr2_cur_immediate_accept = -1;
01285    mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01286    mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01287    memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01288    memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01289    memset(r2links, 0, sizeof(r2links));
01290    for (r = 0; r < NUM_SPANS; r++) {
01291       r2links[r].master = AST_PTHREADT_NULL;
01292    }
01293 }
01294 
01295 static int dahdi_r2_answer(struct dahdi_pvt *p)
01296 {
01297    int res = 0;
01298    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01299     * and does not has support for openr2_chan_answer_call_with_mode
01300     *  */
01301 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01302    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01303    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01304    if (!double_answer) {
01305       /* this still can result in double answer if the channel context 
01306        * was configured that way */
01307       res = openr2_chan_answer_call(p->r2chan);
01308    } else if (wants_double_answer) {
01309       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01310    } else {
01311       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01312    } 
01313 #else
01314    res = openr2_chan_answer_call(p->r2chan);
01315 #endif
01316    return res;
01317 }
01318 
01319 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01320 {
01321    openr2_calling_party_category_t cat;
01322    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01323    struct dahdi_pvt *p = c->tech_pvt;
01324    if (ast_strlen_zero(catstr)) {
01325       ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 
01326             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01327       return p->mfcr2_category;
01328    }
01329    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01330       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01331             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01332       return p->mfcr2_category;
01333    }
01334    ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01335    return cat;
01336 }
01337 
01338 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01339 {
01340    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01341    ast_mutex_lock(&p->lock);
01342    if (p->mfcr2call) {
01343       ast_mutex_unlock(&p->lock);
01344       /* TODO: This can happen when some other thread just finished zt_request requesting this very same
01345       interface but has not yet seized the line (zt_call), and the far end wins and seize the line,
01346       can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since
01347       the other end will see our seize as a forced release and drop the call, we will see an invalid
01348       pattern that will be seen and treated as protocol error. */
01349       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01350       return;
01351    }
01352    p->mfcr2call = 1;
01353    /* better safe than sorry ... */
01354    p->cid_name[0] = 0;
01355    p->cid_num[0] = 0;
01356    p->rdnis[0] = 0;
01357    p->exten[0] = 0;
01358    p->mfcr2_ani_index = 0;
01359    p->mfcr2_dnis_index = 0;
01360    p->mfcr2_dnis_matched = 0;
01361    p->mfcr2_call_accepted = 0;
01362    ast_mutex_unlock(&p->lock);
01363    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01364 }
01365 
01366 static void handle_alarms(struct dahdi_pvt *p, int alarms);
01367 static int get_alarms(struct dahdi_pvt *p);
01368 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01369 {
01370    int res;
01371    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01372    ast_mutex_lock(&p->lock);
01373    p->inalarm = alarm ? 1 : 0;
01374    if (p->inalarm) {
01375       res = get_alarms(p);
01376       /* unknown_alarm may be set here */
01377       handle_alarms(p, res);
01378    } else {
01379       if (!p->unknown_alarm) {
01380          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01381          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01382       } else {
01383          p->unknown_alarm = 0;
01384       }
01385    }
01386    ast_mutex_unlock(&p->lock);
01387    ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01388 }
01389 
01390 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01391 {
01392    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01393 }
01394 
01395 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01396 {
01397    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01398    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01399    if (p->owner) {
01400       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01401       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01402    } 
01403    ast_mutex_lock(&p->lock);
01404    p->mfcr2call = 0;
01405    ast_mutex_unlock(&p->lock);
01406 }
01407 
01408 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01409 {
01410    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01411       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 
01412             p->channel, openr2_proto_get_disconnect_string(cause));
01413       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01414       openr2_chan_set_idle(p->r2chan);
01415       ast_mutex_lock(&p->lock);
01416       p->mfcr2call = 0;
01417       ast_mutex_unlock(&p->lock);
01418    }
01419 }
01420 
01421 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01422 {
01423    struct dahdi_pvt *p;
01424    struct ast_channel *c;
01425    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 
01426          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01427    p = openr2_chan_get_client_data(r2chan);
01428    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01429       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01430       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01431       return;
01432    }
01433    ast_mutex_lock(&p->lock);
01434    p->mfcr2_recvd_category = category;
01435    /* if we're not supposed to use CID, clear whatever we have */
01436    if (!p->use_callerid) {
01437       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01438       p->cid_num[0] = 0;
01439       p->cid_name[0] = 0;
01440    }
01441    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01442    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01443       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01444       p->exten[0] = 's';
01445       p->exten[1] = 0;
01446    }
01447    ast_mutex_unlock(&p->lock);
01448    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01449       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01450             p->channel, p->exten, p->context);
01451       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01452    } else {
01453       /* if the user does not want to accept on offer, then we should launch the PBX thread now */
01454       if (!p->mfcr2_accept_on_offer) {
01455          c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01456          if (!c) {
01457             ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01458             dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01459          }
01460          /* Don't disable reading since we still need to generate MF tone to accept
01461             the call or reject it and detect the tone off condition of the other end */
01462       } else if (p->mfcr2_charge_calls) {
01463          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01464          openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01465       } else {
01466          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01467          openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01468       }  
01469    }  
01470 }
01471 
01472 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01473 {
01474    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01475    ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01476    ast_mutex_lock(&p->lock);
01477    p->mfcr2call = 0;
01478    ast_mutex_unlock(&p->lock);
01479 }
01480 
01481 static void dahdi_enable_ec(struct dahdi_pvt *p);
01482 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01483 {
01484    struct dahdi_pvt *p = NULL;
01485    struct ast_channel *c = NULL;
01486    p = openr2_chan_get_client_data(r2chan);
01487    dahdi_enable_ec(p);
01488    p->mfcr2_call_accepted = 1;
01489    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01490       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01491       /* if accept on offer is not set, it means at this point the PBX thread is already
01492          launched and therefore this callback is being executed in the PBX thread rather than
01493          the monitor thread, don't launch any other thread, just disable the R2 reading and
01494          answer the call */
01495       if (!p->mfcr2_accept_on_offer) {
01496          openr2_chan_disable_read(r2chan);
01497          ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01498          dahdi_r2_answer(p);
01499          return;
01500       }
01501       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01502       if (c) {
01503          /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01504          openr2_chan_disable_read(r2chan);
01505       } else {
01506          ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01507          dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01508          return;
01509       }
01510    } else {
01511       ast_verbose("Call accepted on forward channel %d\n", p->channel);
01512       p->subs[SUB_REAL].needringing = 1;
01513       p->dialing = 0;
01514       /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01515       openr2_chan_disable_read(r2chan);
01516    }  
01517 }
01518 
01519 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01520 {
01521    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01522    ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01523    p->subs[SUB_REAL].needanswer = 1;
01524 }
01525 
01526 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01527 {
01528    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01529 }
01530 
01531 /*static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01532 {
01533    switch (cause) {
01534    case OR2_CAUSE_BUSY_NUMBER:
01535       return AST_CAUSE_BUSY;
01536    case OR2_CAUSE_NETWORK_CONGESTION:
01537       return AST_CAUSE_CONGESTION;
01538    case OR2_CAUSE_OUT_OF_ORDER:
01539       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01540    case OR2_CAUSE_UNALLOCATED_NUMBER:
01541       return AST_CAUSE_UNREGISTERED;
01542    case OR2_CAUSE_NO_ANSWER:
01543       return AST_CAUSE_NO_ANSWER;
01544    case OR2_CAUSE_NORMAL_CLEARING:
01545       return AST_CAUSE_NORMAL_CLEARING;
01546    case OR2_CAUSE_UNSPECIFIED:
01547    default:
01548       return AST_CAUSE_NOTDEFINED;
01549    }  
01550 }*/
01551 
01552 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01553 {
01554    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01555    ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01556    ast_mutex_lock(&p->lock);
01557    if (p->owner) {
01558       /* when we have an owner we don't call openr2_chan_disconnect_call here, that will
01559          be done in zt_hangup */
01560       if (p->owner->_state == AST_STATE_UP) {
01561          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01562          ast_mutex_unlock(&p->lock);
01563       } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01564          /* being the forward side we must report what happened to the call to whoever requested it */
01565          switch (cause) {
01566          case OR2_CAUSE_BUSY_NUMBER:
01567             p->owner->hangupcause = AST_CAUSE_BUSY;
01568             p->subs[SUB_REAL].needbusy = 1;
01569             break;
01570          case OR2_CAUSE_NUMBER_CHANGED:
01571             p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01572             p->subs[SUB_REAL].needcongestion = 1;
01573             break;
01574          case OR2_CAUSE_NETWORK_CONGESTION:
01575             p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01576             p->subs[SUB_REAL].needcongestion = 1;
01577             break;
01578          case OR2_CAUSE_OUT_OF_ORDER:
01579             p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01580             p->subs[SUB_REAL].needcongestion = 1;
01581             break;
01582          case OR2_CAUSE_UNALLOCATED_NUMBER:
01583             p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01584             p->subs[SUB_REAL].needcongestion = 1;
01585             break;
01586          case OR2_CAUSE_NO_ANSWER:
01587             p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01588             p->subs[SUB_REAL].needcongestion = 1;
01589             break;
01590          case OR2_CAUSE_UNSPECIFIED:
01591             p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01592             p->subs[SUB_REAL].needcongestion = 1;
01593             break;
01594          case OR2_CAUSE_NORMAL_CLEARING:
01595             p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01596             p->subs[SUB_REAL].needcongestion = 1;
01597             break;
01598          default:
01599             ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01600          }
01601          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01602          ast_mutex_unlock(&p->lock);
01603       } else {
01604          ast_mutex_unlock(&p->lock);
01605          /* being the backward side and not UP yet, we only need to request hangup */
01606          /* TODO: what about doing this same thing when were AST_STATE_UP? */
01607          ast_queue_hangup(p->owner);
01608       }  
01609    } else {
01610       ast_mutex_unlock(&p->lock);
01611       /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */
01612       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01613    }
01614 }
01615 
01616 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01617 {
01618    switch (level) {
01619    case OR2_LOG_NOTICE:
01620       ast_verbose("%s", logmessage);
01621       break;
01622    case OR2_LOG_WARNING:
01623       ast_log(LOG_WARNING, "%s", logmessage);
01624       break;
01625    case OR2_LOG_ERROR:
01626       ast_log(LOG_ERROR, "%s", logmessage);
01627       break;
01628    case OR2_LOG_STACK_TRACE:
01629    case OR2_LOG_MF_TRACE:
01630    case OR2_LOG_CAS_TRACE:
01631    case OR2_LOG_DEBUG:
01632    case OR2_LOG_EX_DEBUG:
01633       ast_log(LOG_DEBUG, "%s", logmessage);
01634       break;
01635    default:
01636       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01637       ast_log(LOG_NOTICE, "%s", logmessage);
01638       break;
01639    }
01640 }
01641 
01642 #define DAHDI_R2_REMOTE_BLOCK (1 << 0)
01643 #define DAHDI_R2_LOCAL_BLOCK (1 << 1)
01644 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01645 {
01646    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01647    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01648    ast_mutex_lock(&p->lock);
01649    p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01650    ast_mutex_unlock(&p->lock);
01651 }
01652 
01653 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01654 {
01655    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01656    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01657    ast_mutex_lock(&p->lock);
01658    p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01659    ast_mutex_unlock(&p->lock);
01660 }
01661 
01662 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01663    __attribute__((format (printf, 3, 0)));
01664 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01665 {
01666    char logmsg[256];
01667    char completemsg[sizeof(logmsg)+50];
01668    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01669    snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01670    dahdi_r2_write_log(level, completemsg);
01671 }
01672 
01673 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01674    __attribute__((format (printf, 3, 0)));
01675 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01676 {
01677    char logmsg[256];
01678    char completemsg[sizeof(logmsg)+50];
01679    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01680    snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01681    dahdi_r2_write_log(level, completemsg);
01682 }
01683 
01684 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01685 {
01686    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01687    /* if 'immediate' is set, let's stop requesting DNIS */
01688    if (p->immediate) {
01689       return 0;
01690    }
01691    p->exten[p->mfcr2_dnis_index] = digit;
01692    p->rdnis[p->mfcr2_dnis_index] = digit;
01693    p->mfcr2_dnis_index++;
01694    p->exten[p->mfcr2_dnis_index] = 0;
01695    p->rdnis[p->mfcr2_dnis_index] = 0;
01696    /*
01697    ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten);
01698    int ret;
01699    ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num);
01700    ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01701    ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num);
01702    ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01703    */
01704    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
01705    if ((p->mfcr2_dnis_matched || 
01706        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01707        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01708       return 0;
01709    }
01710    /* otherwise keep going */
01711    return 1;
01712 }
01713 
01714 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
01715 {
01716    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01717    p->cid_num[p->mfcr2_ani_index] = digit;
01718    p->cid_name[p->mfcr2_ani_index] = digit;
01719    p->mfcr2_ani_index++;
01720    p->cid_num[p->mfcr2_ani_index] = 0;
01721    p->cid_name[p->mfcr2_ani_index] = 0;
01722 }
01723 
01724 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
01725 {
01726    ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01727 }
01728 
01729 static openr2_event_interface_t dahdi_r2_event_iface = {
01730    .on_call_init = dahdi_r2_on_call_init,
01731    .on_call_offered = dahdi_r2_on_call_offered,
01732    .on_call_accepted = dahdi_r2_on_call_accepted,
01733    .on_call_answered = dahdi_r2_on_call_answered,
01734    .on_call_disconnect = dahdi_r2_on_call_disconnect,
01735    .on_call_end = dahdi_r2_on_call_end,
01736    .on_call_read = dahdi_r2_on_call_read,
01737    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
01738    .on_os_error = dahdi_r2_on_os_error,
01739    .on_protocol_error = dahdi_r2_on_protocol_error,
01740    .on_line_blocked = dahdi_r2_on_line_blocked,
01741    .on_line_idle = dahdi_r2_on_line_idle,
01742    /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
01743    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
01744    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
01745    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
01746    /* so far we do nothing with billing pulses, just log it */
01747    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received 
01748 };
01749 
01750 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
01751 {
01752    return AST_ALAW(sample);
01753 }
01754 
01755 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
01756 {
01757    return AST_LIN2A(sample);
01758 }
01759 
01760 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
01761    dahdi_r2_alaw_to_linear,
01762    dahdi_r2_linear_to_alaw
01763 };
01764 
01765 #endif /* HAVE_OPENR2 */
01766 
01767 static int restore_gains(struct dahdi_pvt *p);
01768 
01769 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01770 {
01771    int tchan;
01772    int tinthreeway;
01773    struct ast_channel *towner;
01774 
01775    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01776 
01777    tchan = p->subs[a].chan;
01778    towner = p->subs[a].owner;
01779    tinthreeway = p->subs[a].inthreeway;
01780 
01781    p->subs[a].chan = p->subs[b].chan;
01782    p->subs[a].owner = p->subs[b].owner;
01783    p->subs[a].inthreeway = p->subs[b].inthreeway;
01784 
01785    p->subs[b].chan = tchan;
01786    p->subs[b].owner = towner;
01787    p->subs[b].inthreeway = tinthreeway;
01788 
01789    if (p->subs[a].owner) 
01790       p->subs[a].owner->fds[0] = p->subs[a].dfd;
01791    if (p->subs[b].owner) 
01792       p->subs[b].owner->fds[0] = p->subs[b].dfd;
01793    wakeup_sub(p, a, NULL);
01794    wakeup_sub(p, b, NULL);
01795 }
01796 
01797 static int dahdi_open(char *fn)
01798 {
01799    int fd;
01800    int isnum;
01801    int chan = 0;
01802    int bs;
01803    int x;
01804    isnum = 1;
01805    for (x = 0; x < strlen(fn); x++) {
01806       if (!isdigit(fn[x])) {
01807          isnum = 0;
01808          break;
01809       }
01810    }
01811    if (isnum) {
01812       chan = atoi(fn);
01813       if (chan < 1) {
01814          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01815          return -1;
01816       }
01817       fn = DAHDI_FILE_CHANNEL;
01818    }
01819    fd = open(fn, O_RDWR | O_NONBLOCK);
01820    if (fd < 0) {
01821       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01822       return -1;
01823    }
01824    if (chan) {
01825       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01826          x = errno;
01827          close(fd);
01828          errno = x;
01829          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01830          return -1;
01831       }
01832    }
01833    bs = READ_SIZE;
01834    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01835       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01836       x = errno;
01837       close(fd);
01838       errno = x;
01839       return -1;
01840    }
01841    return fd;
01842 }
01843 
01844 static void dahdi_close(int fd)
01845 {
01846    if (fd > 0)
01847       close(fd);
01848 }
01849 
01850 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01851 {
01852    dahdi_close(chan_pvt->subs[sub_num].dfd);
01853    chan_pvt->subs[sub_num].dfd = -1;
01854 }
01855  
01856 #ifdef HAVE_PRI
01857 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01858 {
01859    dahdi_close(pri->fds[fd_num]);
01860    pri->fds[fd_num] = -1;
01861 }
01862 #endif
01863 
01864 static int dahdi_setlinear(int dfd, int linear)
01865 {
01866    int res;
01867    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01868    if (res)
01869       return res;
01870    return 0;
01871 }
01872 
01873 
01874 static int alloc_sub(struct dahdi_pvt *p, int x)
01875 {
01876    struct dahdi_bufferinfo bi;
01877    int res;
01878    if (p->subs[x].dfd < 0) {
01879       p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01880       if (p->subs[x].dfd > -1) {
01881          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01882          if (!res) {
01883             bi.txbufpolicy = p->buf_policy;
01884             bi.rxbufpolicy = p->buf_policy;
01885             bi.numbufs = p->buf_no;
01886             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01887             if (res < 0) {
01888                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01889             }
01890          } else 
01891             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01892          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01893             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01894             dahdi_close_sub(p, x);
01895             return -1;
01896          }
01897          if (option_debug)
01898             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01899          return 0;
01900       } else
01901          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01902       return -1;
01903    }
01904    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01905    return -1;
01906 }
01907 
01908 static int unalloc_sub(struct dahdi_pvt *p, int x)
01909 {
01910    if (!x) {
01911       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01912       return -1;
01913    }
01914    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01915    dahdi_close_sub(p, x);
01916    p->subs[x].linear = 0;
01917    p->subs[x].chan = 0;
01918    p->subs[x].owner = NULL;
01919    p->subs[x].inthreeway = 0;
01920    p->polarity = POLARITY_IDLE;
01921    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01922    return 0;
01923 }
01924 
01925 static int digit_to_dtmfindex(char digit)
01926 {
01927    if (isdigit(digit))
01928       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01929    else if (digit >= 'A' && digit <= 'D')
01930       return DAHDI_TONE_DTMF_A + (digit - 'A');
01931    else if (digit >= 'a' && digit <= 'd')
01932       return DAHDI_TONE_DTMF_A + (digit - 'a');
01933    else if (digit == '*')
01934       return DAHDI_TONE_DTMF_s;
01935    else if (digit == '#')
01936       return DAHDI_TONE_DTMF_p;
01937    else
01938       return -1;
01939 }
01940 
01941 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01942 {
01943    struct dahdi_pvt *pvt;
01944    int index;
01945    int dtmf = -1;
01946    
01947    pvt = chan->tech_pvt;
01948 
01949    ast_mutex_lock(&pvt->lock);
01950 
01951    index = dahdi_get_index(chan, pvt, 0);
01952 
01953    if ((index != SUB_REAL) || !pvt->owner)
01954       goto out;
01955 
01956 #ifdef HAVE_PRI
01957    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01958       if (pvt->setup_ack) {
01959          if (!pri_grab(pvt, pvt->pri)) {
01960             pri_information(pvt->pri->pri, pvt->call, digit);
01961             pri_rel(pvt->pri);
01962          } else
01963             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01964       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01965          int res;
01966          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01967          res = strlen(pvt->dialdest);
01968          pvt->dialdest[res++] = digit;
01969          pvt->dialdest[res] = '\0';
01970       }
01971       goto out;
01972    }
01973 #endif
01974    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01975       goto out;
01976 
01977    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01978       int res;
01979       struct dahdi_dialoperation zo = {
01980          .op = DAHDI_DIAL_OP_APPEND,
01981          .dialstr[0] = 'T',
01982          .dialstr[1] = digit,
01983          .dialstr[2] = 0,
01984       };
01985       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01986          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01987       else
01988          pvt->dialing = 1;
01989    } else {
01990       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01991       pvt->dialing = 1;
01992       pvt->begindigit = digit;
01993    }
01994 
01995 out:
01996    ast_mutex_unlock(&pvt->lock);
01997 
01998    return 0;
01999 }
02000 
02001 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02002 {
02003    struct dahdi_pvt *pvt;
02004    int res = 0;
02005    int index;
02006    int x;
02007    
02008    pvt = chan->tech_pvt;
02009 
02010    ast_mutex_lock(&pvt->lock);
02011    
02012    index = dahdi_get_index(chan, pvt, 0);
02013 
02014    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02015       goto out;
02016 
02017 #ifdef HAVE_PRI
02018    /* This means that the digit was already sent via PRI signalling */
02019    if (pvt->sig == SIG_PRI && !pvt->begindigit)
02020       goto out;
02021 #endif
02022 
02023    if (pvt->begindigit) {
02024       x = -1;
02025       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02026       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02027       pvt->dialing = 0;
02028       pvt->begindigit = 0;
02029    }
02030 
02031 out:
02032    ast_mutex_unlock(&pvt->lock);
02033 
02034    return res;
02035 }
02036 
02037 static char *events[] = {
02038    "No event",
02039    "On hook",
02040    "Ring/Answered",
02041    "Wink/Flash",
02042    "Alarm",
02043    "No more alarm",
02044    "HDLC Abort",
02045    "HDLC Overrun",
02046    "HDLC Bad FCS",
02047    "Dial Complete",
02048    "Ringer On",
02049    "Ringer Off",
02050    "Hook Transition Complete",
02051    "Bits Changed",
02052    "Pulse Start",
02053    "Timer Expired",
02054    "Timer Ping",
02055    "Polarity Reversal",
02056    "Ring Begin",
02057 };
02058 
02059 static struct {
02060    int alarm;
02061    char *name;
02062 } alarms[] = {
02063    { DAHDI_ALARM_RED, "Red Alarm" },
02064    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02065    { DAHDI_ALARM_BLUE, "Blue Alarm" },
02066    { DAHDI_ALARM_RECOVER, "Recovering" },
02067    { DAHDI_ALARM_LOOPBACK, "Loopback" },
02068    { DAHDI_ALARM_NOTOPEN, "Not Open" },
02069    { DAHDI_ALARM_NONE, "None" },
02070 };
02071 
02072 static char *alarm2str(int alarm)
02073 {
02074    int x;
02075    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02076       if (alarms[x].alarm & alarm)
02077          return alarms[x].name;
02078    }
02079    return alarm ? "Unknown Alarm" : "No Alarm";
02080 }
02081 
02082 static char *event2str(int event)
02083 {
02084    static char buf[256];
02085    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02086       return events[event];
02087    sprintf(buf, "Event %d", event); /* safe */
02088    return buf;
02089 }
02090 
02091 #ifdef HAVE_PRI
02092 static char *dialplan2str(int dialplan)
02093 {
02094    if (dialplan == -1) {
02095       return("Dynamically set dialplan in ISDN");
02096    }
02097    return (pri_plan2str(dialplan));
02098 }
02099 #endif
02100 
02101 static char *dahdi_sig2str(int sig)
02102 {
02103    static char buf[256];
02104    switch (sig) {
02105    case SIG_EM:
02106       return "E & M Immediate";
02107    case SIG_EMWINK:
02108       return "E & M Wink";
02109    case SIG_EM_E1:
02110       return "E & M E1";
02111    case SIG_FEATD:
02112       return "Feature Group D (DTMF)";
02113    case SIG_FEATDMF:
02114       return "Feature Group D (MF)";
02115    case SIG_FEATDMF_TA:
02116       return "Feature Groud D (MF) Tandem Access";
02117    case SIG_FEATB:
02118       return "Feature Group B (MF)";
02119    case SIG_E911:
02120       return "E911 (MF)";
02121    case SIG_FGC_CAMA:
02122       return "FGC/CAMA (Dialpulse)";
02123    case SIG_FGC_CAMAMF:
02124       return "FGC/CAMA (MF)";
02125    case SIG_FXSLS:
02126       return "FXS Loopstart";
02127    case SIG_FXSGS:
02128       return "FXS Groundstart";
02129    case SIG_FXSKS:
02130       return "FXS Kewlstart";
02131    case SIG_FXOLS:
02132       return "FXO Loopstart";
02133    case SIG_FXOGS:
02134       return "FXO Groundstart";
02135    case SIG_FXOKS:
02136       return "FXO Kewlstart";
02137    case SIG_PRI:
02138       return "ISDN PRI";
02139    case SIG_MFCR2:
02140       return "MFC/R2";
02141    case SIG_SF:
02142       return "SF (Tone) Immediate";
02143    case SIG_SFWINK:
02144       return "SF (Tone) Wink";
02145    case SIG_SF_FEATD:
02146       return "SF (Tone) with Feature Group D (DTMF)";
02147    case SIG_SF_FEATDMF:
02148       return "SF (Tone) with Feature Group D (MF)";
02149    case SIG_SF_FEATB:
02150       return "SF (Tone) with Feature Group B (MF)";
02151    case SIG_GR303FXOKS:
02152       return "GR-303 with FXOKS";
02153    case SIG_GR303FXSKS:
02154       return "GR-303 with FXSKS";
02155    case 0:
02156       return "Pseudo";
02157    default:
02158       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02159       return buf;
02160    }
02161 }
02162 
02163 #define sig2str dahdi_sig2str
02164 
02165 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
02166 {
02167    /* If the conference already exists, and we're already in it
02168       don't bother doing anything */
02169    struct dahdi_confinfo zi;
02170    
02171    memset(&zi, 0, sizeof(zi));
02172    zi.chan = 0;
02173 
02174    if (slavechannel > 0) {
02175       /* If we have only one slave, do a digital mon */
02176       zi.confmode = DAHDI_CONF_DIGITALMON;
02177       zi.confno = slavechannel;
02178    } else {
02179       if (!index) {
02180          /* Real-side and pseudo-side both participate in conference */
02181          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02182             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02183       } else
02184          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02185       zi.confno = p->confno;
02186    }
02187    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02188       return 0;
02189    if (c->dfd < 0)
02190       return 0;
02191    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02192       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02193       return -1;
02194    }
02195    if (slavechannel < 1) {
02196       p->confno = zi.confno;
02197    }
02198    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02199    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02200    return 0;
02201 }
02202 
02203 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02204 {
02205    /* If they're listening to our channel, they're ours */  
02206    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02207       return 1;
02208    /* If they're a talker on our (allocated) conference, they're ours */
02209    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02210       return 1;
02211    return 0;
02212 }
02213 
02214 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
02215 {
02216    struct dahdi_confinfo zi;
02217    if (/* Can't delete if there's no dfd */
02218       (c->dfd < 0) ||
02219       /* Don't delete from the conference if it's not our conference */
02220       !isourconf(p, c)
02221       /* Don't delete if we don't think it's conferenced at all (implied) */
02222       ) return 0;
02223    memset(&zi, 0, sizeof(zi));
02224    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02225       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02226       return -1;
02227    }
02228    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02229    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02230    return 0;
02231 }
02232 
02233 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02234 {
02235    int x;
02236    int useslavenative;
02237    struct dahdi_pvt *slave = NULL;
02238    /* Start out optimistic */
02239    useslavenative = 1;
02240    /* Update conference state in a stateless fashion */
02241    for (x = 0; x < 3; x++) {
02242       /* Any three-way calling makes slave native mode *definitely* out
02243          of the question */
02244       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02245          useslavenative = 0;
02246    }
02247    /* If we don't have any 3-way calls, check to see if we have
02248       precisely one slave */
02249    if (useslavenative) {
02250       for (x = 0; x < MAX_SLAVES; x++) {
02251          if (p->slaves[x]) {
02252             if (slave) {
02253                /* Whoops already have a slave!  No 
02254                   slave native and stop right away */
02255                slave = NULL;
02256                useslavenative = 0;
02257                break;
02258             } else {
02259                /* We have one slave so far */
02260                slave = p->slaves[x];
02261             }
02262          }
02263       }
02264    }
02265    /* If no slave, slave native definitely out */
02266    if (!slave)
02267       useslavenative = 0;
02268    else if (slave->law != p->law) {
02269       useslavenative = 0;
02270       slave = NULL;
02271    }
02272    if (out)
02273       *out = slave;
02274    return useslavenative;
02275 }
02276 
02277 static int reset_conf(struct dahdi_pvt *p)
02278 {
02279    p->confno = -1;
02280    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02281    if (p->subs[SUB_REAL].dfd > -1) {
02282       struct dahdi_confinfo zi;
02283 
02284       memset(&zi, 0, sizeof(zi));
02285       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02286          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02287    }
02288    return 0;
02289 }
02290 
02291 static int update_conf(struct dahdi_pvt *p)
02292 {
02293    int needconf = 0;
02294    int x;
02295    int useslavenative;
02296    struct dahdi_pvt *slave = NULL;
02297 
02298    useslavenative = isslavenative(p, &slave);
02299    /* Start with the obvious, general stuff */
02300    for (x = 0; x < 3; x++) {
02301       /* Look for three way calls */
02302       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02303          conf_add(p, &p->subs[x], x, 0);
02304          needconf++;
02305       } else {
02306          conf_del(p, &p->subs[x], x);
02307       }
02308    }
02309    /* If we have a slave, add him to our conference now. or DAX
02310       if this is slave native */
02311    for (x = 0; x < MAX_SLAVES; x++) {
02312       if (p->slaves[x]) {
02313          if (useslavenative)
02314             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02315          else {
02316             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02317             needconf++;
02318          }
02319       }
02320    }
02321    /* If we're supposed to be in there, do so now */
02322    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02323       if (useslavenative)
02324          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02325       else {
02326          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02327          needconf++;
02328       }
02329    }
02330    /* If we have a master, add ourselves to his conference */
02331    if (p->master) {
02332       if (isslavenative(p->master, NULL)) {
02333          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02334       } else {
02335          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02336       }
02337    }
02338    if (!needconf) {
02339       /* Nobody is left (or should be left) in our conference.
02340          Kill it. */
02341       p->confno = -1;
02342    }
02343    if (option_debug)
02344       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02345    return 0;
02346 }
02347 
02348 static void dahdi_enable_ec(struct dahdi_pvt *p)
02349 {
02350    int x;
02351    int res;
02352    if (!p)
02353       return;
02354    if (p->echocanon) {
02355       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02356       return;
02357    }
02358    if (p->digital) {
02359       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02360       return;
02361    }
02362    if (p->echocancel) {
02363       if (p->sig == SIG_PRI) {
02364          x = 1;
02365          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02366          if (res)
02367             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02368       }
02369       x = p->echocancel;
02370       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02371       if (res) 
02372          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02373       else {
02374          p->echocanon = 1;
02375          if (option_debug)
02376             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02377       }
02378    } else if (option_debug)
02379       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02380 }
02381 
02382 static void dahdi_train_ec(struct dahdi_pvt *p)
02383 {
02384    int x;
02385    int res;
02386    if (p && p->echocancel && p->echotraining) {
02387       x = p->echotraining;
02388       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02389       if (res)
02390          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02391       else {
02392          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02393       }
02394    } else
02395       ast_log(LOG_DEBUG, "No echo training requested\n");
02396 }
02397 
02398 static void dahdi_disable_ec(struct dahdi_pvt *p)
02399 {
02400    int x;
02401    int res;
02402    if (p->echocancel) {
02403       x = 0;
02404       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02405       if (res)
02406          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02407       else if (option_debug)
02408          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02409    }
02410    p->echocanon = 0;
02411 }
02412 
02413 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02414 {
02415    int j;
02416    int k;
02417    float linear_gain = pow(10.0, gain / 20.0);
02418 
02419    switch (law) {
02420    case DAHDI_LAW_ALAW:
02421       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02422          if (gain) {
02423             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02424             if (k > 32767) k = 32767;
02425             if (k < -32767) k = -32767;
02426             g->txgain[j] = AST_LIN2A(k);
02427          } else {
02428             g->txgain[j] = j;
02429          }
02430       }
02431       break;
02432    case DAHDI_LAW_MULAW:
02433       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02434          if (gain) {
02435             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02436             if (k > 32767) k = 32767;
02437             if (k < -32767) k = -32767;
02438             g->txgain[j] = AST_LIN2MU(k);
02439          } else {
02440             g->txgain[j] = j;
02441          }
02442       }
02443       break;
02444    }
02445 }
02446 
02447 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02448 {
02449    int j;
02450    int k;
02451    float linear_gain = pow(10.0, gain / 20.0);
02452 
02453    switch (law) {
02454    case DAHDI_LAW_ALAW:
02455       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02456          if (gain) {
02457             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02458             if (k > 32767) k = 32767;
02459             if (k < -32767) k = -32767;
02460             g->rxgain[j] = AST_LIN2A(k);
02461          } else {
02462             g->rxgain[j] = j;
02463          }
02464       }
02465       break;
02466    case DAHDI_LAW_MULAW:
02467       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02468          if (gain) {
02469             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02470             if (k > 32767) k = 32767;
02471             if (k < -32767) k = -32767;
02472             g->rxgain[j] = AST_LIN2MU(k);
02473          } else {
02474             g->rxgain[j] = j;
02475          }
02476       }
02477       break;
02478    }
02479 }
02480 
02481 static int set_actual_txgain(int fd, int chan, float gain, int law)
02482 {
02483    struct dahdi_gains g;
02484    int res;
02485 
02486    memset(&g, 0, sizeof(g));
02487    g.chan = chan;
02488    res = ioctl(fd, DAHDI_GETGAINS, &g);
02489    if (res) {
02490       if (option_debug)
02491          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02492       return res;
02493    }
02494 
02495    fill_txgain(&g, gain, law);
02496 
02497    return ioctl(fd, DAHDI_SETGAINS, &g);
02498 }
02499 
02500 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02501 {
02502    struct dahdi_gains g;
02503    int res;
02504 
02505    memset(&g, 0, sizeof(g));
02506    g.chan = chan;
02507    res = ioctl(fd, DAHDI_GETGAINS, &g);
02508    if (res) {
02509       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02510       return res;
02511    }
02512 
02513    fill_rxgain(&g, gain, law);
02514 
02515    return ioctl(fd, DAHDI_SETGAINS, &g);
02516 }
02517 
02518 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02519 {
02520    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02521 }
02522 
02523 static int bump_gains(struct dahdi_pvt *p)
02524 {
02525    int res;
02526 
02527    /* Bump receive gain by 5.0db */
02528    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02529    if (res) {
02530       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02531       return -1;
02532    }
02533 
02534    return 0;
02535 }
02536 
02537 static int restore_gains(struct dahdi_pvt *p)
02538 {
02539    int res;
02540 
02541    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02542    if (res) {
02543       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02544       return -1;
02545    }
02546 
02547    return 0;
02548 }
02549 
02550 static inline int dahdi_set_hook(int fd, int hs)
02551 {
02552    int x, res;
02553 
02554    x = hs;
02555    res = ioctl(fd, DAHDI_HOOK, &x);
02556 
02557    if (res < 0) {
02558       if (errno == EINPROGRESS)
02559          return 0;
02560       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02561       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02562    }
02563 
02564    return res;
02565 }
02566 
02567 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02568 {
02569    int x, y, res;
02570    x = muted;
02571    if (p->sig == SIG_PRI) {
02572       y = 1;
02573       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02574       if (res)
02575          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02576    }
02577    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02578    if (res < 0)
02579       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02580    return res;
02581 }
02582 
02583 static int save_conference(struct dahdi_pvt *p)
02584 {
02585    struct dahdi_confinfo c;
02586    int res;
02587    if (p->saveconf.confmode) {
02588       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02589       return -1;
02590    }
02591    p->saveconf.chan = 0;
02592    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02593    if (res) {
02594       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02595       p->saveconf.confmode = 0;
02596       return -1;
02597    }
02598    memset(&c, 0, sizeof(c));
02599    c.confmode = DAHDI_CONF_NORMAL;
02600    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02601    if (res) {
02602       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02603       return -1;
02604    }
02605    if (option_debug)
02606       ast_log(LOG_DEBUG, "Disabled conferencing\n");
02607    return 0;
02608 }
02609 
02610 static int restore_conference(struct dahdi_pvt *p)
02611 {
02612    int res;
02613    if (p->saveconf.confmode) {
02614       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02615       p->saveconf.confmode = 0;
02616       if (res) {
02617          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02618          return -1;
02619       }
02620    }
02621    if (option_debug)
02622       ast_log(LOG_DEBUG, "Restored conferencing\n");
02623    return 0;
02624 }
02625 
02626 static int send_callerid(struct dahdi_pvt *p);
02627 
02628 static int send_cwcidspill(struct dahdi_pvt *p)
02629 {
02630    p->callwaitcas = 0;
02631    p->cidcwexpire = 0;
02632    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02633       return -1;
02634    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02635    /* Make sure we account for the end */
02636    p->cidlen += READ_SIZE * 4;
02637    p->cidpos = 0;
02638    send_callerid(p);
02639    if (option_verbose > 2)
02640       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02641    return 0;
02642 }
02643 
02644 static int has_voicemail(struct dahdi_pvt *p)
02645 {
02646 
02647    return ast_app_has_voicemail(p->mailbox, NULL);
02648 }
02649 
02650 static int send_callerid(struct dahdi_pvt *p)
02651 {
02652    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02653    int res;
02654    /* Take out of linear mode if necessary */
02655    if (p->subs[SUB_REAL].linear) {
02656       p->subs[SUB_REAL].linear = 0;
02657       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02658    }
02659    while (p->cidpos < p->cidlen) {
02660       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02661       if (res < 0) {
02662          if (errno == EAGAIN)
02663             return 0;
02664          else {
02665             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02666             return -1;
02667          }
02668       }
02669       if (!res)
02670          return 0;
02671       p->cidpos += res;
02672    }
02673    free(p->cidspill);
02674    p->cidspill = NULL;
02675    if (p->callwaitcas) {
02676       /* Wait for CID/CW to expire */
02677       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02678    } else
02679       restore_conference(p);
02680    return 0;
02681 }
02682 
02683 static int dahdi_callwait(struct ast_channel *ast)
02684 {
02685    struct dahdi_pvt *p = ast->tech_pvt;
02686    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02687    if (p->cidspill) {
02688       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02689       free(p->cidspill);
02690    }
02691    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02692       return -1;
02693    save_conference(p);
02694    /* Silence */
02695    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02696    if (!p->callwaitrings && p->callwaitingcallerid) {
02697       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02698       p->callwaitcas = 1;
02699       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02700    } else {
02701       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02702       p->callwaitcas = 0;
02703       p->cidlen = 2400 + READ_SIZE * 4;
02704    }
02705    p->cidpos = 0;
02706    send_callerid(p);
02707    
02708    return 0;
02709 }
02710 
02711 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02712 {
02713    struct dahdi_pvt *p = ast->tech_pvt;
02714    int x, res, index,mysig;
02715    char *c, *n, *l;
02716 #ifdef HAVE_PRI
02717    char *s = NULL;
02718 #endif
02719    char dest[256]; /* must be same length as p->dialdest */
02720    ast_mutex_lock(&p->lock);
02721    ast_copy_string(dest, rdest, sizeof(dest));
02722    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02723    if ((ast->_state == AST_STATE_BUSY)) {
02724       p->subs[SUB_REAL].needbusy = 1;
02725       ast_mutex_unlock(&p->lock);
02726       return 0;
02727    }
02728    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02729       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02730       ast_mutex_unlock(&p->lock);
02731       return -1;
02732    }
02733    p->dialednone = 0;
02734    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02735    {
02736       /* Special pseudo -- automatically up */
02737       ast_setstate(ast, AST_STATE_UP); 
02738       ast_mutex_unlock(&p->lock);
02739       return 0;
02740    }
02741    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02742    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02743    if (res)
02744       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02745    p->outgoing = 1;
02746 
02747    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02748 
02749    mysig = p->sig;
02750    if (p->outsigmod > -1)
02751       mysig = p->outsigmod;
02752 
02753    switch (mysig) {
02754    case SIG_FXOLS:
02755    case SIG_FXOGS:
02756    case SIG_FXOKS:
02757       if (p->owner == ast) {
02758          /* Normal ring, on hook */
02759          
02760          /* Don't send audio while on hook, until the call is answered */
02761          p->dialing = 1;
02762          if (p->use_callerid) {
02763             /* Generate the Caller-ID spill if desired */
02764             if (p->cidspill) {
02765                ast_log(LOG_WARNING, "cidspill already exists??\n");
02766                free(p->cidspill);
02767             }
02768             p->callwaitcas = 0;
02769             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02770                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02771                p->cidpos = 0;
02772                send_callerid(p);
02773             }
02774          }
02775          /* Choose proper cadence */
02776          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02777             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02778                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02779             p->cidrings = cidrings[p->distinctivering - 1];
02780          } else {
02781             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02782                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02783             p->cidrings = p->sendcalleridafter;
02784          }
02785 
02786          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02787          c = strchr(dest, '/');
02788          if (c)
02789             c++;
02790          if (c && (strlen(c) < p->stripmsd)) {
02791             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02792             c = NULL;
02793          }
02794          if (c) {
02795             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02796             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02797             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02798          } else {
02799             p->dop.dialstr[0] = '\0';
02800          }
02801          x = DAHDI_RING;
02802          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02803             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02804             ast_mutex_unlock(&p->lock);
02805             return -1;
02806          }
02807          p->dialing = 1;
02808       } else {
02809          /* Call waiting call */
02810          p->callwaitrings = 0;
02811          if (ast->cid.cid_num)
02812             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02813          else
02814             p->callwait_num[0] = '\0';
02815          if (ast->cid.cid_name)
02816             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02817          else
02818             p->callwait_name[0] = '\0';
02819          /* Call waiting tone instead */
02820          if (dahdi_callwait(ast)) {
02821             ast_mutex_unlock(&p->lock);
02822             return -1;
02823          }
02824          /* Make ring-back */
02825          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02826             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02827             
02828       }
02829       n = ast->cid.cid_name;
02830       l = ast->cid.cid_num;
02831       if (l)
02832          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02833       else
02834          p->lastcid_num[0] = '\0';
02835       if (n)
02836          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02837       else
02838          p->lastcid_name[0] = '\0';
02839       ast_setstate(ast, AST_STATE_RINGING);
02840       index = dahdi_get_index(ast, p, 0);
02841       if (index > -1) {
02842          p->subs[index].needringing = 1;
02843       }
02844       break;
02845    case SIG_FXSLS:
02846    case SIG_FXSGS:
02847    case SIG_FXSKS:
02848    case SIG_EMWINK:
02849    case SIG_EM:
02850    case SIG_EM_E1:
02851    case SIG_FEATD:
02852    case SIG_FEATDMF:
02853    case SIG_E911:
02854    case SIG_FGC_CAMA:
02855    case SIG_FGC_CAMAMF:
02856    case SIG_FEATB:
02857    case SIG_SFWINK:
02858    case SIG_SF:
02859    case SIG_SF_FEATD:
02860    case SIG_SF_FEATDMF:
02861    case SIG_FEATDMF_TA:
02862    case SIG_SF_FEATB:
02863       c = strchr(dest, '/');
02864       if (c)
02865          c++;
02866       else
02867          c = "";
02868       if (strlen(c) < p->stripmsd) {
02869          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02870          ast_mutex_unlock(&p->lock);
02871          return -1;
02872       }
02873 #ifdef HAVE_PRI
02874       /* Start the trunk, if not GR-303 */
02875       if (!p->pri) {
02876 #endif
02877          x = DAHDI_START;
02878          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02879          if (res < 0) {
02880             if (errno != EINPROGRESS) {
02881                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02882                ast_mutex_unlock(&p->lock);
02883                return -1;
02884             }
02885          }
02886 #ifdef HAVE_PRI
02887       }
02888 #endif
02889       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02890       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02891 
02892       c += p->stripmsd;
02893 
02894       switch (mysig) {
02895       case SIG_FEATD:
02896          l = ast->cid.cid_num;
02897          if (l) 
02898             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02899          else
02900             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02901          break;
02902       case SIG_FEATDMF:
02903          l = ast->cid.cid_num;
02904          if (l) 
02905             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02906          else
02907             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02908          break;
02909       case SIG_FEATDMF_TA:
02910       {
02911          const char *cic, *ozz;
02912 
02913          /* If you have to go through a Tandem Access point you need to use this */
02914          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02915          if (!ozz)
02916             ozz = defaultozz;
02917          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02918          if (!cic)
02919             cic = defaultcic;
02920          if (!ozz || !cic) {
02921             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02922             ast_mutex_unlock(&p->lock);
02923             return -1;
02924          }
02925          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02926          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02927          p->whichwink = 0;
02928       }
02929          break;
02930       case SIG_E911:
02931          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02932          break;
02933       case SIG_FGC_CAMA:
02934          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02935          break;
02936       case SIG_FGC_CAMAMF:
02937       case SIG_FEATB:
02938          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02939          break;
02940       default:
02941          if (p->pulse)
02942             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02943          else
02944             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02945          break;
02946       }
02947 
02948       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02949          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02950          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02951          p->echorest[sizeof(p->echorest) - 1] = '\0';
02952          p->echobreak = 1;
02953          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02954       } else
02955          p->echobreak = 0;
02956       if (!res) {
02957          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02958             int saveerr = errno;
02959 
02960             x = DAHDI_ONHOOK;
02961             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02962             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02963             ast_mutex_unlock(&p->lock);
02964             return -1;
02965          }
02966       } else
02967          ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
02968       p->dialing = 1;
02969       if (ast_strlen_zero(c))
02970          p->dialednone = 1;
02971       ast_setstate(ast, AST_STATE_DIALING);
02972       break;
02973    case 0:
02974       /* Special pseudo -- automatically up*/
02975       ast_setstate(ast, AST_STATE_UP);
02976       break;      
02977    case SIG_PRI:
02978    case SIG_MFCR2:
02979       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02980       p->dialdest[0] = '\0';
02981       p->dialing = 1;
02982       break;
02983    default:
02984       ast_log(LOG_DEBUG, "not yet implemented\n");
02985       ast_mutex_unlock(&p->lock);
02986       return -1;
02987    }
02988 #ifdef HAVE_OPENR2
02989    if (p->mfcr2) {
02990       int strip = p->stripmsd;
02991       int callres = 0;
02992       c = strchr(dest, '/');
02993       if (c) {
02994          c++;
02995       } else {
02996          c = dest;
02997       }
02998       if (!p->hidecallerid) {
02999          l = ast->cid.cid_num;
03000       } else {
03001          l = NULL;
03002       }
03003       if (strlen(c) < strip) {
03004          ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03005          strip = 0;
03006       }
03007       p->dialing = 1;
03008       callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03009       if (-1 == callres) {
03010          ast_mutex_unlock(&p->lock);
03011          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03012          return -1;
03013       }
03014       ast_setstate(ast, AST_STATE_DIALING);
03015    }
03016 #endif /* HAVE_OPENR2 */
03017 #ifdef HAVE_PRI
03018    if (p->pri) {
03019       struct pri_sr *sr;
03020 #ifdef SUPPORT_USERUSER
03021       const char *useruser;
03022 #endif
03023       int pridialplan;
03024       int dp_strip;
03025       int prilocaldialplan;
03026       int ldp_strip;
03027       int exclusive;
03028       const char *rr_str;
03029       int redirect_reason;
03030 
03031       c = strchr(dest, '/');
03032       if (c) {
03033          c++;
03034       } else {
03035          c = "";
03036       }
03037 
03038       l = NULL;
03039       n = NULL;
03040       if (!p->hidecallerid) {
03041          l = ast->cid.cid_num;
03042          if (!p->hidecalleridname) {
03043             n = ast->cid.cid_name;
03044          }
03045       }
03046 
03047 
03048       if (strlen(c) < p->stripmsd) {
03049          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03050          ast_mutex_unlock(&p->lock);
03051          return -1;
03052       }
03053       if (mysig != SIG_FXSKS) {
03054          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03055          s = strchr(c + p->stripmsd, 'w');
03056          if (s) {
03057             if (strlen(s) > 1)
03058                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03059             else
03060                p->dop.dialstr[0] = '\0';
03061             *s = '\0';
03062          } else {
03063             p->dop.dialstr[0] = '\0';
03064          }
03065       }
03066       if (pri_grab(p, p->pri)) {
03067          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03068          ast_mutex_unlock(&p->lock);
03069          return -1;
03070       }
03071       if (!(p->call = pri_new_call(p->pri->pri))) {
03072          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03073          pri_rel(p->pri);
03074          ast_mutex_unlock(&p->lock);
03075          return -1;
03076       }
03077       if (!(sr = pri_sr_new())) {
03078          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03079          pri_destroycall(p->pri->pri, p->call);
03080          p->call = NULL;
03081          pri_rel(p->pri);
03082          ast_mutex_unlock(&p->lock);
03083          return -1;
03084       }
03085       if (p->bearer || (mysig == SIG_FXSKS)) {
03086          if (p->bearer) {
03087             ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03088             p->bearer->call = p->call;
03089          } else
03090             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03091          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03092       }
03093       p->digital = IS_DIGITAL(ast->transfercapability);
03094 
03095       /* Should the picked channel be used exclusively? */
03096       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03097          exclusive = 1;
03098       } else {
03099          exclusive = 0;
03100       }
03101       
03102       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03103       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
03104                (p->digital ? -1 : 
03105                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03106       if (p->pri->facilityenable)
03107          pri_facility_enable(p->pri->pri);
03108 
03109       if (option_verbose > 2)
03110          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03111       dp_strip = 0;
03112       pridialplan = p->pri->dialplan - 1;
03113       if (pridialplan == -2) { /* compute dynamically */
03114          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03115             dp_strip = strlen(p->pri->internationalprefix);
03116             pridialplan = PRI_INTERNATIONAL_ISDN;
03117          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03118             dp_strip = strlen(p->pri->nationalprefix);
03119             pridialplan = PRI_NATIONAL_ISDN;
03120          } else {
03121             pridialplan = PRI_LOCAL_ISDN;
03122          }
03123       }
03124       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03125 
03126       ldp_strip = 0;
03127       prilocaldialplan = p->pri->localdialplan - 1;
03128       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
03129          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03130             ldp_strip = strlen(p->pri->internationalprefix);
03131             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03132          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03133             ldp_strip = strlen(p->pri->nationalprefix);
03134             prilocaldialplan = PRI_NATIONAL_ISDN;
03135          } else {
03136             prilocaldialplan = PRI_LOCAL_ISDN;
03137          }
03138       }
03139       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03140          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03141       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03142          if (!strcasecmp(rr_str, "UNKNOWN"))
03143             redirect_reason = 0;
03144          else if (!strcasecmp(rr_str, "BUSY"))
03145             redirect_reason = 1;
03146          else if (!strcasecmp(rr_str, "NO_REPLY"))
03147             redirect_reason = 2;
03148          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03149             redirect_reason = 15;
03150          else
03151             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03152       } else
03153          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03154       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03155 
03156 #ifdef SUPPORT_USERUSER
03157       /* User-user info */
03158       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03159 
03160       if (useruser)
03161          pri_sr_set_useruser(sr, useruser);
03162 #endif
03163 
03164       if (pri_setup(p->pri->pri, p->call, sr)) {
03165          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
03166             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03167          pri_rel(p->pri);
03168          ast_mutex_unlock(&p->lock);
03169          pri_sr_free(sr);
03170          return -1;
03171       }
03172       pri_sr_free(sr);
03173       ast_setstate(ast, AST_STATE_DIALING);
03174       pri_rel(p->pri);
03175    }
03176 #endif      
03177    ast_mutex_unlock(&p->lock);
03178    return 0;
03179 }
03180 
03181 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03182 {
03183    struct dahdi_pvt *p = *pvt;
03184    /* Remove channel from the list */
03185    if (p->prev)
03186       p->prev->next = p->next;
03187    if (p->next)
03188       p->next->prev = p->prev;
03189    if (p->use_smdi)
03190       ast_smdi_interface_unref(p->smdi_iface);
03191    ast_mutex_destroy(&p->lock);
03192    dahdi_close_sub(p, SUB_REAL);
03193    if (p->owner)
03194       p->owner->tech_pvt = NULL;
03195    free(p);
03196    *pvt = NULL;
03197 }
03198 
03199 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03200 {
03201    int owned = 0;
03202    int i = 0;
03203 
03204    if (!now) {
03205       if (cur->owner) {
03206          owned = 1;
03207       }
03208 
03209       for (i = 0; i < 3; i++) {
03210          if (cur->subs[i].owner) {
03211             owned = 1;
03212          }
03213       }
03214       if (!owned) {
03215          if (prev) {
03216             prev->next = cur->next;
03217             if (prev->next)
03218                prev->next->prev = prev;
03219             else
03220                ifend = prev;
03221          } else {
03222             iflist = cur->next;
03223             if (iflist)
03224                iflist->prev = NULL;
03225             else
03226                ifend = NULL;
03227          }
03228          destroy_dahdi_pvt(&cur);
03229       }
03230    } else {
03231       if (prev) {
03232          prev->next = cur->next;
03233          if (prev->next)
03234             prev->next->prev = prev;
03235          else
03236             ifend = prev;
03237       } else {
03238          iflist = cur->next;
03239          if (iflist)
03240             iflist->prev = NULL;
03241          else
03242             ifend = NULL;
03243       }
03244       destroy_dahdi_pvt(&cur);
03245    }
03246    return 0;
03247 }
03248 
03249 static void destroy_all_channels(void)
03250 {
03251    int x;
03252    struct dahdi_pvt *p, *pl;
03253 
03254    while (num_restart_pending) {
03255       usleep(1);
03256    }
03257 
03258    ast_mutex_lock(&iflock);
03259    /* Destroy all the interfaces and free their memory */
03260    p = iflist;
03261    while (p) {
03262       /* Free any callerid */
03263       if (p->cidspill)
03264          ast_free(p->cidspill);
03265       pl = p;
03266       p = p->next;
03267       x = pl->channel;
03268       /* Free associated memory */
03269       if (pl)
03270          destroy_dahdi_pvt(&pl);
03271       if (option_verbose > 2) 
03272          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03273    }
03274    iflist = NULL;
03275    ifcount = 0;
03276    ast_mutex_unlock(&iflock);
03277 }
03278 
03279 #ifdef HAVE_PRI
03280 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03281 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
03282 
03283 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03284 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03285 
03286 static char *dahdi_send_keypad_facility_descrip = 
03287 "  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03288 "  IE over the current channel.\n";
03289 static char *zap_send_keypad_facility_descrip = 
03290 "  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03291 "  IE over the current channel.\n";
03292 
03293 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
03294 {
03295    /* Data will be our digit string */
03296    struct dahdi_pvt *p;
03297    char *digits = (char *) data;
03298 
03299    if (ast_strlen_zero(digits)) {
03300       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03301       return -1;
03302    }
03303 
03304    p = (struct dahdi_pvt *)chan->tech_pvt;
03305 
03306    if (!p) {
03307       ast_log(LOG_DEBUG, "Unable to find technology private\n");
03308       return -1;
03309    }
03310 
03311    ast_mutex_lock(&p->lock);
03312 
03313    if (!p->pri || !p->call) {
03314       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03315       ast_mutex_unlock(&p->lock);
03316       return -1;
03317    }
03318 
03319    if (!pri_grab(p, p->pri)) {
03320       pri_keypad_facility(p->pri->pri, p->call, digits);
03321       pri_rel(p->pri);
03322    } else {
03323       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03324       ast_mutex_unlock(&p->lock);
03325       return -1;
03326    }
03327 
03328    ast_mutex_unlock(&p->lock);
03329 
03330    return 0;
03331 }
03332 
03333 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03334 {
03335    return send_keypad_facility_exec(chan, data);
03336 }
03337 
03338 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03339 {
03340    ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);  
03341    return send_keypad_facility_exec(chan, data);
03342 }
03343 
03344 static int pri_is_up(struct dahdi_pri *pri)
03345 {
03346    int x;
03347    for (x = 0; x < NUM_DCHANS; x++) {
03348       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03349          return 1;
03350    }
03351    return 0;
03352 }
03353 
03354 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03355 {
03356    bearer->owner = &inuse;
03357    bearer->realcall = crv;
03358    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03359    if (crv->subs[SUB_REAL].owner)
03360       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03361    crv->bearer = bearer;
03362    crv->call = bearer->call;
03363    crv->pri = pri;
03364    return 0;
03365 }
03366 
03367 static char *pri_order(int level)
03368 {
03369    switch (level) {
03370    case 0:
03371       return "Primary";
03372    case 1:
03373       return "Secondary";
03374    case 2:
03375       return "Tertiary";
03376    case 3:
03377       return "Quaternary";
03378    default:
03379       return "<Unknown>";
03380    }     
03381 }
03382 
03383 /* Returns fd of the active dchan */
03384 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03385 {
03386    int x = -1;
03387 
03388    for (x = 0; x < NUM_DCHANS; x++) {
03389       if ((pri->dchans[x] == pri->pri))
03390          break;
03391    }
03392 
03393    return pri->fds[x];
03394 }
03395 
03396 static int pri_find_dchan(struct dahdi_pri *pri)
03397 {
03398    int oldslot = -1;
03399    struct pri *old;
03400    int newslot = -1;
03401    int x;
03402    old = pri->pri;
03403    for (x = 0; x < NUM_DCHANS; x++) {
03404       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03405          newslot = x;
03406       if (pri->dchans[x] == old) {
03407          oldslot = x;
03408       }
03409    }
03410    if (newslot < 0) {
03411       newslot = 0;
03412       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03413          pri->dchannels[newslot]);
03414    }
03415    if (old && (oldslot != newslot))
03416       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03417          pri->dchannels[oldslot], pri->dchannels[newslot]);
03418    pri->pri = pri->dchans[newslot];
03419    return 0;
03420 }
03421 #endif
03422 
03423 #ifdef HAVE_OPENR2
03424 static char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
03425 static char *zap_accept_r2_call_app = "ZapAcceptR2Call";
03426 
03427 static char *dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03428 static char *zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03429 
03430 static char *dahdi_accept_r2_call_descrip = 
03431 "  DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03432 "  You can specify yes or no as argument to accept with or without charge.\n";
03433 
03434 static char *zap_accept_r2_call_descrip = 
03435 "  ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03436 "  You can specify yes or no as argument to accept with or without charge.\n";
03437 
03438 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
03439 {
03440    /* data is whether to accept with charge or no charge */
03441    openr2_call_mode_t accept_mode;
03442    int res, timeout, maxloops;
03443    struct ast_frame *f;
03444    struct dahdi_pvt *p;
03445    char *parse;
03446    AST_DECLARE_APP_ARGS(args,
03447          AST_APP_ARG(charge);
03448    );
03449 
03450    if (ast_strlen_zero(data)) {
03451       ast_log(LOG_DEBUG, "No data sent to application!\n");
03452       return -1;
03453    }
03454 
03455    if (chan->tech != &dahdi_tech) {
03456       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03457       return -1;
03458    }
03459 
03460    p = (struct dahdi_pvt *)chan->tech_pvt;
03461    if (!p) {
03462       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03463       return -1;
03464    }
03465 
03466    parse = ast_strdupa(data);
03467    AST_STANDARD_APP_ARGS(args, parse);
03468 
03469    if (ast_strlen_zero(args.charge)) {
03470       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03471       return -1;
03472    }
03473 
03474    ast_mutex_lock(&p->lock);
03475    if (!p->mfcr2 || !p->mfcr2call) {
03476       ast_mutex_unlock(&p->lock);
03477       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03478       return -1;
03479    }
03480 
03481    if (p->mfcr2_call_accepted) {
03482       ast_mutex_unlock(&p->lock);
03483       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03484       return 0;
03485    }
03486    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03487    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03488       ast_mutex_unlock(&p->lock);
03489       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03490       return -1;
03491    }
03492    ast_mutex_unlock(&p->lock);
03493 
03494    res = 0;
03495    timeout = 100;
03496    maxloops = 50; /* wait up to 5 seconds */
03497    /* we need to read() until the call is accepted */
03498    while (maxloops > 0) {
03499       maxloops--;
03500       if (ast_check_hangup(chan)) {
03501          break;
03502       }
03503       res = ast_waitfor(chan, timeout);
03504       if (res < 0) {
03505          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03506          res = -1;
03507          break;
03508       }
03509       if (res == 0) {
03510          continue;
03511       }
03512       f = ast_read(chan);
03513       if (!f) {
03514          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03515          res = -1;
03516          break;
03517       }
03518       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03519          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03520          ast_frfree(f);
03521          res = -1;
03522          break;
03523       }
03524       ast_frfree(f);
03525       ast_mutex_lock(&p->lock);
03526       if (p->mfcr2_call_accepted) {
03527          ast_mutex_unlock(&p->lock);
03528          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03529          break;
03530       }
03531       ast_mutex_unlock(&p->lock);
03532    }
03533    if (res == -1) {
03534       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03535    }
03536    return res;
03537 }
03538 
03539 static int zap_accept_r2_call_exec(struct ast_channel *chan, void *data)
03540 {
03541    return dahdi_accept_r2_call_exec(chan, data);
03542 }
03543 
03544 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
03545 {
03546    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03547    switch (cause) {
03548    case AST_CAUSE_USER_BUSY:
03549    case AST_CAUSE_CALL_REJECTED:
03550    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
03551       r2cause = OR2_CAUSE_BUSY_NUMBER;
03552       break;
03553 
03554    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03555    case AST_CAUSE_SWITCH_CONGESTION:
03556       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03557       break;
03558 
03559    case AST_CAUSE_UNALLOCATED:
03560       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03561       break;
03562 
03563    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03564    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03565       r2cause = OR2_CAUSE_OUT_OF_ORDER;
03566       break;
03567 
03568    case AST_CAUSE_NO_ANSWER:
03569    case AST_CAUSE_NO_USER_RESPONSE:
03570       r2cause = OR2_CAUSE_NO_ANSWER;
03571       break;
03572 
03573    default:
03574       r2cause = OR2_CAUSE_NORMAL_CLEARING;
03575       break;
03576    }
03577    ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 
03578          r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03579    return r2cause;
03580 }
03581 #endif
03582 
03583 static int dahdi_hangup(struct ast_channel *ast)
03584 {
03585    int res;
03586    int index,x, law;
03587    /*static int restore_gains(struct dahdi_pvt *p);*/
03588    struct dahdi_pvt *p = ast->tech_pvt;
03589    struct dahdi_pvt *tmp = NULL;
03590    struct dahdi_pvt *prev = NULL;
03591    struct dahdi_params par;
03592 
03593    if (option_debug)
03594       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03595    if (!ast->tech_pvt) {
03596       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03597       return 0;
03598    }
03599    
03600    ast_mutex_lock(&p->lock);
03601    
03602    index = dahdi_get_index(ast, p, 1);
03603 
03604    if (p->sig == SIG_PRI) {
03605       x = 1;
03606       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03607       p->cid_num[0] = '\0';
03608       p->cid_name[0] = '\0';
03609    }
03610 
03611    x = 0;
03612    dahdi_confmute(p, 0);
03613    restore_gains(p);
03614    if (p->origcid_num) {
03615       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03616       free(p->origcid_num);
03617       p->origcid_num = NULL;
03618    }  
03619    if (p->origcid_name) {
03620       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03621       free(p->origcid_name);
03622       p->origcid_name = NULL;
03623    }  
03624    if (p->dsp)
03625       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03626    p->exten[0] = '\0';
03627 
03628    if (option_debug)
03629       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03630       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03631    p->ignoredtmf = 0;
03632    
03633    if (index > -1) {
03634       /* Real channel, do some fixup */
03635       p->subs[index].owner = NULL;
03636       p->subs[index].needanswer = 0;
03637       p->subs[index].needflash = 0;
03638       p->subs[index].needringing = 0;
03639       p->subs[index].needbusy = 0;
03640       p->subs[index].needcongestion = 0;
03641       p->subs[index].linear = 0;
03642       p->subs[index].needcallerid = 0;
03643       p->polarity = POLARITY_IDLE;
03644       dahdi_setlinear(p->subs[index].dfd, 0);
03645       if (index == SUB_REAL) {
03646          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03647             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03648             if (p->subs[SUB_CALLWAIT].inthreeway) {
03649                /* We had flipped over to answer a callwait and now it's gone */
03650                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03651                /* Move to the call-wait, but un-own us until they flip back. */
03652                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03653                unalloc_sub(p, SUB_CALLWAIT);
03654                p->owner = NULL;
03655             } else {
03656                /* The three way hung up, but we still have a call wait */
03657                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
03658                swap_subs(p, SUB_THREEWAY, SUB_REAL);
03659                unalloc_sub(p, SUB_THREEWAY);
03660                if (p->subs[SUB_REAL].inthreeway) {
03661                   /* This was part of a three way call.  Immediately make way for
03662                      another call */
03663                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03664                   p->owner = p->subs[SUB_REAL].owner;
03665                } else {
03666                   /* This call hasn't been completed yet...  Set owner to NULL */
03667                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03668                   p->owner = NULL;
03669                }
03670                p->subs[SUB_REAL].inthreeway = 0;
03671             }
03672          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03673             /* Move to the call-wait and switch back to them. */
03674             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03675             unalloc_sub(p, SUB_CALLWAIT);
03676             p->owner = p->subs[SUB_REAL].owner;
03677             if (p->owner->_state != AST_STATE_UP)
03678                p->subs[SUB_REAL].needanswer = 1;
03679             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03680                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03681          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03682             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03683             unalloc_sub(p, SUB_THREEWAY);
03684             if (p->subs[SUB_REAL].inthreeway) {
03685                /* This was part of a three way call.  Immediately make way for
03686                   another call */
03687                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03688                p->owner = p->subs[SUB_REAL].owner;
03689             } else {
03690                /* This call hasn't been completed yet...  Set owner to NULL */
03691                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03692                p->owner = NULL;
03693             }
03694             p->subs[SUB_REAL].inthreeway = 0;
03695          }
03696       } else if (index == SUB_CALLWAIT) {
03697          /* Ditch the holding callwait call, and immediately make it availabe */
03698          if (p->subs[SUB_CALLWAIT].inthreeway) {
03699             /* This is actually part of a three way, placed on hold.  Place the third part
03700                on music on hold now */
03701             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03702                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
03703                   S_OR(p->mohsuggest, NULL),
03704                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03705             }
03706             p->subs[SUB_THREEWAY].inthreeway = 0;
03707             /* Make it the call wait now */
03708             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03709             unalloc_sub(p, SUB_THREEWAY);
03710          } else
03711             unalloc_sub(p, SUB_CALLWAIT);
03712       } else if (index == SUB_THREEWAY) {
03713          if (p->subs[SUB_CALLWAIT].inthreeway) {
03714             /* The other party of the three way call is currently in a call-wait state.
03715                Start music on hold for them, and take the main guy out of the third call */
03716             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03717                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
03718                   S_OR(p->mohsuggest, NULL),
03719                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03720             }
03721             p->subs[SUB_CALLWAIT].inthreeway = 0;
03722          }
03723          p->subs[SUB_REAL].inthreeway = 0;
03724          /* If this was part of a three way call index, let us make
03725             another three way call */
03726          unalloc_sub(p, SUB_THREEWAY);
03727       } else {
03728          /* This wasn't any sort of call, but how are we an index? */
03729          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03730       }
03731    }
03732 
03733    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03734       p->owner = NULL;
03735       p->ringt = 0;
03736       p->distinctivering = 0;
03737       p->confirmanswer = 0;
03738       p->cidrings = 1;
03739       p->outgoing = 0;
03740       p->digital = 0;
03741       p->faxhandled = 0;
03742       p->pulsedial = 0;
03743       p->onhooktime = time(NULL);
03744 #ifdef HAVE_PRI
03745       p->proceeding = 0;
03746       p->dialing = 0;
03747       p->progress = 0;
03748       p->alerting = 0;
03749       p->setup_ack = 0;
03750 #endif      
03751       if (p->dsp) {
03752          ast_dsp_free(p->dsp);
03753          p->dsp = NULL;
03754       }
03755 
03756       law = DAHDI_LAW_DEFAULT;
03757       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03758       if (res < 0) 
03759          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03760       /* Perform low level hangup if no owner left */
03761 #ifdef HAVE_OPENR2
03762       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03763          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03764          ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03765          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03766             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03767          } else {
03768             const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03769             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03770             openr2_call_disconnect_cause_t r2cause = r2cause_user
03771                                ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03772                                : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03773             dahdi_r2_disconnect_call(p, r2cause);
03774          }
03775       } else if (p->mfcr2call) {
03776          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03777          p->mfcr2call = 0;
03778       }
03779 #endif
03780 #ifdef HAVE_PRI
03781       if (p->pri) {
03782 #ifdef SUPPORT_USERUSER
03783          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03784 #endif
03785 
03786          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03787          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03788             if (!pri_grab(p, p->pri)) {
03789                if (p->alreadyhungup) {
03790                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
03791 
03792 #ifdef SUPPORT_USERUSER
03793                   pri_call_set_useruser(p->call, useruser);
03794 #endif
03795 
03796                   pri_hangup(p->pri->pri, p->call, -1);
03797                   p->call = NULL;
03798                   if (p->bearer) 
03799                      p->bearer->call = NULL;
03800                } else {
03801                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03802                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03803                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03804 
03805 #ifdef SUPPORT_USERUSER
03806                   pri_call_set_useruser(p->call, useruser);
03807 #endif
03808 
03809                   p->alreadyhungup = 1;
03810                   if (p->bearer)
03811                      p->bearer->alreadyhungup = 1;
03812                   if (cause) {
03813                      if (atoi(cause))
03814                         icause = atoi(cause);
03815                   }
03816                   pri_hangup(p->pri->pri, p->call, icause);
03817                }
03818                if (res < 0) 
03819                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03820                pri_rel(p->pri);        
03821             } else {
03822                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03823                res = -1;
03824             }
03825          } else {
03826             if (p->bearer)
03827                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03828             p->call = NULL;
03829             res = 0;
03830          }
03831       }
03832 #endif
03833       if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03834          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03835       if (res < 0) {
03836          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03837       }
03838       switch (p->sig) {
03839       case SIG_FXOGS:
03840       case SIG_FXOLS:
03841       case SIG_FXOKS:
03842          memset(&par, 0, sizeof(par));
03843          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03844          if (!res) {
03845 #if 0
03846             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03847 #endif
03848             /* If they're off hook, try playing congestion */
03849             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03850                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03851             else
03852                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03853          }
03854          break;
03855       case SIG_FXSGS:
03856       case SIG_FXSLS:
03857       case SIG_FXSKS:
03858          /* Make sure we're not made available for at least two seconds assuming
03859             we were actually used for an inbound or outbound call. */
03860          if (ast->_state != AST_STATE_RESERVED) {
03861             time(&p->guardtime);
03862             p->guardtime += 2;
03863          }
03864          break;
03865       default:
03866          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03867       }
03868       if (p->cidspill)
03869          free(p->cidspill);
03870       if (p->sig)
03871          dahdi_disable_ec(p);
03872       x = 0;
03873       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03874       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03875       p->didtdd = 0;
03876       p->cidspill = NULL;
03877       p->callwaitcas = 0;
03878       p->callwaiting = p->permcallwaiting;
03879       p->hidecallerid = p->permhidecallerid;
03880       p->dialing = 0;
03881       p->rdnis[0] = '\0';
03882       update_conf(p);
03883       reset_conf(p);
03884       /* Restore data mode */
03885       if (p->sig == SIG_PRI) {
03886          x = 0;
03887          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03888       }
03889 #ifdef HAVE_PRI
03890       if (p->bearer) {
03891          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03892          /* Free up the bearer channel as well, and
03893             don't use its file descriptor anymore */
03894          update_conf(p->bearer);
03895          reset_conf(p->bearer);
03896          p->bearer->owner = NULL;
03897          p->bearer->realcall = NULL;
03898          p->bearer = NULL;
03899          p->subs[SUB_REAL].dfd = -1;
03900          p->pri = NULL;
03901       }
03902 #endif
03903       if (num_restart_pending == 0)
03904          restart_monitor();
03905    }
03906 
03907    p->callwaitingrepeat = 0;
03908    p->cidcwexpire = 0;
03909    p->oprmode = 0;
03910    ast->tech_pvt = NULL;
03911    ast_mutex_unlock(&p->lock);
03912    ast_module_unref(ast_module_info->self);
03913    if (option_verbose > 2) 
03914       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03915 
03916    ast_mutex_lock(&iflock);
03917 
03918    if (p->restartpending) {
03919       num_restart_pending--;
03920    }
03921 
03922    tmp = iflist;
03923    prev = NULL;
03924    if (p->destroy) {
03925       while (tmp) {
03926          if (tmp == p) {
03927             destroy_channel(prev, tmp, 0);
03928             break;
03929          } else {
03930             prev = tmp;
03931             tmp = tmp->next;
03932          }
03933       }
03934    }
03935    ast_mutex_unlock(&iflock);
03936    return 0;
03937 }
03938 
03939 static int dahdi_answer(struct ast_channel *ast)
03940 {
03941    struct dahdi_pvt *p = ast->tech_pvt;
03942    int res = 0;
03943    int index;
03944    int oldstate = ast->_state;
03945    ast_setstate(ast, AST_STATE_UP);
03946    ast_mutex_lock(&p->lock);
03947    index = dahdi_get_index(ast, p, 0);
03948    if (index < 0)
03949       index = SUB_REAL;
03950    /* nothing to do if a radio channel */
03951    if ((p->radio || (p->oprmode < 0))) {
03952       ast_mutex_unlock(&p->lock);
03953       return 0;
03954    }
03955    switch (p->sig) {
03956    case SIG_FXSLS:
03957    case SIG_FXSGS:
03958    case SIG_FXSKS:
03959       p->ringt = 0;
03960       /* Fall through */
03961    case SIG_EM:
03962    case SIG_EM_E1:
03963    case SIG_EMWINK:
03964    case SIG_FEATD:
03965    case SIG_FEATDMF:
03966    case SIG_FEATDMF_TA:
03967    case SIG_E911:
03968    case SIG_FGC_CAMA:
03969    case SIG_FGC_CAMAMF:
03970    case SIG_FEATB:
03971    case SIG_SF:
03972    case SIG_SFWINK:
03973    case SIG_SF_FEATD:
03974    case SIG_SF_FEATDMF:
03975    case SIG_SF_FEATB:
03976    case SIG_FXOLS:
03977    case SIG_FXOGS:
03978    case SIG_FXOKS:
03979       /* Pick up the line */
03980       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03981       if (p->hanguponpolarityswitch) {
03982          gettimeofday(&p->polaritydelaytv, NULL);
03983       }
03984       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03985       tone_zone_play_tone(p->subs[index].dfd, -1);
03986       p->dialing = 0;
03987       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03988          if (oldstate == AST_STATE_RINGING) {
03989             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03990             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03991             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03992             p->owner = p->subs[SUB_REAL].owner;
03993          }
03994       }
03995       if (p->sig & __DAHDI_SIG_FXS) {
03996          dahdi_enable_ec(p);
03997          dahdi_train_ec(p);
03998       }
03999       break;
04000 #ifdef HAVE_PRI
04001    case SIG_PRI:
04002       /* Send a pri acknowledge */
04003       if (!pri_grab(p, p->pri)) {
04004          p->proceeding = 1;
04005          p->dialing = 0;
04006          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04007          pri_rel(p->pri);
04008       } else {
04009          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04010          res = -1;
04011       }
04012       break;
04013 #endif
04014 #ifdef HAVE_OPENR2
04015    case SIG_MFCR2:
04016       if (!p->mfcr2_accept_on_offer) {
04017          /* the call was not accepted on offer, so it must be accepted now before answering,
04018             the answer will be executed when the callback on_call_accepted is executed */
04019          if (p->mfcr2_charge_calls) {
04020             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04021             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04022          } else {
04023             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04024             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04025          }
04026       } else {
04027          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04028          res = dahdi_r2_answer(p);
04029       }
04030       break;
04031 #endif
04032    case 0:
04033       ast_mutex_unlock(&p->lock);
04034       return 0;
04035    default:
04036       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04037       res = -1;
04038    }
04039    ast_mutex_unlock(&p->lock);
04040    return res;
04041 }
04042 
04043 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04044 {
04045    char *cp;
04046    signed char *scp;
04047    int x;
04048    int index;
04049    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04050    struct oprmode *oprmode;
04051    
04052 
04053    /* all supported options require data */
04054    if (!data || (datalen < 1)) {
04055       errno = EINVAL;
04056       return -1;
04057    }
04058 
04059    switch (option) {
04060    case AST_OPTION_TXGAIN:
04061       scp = (signed char *) data;
04062       index = dahdi_get_index(chan, p, 0);
04063       if (index < 0) {
04064          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04065          return -1;
04066       }
04067       if (option_debug)
04068          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04069       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04070    case AST_OPTION_RXGAIN:
04071       scp = (signed char *) data;
04072       index = dahdi_get_index(chan, p, 0);
04073       if (index < 0) {
04074          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04075          return -1;
04076       }
04077       if (option_debug)
04078          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04079       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04080    case AST_OPTION_TONE_VERIFY:
04081       if (!p->dsp)
04082          break;
04083       cp = (char *) data;
04084       switch (*cp) {
04085       case 1:
04086          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04087          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
04088          break;
04089       case 2:
04090          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04091          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
04092          break;
04093       default:
04094          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04095          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
04096          break;
04097       }
04098       break;
04099    case AST_OPTION_TDD:
04100       /* turn on or off TDD */
04101       cp = (char *) data;
04102       p->mate = 0;
04103       if (!*cp) { /* turn it off */
04104          if (option_debug)
04105             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04106          if (p->tdd)
04107             tdd_free(p->tdd);
04108          p->tdd = 0;
04109          break;
04110       }
04111       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04112          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04113       dahdi_disable_ec(p);
04114       /* otherwise, turn it on */
04115       if (!p->didtdd) { /* if havent done it yet */
04116          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
04117          unsigned char *buf;
04118          int size, res, fd, len;
04119          struct pollfd fds[1];
04120 
04121          buf = mybuf;
04122          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
04123          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
04124          len = 40000;
04125          index = dahdi_get_index(chan, p, 0);
04126          if (index < 0) {
04127             ast_log(LOG_WARNING, "No index in TDD?\n");
04128             return -1;
04129          }
04130          fd = p->subs[index].dfd;
04131          while (len) {
04132             if (ast_check_hangup(chan))
04133                return -1;
04134             size = len;
04135             if (size > READ_SIZE)
04136                size = READ_SIZE;
04137             fds[0].fd = fd;
04138             fds[0].events = POLLPRI | POLLOUT;
04139             fds[0].revents = 0;
04140             res = poll(fds, 1, -1);
04141             if (!res) {
04142                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04143                continue;
04144             }
04145             /* if got exception */
04146             if (fds[0].revents & POLLPRI)
04147                return -1;
04148             if (!(fds[0].revents & POLLOUT)) {
04149                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04150                continue;
04151             }
04152             res = write(fd, buf, size);
04153             if (res != size) {
04154                if (res == -1) return -1;
04155                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04156                break;
04157             }
04158             len -= size;
04159             buf += size;
04160          }
04161          p->didtdd = 1; /* set to have done it now */    
04162       }
04163       if (*cp == 2) { /* Mate mode */
04164          if (p->tdd)
04165             tdd_free(p->tdd);
04166          p->tdd = 0;
04167          p->mate = 1;
04168          break;
04169       }     
04170       if (!p->tdd) { /* if we dont have one yet */
04171          p->tdd = tdd_new(); /* allocate one */
04172       }     
04173       break;
04174    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
04175       if (!p->dsp)
04176          break;
04177       cp = (char *) data;
04178       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04179          *cp ? "ON" : "OFF", (int) *cp, chan->name);
04180                 p->dtmfrelax = 0;
04181                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04182                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04183       break;
04184    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
04185       cp = (char *) data;
04186       if (!*cp) {    
04187          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04188          x = 0;
04189          dahdi_disable_ec(p);
04190       } else {    
04191          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04192          x = 1;
04193       }
04194       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04195          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04196       break;
04197    case AST_OPTION_OPRMODE:  /* Operator services mode */
04198       oprmode = (struct oprmode *) data;
04199       pp = oprmode->peer->tech_pvt;
04200       p->oprmode = pp->oprmode = 0;
04201       /* setup peers */
04202       p->oprpeer = pp;
04203       pp->oprpeer = p;
04204       /* setup modes, if any */
04205       if (oprmode->mode) 
04206       {
04207          pp->oprmode = oprmode->mode;
04208          p->oprmode = -oprmode->mode;
04209       }
04210       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04211          oprmode->mode, chan->name,oprmode->peer->name);;
04212       break;
04213    case AST_OPTION_ECHOCAN:
04214       cp = (char *) data;
04215       if (*cp) {
04216          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
04217          dahdi_enable_ec(p);
04218       } else {
04219          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
04220          dahdi_disable_ec(p);
04221       }
04222       break;
04223    }
04224    errno = 0;
04225 
04226    return 0;
04227 }
04228 
04229 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
04230 {
04231    struct dahdi_pvt *p = chan->tech_pvt;
04232    
04233    if (!strcasecmp(data, "rxgain")) {
04234       ast_mutex_lock(&p->lock);
04235       snprintf(buf, len, "%f", p->rxgain);
04236       ast_mutex_unlock(&p->lock);   
04237    } else if (!strcasecmp(data, "txgain")) {
04238       ast_mutex_lock(&p->lock);
04239       snprintf(buf, len, "%f", p->txgain);
04240       ast_mutex_unlock(&p->lock);   
04241    } else {
04242       ast_copy_string(buf, "", len);
04243    }
04244    return 0;
04245 }
04246 
04247 
04248 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04249 {
04250    /* Unlink a specific slave or all slaves/masters from a given master */
04251    int x;
04252    int hasslaves;
04253    if (!master)
04254       return;
04255    if (needlock) {
04256       ast_mutex_lock(&master->lock);
04257       if (slave) {
04258          while (ast_mutex_trylock(&slave->lock)) {
04259             DEADLOCK_AVOIDANCE(&master->lock);
04260          }
04261       }
04262    }
04263    hasslaves = 0;
04264    for (x = 0; x < MAX_SLAVES; x++) {
04265       if (master->slaves[x]) {
04266          if (!slave || (master->slaves[x] == slave)) {
04267             /* Take slave out of the conference */
04268             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04269             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04270             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04271             master->slaves[x]->master = NULL;
04272             master->slaves[x] = NULL;
04273          } else
04274             hasslaves = 1;
04275       }
04276       if (!hasslaves)
04277          master->inconference = 0;
04278    }
04279    if (!slave) {
04280       if (master->master) {
04281          /* Take master out of the conference */
04282          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04283          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04284          hasslaves = 0;
04285          for (x = 0; x < MAX_SLAVES; x++) {
04286             if (master->master->slaves[x] == master)
04287                master->master->slaves[x] = NULL;
04288             else if (master->master->slaves[x])
04289                hasslaves = 1;
04290          }
04291          if (!hasslaves)
04292             master->master->inconference = 0;
04293       }
04294       master->master = NULL;
04295    }
04296    update_conf(master);
04297    if (needlock) {
04298       if (slave)
04299          ast_mutex_unlock(&slave->lock);
04300       ast_mutex_unlock(&master->lock);
04301    }
04302 }
04303 
04304 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04305    int x;
04306    if (!slave || !master) {
04307       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04308       return;
04309    }
04310    for (x = 0; x < MAX_SLAVES; x++) {
04311       if (!master->slaves[x]) {
04312          master->slaves[x] = slave;
04313          break;
04314       }
04315    }
04316    if (x >= MAX_SLAVES) {
04317       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04318       master->slaves[MAX_SLAVES - 1] = slave;
04319    }
04320    if (slave->master) 
04321       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04322    slave->master = master;
04323    
04324    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04325 }
04326 
04327 static void disable_dtmf_detect(struct dahdi_pvt *p)
04328 {
04329 #ifdef DAHDI_TONEDETECT
04330    int val;
04331 #endif
04332 
04333    p->ignoredtmf = 1;
04334 
04335 #ifdef DAHDI_TONEDETECT
04336    val = 0;
04337    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04338 #endif      
04339    if (!p->hardwaredtmf && p->dsp) {
04340       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04341       ast_dsp_set_features(p->dsp, p->dsp_features);
04342    }
04343 }
04344 
04345 static void enable_dtmf_detect(struct dahdi_pvt *p)
04346 {
04347 #ifdef DAHDI_TONEDETECT
04348    int val;
04349 #endif
04350 
04351    if (p->channel == CHAN_PSEUDO)
04352       return;
04353 
04354    p->ignoredtmf = 0;
04355 
04356 #ifdef DAHDI_TONEDETECT
04357    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04358    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04359 #endif      
04360    if (!p->hardwaredtmf && p->dsp) {
04361       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04362       ast_dsp_set_features(p->dsp, p->dsp_features);
04363    }
04364 }
04365 
04366 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
04367 {
04368    struct ast_channel *who;
04369    struct dahdi_pvt *p0, *p1, *op0, *op1;
04370    struct dahdi_pvt *master = NULL, *slave = NULL;
04371    struct ast_frame *f;
04372    int inconf = 0;
04373    int nothingok = 1;
04374    int ofd0, ofd1;
04375    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04376    int os0 = -1, os1 = -1;
04377    int priority = 0;
04378    struct ast_channel *oc0, *oc1;
04379    enum ast_bridge_result res;
04380 
04381 #ifdef PRI_2BCT
04382    int triedtopribridge = 0;
04383    q931_call *q931c0 = NULL, *q931c1 = NULL;
04384 #endif
04385 
04386    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
04387       There is code below to handle it properly until DTMF is actually seen,
04388       but due to currently unresolved issues it's ignored...
04389    */
04390 
04391    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04392       return AST_BRIDGE_FAILED_NOWARN;
04393 
04394    ast_mutex_lock(&c0->lock);
04395    while (ast_mutex_trylock(&c1->lock)) {
04396       DEADLOCK_AVOIDANCE(&c0->lock);
04397    }
04398 
04399    p0 = c0->tech_pvt;
04400    p1 = c1->tech_pvt;
04401    /* cant do pseudo-channels here */
04402    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04403       ast_mutex_unlock(&c0->lock);
04404       ast_mutex_unlock(&c1->lock);
04405       return AST_BRIDGE_FAILED_NOWARN;
04406    }
04407 
04408    oi0 = dahdi_get_index(c0, p0, 0);
04409    oi1 = dahdi_get_index(c1, p1, 0);
04410    if ((oi0 < 0) || (oi1 < 0)) {
04411       ast_mutex_unlock(&c0->lock);
04412       ast_mutex_unlock(&c1->lock);
04413       return AST_BRIDGE_FAILED;
04414    }
04415 
04416    op0 = p0 = c0->tech_pvt;
04417    op1 = p1 = c1->tech_pvt;
04418    ofd0 = c0->fds[0];
04419    ofd1 = c1->fds[0];
04420    oc0 = p0->owner;
04421    oc1 = p1->owner;
04422 
04423    if (ast_mutex_trylock(&p0->lock)) {
04424       /* Don't block, due to potential for deadlock */
04425       ast_mutex_unlock(&c0->lock);
04426       ast_mutex_unlock(&c1->lock);
04427       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04428       return AST_BRIDGE_RETRY;
04429    }
04430    if (ast_mutex_trylock(&p1->lock)) {
04431       /* Don't block, due to potential for deadlock */
04432       ast_mutex_unlock(&p0->lock);
04433       ast_mutex_unlock(&c0->lock);
04434       ast_mutex_unlock(&c1->lock);
04435       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04436       return AST_BRIDGE_RETRY;
04437    }
04438 
04439    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04440       if (p0->owner && p1->owner) {
04441          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
04442          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04443             master = p0;
04444             slave = p1;
04445             inconf = 1;
04446          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04447             master = p1;
04448             slave = p0;
04449             inconf = 1;
04450          } else {
04451             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
04452             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04453                p0->channel,
04454                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04455                p0->subs[SUB_REAL].inthreeway, p0->channel,
04456                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04457                p1->subs[SUB_REAL].inthreeway);
04458          }
04459          nothingok = 0;
04460       }
04461    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04462       if (p1->subs[SUB_THREEWAY].inthreeway) {
04463          master = p1;
04464          slave = p0;
04465          nothingok = 0;
04466       }
04467    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04468       if (p0->subs[SUB_THREEWAY].inthreeway) {
04469          master = p0;
04470          slave = p1;
04471          nothingok = 0;
04472       }
04473    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04474       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
04475          don't put us in anything */
04476       if (p1->subs[SUB_CALLWAIT].inthreeway) {
04477          master = p1;
04478          slave = p0;
04479          nothingok = 0;
04480       }
04481    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04482       /* Same as previous */
04483       if (p0->subs[SUB_CALLWAIT].inthreeway) {
04484          master = p0;
04485          slave = p1;
04486          nothingok = 0;
04487       }
04488    }
04489    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04490       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04491    if (master && slave) {
04492       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
04493          in an active threeway call with a channel that is ringing, we should
04494          indicate ringing. */
04495       if ((oi1 == SUB_THREEWAY) && 
04496           p1->subs[SUB_THREEWAY].inthreeway && 
04497           p1->subs[SUB_REAL].owner && 
04498           p1->subs[SUB_REAL].inthreeway && 
04499           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04500          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04501          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04502          os1 = p1->subs[SUB_REAL].owner->_state;
04503       } else {
04504          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04505          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04506       }
04507       if ((oi0 == SUB_THREEWAY) && 
04508           p0->subs[SUB_THREEWAY].inthreeway && 
04509           p0->subs[SUB_REAL].owner && 
04510           p0->subs[SUB_REAL].inthreeway && 
04511           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04512          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04513          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04514          os0 = p0->subs[SUB_REAL].owner->_state;
04515       } else {
04516          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04517          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04518       }
04519       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04520          if (!p0->echocanbridged || !p1->echocanbridged) {
04521             /* Disable echo cancellation if appropriate */
04522             dahdi_disable_ec(p0);
04523             dahdi_disable_ec(p1);
04524          }
04525       }
04526       dahdi_link(slave, master);
04527       master->inconference = inconf;
04528    } else if (!nothingok)
04529       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04530 
04531    update_conf(p0);
04532    update_conf(p1);
04533    t0 = p0->subs[SUB_REAL].inthreeway;
04534    t1 = p1->subs[SUB_REAL].inthreeway;
04535 
04536    ast_mutex_unlock(&p0->lock);
04537    ast_mutex_unlock(&p1->lock);
04538 
04539    ast_mutex_unlock(&c0->lock);
04540    ast_mutex_unlock(&c1->lock);
04541 
04542    /* Native bridge failed */
04543    if ((!master || !slave) && !nothingok) {
04544       dahdi_enable_ec(p0);
04545       dahdi_enable_ec(p1);
04546       return AST_BRIDGE_FAILED;
04547    }
04548    
04549    if (option_verbose > 2) 
04550       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04551 
04552    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04553       disable_dtmf_detect(op0);
04554 
04555    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04556       disable_dtmf_detect(op1);
04557 
04558    for (;;) {
04559       struct ast_channel *c0_priority[2] = {c0, c1};
04560       struct ast_channel *c1_priority[2] = {c1, c0};
04561 
04562       /* Here's our main loop...  Start by locking things, looking for private parts, 
04563          and then balking if anything is wrong */
04564       ast_mutex_lock(&c0->lock);
04565       while (ast_mutex_trylock(&c1->lock)) {
04566          DEADLOCK_AVOIDANCE(&c0->lock);
04567       }
04568 
04569       p0 = c0->tech_pvt;
04570       p1 = c1->tech_pvt;
04571 
04572       if (op0 == p0)
04573          i0 = dahdi_get_index(c0, p0, 1);
04574       if (op1 == p1)
04575          i1 = dahdi_get_index(c1, p1, 1);
04576       ast_mutex_unlock(&c0->lock);
04577       ast_mutex_unlock(&c1->lock);
04578 
04579       if (!timeoutms || 
04580           (op0 != p0) ||
04581           (op1 != p1) || 
04582           (ofd0 != c0->fds[0]) || 
04583           (ofd1 != c1->fds[0]) ||
04584           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
04585           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
04586           (oc0 != p0->owner) || 
04587           (oc1 != p1->owner) ||
04588           (t0 != p0->subs[SUB_REAL].inthreeway) ||
04589           (t1 != p1->subs[SUB_REAL].inthreeway) ||
04590           (oi0 != i0) ||
04591           (oi1 != i1)) {
04592          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04593             op0->channel, oi0, op1->channel, oi1);
04594          res = AST_BRIDGE_RETRY;
04595          goto return_from_bridge;
04596       }
04597 
04598 #ifdef PRI_2BCT
04599       q931c0 = p0->call;
04600       q931c1 = p1->call;
04601       if (p0->transfer && p1->transfer 
04602           && q931c0 && q931c1 
04603           && !triedtopribridge) {
04604          pri_channel_bridge(q931c0, q931c1);
04605          triedtopribridge = 1;
04606       }
04607 #endif
04608 
04609       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04610       if (!who) {
04611          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04612          continue;
04613       }
04614       f = ast_read(who);
04615       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04616          *fo = f;
04617          *rc = who;
04618          res = AST_BRIDGE_COMPLETE;
04619          goto return_from_bridge;
04620       }
04621       if (f->frametype == AST_FRAME_DTMF) {
04622          if ((who == c0) && p0->pulsedial) {
04623             ast_write(c1, f);
04624          } else if ((who == c1) && p1->pulsedial) {
04625             ast_write(c0, f);
04626          } else {
04627             *fo = f;
04628             *rc = who;
04629             res = AST_BRIDGE_COMPLETE;
04630             goto return_from_bridge;
04631          }
04632       }
04633       ast_frfree(f);
04634       
04635       /* Swap who gets priority */
04636       priority = !priority;
04637    }
04638 
04639 return_from_bridge:
04640    if (op0 == p0)
04641       dahdi_enable_ec(p0);
04642 
04643    if (op1 == p1)
04644       dahdi_enable_ec(p1);
04645 
04646    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04647       enable_dtmf_detect(op0);
04648 
04649    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04650       enable_dtmf_detect(op1);
04651 
04652    dahdi_unlink(slave, master, 1);
04653 
04654    return res;
04655 }
04656 
04657 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04658 {
04659    struct dahdi_pvt *p = newchan->tech_pvt;
04660    int x;
04661    ast_mutex_lock(&p->lock);
04662    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04663    if (p->owner == oldchan) {
04664       p->owner = newchan;
04665    }
04666    for (x = 0; x < 3; x++)
04667       if (p->subs[x].owner == oldchan) {
04668          if (!x)
04669             dahdi_unlink(NULL, p, 0);
04670          p->subs[x].owner = newchan;
04671       }
04672    if (newchan->_state == AST_STATE_RINGING) 
04673       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04674    update_conf(p);
04675    ast_mutex_unlock(&p->lock);
04676    return 0;
04677 }
04678 
04679 static int dahdi_ring_phone(struct dahdi_pvt *p)
04680 {
04681    int x;
04682    int res;
04683    /* Make sure our transmit state is on hook */
04684    x = 0;
04685    x = DAHDI_ONHOOK;
04686    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04687    do {
04688       x = DAHDI_RING;
04689       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04690       if (res) {
04691          switch (errno) {
04692          case EBUSY:
04693          case EINTR:
04694             /* Wait just in case */
04695             usleep(10000);
04696             continue;
04697          case EINPROGRESS:
04698             res = 0;
04699             break;
04700          default:
04701             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04702             res = 0;
04703          }
04704       }
04705    } while (res);
04706    return res;
04707 }
04708 
04709 static void *ss_thread(void *data);
04710 
04711 static int attempt_transfer(struct dahdi_pvt *p)
04712 {
04713    /* In order to transfer, we need at least one of the channels to
04714       actually be in a call bridge.  We can't conference two applications
04715       together (but then, why would we want to?) */
04716    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04717       /* The three-way person we're about to transfer to could still be in MOH, so
04718          stop if now if appropriate */
04719       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04720          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04721       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04722          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04723       }
04724       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04725          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04726       }
04727        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04728          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04729                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04730          return -1;
04731       }
04732       /* Orphan the channel after releasing the lock */
04733       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04734       unalloc_sub(p, SUB_THREEWAY);
04735    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04736       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04737       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04738          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04739       }
04740       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04741          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04742       }
04743       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04744          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04745                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04746          return -1;
04747       }
04748       /* Three-way is now the REAL */
04749       swap_subs(p, SUB_THREEWAY, SUB_REAL);
04750       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
04751       unalloc_sub(p, SUB_THREEWAY);
04752       /* Tell the caller not to hangup */
04753       return 1;
04754    } else {
04755       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04756                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04757       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04758       return -1;
04759    }
04760    return 0;
04761 }
04762 
04763 static int check_for_conference(struct dahdi_pvt *p)
04764 {
04765    struct dahdi_confinfo ci;
04766    /* Fine if we already have a master, etc */
04767    if (p->master || (p->confno > -1))
04768       return 0;
04769    memset(&ci, 0, sizeof(ci));
04770    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04771       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04772       return 0;
04773    }
04774    /* If we have no master and don't have a confno, then 
04775       if we're in a conference, it's probably a MeetMe room or
04776       some such, so don't let us 3-way out! */
04777    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04778       if (option_verbose > 2) 
04779          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
04780       return 1;
04781    }
04782    return 0;
04783 }
04784 
04785 static int get_alarms(struct dahdi_pvt *p)
04786 {
04787    int res;
04788    struct dahdi_spaninfo zi;
04789 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04790    /*
04791     * The conditional compilation is needed only in asterisk-1.4 for
04792     * backward compatibility with old zaptel drivers that don't have
04793     * a DAHDI_PARAMS.chan_alarms field.
04794     */
04795    struct dahdi_params params;
04796 #endif
04797 
04798    memset(&zi, 0, sizeof(zi));
04799    zi.spanno = p->span;
04800 
04801    /* First check for span alarms */
04802    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04803       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04804       return 0;
04805    }
04806    if (zi.alarms != DAHDI_ALARM_NONE)
04807       return zi.alarms;
04808 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04809    /* No alarms on the span. Check for channel alarms. */
04810    memset(&params, 0, sizeof(params));
04811    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04812       return params.chan_alarms;
04813    /* ioctl failed */
04814    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04815 #endif
04816    return DAHDI_ALARM_NONE;
04817 }
04818 
04819 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04820 {
04821    struct dahdi_pvt *p = ast->tech_pvt;
04822    struct ast_frame *f = *dest;
04823 
04824    if (option_debug)
04825       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04826 
04827    if (p->confirmanswer) {
04828       if (option_debug)
04829          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04830       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04831          of a DTMF digit */
04832       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04833       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04834       *dest = &p->subs[index].f;
04835       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04836       p->confirmanswer = 0;
04837    } else if (p->callwaitcas) {
04838       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04839          if (option_debug)
04840             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04841          if (p->cidspill)
04842             free(p->cidspill);
04843          send_cwcidspill(p);
04844       }
04845       if ((f->subclass != 'm') && (f->subclass != 'u')) 
04846          p->callwaitcas = 0;
04847       p->subs[index].f.frametype = AST_FRAME_NULL;
04848       p->subs[index].f.subclass = 0;
04849       *dest = &p->subs[index].f;
04850    } else if (f->subclass == 'f') {
04851       /* Fax tone -- Handle and return NULL */
04852       if ((p->callprogress & 0x6) && !p->faxhandled) {
04853          p->faxhandled = 1;
04854          if (strcmp(ast->exten, "fax")) {
04855             const char *target_context = S_OR(ast->macrocontext, ast->context);
04856 
04857             /* We need to unlock 'ast' here because ast_exists_extension has the
04858              * potential to start autoservice on the channel. Such action is prone
04859              * to deadlock.
04860              */
04861             ast_mutex_unlock(&p->lock);
04862             ast_channel_unlock(ast);
04863             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04864                ast_channel_lock(ast);
04865                ast_mutex_lock(&p->lock);
04866                if (option_verbose > 2)
04867                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04868                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04869                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04870                if (ast_async_goto(ast, target_context, "fax", 1))
04871                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04872             } else {
04873                ast_channel_lock(ast);
04874                ast_mutex_lock(&p->lock);
04875                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04876             }
04877          } else if (option_debug)
04878             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04879       } else if (option_debug)
04880             ast_log(LOG_DEBUG, "Fax already handled\n");
04881       dahdi_confmute(p, 0);
04882       p->subs[index].f.frametype = AST_FRAME_NULL;
04883       p->subs[index].f.subclass = 0;
04884       *dest = &p->subs[index].f;
04885    } else if (f->subclass == 'm') {
04886       /* Confmute request */
04887       dahdi_confmute(p, 1);
04888       p->subs[index].f.frametype = AST_FRAME_NULL;
04889       p->subs[index].f.subclass = 0;
04890       *dest = &p->subs[index].f;    
04891    } else if (f->subclass == 'u') {
04892       /* Unmute */
04893       dahdi_confmute(p, 0);
04894       p->subs[index].f.frametype = AST_FRAME_NULL;
04895       p->subs[index].f.subclass = 0;
04896       *dest = &p->subs[index].f;    
04897    } else
04898       dahdi_confmute(p, 0);
04899 }
04900          
04901 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04902 {
04903    const char *alarm_str = alarm2str(alarms);
04904    
04905    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
04906     * doesn't know what to do with it.  Don't confuse users with log messages. */
04907    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04908       p->unknown_alarm = 1;
04909       return;
04910    } else {
04911       p->unknown_alarm = 0;
04912    }
04913    
04914    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04915    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04916             "Alarm: %s\r\n"
04917             "Channel: %d\r\n",
04918             alarm_str, p->channel);
04919 }
04920 
04921 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04922 {
04923    int res, x;
04924    int index, mysig;
04925    char *c;
04926    struct dahdi_pvt *p = ast->tech_pvt;
04927    pthread_t threadid;
04928    pthread_attr_t attr;
04929    struct ast_channel *chan;
04930    struct ast_frame *f;
04931 
04932    index = dahdi_get_index(ast, p, 0);
04933    mysig = p->sig;
04934    if (p->outsigmod > -1)
04935       mysig = p->outsigmod;
04936    p->subs[index].f.frametype = AST_FRAME_NULL;
04937    p->subs[index].f.subclass = 0;
04938    p->subs[index].f.datalen = 0;
04939    p->subs[index].f.samples = 0;
04940    p->subs[index].f.mallocd = 0;
04941    p->subs[index].f.offset = 0;
04942    p->subs[index].f.src = "dahdi_handle_event";
04943    p->subs[index].f.data = NULL;
04944    f = &p->subs[index].f;
04945 
04946    if (index < 0)
04947       return &p->subs[index].f;
04948    if (p->fake_event) {
04949       res = p->fake_event;
04950       p->fake_event = 0;
04951    } else
04952       res = dahdi_get_event(p->subs[index].dfd);
04953 
04954    if (option_debug)
04955       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04956 
04957    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04958       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04959 
04960       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04961 #ifdef HAVE_PRI
04962       if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04963          /* absorb event */
04964       } else {
04965 #endif
04966          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04967          p->subs[index].f.subclass = res & 0xff;
04968 #ifdef HAVE_PRI
04969       }
04970 #endif
04971       dahdi_handle_dtmfup(ast, index, &f);
04972       return f;
04973    }
04974 
04975    if (res & DAHDI_EVENT_DTMFDOWN) {
04976       if (option_debug)
04977          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04978       /* Mute conference */
04979       dahdi_confmute(p, 1);
04980       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04981       p->subs[index].f.subclass = res & 0xff;
04982       return &p->subs[index].f;
04983    }
04984 
04985    switch (res) {
04986 #ifdef DAHDI_EVENT_EC_DISABLED
04987       case DAHDI_EVENT_EC_DISABLED:
04988          if (option_verbose > 2) 
04989             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04990          p->echocanon = 0;
04991          break;
04992 #endif
04993       case DAHDI_EVENT_BITSCHANGED:
04994 #ifdef HAVE_OPENR2
04995          if (p->sig != SIG_MFCR2) {
04996             ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04997          } else {
04998             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
04999             openr2_chan_handle_cas(p->r2chan);
05000          }
05001 #else
05002          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05003 #endif
05004       case DAHDI_EVENT_PULSE_START:
05005          /* Stop tone if there's a pulse start and the PBX isn't started */
05006          if (!ast->pbx)
05007             tone_zone_play_tone(p->subs[index].dfd, -1);
05008          break;   
05009       case DAHDI_EVENT_DIALCOMPLETE:
05010 #ifdef HAVE_OPENR2
05011          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05012             /* we don't need to do anything for this event for R2 signaling 
05013                if the call is being setup */
05014             break;
05015          }
05016 #endif
05017          if (p->inalarm) break;
05018          if ((p->radio || (p->oprmode < 0))) break;
05019          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05020             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05021             return NULL;
05022          }
05023          if (!x) { /* if not still dialing in driver */
05024             dahdi_enable_ec(p);
05025             if (p->echobreak) {
05026                dahdi_train_ec(p);
05027                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05028                p->dop.op = DAHDI_DIAL_OP_REPLACE;
05029                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05030                p->echobreak = 0;
05031             } else {
05032                p->dialing = 0;
05033                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05034                   /* if thru with dialing after offhook */
05035                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05036                      ast_setstate(ast, AST_STATE_UP);
05037                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05038                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05039                      break;
05040                   } else { /* if to state wait for offhook to dial rest */
05041                      /* we now wait for off hook */
05042                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05043                   }
05044                }
05045                if (ast->_state == AST_STATE_DIALING) {
05046                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05047                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05048                   } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) ||  (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
05049                      ast_setstate(ast, AST_STATE_RINGING);
05050                   } else if (!p->answeronpolarityswitch) {
05051                      ast_setstate(ast, AST_STATE_UP);
05052                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05053                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05054                      /* If aops=0 and hops=1, this is necessary */
05055                      p->polarity = POLARITY_REV;
05056                   } else {
05057                      /* Start clean, so we can catch the change to REV polarity when party answers */
05058                      p->polarity = POLARITY_IDLE;
05059                   }
05060                }
05061             }
05062          }
05063          break;
05064       case DAHDI_EVENT_ALARM:
05065 #ifdef HAVE_PRI
05066          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05067             /* T309 is not enabled : hangup calls when alarm occurs */
05068             if (p->call) {
05069                if (p->pri && p->pri->pri) {
05070                   if (!pri_grab(p, p->pri)) {
05071                      pri_hangup(p->pri->pri, p->call, -1);
05072                      pri_destroycall(p->pri->pri, p->call);
05073                      p->call = NULL;
05074                      pri_rel(p->pri);
05075                   } else
05076                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05077                } else
05078                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05079             }
05080             if (p->owner)
05081                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05082          }
05083          if (p->bearer)
05084             p->bearer->inalarm = 1;
05085          else
05086 #endif
05087          p->inalarm = 1;
05088          res = get_alarms(p);
05089          handle_alarms(p, res);
05090 #ifdef HAVE_PRI
05091          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05092             /* fall through intentionally */
05093          } else {
05094             break;
05095          }
05096 #endif
05097 #ifdef HAVE_OPENR2
05098          if (p->sig == SIG_MFCR2)
05099             break;
05100 #endif
05101       case DAHDI_EVENT_ONHOOK:
05102          if (p->radio) {
05103             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05104             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05105             break;
05106          }
05107          if (p->oprmode < 0)
05108          {
05109             if (p->oprmode != -1) break;
05110             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05111             {
05112                /* Make sure it starts ringing */
05113                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05114                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05115                save_conference(p->oprpeer);
05116                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05117             }
05118             break;
05119          }
05120          switch (p->sig) {
05121          case SIG_FXOLS:
05122          case SIG_FXOGS:
05123          case SIG_FXOKS:
05124             p->onhooktime = time(NULL);
05125             p->msgstate = -1;
05126             /* Check for some special conditions regarding call waiting */
05127             if (index == SUB_REAL) {
05128                /* The normal line was hung up */
05129                if (p->subs[SUB_CALLWAIT].owner) {
05130                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
05131                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05132                   if (option_verbose > 2) 
05133                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05134                   unalloc_sub(p, SUB_CALLWAIT); 
05135 #if 0
05136                   p->subs[index].needanswer = 0;
05137                   p->subs[index].needringing = 0;
05138 #endif                  
05139                   p->callwaitingrepeat = 0;
05140                   p->cidcwexpire = 0;
05141                   p->owner = NULL;
05142                   /* Don't start streaming audio yet if the incoming call isn't up yet */
05143                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05144                      p->dialing = 1;
05145                   dahdi_ring_phone(p);
05146                } else if (p->subs[SUB_THREEWAY].owner) {
05147                   unsigned int mssinceflash;
05148                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
05149                      the private structure -- not especially easy or clean */
05150                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
05151                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
05152                      ast_mutex_unlock(&p->lock);
05153                      DEADLOCK_AVOIDANCE(&ast->lock);
05154                      /* We can grab ast and p in that order, without worry.  We should make sure
05155                         nothing seriously bad has happened though like some sort of bizarre double
05156                         masquerade! */
05157                      ast_mutex_lock(&p->lock);
05158                      if (p->owner != ast) {
05159                         ast_log(LOG_WARNING, "This isn't good...\n");
05160                         return NULL;
05161                      }
05162                   }
05163                   if (!p->subs[SUB_THREEWAY].owner) {
05164                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05165                      return NULL;
05166                   }
05167                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05168                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05169                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
05170                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
05171                         hanging up.  Hangup both channels now */
05172                      if (p->subs[SUB_THREEWAY].owner)
05173                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05174                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05175                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05176                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05177                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05178                      if (p->transfer) {
05179                         /* In any case this isn't a threeway call anymore */
05180                         p->subs[SUB_REAL].inthreeway = 0;
05181                         p->subs[SUB_THREEWAY].inthreeway = 0;
05182                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
05183                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05184                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05185                            /* Swap subs and dis-own channel */
05186                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
05187                            p->owner = NULL;
05188                            /* Ring the phone */
05189                            dahdi_ring_phone(p);
05190                         } else {
05191                            if ((res = attempt_transfer(p)) < 0) {
05192                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05193                               if (p->subs[SUB_THREEWAY].owner)
05194                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05195                            } else if (res) {
05196                               /* Don't actually hang up at this point */
05197                               if (p->subs[SUB_THREEWAY].owner)
05198                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05199                               break;
05200                            }
05201                         }
05202                      } else {
05203                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05204                         if (p->subs[SUB_THREEWAY].owner)
05205                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05206                      }
05207                   } else {
05208                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05209                      /* Swap subs and dis-own channel */
05210                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05211                      p->owner = NULL;
05212                      /* Ring the phone */
05213                      dahdi_ring_phone(p);
05214                   }
05215                }
05216             } else {
05217                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05218             }
05219             /* Fall through */
05220          default:
05221             dahdi_disable_ec(p);
05222             return NULL;
05223          }
05224          break;
05225       case DAHDI_EVENT_RINGOFFHOOK:
05226          if (p->inalarm) break;
05227          if (p->oprmode < 0)
05228          {
05229             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05230             {
05231                /* Make sure it stops ringing */
05232                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05233                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05234                restore_conference(p->oprpeer);
05235             }
05236             break;
05237          }
05238          if (p->radio)
05239          {
05240             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05241             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05242             break;
05243          }
05244          /* for E911, its supposed to wait for offhook then dial
05245             the second half of the dial string */
05246          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05247             c = strchr(p->dialdest, '/');
05248             if (c)
05249                c++;
05250             else
05251                c = p->dialdest;
05252             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05253             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05254             if (strlen(p->dop.dialstr) > 4) {
05255                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05256                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05257                p->echorest[sizeof(p->echorest) - 1] = '\0';
05258                p->echobreak = 1;
05259                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05260             } else
05261                p->echobreak = 0;
05262             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05263                int saveerr = errno;
05264 
05265                x = DAHDI_ONHOOK;
05266                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05267                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05268                return NULL;
05269                }
05270             p->dialing = 1;
05271             return &p->subs[index].f;
05272          }
05273          switch (p->sig) {
05274          case SIG_FXOLS:
05275          case SIG_FXOGS:
05276          case SIG_FXOKS:
05277             switch (ast->_state) {
05278             case AST_STATE_RINGING:
05279                dahdi_enable_ec(p);
05280                dahdi_train_ec(p);
05281                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05282                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05283                /* Make sure it stops ringing */
05284                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05285                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05286                if (p->cidspill) {
05287                   /* Cancel any running CallerID spill */
05288                   free(p->cidspill);
05289                   p->cidspill = NULL;
05290                }
05291                p->dialing = 0;
05292                p->callwaitcas = 0;
05293                if (p->confirmanswer) {
05294                   /* Ignore answer if "confirm answer" is enabled */
05295                   p->subs[index].f.frametype = AST_FRAME_NULL;
05296                   p->subs[index].f.subclass = 0;
05297                } else if (!ast_strlen_zero(p->dop.dialstr)) {
05298                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
05299                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05300                   if (res < 0) {
05301                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05302                      p->dop.dialstr[0] = '\0';
05303                      return NULL;
05304                   } else {
05305                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05306                      p->subs[index].f.frametype = AST_FRAME_NULL;
05307                      p->subs[index].f.subclass = 0;
05308                      p->dialing = 1;
05309                   }
05310                   p->dop.dialstr[0] = '\0';
05311                   ast_setstate(ast, AST_STATE_DIALING);
05312                } else
05313                   ast_setstate(ast, AST_STATE_UP);
05314                return &p->subs[index].f;
05315             case AST_STATE_DOWN:
05316                ast_setstate(ast, AST_STATE_RING);
05317                ast->rings = 1;
05318                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05319                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05320                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05321                return &p->subs[index].f;
05322             case AST_STATE_UP:
05323                /* Make sure it stops ringing */
05324                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05325                /* Okay -- probably call waiting*/
05326                if (ast_bridged_channel(p->owner))
05327                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05328                p->subs[index].needunhold = 1;
05329                break;
05330             case AST_STATE_RESERVED:
05331                /* Start up dialtone */
05332                if (has_voicemail(p))
05333                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05334                else
05335                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05336                break;
05337             default:
05338                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05339             }
05340             break;
05341          case SIG_FXSLS:
05342          case SIG_FXSGS:
05343          case SIG_FXSKS:
05344             if (ast->_state == AST_STATE_RING) {
05345                p->ringt = p->ringt_base;
05346             }
05347 
05348             /* Fall through */
05349          case SIG_EM:
05350          case SIG_EM_E1:
05351          case SIG_EMWINK:
05352          case SIG_FEATD:
05353          case SIG_FEATDMF:
05354          case SIG_FEATDMF_TA:
05355          case SIG_E911:
05356          case SIG_FGC_CAMA:
05357          case SIG_FGC_CAMAMF:
05358          case SIG_FEATB:
05359          case SIG_SF:
05360          case SIG_SFWINK:
05361          case SIG_SF_FEATD:
05362          case SIG_SF_FEATDMF:
05363          case SIG_SF_FEATB:
05364             if (ast->_state == AST_STATE_PRERING)
05365                ast_setstate(ast, AST_STATE_RING);
05366             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05367                if (option_debug)
05368                   ast_log(LOG_DEBUG, "Ring detected\n");
05369                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05370                p->subs[index].f.subclass = AST_CONTROL_RING;
05371             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05372                if (option_debug)
05373                   ast_log(LOG_DEBUG, "Line answered\n");
05374                if (p->confirmanswer) {
05375                   p->subs[index].f.frametype = AST_FRAME_NULL;
05376                   p->subs[index].f.subclass = 0;
05377                } else {
05378                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
05379                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05380                   ast_setstate(ast, AST_STATE_UP);
05381                }
05382             } else if (ast->_state != AST_STATE_RING)
05383                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05384             break;
05385          default:
05386             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05387          }
05388          break;
05389 #ifdef DAHDI_EVENT_RINGBEGIN
05390       case DAHDI_EVENT_RINGBEGIN:
05391          switch (p->sig) {
05392          case SIG_FXSLS:
05393          case SIG_FXSGS:
05394          case SIG_FXSKS:
05395             if (ast->_state == AST_STATE_RING) {
05396                p->ringt = p->ringt_base;
05397             }
05398             break;
05399          }
05400          break;
05401 #endif         
05402       case DAHDI_EVENT_RINGEROFF:
05403          if (p->inalarm) break;
05404          if ((p->radio || (p->oprmode < 0))) break;
05405          ast->rings++;
05406          if ((ast->rings > p->cidrings) && (p->cidspill)) {
05407             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
05408             free(p->cidspill);
05409             p->cidspill = NULL;
05410             p->callwaitcas = 0;
05411          }
05412          p->subs[index].f.frametype = AST_FRAME_CONTROL;
05413          p->subs[index].f.subclass = AST_CONTROL_RINGING;
05414          break;
05415       case DAHDI_EVENT_RINGERON:
05416          break;
05417       case DAHDI_EVENT_NOALARM:
05418          p->inalarm = 0;
05419 #ifdef HAVE_PRI
05420          /* Extremely unlikely but just in case */
05421          if (p->bearer)
05422             p->bearer->inalarm = 0;
05423 #endif            
05424          if (!p->unknown_alarm) {
05425             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05426             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05427                "Channel: %d\r\n", p->channel);
05428          } else {
05429             p->unknown_alarm = 0;
05430          }
05431          break;
05432       case DAHDI_EVENT_WINKFLASH:
05433          if (p->inalarm) break;
05434          if (p->radio) break;
05435          if (p->oprmode < 0) break;
05436          if (p->oprmode > 1)
05437          {
05438             struct dahdi_params par;
05439 
05440             memset(&par, 0, sizeof(par));
05441             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05442             {
05443                if (!par.rxisoffhook)
05444                {
05445                   /* Make sure it stops ringing */
05446                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05447                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05448                   save_conference(p);
05449                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05450                }
05451             }
05452             break;
05453          }
05454          /* Remember last time we got a flash-hook */
05455          gettimeofday(&p->flashtime, NULL);
05456          switch (mysig) {
05457          case SIG_FXOLS:
05458          case SIG_FXOGS:
05459          case SIG_FXOKS:
05460             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05461                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05462             p->callwaitcas = 0;
05463 
05464             if (index != SUB_REAL) {
05465                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05466                goto winkflashdone;
05467             }
05468             
05469             if (p->subs[SUB_CALLWAIT].owner) {
05470                /* Swap to call-wait */
05471                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05472                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05473                p->owner = p->subs[SUB_REAL].owner;
05474                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05475                if (p->owner->_state == AST_STATE_RINGING) {
05476                   ast_setstate(p->owner, AST_STATE_UP);
05477                   p->subs[SUB_REAL].needanswer = 1;
05478                }
05479                p->callwaitingrepeat = 0;
05480                p->cidcwexpire = 0;
05481                /* Start music on hold if appropriate */
05482                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05483                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05484                      S_OR(p->mohsuggest, NULL),
05485                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05486                }
05487                p->subs[SUB_CALLWAIT].needhold = 1;
05488                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05489                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05490                      S_OR(p->mohsuggest, NULL),
05491                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05492                }
05493                p->subs[SUB_REAL].needunhold = 1;
05494             } else if (!p->subs[SUB_THREEWAY].owner) {
05495                if (!p->threewaycalling) {
05496                   /* Just send a flash if no 3-way calling */
05497                   p->subs[SUB_REAL].needflash = 1;
05498                   goto winkflashdone;
05499                } else if (!check_for_conference(p)) {
05500                   char cid_num[256];
05501                   char cid_name[256];
05502 
05503                   cid_num[0] = 0;
05504                   cid_name[0] = 0;
05505                   if (p->dahditrcallerid && p->owner) {
05506                      if (p->owner->cid.cid_num)
05507                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05508                      if (p->owner->cid.cid_name)
05509                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05510                   }
05511                   /* XXX This section needs much more error checking!!! XXX */
05512                   /* Start a 3-way call if feasible */
05513                   if (!((ast->pbx) ||
05514                         (ast->_state == AST_STATE_UP) ||
05515                         (ast->_state == AST_STATE_RING))) {
05516                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05517                         goto winkflashdone;
05518                   }
05519                   if (alloc_sub(p, SUB_THREEWAY)) {
05520                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05521                      goto winkflashdone;
05522                   }
05523                   /* Make new channel */
05524                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05525                   if (p->dahditrcallerid) {
05526                      if (!p->origcid_num)
05527                         p->origcid_num = ast_strdup(p->cid_num);
05528                      if (!p->origcid_name)
05529                         p->origcid_name = ast_strdup(p->cid_name);
05530                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05531                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05532                   }
05533                   /* Swap things around between the three-way and real call */
05534                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
05535                   /* Disable echo canceller for better dialing */
05536                   dahdi_disable_ec(p);
05537                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05538                   if (res)
05539                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05540                   p->owner = chan;
05541                   pthread_attr_init(&attr);
05542                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05543                   if (!chan) {
05544                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05545                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05546                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05547                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05548                      dahdi_enable_ec(p);
05549                      ast_hangup(chan);
05550                   } else {
05551                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05552                      int way3bridge = 0, cdr3way = 0;
05553                      
05554                      if (!other) {
05555                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05556                      } else
05557                         way3bridge = 1;
05558                      
05559                      if (p->subs[SUB_THREEWAY].owner->cdr)
05560                         cdr3way = 1;
05561                      
05562                      if (option_verbose > 2) 
05563                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05564                      /* Start music on hold if appropriate */
05565                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05566                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05567                            S_OR(p->mohsuggest, NULL),
05568                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05569                      }
05570                      p->subs[SUB_THREEWAY].needhold = 1;
05571                   }
05572                   pthread_attr_destroy(&attr);
05573                }
05574             } else {
05575                /* Already have a 3 way call */
05576                if (p->subs[SUB_THREEWAY].inthreeway) {
05577                   /* Call is already up, drop the last person */
05578                   if (option_debug)
05579                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05580                   /* If the primary call isn't answered yet, use it */
05581                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05582                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
05583                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05584                      p->owner = p->subs[SUB_REAL].owner;
05585                   }
05586                   /* Drop the last call and stop the conference */
05587                   if (option_verbose > 2)
05588                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05589                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05590                   p->subs[SUB_REAL].inthreeway = 0;
05591                   p->subs[SUB_THREEWAY].inthreeway = 0;
05592                } else {
05593                   /* Lets see what we're up to */
05594                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
05595                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05596                      int otherindex = SUB_THREEWAY;
05597                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05598                      int way3bridge = 0, cdr3way = 0;
05599                      
05600                      if (!other) {
05601                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05602                      } else
05603                         way3bridge = 1;
05604                      
05605                      if (p->subs[SUB_THREEWAY].owner->cdr)
05606                         cdr3way = 1;
05607 
05608                      if (option_verbose > 2)
05609                         ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05610                      /* Put them in the threeway, and flip */
05611                      p->subs[SUB_THREEWAY].inthreeway = 1;
05612                      p->subs[SUB_REAL].inthreeway = 1;
05613                      if (ast->_state == AST_STATE_UP) {
05614                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
05615                         otherindex = SUB_REAL;
05616                      }
05617                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05618                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05619                      p->subs[otherindex].needunhold = 1;
05620                      p->owner = p->subs[SUB_REAL].owner;
05621                      if (ast->_state == AST_STATE_RINGING) {
05622                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
05623                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05624                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05625                      }
05626                   } else {
05627                      if (option_verbose > 2)
05628                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05629                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05630                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05631                      p->owner = p->subs[SUB_REAL].owner;
05632                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05633                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05634                      p->subs[SUB_REAL].needunhold = 1;
05635                      dahdi_enable_ec(p);
05636                   }
05637                      
05638                }
05639             }
05640          winkflashdone:              
05641             update_conf(p);
05642             break;
05643          case SIG_EM:
05644          case SIG_EM_E1:
05645          case SIG_FEATD:
05646          case SIG_SF:
05647          case SIG_SFWINK:
05648          case SIG_SF_FEATD:
05649          case SIG_FXSLS:
05650          case SIG_FXSGS:
05651             if (p->dialing)
05652                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
05653             else
05654                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05655             break;
05656          case SIG_FEATDMF_TA:
05657             switch (p->whichwink) {
05658             case 0:
05659                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05660                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05661                break;
05662             case 1:
05663                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05664                break;
05665             case 2:
05666                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05667                return NULL;
05668             }
05669             p->whichwink++;
05670             /* Fall through */
05671          case SIG_FEATDMF:
05672          case SIG_E911:
05673          case SIG_FGC_CAMAMF:
05674          case SIG_FGC_CAMA:
05675          case SIG_FEATB:
05676          case SIG_SF_FEATDMF:
05677          case SIG_SF_FEATB:
05678          case SIG_EMWINK:
05679             /* FGD MF and EMWINK *Must* wait for wink */
05680             if (!ast_strlen_zero(p->dop.dialstr)) {
05681                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05682                if (res < 0) {
05683                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05684                   p->dop.dialstr[0] = '\0';
05685                   return NULL;
05686                } else 
05687                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05688             }
05689             p->dop.dialstr[0] = '\0';
05690             break;
05691          default:
05692             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05693          }
05694          break;
05695       case DAHDI_EVENT_HOOKCOMPLETE:
05696          if (p->inalarm) break;
05697          if ((p->radio || (p->oprmode < 0))) break;
05698          switch (mysig) {
05699          case SIG_FXSLS:  /* only interesting for FXS */
05700          case SIG_FXSGS:
05701          case SIG_FXSKS:
05702          case SIG_EM:
05703          case SIG_EM_E1:
05704          case SIG_EMWINK:
05705          case SIG_FEATD:
05706          case SIG_SF:
05707          case SIG_SFWINK:
05708          case SIG_SF_FEATD:
05709             if (!ast_strlen_zero(p->dop.dialstr)) {
05710                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05711                if (res < 0) {
05712                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05713                   p->dop.dialstr[0] = '\0';
05714                   return NULL;
05715                } else 
05716                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05717             }
05718             p->dop.dialstr[0] = '\0';
05719             p->dop.op = DAHDI_DIAL_OP_REPLACE;
05720             break;
05721          case SIG_FEATDMF:
05722          case SIG_FEATDMF_TA:
05723          case SIG_E911:
05724          case SIG_FGC_CAMA:
05725          case SIG_FGC_CAMAMF:
05726          case SIG_FEATB:
05727          case SIG_SF_FEATDMF:
05728          case SIG_SF_FEATB:
05729             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05730             break;
05731          default:
05732             break;
05733          }
05734          break;
05735       case DAHDI_EVENT_POLARITY:
05736          /*
05737           * If we get a Polarity Switch event, check to see
05738           * if we should change the polarity state and
05739           * mark the channel as UP or if this is an indication
05740           * of remote end disconnect.
05741           */
05742          if (p->polarity == POLARITY_IDLE) {
05743             p->polarity = POLARITY_REV;
05744             if (p->answeronpolarityswitch &&
05745                 ((ast->_state == AST_STATE_DIALING) ||
05746                 (ast->_state == AST_STATE_RINGING))) {
05747                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
05748                ast_setstate(p->owner, AST_STATE_UP);
05749                if (p->hanguponpolarityswitch) {
05750                   gettimeofday(&p->polaritydelaytv, NULL);
05751                }
05752             } else
05753                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05754          } 
05755          /* Removed else statement from here as it was preventing hangups from ever happening*/
05756          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
05757          if (p->hanguponpolarityswitch &&
05758             (p->polarityonanswerdelay > 0) &&
05759                 (p->polarity == POLARITY_REV) &&
05760             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05761                                 /* Added log_debug information below to provide a better indication of what is going on */
05762             ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
05763          
05764             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05765                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05766                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05767                p->polarity = POLARITY_IDLE;
05768             } else {
05769                ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
05770             }
05771          } else {
05772             p->polarity = POLARITY_IDLE;
05773             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05774          }
05775                         /* Added more log_debug information below to provide a better indication of what is going on */
05776          ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
05777          break;
05778       default:
05779          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05780    }
05781    return &p->subs[index].f;
05782 }
05783 
05784 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05785 {
05786    struct dahdi_pvt *p = ast->tech_pvt;
05787    int res;
05788    int usedindex=-1;
05789    int index;
05790    struct ast_frame *f;
05791 
05792 
05793    index = dahdi_get_index(ast, p, 1);
05794    
05795    p->subs[index].f.frametype = AST_FRAME_NULL;
05796    p->subs[index].f.datalen = 0;
05797    p->subs[index].f.samples = 0;
05798    p->subs[index].f.mallocd = 0;
05799    p->subs[index].f.offset = 0;
05800    p->subs[index].f.subclass = 0;
05801    p->subs[index].f.delivery = ast_tv(0,0);
05802    p->subs[index].f.src = "dahdi_exception";
05803    p->subs[index].f.data = NULL;
05804    
05805    
05806    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05807       /* If nobody owns us, absorb the event appropriately, otherwise
05808          we loop indefinitely.  This occurs when, during call waiting, the
05809          other end hangs up our channel so that it no longer exists, but we
05810          have neither FLASH'd nor ONHOOK'd to signify our desire to
05811          change to the other channel. */
05812       if (p->fake_event) {
05813          res = p->fake_event;
05814          p->fake_event = 0;
05815       } else
05816          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05817       /* Switch to real if there is one and this isn't something really silly... */
05818       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05819          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05820          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
05821          p->owner = p->subs[SUB_REAL].owner;
05822          if (p->owner && ast_bridged_channel(p->owner))
05823             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05824          p->subs[SUB_REAL].needunhold = 1;
05825       }
05826       switch (res) {
05827       case DAHDI_EVENT_ONHOOK:
05828          dahdi_disable_ec(p);
05829          if (p->owner) {
05830             if (option_verbose > 2) 
05831                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05832             dahdi_ring_phone(p);
05833             p->callwaitingrepeat = 0;
05834             p->cidcwexpire = 0;
05835          } else
05836             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05837          update_conf(p);
05838          break;
05839       case DAHDI_EVENT_RINGOFFHOOK:
05840          dahdi_enable_ec(p);
05841          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05842          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05843             p->subs[SUB_REAL].needanswer = 1;
05844             p->dialing = 0;
05845          }
05846          break;
05847       case DAHDI_EVENT_HOOKCOMPLETE:
05848       case DAHDI_EVENT_RINGERON:
05849       case DAHDI_EVENT_RINGEROFF:
05850          /* Do nothing */
05851          break;
05852       case DAHDI_EVENT_WINKFLASH:
05853          gettimeofday(&p->flashtime, NULL);
05854          if (p->owner) {
05855             if (option_verbose > 2) 
05856                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05857             if (p->owner->_state != AST_STATE_UP) {
05858                /* Answer if necessary */
05859                usedindex = dahdi_get_index(p->owner, p, 0);
05860                if (usedindex > -1) {
05861                   p->subs[usedindex].needanswer = 1;
05862                }
05863                ast_setstate(p->owner, AST_STATE_UP);
05864             }
05865             p->callwaitingrepeat = 0;
05866             p->cidcwexpire = 0;
05867             if (ast_bridged_channel(p->owner))
05868                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05869             p->subs[SUB_REAL].needunhold = 1;
05870          } else
05871             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05872          update_conf(p);
05873          break;
05874       default:
05875          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05876       }
05877       f = &p->subs[index].f;
05878       return f;
05879    }
05880    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
05881       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05882    /* If it's not us, return NULL immediately */
05883    if (ast != p->owner) {
05884       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05885       f = &p->subs[index].f;
05886       return f;
05887    }
05888    f = dahdi_handle_event(ast);
05889    return f;
05890 }
05891 
05892 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05893 {
05894    struct dahdi_pvt *p = ast->tech_pvt;
05895    struct ast_frame *f;
05896    ast_mutex_lock(&p->lock);
05897    f = __dahdi_exception(ast);
05898    ast_mutex_unlock(&p->lock);
05899    return f;
05900 }
05901 
05902 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
05903 {
05904    struct dahdi_pvt *p = ast->tech_pvt;
05905    int res;
05906    int index;
05907    void *readbuf;
05908    struct ast_frame *f;
05909 
05910    while (ast_mutex_trylock(&p->lock)) {
05911       DEADLOCK_AVOIDANCE(&ast->lock);
05912    }
05913 
05914    index = dahdi_get_index(ast, p, 0);
05915    
05916    /* Hang up if we don't really exist */
05917    if (index < 0) {
05918       ast_log(LOG_WARNING, "We dont exist?\n");
05919       ast_mutex_unlock(&p->lock);
05920       return NULL;
05921    }
05922    
05923    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05924       ast_mutex_unlock(&p->lock);
05925       return NULL;
05926    }
05927 
05928    p->subs[index].f.frametype = AST_FRAME_NULL;
05929    p->subs[index].f.datalen = 0;
05930    p->subs[index].f.samples = 0;
05931    p->subs[index].f.mallocd = 0;
05932    p->subs[index].f.offset = 0;
05933    p->subs[index].f.subclass = 0;
05934    p->subs[index].f.delivery = ast_tv(0,0);
05935    p->subs[index].f.src = "dahdi_read";
05936    p->subs[index].f.data = NULL;
05937    
05938    /* make sure it sends initial key state as first frame */
05939    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05940    {
05941       struct dahdi_params ps;
05942 
05943       memset(&ps, 0, sizeof(ps));
05944       ps.channo = p->channel;
05945       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05946          ast_mutex_unlock(&p->lock);
05947          return NULL;
05948       }
05949       p->firstradio = 1;
05950       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05951       if (ps.rxisoffhook)
05952       {
05953          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05954       }
05955       else
05956       {
05957          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05958       }
05959       ast_mutex_unlock(&p->lock);
05960       return &p->subs[index].f;
05961    }
05962    if (p->ringt == 1) {
05963       ast_mutex_unlock(&p->lock);
05964       return NULL;
05965    }
05966    else if (p->ringt > 0) 
05967       p->ringt--;
05968 
05969 #ifdef HAVE_OPENR2
05970    if (p->mfcr2) {
05971       openr2_chan_process_event(p->r2chan);
05972    }  
05973 #endif
05974 
05975    if (p->subs[index].needringing) {
05976       /* Send ringing frame if requested */
05977       p->subs[index].needringing = 0;
05978       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05979       p->subs[index].f.subclass = AST_CONTROL_RINGING;
05980       ast_setstate(ast, AST_STATE_RINGING);
05981       ast_mutex_unlock(&p->lock);
05982       return &p->subs[index].f;
05983    }
05984 
05985    if (p->subs[index].needbusy) {
05986       /* Send busy frame if requested */
05987       p->subs[index].needbusy = 0;
05988       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05989       p->subs[index].f.subclass = AST_CONTROL_BUSY;
05990       ast_mutex_unlock(&p->lock);
05991       return &p->subs[index].f;
05992    }
05993 
05994    if (p->subs[index].needcongestion) {
05995       /* Send congestion frame if requested */
05996       p->subs[index].needcongestion = 0;
05997       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05998       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05999       ast_mutex_unlock(&p->lock);
06000       return &p->subs[index].f;
06001    }
06002 
06003    if (p->subs[index].needcallerid) {
06004       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06005                      S_OR(p->lastcid_name, NULL),
06006                      S_OR(p->lastcid_num, NULL)
06007                      );
06008       p->subs[index].needcallerid = 0;
06009    }
06010    
06011    if (p->subs[index].needanswer) {
06012       /* Send answer frame if requested */
06013       p->subs[index].needanswer = 0;
06014       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06015       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06016       ast_mutex_unlock(&p->lock);
06017       return &p->subs[index].f;
06018    }  
06019 
06020 #ifdef HAVE_OPENR2
06021    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06022       /* openr2 took care of reading and handling any event 
06023         (needanswer, needbusy etc), if we continue we will read()
06024         twice, lets just return a null frame. This should only
06025         happen when openr2 is dialing out */
06026       p->subs[index].f.frametype = AST_FRAME_NULL;
06027       p->subs[index].f.subclass = 0;
06028       p->subs[index].f.samples = 0;
06029       p->subs[index].f.mallocd = 0;
06030       p->subs[index].f.offset = 0;
06031       p->subs[index].f.data = NULL;
06032       p->subs[index].f.datalen= 0;
06033       ast_mutex_unlock(&p->lock);
06034       return &p->subs[index].f;
06035    }
06036 #endif
06037    
06038    if (p->subs[index].needflash) {
06039       /* Send answer frame if requested */
06040       p->subs[index].needflash = 0;
06041       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06042       p->subs[index].f.subclass = AST_CONTROL_FLASH;
06043       ast_mutex_unlock(&p->lock);
06044       return &p->subs[index].f;
06045    }  
06046    
06047    if (p->subs[index].needhold) {
06048       /* Send answer frame if requested */
06049       p->subs[index].needhold = 0;
06050       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06051       p->subs[index].f.subclass = AST_CONTROL_HOLD;
06052       ast_mutex_unlock(&p->lock);
06053       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06054       return &p->subs[index].f;
06055    }  
06056    
06057    if (p->subs[index].needunhold) {
06058       /* Send answer frame if requested */
06059       p->subs[index].needunhold = 0;
06060       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06061       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06062       ast_mutex_unlock(&p->lock);
06063       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06064       return &p->subs[index].f;
06065    }  
06066    
06067    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06068       if (!p->subs[index].linear) {
06069          p->subs[index].linear = 1;
06070          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06071          if (res) 
06072             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06073       }
06074    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06075          (ast->rawreadformat == AST_FORMAT_ALAW)) {
06076       if (p->subs[index].linear) {
06077          p->subs[index].linear = 0;
06078          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06079          if (res) 
06080             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06081       }
06082    } else {
06083       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06084       ast_mutex_unlock(&p->lock);
06085       return NULL;
06086    }
06087    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06088    CHECK_BLOCKING(ast);
06089    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06090    ast_clear_flag(ast, AST_FLAG_BLOCKING);
06091    /* Check for hangup */
06092    if (res < 0) {
06093       f = NULL;
06094       if (res == -1)  {
06095          if (errno == EAGAIN) {
06096             /* Return "NULL" frame if there is nobody there */
06097             ast_mutex_unlock(&p->lock);
06098             return &p->subs[index].f;
06099          } else if (errno == ELAST) {
06100             f = __dahdi_exception(ast);
06101          } else
06102             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06103       }
06104       ast_mutex_unlock(&p->lock);
06105       return f;
06106    }
06107    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06108       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06109       f = __dahdi_exception(ast);
06110       ast_mutex_unlock(&p->lock);
06111       return f;
06112    }
06113    if (p->tdd) { /* if in TDD mode, see if we receive that */
06114       int c;
06115 
06116       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06117       if (c < 0) {
06118          ast_log(LOG_DEBUG,"tdd_feed failed\n");
06119          ast_mutex_unlock(&p->lock);
06120          return NULL;
06121       }
06122       if (c) { /* if a char to return */
06123          p->subs[index].f.subclass = 0;
06124          p->subs[index].f.frametype = AST_FRAME_TEXT;
06125          p->subs[index].f.mallocd = 0;
06126          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06127          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06128          p->subs[index].f.datalen = 1;
06129          *((char *) p->subs[index].f.data) = c;
06130          ast_mutex_unlock(&p->lock);
06131          return &p->subs[index].f;
06132       }
06133    }
06134    /* Ensure the CW timer decrements only on a single subchannel */
06135    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06136       p->callwaitingrepeat--;
06137    }
06138    if (p->cidcwexpire)
06139       p->cidcwexpire--;
06140    /* Repeat callwaiting */
06141    if (p->callwaitingrepeat == 1) {
06142       p->callwaitrings++;
06143       dahdi_callwait(ast);
06144    }
06145    /* Expire CID/CW */
06146    if (p->cidcwexpire == 1) {
06147       if (option_verbose > 2)
06148          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06149       restore_conference(p);
06150    }
06151    if (p->subs[index].linear) {
06152       p->subs[index].f.datalen = READ_SIZE * 2;
06153    } else 
06154       p->subs[index].f.datalen = READ_SIZE;
06155 
06156    /* Handle CallerID Transmission */
06157    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06158       send_callerid(p);
06159    }
06160 
06161    p->subs[index].f.frametype = AST_FRAME_VOICE;
06162    p->subs[index].f.subclass = ast->rawreadformat;
06163    p->subs[index].f.samples = READ_SIZE;
06164    p->subs[index].f.mallocd = 0;
06165    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06166    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06167 #if 0
06168    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06169 #endif   
06170    if (p->dialing || /* Transmitting something */
06171       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
06172       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
06173       ) {
06174       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
06175          don't send anything */
06176       p->subs[index].f.frametype = AST_FRAME_NULL;
06177       p->subs[index].f.subclass = 0;
06178       p->subs[index].f.samples = 0;
06179       p->subs[index].f.mallocd = 0;
06180       p->subs[index].f.offset = 0;
06181       p->subs[index].f.data = NULL;
06182       p->subs[index].f.datalen= 0;
06183    }
06184    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
06185       /* Perform busy detection. etc on the dahdi line */
06186       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06187       if (f) {
06188          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06189             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06190                /* Treat this as a "hangup" instead of a "busy" on the assumption that
06191                   a busy  */
06192                f = NULL;
06193             }
06194          } else if (f->frametype == AST_FRAME_DTMF) {
06195 #ifdef HAVE_PRI
06196             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06197                ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06198                (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06199                /* Don't accept in-band DTMF when in overlap dial mode */
06200                f->frametype = AST_FRAME_NULL;
06201                f->subclass = 0;
06202             }
06203 #endif            
06204             /* DSP clears us of being pulse */
06205             p->pulsedial = 0;
06206          }
06207       }
06208    } else 
06209       f = &p->subs[index].f; 
06210 
06211    if (f && (f->frametype == AST_FRAME_DTMF))
06212       dahdi_handle_dtmfup(ast, index, &f);
06213 
06214    /* If we have a fake_event, trigger exception to handle it */
06215    if (p->fake_event)
06216       ast_set_flag(ast, AST_FLAG_EXCEPTION);
06217 
06218    ast_mutex_unlock(&p->lock);
06219    return f;
06220 }
06221 
06222 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06223 {
06224    int sent=0;
06225    int size;
06226    int res;
06227    int fd;
06228    fd = p->subs[index].dfd;
06229    while (len) {
06230       size = len;
06231       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06232          size = (linear ? READ_SIZE * 2 : READ_SIZE);
06233       res = write(fd, buf, size);
06234       if (res != size) {
06235          if (option_debug)
06236             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06237          return sent;
06238       }
06239       len -= size;
06240       buf += size;
06241    }
06242    return sent;
06243 }
06244 
06245 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06246 {
06247    struct dahdi_pvt *p = ast->tech_pvt;
06248    int res;
06249    int index;
06250    index = dahdi_get_index(ast, p, 0);
06251    if (index < 0) {
06252       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06253       return -1;
06254    }
06255 
06256 #if 0
06257 #ifdef HAVE_PRI
06258    ast_mutex_lock(&p->lock);
06259    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06260       if (p->pri->pri) {      
06261          if (!pri_grab(p, p->pri)) {
06262                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06263                pri_rel(p->pri);
06264          } else
06265                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06266       }
06267       p->proceeding=1;
06268    }
06269    ast_mutex_unlock(&p->lock);
06270 #endif
06271 #endif
06272    /* Write a frame of (presumably voice) data */
06273    if (frame->frametype != AST_FRAME_VOICE) {
06274       if (frame->frametype != AST_FRAME_IMAGE)
06275          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06276       return 0;
06277    }
06278    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06279        (frame->subclass != AST_FORMAT_ULAW) &&
06280        (frame->subclass != AST_FORMAT_ALAW)) {
06281       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06282       return -1;
06283    }
06284    if (p->dialing) {
06285       if (option_debug)
06286          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06287       return 0;
06288    }
06289    if (!p->owner) {
06290       if (option_debug)
06291          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06292       return 0;
06293    }
06294    if (p->cidspill) {
06295       if (option_debug)
06296          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06297       return 0;
06298    }
06299    /* Return if it's not valid data */
06300    if (!frame->data || !frame->datalen)
06301       return 0;
06302 
06303    if (frame->subclass == AST_FORMAT_SLINEAR) {
06304       if (!p->subs[index].linear) {
06305          p->subs[index].linear = 1;
06306          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06307          if (res)
06308             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06309       }
06310       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06311    } else {
06312       /* x-law already */
06313       if (p->subs[index].linear) {
06314          p->subs[index].linear = 0;
06315          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06316          if (res)
06317             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06318       }
06319       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06320    }
06321    if (res < 0) {
06322       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06323       return -1;
06324    } 
06325    return 0;
06326 }
06327 
06328 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06329 {
06330    struct dahdi_pvt *p = chan->tech_pvt;
06331    int res=-1;
06332    int index;
06333    int func = DAHDI_FLASH;
06334    ast_mutex_lock(&p->lock);
06335    index = dahdi_get_index(chan, p, 0);
06336    ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06337 #ifdef HAVE_OPENR2
06338    if (p->mfcr2 && !p->mfcr2_call_accepted) {
06339       ast_mutex_unlock(&p->lock);
06340       /* if this an R2 call and the call is not yet accepted we don't want the 
06341          tone indications to mess up with the MF tones */
06342       return 0;
06343    }
06344 #endif
06345    if (index == SUB_REAL) {
06346       switch (condition) {
06347       case AST_CONTROL_BUSY:
06348 #ifdef HAVE_PRI
06349          if (p->priindication_oob && p->sig == SIG_PRI) {
06350             chan->hangupcause = AST_CAUSE_USER_BUSY;
06351             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06352             res = 0;
06353          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06354             if (p->pri->pri) {      
06355                if (!pri_grab(p, p->pri)) {
06356                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06357                   pri_rel(p->pri);
06358                }
06359                else
06360                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06361             }
06362             p->progress = 1;
06363             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06364          } else
06365 #endif
06366             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06367          break;
06368       case AST_CONTROL_RINGING:
06369 #ifdef HAVE_PRI
06370          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06371             if (p->pri->pri) {      
06372                if (!pri_grab(p, p->pri)) {
06373                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06374                   pri_rel(p->pri);
06375                }
06376                else
06377                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06378             }
06379             p->alerting = 1;
06380          }
06381 #endif
06382          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06383          if (chan->_state != AST_STATE_UP) {
06384             if ((chan->_state != AST_STATE_RING) ||
06385                ((p->sig != SIG_FXSKS) &&
06386                 (p->sig != SIG_FXSLS) &&
06387                 (p->sig != SIG_FXSGS)))
06388                ast_setstate(chan, AST_STATE_RINGING);
06389          }
06390          break;
06391       case AST_CONTROL_PROCEEDING:
06392          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06393 #ifdef HAVE_PRI
06394          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06395             if (p->pri->pri) {      
06396                if (!pri_grab(p, p->pri)) {
06397                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06398                   pri_rel(p->pri);
06399                }
06400                else
06401                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06402             }
06403             p->proceeding = 1;
06404             p->dialing = 0;
06405          }
06406 #endif
06407          /* don't continue in ast_indicate */
06408          res = 0;
06409          break;
06410       case AST_CONTROL_PROGRESS:
06411          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06412 #ifdef HAVE_PRI
06413          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
06414          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06415             if (p->pri->pri) {      
06416                if (!pri_grab(p, p->pri)) {
06417                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06418                   pri_rel(p->pri);
06419                }
06420                else
06421                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06422             }
06423             p->progress = 1;
06424          }
06425 #endif
06426          /* don't continue in ast_indicate */
06427          res = 0;
06428          break;
06429       case AST_CONTROL_CONGESTION:
06430          chan->hangupcause = AST_CAUSE_CONGESTION;
06431 #ifdef HAVE_PRI
06432          if (p->priindication_oob && p->sig == SIG_PRI) {
06433             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06434             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06435             res = 0;
06436          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06437             if (p->pri) {     
06438                if (!pri_grab(p, p->pri)) {
06439                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06440                   pri_rel(p->pri);
06441                } else
06442                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06443             }
06444             p->progress = 1;
06445             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06446          } else
06447 #endif
06448             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06449          break;
06450       case AST_CONTROL_HOLD:
06451 #ifdef HAVE_PRI
06452          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06453             if (!pri_grab(p, p->pri)) {
06454                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06455                pri_rel(p->pri);
06456             } else
06457                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06458          } else
06459 #endif
06460             ast_moh_start(chan, data, p->mohinterpret);
06461          break;
06462       case AST_CONTROL_UNHOLD:
06463 #ifdef HAVE_PRI
06464          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06465             if (!pri_grab(p, p->pri)) {
06466                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06467                pri_rel(p->pri);
06468             } else
06469                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06470          } else
06471 #endif
06472             ast_moh_stop(chan);
06473          break;
06474       case AST_CONTROL_RADIO_KEY:
06475          if (p->radio) 
06476              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06477          res = 0;
06478          break;
06479       case AST_CONTROL_RADIO_UNKEY:
06480          if (p->radio)
06481              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06482          res = 0;
06483          break;
06484       case AST_CONTROL_FLASH:
06485          /* flash hookswitch */
06486          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06487             /* Clear out the dial buffer */
06488             p->dop.dialstr[0] = '\0';
06489             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06490                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06491                   chan->name, strerror(errno));
06492             } else
06493                res = 0;
06494          } else
06495             res = 0;
06496          break;
06497       case AST_CONTROL_SRCUPDATE:
06498          res = 0;
06499          break;
06500       case -1:
06501          res = tone_zone_play_tone(p->subs[index].dfd, -1);
06502          break;
06503       }
06504    } else
06505       res = 0;
06506    ast_mutex_unlock(&p->lock);
06507    return res;
06508 }
06509 
06510 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06511 {
06512    struct ast_channel *tmp;
06513    int deflaw;
06514    int res;
06515    int x,y;
06516    int features;
06517    char *b2 = NULL;
06518    struct dahdi_params ps;
06519    char chanprefix[*dahdi_chan_name_len + 4];
06520 
06521    if (i->subs[index].owner) {
06522       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06523       return NULL;
06524    }
06525    y = 1;
06526    do {
06527       if (b2)
06528          free(b2);
06529 #ifdef HAVE_PRI
06530       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06531          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06532       else
06533 #endif
06534       if (i->channel == CHAN_PSEUDO)
06535          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
06536       else  
06537          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
06538       for (x = 0; x < 3; x++) {
06539          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
06540             break;
06541       }
06542       y++;
06543    } while (x < 3);
06544    strcpy(chanprefix, dahdi_chan_name);
06545    strcat(chanprefix, "/%s");
06546    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
06547    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
06548       free(b2);
06549    if (!tmp)
06550       return NULL;
06551    tmp->tech = chan_tech;
06552    memset(&ps, 0, sizeof(ps));
06553    ps.channo = i->channel;
06554    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06555    if (res) {
06556       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06557       ps.curlaw = DAHDI_LAW_MULAW;
06558    }
06559    if (ps.curlaw == DAHDI_LAW_ALAW)
06560       deflaw = AST_FORMAT_ALAW;
06561    else
06562       deflaw = AST_FORMAT_ULAW;
06563    if (law) {
06564       if (law == DAHDI_LAW_ALAW)
06565          deflaw = AST_FORMAT_ALAW;
06566       else
06567          deflaw = AST_FORMAT_ULAW;
06568    }
06569    tmp->fds[0] = i->subs[index].dfd;
06570    tmp->nativeformats = deflaw;
06571    /* Start out assuming ulaw since it's smaller :) */
06572    tmp->rawreadformat = deflaw;
06573    tmp->readformat = deflaw;
06574    tmp->rawwriteformat = deflaw;
06575    tmp->writeformat = deflaw;
06576    i->subs[index].linear = 0;
06577    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06578    features = 0;
06579    if (index == SUB_REAL) {
06580       if (i->busydetect && CANBUSYDETECT(i))
06581          features |= DSP_FEATURE_BUSY_DETECT;
06582       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
06583          features |= DSP_FEATURE_CALL_PROGRESS;
06584       if ((!i->outgoing && (i->callprogress & 4)) || 
06585           (i->outgoing && (i->callprogress & 2))) {
06586          features |= DSP_FEATURE_FAX_DETECT;
06587       }
06588 #ifdef DAHDI_TONEDETECT
06589       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06590       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06591 #endif      
06592          i->hardwaredtmf = 0;
06593          features |= DSP_FEATURE_DTMF_DETECT;
06594 #ifdef DAHDI_TONEDETECT
06595       } else if (NEED_MFDETECT(i)) {
06596          i->hardwaredtmf = 1;
06597          features |= DSP_FEATURE_DTMF_DETECT;
06598       }
06599 #endif
06600    }
06601    if (features) {
06602       if (i->dsp) {
06603          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
06604       } else {
06605          if (i->channel != CHAN_PSEUDO)
06606             i->dsp = ast_dsp_new();
06607          else
06608             i->dsp = NULL;
06609          if (i->dsp) {
06610             i->dsp_features = features;
06611 #ifdef HAVE_PRI
06612             /* We cannot do progress detection until receives PROGRESS message */
06613             if (i->outgoing && (i->sig == SIG_PRI)) {
06614                /* Remember requested DSP features, don't treat
06615                   talking as ANSWER */
06616                i->dsp_features = features & ~DSP_PROGRESS_TALK;
06617                features = 0;
06618             }
06619 #endif
06620             ast_dsp_set_features(i->dsp, features);
06621             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06622             if (!ast_strlen_zero(progzone))
06623                ast_dsp_set_call_progress_zone(i->dsp, progzone);
06624             if (i->busydetect && CANBUSYDETECT(i)) {
06625                if(i->silencethreshold > 0)
06626                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06627                ast_dsp_set_busy_count(i->dsp, i->busycount);
06628                if(i->busytonelength > 0)
06629                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06630                if((i->busytonelength == i->busyquietlength) && i->busycompare)
06631                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06632             }
06633          }
06634       }
06635    }
06636       
06637    if (state == AST_STATE_RING)
06638       tmp->rings = 1;
06639    tmp->tech_pvt = i;
06640    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06641       /* Only FXO signalled stuff can be picked up */
06642       tmp->callgroup = i->callgroup;
06643       tmp->pickupgroup = i->pickupgroup;
06644    }
06645    if (!ast_strlen_zero(i->language))
06646       ast_string_field_set(tmp, language, i->language);
06647    if (!i->owner)
06648       i->owner = tmp;
06649    if (!ast_strlen_zero(i->accountcode))
06650       ast_string_field_set(tmp, accountcode, i->accountcode);
06651    if (i->amaflags)
06652       tmp->amaflags = i->amaflags;
06653    i->subs[index].owner = tmp;
06654    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06655    ast_string_field_set(tmp, call_forward, i->call_forward);
06656    /* If we've been told "no ADSI" then enforce it */
06657    if (!i->adsi)
06658       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06659    if (!ast_strlen_zero(i->exten))
06660       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06661    if (!ast_strlen_zero(i->rdnis))
06662       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06663    if (!ast_strlen_zero(i->dnid))
06664       tmp->cid.cid_dnid = ast_strdup(i->dnid);
06665 
06666    /* Don't use ast_set_callerid() here because it will
06667     * generate a needless NewCallerID event */
06668 #ifdef PRI_ANI
06669    if (!ast_strlen_zero(i->cid_ani))
06670       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06671    else  
06672       tmp->cid.cid_ani = ast_strdup(i->cid_num);
06673 #else
06674    tmp->cid.cid_ani = ast_strdup(i->cid_num);
06675 #endif
06676    tmp->cid.cid_pres = i->callingpres;
06677    tmp->cid.cid_ton = i->cid_ton;
06678 #ifdef HAVE_PRI
06679    tmp->transfercapability = transfercapability;
06680    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06681    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
06682       i->digital = 1;
06683    /* Assume calls are not idle calls unless we're told differently */
06684    i->isidlecall = 0;
06685    i->alreadyhungup = 0;
06686 #endif
06687    /* clear the fake event in case we posted one before we had ast_channel */
06688    i->fake_event = 0;
06689    /* Assure there is no confmute on this channel */
06690    dahdi_confmute(i, 0);
06691    /* Configure the new channel jb */
06692    ast_jb_configure(tmp, &global_jbconf);
06693    if (startpbx) {
06694 #ifdef HAVE_OPENR2
06695       if (i->mfcr2call) {
06696          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
06697       }
06698 #endif
06699       if (ast_pbx_start(tmp)) {
06700          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06701          ast_hangup(tmp);
06702          i->owner = NULL;
06703          return NULL;
06704       }
06705    }
06706 
06707    ast_module_ref(ast_module_info->self);
06708    
06709    return tmp;
06710 }
06711 
06712 
06713 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06714 {
06715    char c;
06716 
06717    *str = 0; /* start with empty output buffer */
06718    for (;;)
06719    {
06720       /* Wait for the first digit (up to specified ms). */
06721       c = ast_waitfordigit(chan, ms);
06722       /* if timeout, hangup or error, return as such */
06723       if (c < 1)
06724          return c;
06725       *str++ = c;
06726       *str = 0;
06727       if (strchr(term, c))
06728          return 1;
06729    }
06730 }
06731 
06732 static int dahdi_wink(struct dahdi_pvt *p, int index)
06733 {
06734    int j;
06735    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06736    for (;;)
06737    {
06738          /* set bits of interest */
06739       j = DAHDI_IOMUX_SIGEVENT;
06740           /* wait for some happening */
06741       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06742          /* exit loop if we have it */
06743       if (j & DAHDI_IOMUX_SIGEVENT) break;
06744    }
06745      /* get the event info */
06746    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06747    return 0;
06748 }
06749 
06750 static void *ss_thread(void *data)
06751 {
06752    struct ast_channel *chan = data;
06753    struct dahdi_pvt *p = chan->tech_pvt;
06754    char exten[AST_MAX_EXTENSION] = "";
06755    char exten2[AST_MAX_EXTENSION] = "";
06756    unsigned char buf[256];
06757    char dtmfcid[300];
06758    char dtmfbuf[300];
06759    struct callerid_state *cs = NULL;
06760    char *name = NULL, *number = NULL;
06761    int distMatches;
06762    int curRingData[3];
06763    int receivedRingT;
06764    int counter1;
06765    int counter;
06766    int samples = 0;
06767    struct ast_smdi_md_message *smdi_msg = NULL;
06768    int flags = 0;
06769    int i;
06770    int timeout;
06771    int getforward = 0;
06772    char *s1, *s2;
06773    int len = 0;
06774    int res;
06775    int index;
06776 
06777    ast_mutex_lock(&ss_thread_lock);
06778    ss_thread_count++;
06779    ast_mutex_unlock(&ss_thread_lock);
06780    /* in the bizarre case where the channel has become a zombie before we
06781       even get started here, abort safely
06782    */
06783    if (!p) {
06784       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06785       ast_hangup(chan);
06786       goto quit;
06787    }
06788    if (option_verbose > 2) 
06789       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
06790    index = dahdi_get_index(chan, p, 1);
06791    if (index < 0) {
06792       ast_log(LOG_WARNING, "Huh?\n");
06793       ast_hangup(chan);
06794       goto quit;
06795    }
06796    if (p->dsp)
06797       ast_dsp_digitreset(p->dsp);
06798    switch (p->sig) {
06799 #ifdef HAVE_PRI
06800    case SIG_PRI:
06801       /* Now loop looking for an extension */
06802       ast_copy_string(exten, p->exten, sizeof(exten));
06803       len = strlen(exten);
06804       res = 0;
06805       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06806          if (len && !ast_ignore_pattern(chan->context, exten))
06807             tone_zone_play_tone(p->subs[index].dfd, -1);
06808          else
06809             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06810          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06811             timeout = matchdigittimeout;
06812          else
06813             timeout = gendigittimeout;
06814          res = ast_waitfordigit(chan, timeout);
06815          if (res < 0) {
06816             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06817             ast_hangup(chan);
06818             goto quit;
06819          } else if (res) {
06820             exten[len++] = res;
06821             exten[len] = '\0';
06822          } else
06823             break;
06824       }
06825       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
06826       if (ast_strlen_zero(exten)) {
06827          if (option_verbose > 2)
06828             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
06829          exten[0] = 's';
06830          exten[1] = '\0';
06831       }
06832       tone_zone_play_tone(p->subs[index].dfd, -1);
06833       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06834          /* Start the real PBX */
06835          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06836          if (p->dsp) ast_dsp_digitreset(p->dsp);
06837          dahdi_enable_ec(p);
06838          ast_setstate(chan, AST_STATE_RING);
06839          res = ast_pbx_run(chan);
06840          if (res) {
06841             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06842          }
06843       } else {
06844          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06845          chan->hangupcause = AST_CAUSE_UNALLOCATED;
06846          ast_hangup(chan);
06847          p->exten[0] = '\0';
06848          /* Since we send release complete here, we won't get one */
06849          p->call = NULL;
06850       }
06851       goto quit;
06852       break;
06853 #endif
06854    case SIG_FEATD:
06855    case SIG_FEATDMF:
06856    case SIG_FEATDMF_TA:
06857    case SIG_E911:
06858    case SIG_FGC_CAMAMF:
06859    case SIG_FEATB:
06860    case SIG_EMWINK:
06861    case SIG_SF_FEATD:
06862    case SIG_SF_FEATDMF:
06863    case SIG_SF_FEATB:
06864    case SIG_SFWINK:
06865       if (dahdi_wink(p, index))  
06866          goto quit;
06867       /* Fall through */
06868    case SIG_EM:
06869    case SIG_EM_E1:
06870    case SIG_SF:
06871    case SIG_FGC_CAMA:
06872       res = tone_zone_play_tone(p->subs[index].dfd, -1);
06873       if (p->dsp)
06874          ast_dsp_digitreset(p->dsp);
06875       /* set digit mode appropriately */
06876       if (p->dsp) {
06877          if (NEED_MFDETECT(p))
06878             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
06879          else 
06880             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06881       }
06882       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06883       /* Wait for the first digit only if immediate=no */
06884       if (!p->immediate)
06885          /* Wait for the first digit (up to 5 seconds). */
06886          res = ast_waitfordigit(chan, 5000);
06887       else
06888          res = 0;
06889       if (res > 0) {
06890          /* save first char */
06891          dtmfbuf[0] = res;
06892          switch (p->sig) {
06893          case SIG_FEATD:
06894          case SIG_SF_FEATD:
06895             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06896             if (res > 0)
06897                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06898             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06899             break;
06900          case SIG_FEATDMF_TA:
06901             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06902             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06903             if (dahdi_wink(p, index)) goto quit;
06904             dtmfbuf[0] = 0;
06905             /* Wait for the first digit (up to 5 seconds). */
06906             res = ast_waitfordigit(chan, 5000);
06907             if (res <= 0) break;
06908             dtmfbuf[0] = res;
06909             /* fall through intentionally */
06910          case SIG_FEATDMF:
06911          case SIG_E911:
06912          case SIG_FGC_CAMAMF:
06913          case SIG_SF_FEATDMF:
06914             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06915             /* if international caca, do it again to get real ANO */
06916             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06917             {
06918                if (dahdi_wink(p, index)) goto quit;
06919                dtmfbuf[0] = 0;
06920                /* Wait for the first digit (up to 5 seconds). */
06921                res = ast_waitfordigit(chan, 5000);
06922                if (res <= 0) break;
06923                dtmfbuf[0] = res;
06924                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06925             }
06926             if (res > 0) {
06927                /* if E911, take off hook */
06928                if (p->sig == SIG_E911)
06929                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06930                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06931             }
06932             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06933             break;
06934          case SIG_FEATB:
06935          case SIG_SF_FEATB:
06936             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06937             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06938             break;
06939          case SIG_EMWINK:
06940             /* if we received a '*', we are actually receiving Feature Group D
06941                dial syntax, so use that mode; otherwise, fall through to normal
06942                mode
06943             */
06944             if (res == '*') {
06945                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06946                if (res > 0)
06947                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06948                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06949                break;
06950             }
06951          default:
06952             /* If we got the first digit, get the rest */
06953             len = 1;
06954             dtmfbuf[len] = '\0';
06955             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06956                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06957                   timeout = matchdigittimeout;
06958                } else {
06959                   timeout = gendigittimeout;
06960                }
06961                res = ast_waitfordigit(chan, timeout);
06962                if (res < 0) {
06963                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06964                   ast_hangup(chan);
06965                   goto quit;
06966                } else if (res) {
06967                   dtmfbuf[len++] = res;
06968                   dtmfbuf[len] = '\0';
06969                } else {
06970                   break;
06971                }
06972             }
06973             break;
06974          }
06975       }
06976       if (res == -1) {
06977          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06978          ast_hangup(chan);
06979          goto quit;
06980       } else if (res < 0) {
06981          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06982          ast_hangup(chan);
06983          goto quit;
06984       }
06985 
06986       if (p->sig == SIG_FGC_CAMA) {
06987          char anibuf[100];
06988 
06989          if (ast_safe_sleep(chan,1000) == -1) {
06990                            ast_hangup(chan);
06991                            goto quit;
06992          }
06993                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06994                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06995                         res = my_getsigstr(chan, anibuf, "#", 10000);
06996                         if ((res > 0) && (strlen(anibuf) > 2)) {
06997             if (anibuf[strlen(anibuf) - 1] == '#')
06998                anibuf[strlen(anibuf) - 1] = 0;
06999             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07000          }
07001                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07002       }
07003 
07004       ast_copy_string(exten, dtmfbuf, sizeof(exten));
07005       if (ast_strlen_zero(exten))
07006          ast_copy_string(exten, "s", sizeof(exten));
07007       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07008          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
07009          if (exten[0] == '*') {
07010             char *stringp=NULL;
07011             ast_copy_string(exten2, exten, sizeof(exten2));
07012             /* Parse out extension and callerid */
07013             stringp=exten2 +1;
07014             s1 = strsep(&stringp, "*");
07015             s2 = strsep(&stringp, "*");
07016             if (s2) {
07017                if (!ast_strlen_zero(p->cid_num))
07018                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07019                else
07020                   ast_set_callerid(chan, s1, NULL, s1);
07021                ast_copy_string(exten, s2, sizeof(exten));
07022             } else
07023                ast_copy_string(exten, s1, sizeof(exten));
07024          } else if (p->sig == SIG_FEATD)
07025             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07026       }
07027       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07028          if (exten[0] == '*') {
07029             char *stringp=NULL;
07030             ast_copy_string(exten2, exten, sizeof(exten2));
07031             /* Parse out extension and callerid */
07032             stringp=exten2 +1;
07033             s1 = strsep(&stringp, "#");
07034             s2 = strsep(&stringp, "#");
07035             if (s2) {
07036                if (!ast_strlen_zero(p->cid_num))
07037                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07038                else
07039                   if (*(s1 + 2))
07040                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07041                ast_copy_string(exten, s2 + 1, sizeof(exten));
07042             } else
07043                ast_copy_string(exten, s1 + 2, sizeof(exten));
07044          } else
07045             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07046       }
07047       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07048          if (exten[0] == '*') {
07049             char *stringp=NULL;
07050             ast_copy_string(exten2, exten, sizeof(exten2));
07051             /* Parse out extension and callerid */
07052             stringp=exten2 +1;
07053             s1 = strsep(&stringp, "#");
07054             s2 = strsep(&stringp, "#");
07055             if (s2 && (*(s2 + 1) == '0')) {
07056                if (*(s2 + 2))
07057                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07058             }
07059             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
07060             else ast_copy_string(exten, "911", sizeof(exten));
07061          } else
07062             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07063       }
07064       if (p->sig == SIG_FEATB) {
07065          if (exten[0] == '*') {
07066             char *stringp=NULL;
07067             ast_copy_string(exten2, exten, sizeof(exten2));
07068             /* Parse out extension and callerid */
07069             stringp=exten2 +1;
07070             s1 = strsep(&stringp, "#");
07071             ast_copy_string(exten, exten2 + 1, sizeof(exten));
07072          } else
07073             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07074       }
07075       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07076          dahdi_wink(p, index);
07077                         /* some switches require a minimum guard time between
07078                            the last FGD wink and something that answers
07079                            immediately. This ensures it */
07080                         if (ast_safe_sleep(chan,100)) goto quit;
07081       }
07082       dahdi_enable_ec(p);
07083       if (NEED_MFDETECT(p)) {
07084          if (p->dsp) {
07085             if (!p->hardwaredtmf)
07086                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
07087             else {
07088                ast_dsp_free(p->dsp);
07089                p->dsp = NULL;
07090             }
07091          }
07092       }
07093 
07094       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07095          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07096          if (p->dsp) ast_dsp_digitreset(p->dsp);
07097          res = ast_pbx_run(chan);
07098          if (res) {
07099             ast_log(LOG_WARNING, "PBX exited non-zero\n");
07100             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07101          }
07102          goto quit;
07103       } else {
07104          if (option_verbose > 2)
07105             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07106          sleep(2);
07107          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07108          if (res < 0)
07109             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07110          else
07111             sleep(1);
07112          res = ast_streamfile(chan, "ss-noservice", chan->language);
07113          if (res >= 0)
07114             ast_waitstream(chan, "");
07115          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07116          ast_hangup(chan);
07117          goto quit;
07118       }
07119       break;
07120    case SIG_FXOLS:
07121    case SIG_FXOGS:
07122    case SIG_FXOKS:
07123       /* Read the first digit */
07124       timeout = firstdigittimeout;
07125       /* If starting a threeway call, never timeout on the first digit so someone
07126          can use flash-hook as a "hold" feature */
07127       if (p->subs[SUB_THREEWAY].owner) 
07128          timeout = 999999;
07129       while (len < AST_MAX_EXTENSION-1) {
07130          /* Read digit unless it's supposed to be immediate, in which case the
07131             only answer is 's' */
07132          if (p->immediate) 
07133             res = 's';
07134          else
07135             res = ast_waitfordigit(chan, timeout);
07136          timeout = 0;
07137          if (res < 0) {
07138             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07139             res = tone_zone_play_tone(p->subs[index].dfd, -1);
07140             ast_hangup(chan);
07141             goto quit;
07142          } else if (res)  {
07143             exten[len++]=res;
07144             exten[len] = '\0';
07145          }
07146          if (!ast_ignore_pattern(chan->context, exten))
07147             tone_zone_play_tone(p->subs[index].dfd, -1);
07148          else
07149             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07150          if (!strcmp(exten,ast_pickup_ext())) {
07151             /* Scan all channels and see if there are any
07152              * ringing channels that have call groups
07153              * that equal this channels pickup group
07154              */
07155             if (index == SUB_REAL) {
07156                /* Switch us from Third call to Call Wait */
07157                if (p->subs[SUB_THREEWAY].owner) {
07158                   /* If you make a threeway call and the *8# a call, it should actually
07159                      look like a callwait */
07160                   alloc_sub(p, SUB_CALLWAIT);
07161                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07162                   unalloc_sub(p, SUB_THREEWAY);
07163                }
07164                dahdi_enable_ec(p);
07165                if (ast_pickup_call(chan)) {
07166                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
07167                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07168                   dahdi_wait_event(p->subs[index].dfd);
07169                }
07170                ast_hangup(chan);
07171                goto quit;
07172             } else {
07173                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
07174                ast_hangup(chan);
07175                goto quit;
07176             }
07177 
07178          } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07179             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07180                if (getforward) {
07181                   /* Record this as the forwarding extension */
07182                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
07183                   if (option_verbose > 2)
07184                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07185                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07186                   if (res)
07187                      break;
07188                   usleep(500000);
07189                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07190                   sleep(1);
07191                   memset(exten, 0, sizeof(exten));
07192                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07193                   len = 0;
07194                   getforward = 0;
07195                } else  {
07196                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07197                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07198                   if (!ast_strlen_zero(p->cid_num)) {
07199                      if (!p->hidecallerid)
07200                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
07201                      else
07202                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
07203                   }
07204                   if (!ast_strlen_zero(p->cid_name)) {
07205                      if (!p->hidecallerid)
07206                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
07207                   }
07208                   ast_setstate(chan, AST_STATE_RING);
07209                   dahdi_enable_ec(p);
07210                   res = ast_pbx_run(chan);
07211                   if (res) {
07212                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
07213                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07214                   }
07215                   goto quit;
07216                }
07217             } else {
07218                /* It's a match, but they just typed a digit, and there is an ambiguous match,
07219                   so just set the timeout to matchdigittimeout and wait some more */
07220                timeout = matchdigittimeout;
07221             }
07222          } else if (res == 0) {
07223             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07224             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07225             dahdi_wait_event(p->subs[index].dfd);
07226             ast_hangup(chan);
07227             goto quit;
07228          } else if (p->callwaiting && !strcmp(exten, "*70")) {
07229             if (option_verbose > 2) 
07230                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07231             /* Disable call waiting if enabled */
07232             p->callwaiting = 0;
07233             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07234             if (res) {
07235                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07236                   chan->name, strerror(errno));
07237             }
07238             len = 0;
07239             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07240             memset(exten, 0, sizeof(exten));
07241             timeout = firstdigittimeout;
07242                
07243          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07244             if (option_verbose > 2) 
07245                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07246             /* Disable Caller*ID if enabled */
07247             p->hidecallerid = 1;
07248             if (chan->cid.cid_num)
07249                free(chan->cid.cid_num);
07250             chan->cid.cid_num = NULL;
07251             if (chan->cid.cid_name)
07252                free(chan->cid.cid_name);
07253             chan->cid.cid_name = NULL;
07254             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07255             if (res) {
07256                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07257                   chan->name, strerror(errno));
07258             }
07259             len = 0;
07260             memset(exten, 0, sizeof(exten));
07261             timeout = firstdigittimeout;
07262          } else if (p->callreturn && !strcmp(exten, "*69")) {
07263             res = 0;
07264             if (!ast_strlen_zero(p->lastcid_num)) {
07265                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07266             }
07267             if (!res)
07268                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07269             break;
07270          } else if (!strcmp(exten, "*78")) {
07271             /* Do not disturb */
07272             if (option_verbose > 2)
07273                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07274             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07275                      "Channel: %s/%d\r\n"
07276                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
07277             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07278             p->dnd = 1;
07279             getforward = 0;
07280             memset(exten, 0, sizeof(exten));
07281             len = 0;
07282          } else if (!strcmp(exten, "*79")) {
07283             /* Do not disturb */
07284             if (option_verbose > 2)
07285                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07286             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07287                      "Channel: %s/%d\r\n"
07288                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
07289             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07290             p->dnd = 0;
07291             getforward = 0;
07292             memset(exten, 0, sizeof(exten));
07293             len = 0;
07294          } else if (p->cancallforward && !strcmp(exten, "*72")) {
07295             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07296             getforward = 1;
07297             memset(exten, 0, sizeof(exten));
07298             len = 0;
07299          } else if (p->cancallforward && !strcmp(exten, "*73")) {
07300             if (option_verbose > 2)
07301                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07302             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07303             memset(p->call_forward, 0, sizeof(p->call_forward));
07304             getforward = 0;
07305             memset(exten, 0, sizeof(exten));
07306             len = 0;
07307          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
07308                   p->subs[SUB_THREEWAY].owner &&
07309                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07310             /* This is a three way call, the main call being a real channel, 
07311                and we're parking the first call. */
07312             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07313             if (option_verbose > 2)
07314                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07315             break;
07316          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07317             if (option_verbose > 2)
07318                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07319             res = ast_db_put("blacklist", p->lastcid_num, "1");
07320             if (!res) {
07321                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07322                memset(exten, 0, sizeof(exten));
07323                len = 0;
07324             }
07325          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07326             if (option_verbose > 2) 
07327                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07328             /* Enable Caller*ID if enabled */
07329             p->hidecallerid = 0;
07330             if (chan->cid.cid_num)
07331                free(chan->cid.cid_num);
07332             chan->cid.cid_num = NULL;
07333             if (chan->cid.cid_name)
07334                free(chan->cid.cid_name);
07335             chan->cid.cid_name = NULL;
07336             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07337             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07338             if (res) {
07339                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07340                   chan->name, strerror(errno));
07341             }
07342             len = 0;
07343             memset(exten, 0, sizeof(exten));
07344             timeout = firstdigittimeout;
07345          } else if (!strcmp(exten, "*0")) {
07346             struct ast_channel *nbridge = 
07347                p->subs[SUB_THREEWAY].owner;
07348             struct dahdi_pvt *pbridge = NULL;
07349               /* set up the private struct of the bridged one, if any */
07350             if (nbridge && ast_bridged_channel(nbridge)) 
07351                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07352             if (nbridge && pbridge && 
07353                 (nbridge->tech == chan_tech) && 
07354                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07355                 ISTRUNK(pbridge)) {
07356                int func = DAHDI_FLASH;
07357                /* Clear out the dial buffer */
07358                p->dop.dialstr[0] = '\0';
07359                /* flash hookswitch */
07360                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07361                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
07362                      nbridge->name, strerror(errno));
07363                }
07364                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07365                unalloc_sub(p, SUB_THREEWAY);
07366                p->owner = p->subs[SUB_REAL].owner;
07367                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07368                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07369                ast_hangup(chan);
07370                goto quit;
07371             } else {
07372                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07373                dahdi_wait_event(p->subs[index].dfd);
07374                tone_zone_play_tone(p->subs[index].dfd, -1);
07375                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07376                unalloc_sub(p, SUB_THREEWAY);
07377                p->owner = p->subs[SUB_REAL].owner;
07378                ast_hangup(chan);
07379                goto quit;
07380             }              
07381          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07382                      ((exten[0] != '*') || (strlen(exten) > 2))) {
07383             if (option_debug)
07384                ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
07385             break;
07386          }
07387          if (!timeout)
07388             timeout = gendigittimeout;
07389          if (len && !ast_ignore_pattern(chan->context, exten))
07390             tone_zone_play_tone(p->subs[index].dfd, -1);
07391       }
07392       break;
07393    case SIG_FXSLS:
07394    case SIG_FXSGS:
07395    case SIG_FXSKS:
07396 #ifdef HAVE_PRI
07397       if (p->pri) {
07398          /* This is a GR-303 trunk actually.  Wait for the first ring... */
07399          struct ast_frame *f;
07400          int res;
07401          time_t start;
07402 
07403          time(&start);
07404          ast_setstate(chan, AST_STATE_RING);
07405          while (time(NULL) < start + 3) {
07406             res = ast_waitfor(chan, 1000);
07407             if (res) {
07408                f = ast_read(chan);
07409                if (!f) {
07410                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07411                   ast_hangup(chan);
07412                   goto quit;
07413                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07414                   res = 1;
07415                } else
07416                   res = 0;
07417                ast_frfree(f);
07418                if (res) {
07419                   ast_log(LOG_DEBUG, "Got ring!\n");
07420                   res = 0;
07421                   break;
07422                }
07423             }
07424          }
07425       }
07426 #endif
07427       /* check for SMDI messages */
07428       if (p->use_smdi && p->smdi_iface) {
07429          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07430 
07431          if (smdi_msg != NULL) {
07432             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07433 
07434             if (smdi_msg->type == 'B')
07435                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07436             else if (smdi_msg->type == 'N')
07437                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07438 
07439             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
07440          } else {
07441             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07442          }
07443       }
07444 
07445       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07446             number = smdi_msg->calling_st;
07447 
07448       /* If we want caller id, we're in a prering state due to a polarity reversal
07449        * and we're set to use a polarity reversal to trigger the start of caller id,
07450        * grab the caller id and wait for ringing to start... */
07451       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
07452          /* If set to use DTMF CID signalling, listen for DTMF */
07453          if (p->cid_signalling == CID_SIG_DTMF) {
07454             int i = 0;
07455             cs = NULL;
07456             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
07457                "channel %s\n", chan->name);
07458             dahdi_setlinear(p->subs[index].dfd, 0);
07459             res = 2000;
07460             for (;;) {
07461                struct ast_frame *f;
07462                res = ast_waitfor(chan, res);
07463                if (res <= 0) {
07464                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07465                      "Exiting simple switch\n");
07466                   ast_hangup(chan);
07467                   goto quit;
07468                } 
07469                f = ast_read(chan);
07470                if (!f)
07471                   break;
07472                if (f->frametype == AST_FRAME_DTMF) {
07473                   dtmfbuf[i++] = f->subclass;
07474                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07475                   res = 2000;
07476                }
07477                ast_frfree(f);
07478                if (chan->_state == AST_STATE_RING ||
07479                    chan->_state == AST_STATE_RINGING) 
07480                   break; /* Got ring */
07481             }
07482             dtmfbuf[i] = '\0';
07483             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07484             /* Got cid and ring. */
07485             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
07486             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07487             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
07488                dtmfcid, flags);
07489             /* If first byte is NULL, we have no cid */
07490             if (!ast_strlen_zero(dtmfcid)) 
07491                number = dtmfcid;
07492             else
07493                number = NULL;
07494          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07495          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07496             cs = callerid_new(p->cid_signalling);
07497             if (cs) {
07498                samples = 0;
07499 #if 1
07500                bump_gains(p);
07501 #endif            
07502                /* Take out of linear mode for Caller*ID processing */
07503                dahdi_setlinear(p->subs[index].dfd, 0);
07504                
07505                /* First we wait and listen for the Caller*ID */
07506                for (;;) {  
07507                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07508                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07509                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07510                      callerid_free(cs);
07511                      ast_hangup(chan);
07512                      goto quit;
07513                   }
07514                   if (i & DAHDI_IOMUX_SIGEVENT) {
07515                      res = dahdi_get_event(p->subs[index].dfd);
07516                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07517 
07518                      if (p->cid_signalling == CID_SIG_V23_JP) {
07519 #ifdef DAHDI_EVENT_RINGBEGIN
07520                         if (res == DAHDI_EVENT_RINGBEGIN) {
07521                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07522                            usleep(1);
07523                         }
07524 #endif
07525                      } else {
07526                         res = 0;
07527                         break;
07528                      }
07529                   } else if (i & DAHDI_IOMUX_READ) {
07530                      res = read(p->subs[index].dfd, buf, sizeof(buf));
07531                      if (res < 0) {
07532                         if (errno != ELAST) {
07533                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07534                            callerid_free(cs);
07535                            ast_hangup(chan);
07536                            goto quit;
07537                         }
07538                         break;
07539                      }
07540                      samples += res;
07541 
07542                      if  (p->cid_signalling == CID_SIG_V23_JP) {
07543                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07544                      } else {
07545                         res = callerid_feed(cs, buf, res, AST_LAW(p));
07546                      }
07547 
07548                      if (res < 0) {
07549                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07550                         break;
07551                      } else if (res)
07552                         break;
07553                      else if (samples > (8000 * 10))
07554                         break;
07555                   }
07556                }
07557                if (res == 1) {
07558                   callerid_get(cs, &name, &number, &flags);
07559                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07560                }
07561 
07562                if (p->cid_signalling == CID_SIG_V23_JP) {
07563                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07564                   usleep(1);
07565                   res = 4000;
07566                } else {
07567 
07568                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
07569                   res = 2000;
07570                }
07571 
07572                for (;;) {
07573                   struct ast_frame *f;
07574                   res = ast_waitfor(chan, res);
07575                   if (res <= 0) {
07576                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07577                         "Exiting simple switch\n");
07578                      ast_hangup(chan);
07579                      goto quit;
07580                   } 
07581                   if (!(f = ast_read(chan))) {
07582                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07583                      ast_hangup(chan);
07584                      goto quit;
07585                   }
07586                   ast_frfree(f);
07587                   if (chan->_state == AST_STATE_RING ||
07588                       chan->_state == AST_STATE_RINGING) 
07589                      break; /* Got ring */
07590                }
07591    
07592                /* We must have a ring by now, so, if configured, lets try to listen for
07593                 * distinctive ringing */ 
07594                if (p->usedistinctiveringdetection) {
07595                   len = 0;
07596                   distMatches = 0;
07597                   /* Clear the current ring data array so we dont have old data in it. */
07598                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07599                      curRingData[receivedRingT] = 0;
07600                   receivedRingT = 0;
07601                   counter = 0;
07602                   counter1 = 0;
07603                   /* Check to see if context is what it should be, if not set to be. */
07604                   if (strcmp(p->context,p->defcontext) != 0) {
07605                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07606                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07607                   }
07608       
07609                   for (;;) {  
07610                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07611                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07612                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07613                         callerid_free(cs);
07614                         ast_hangup(chan);
07615                         goto quit;
07616                      }
07617                      if (i & DAHDI_IOMUX_SIGEVENT) {
07618                         res = dahdi_get_event(p->subs[index].dfd);
07619                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07620                         res = 0;
07621                         /* Let us detect distinctive ring */
07622       
07623                         curRingData[receivedRingT] = p->ringt;
07624       
07625                         if (p->ringt < p->ringt_base/2)
07626                            break;
07627                         /* Increment the ringT counter so we can match it against
07628                            values in chan_dahdi.conf for distinctive ring */
07629                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07630                            break;
07631                      } else if (i & DAHDI_IOMUX_READ) {
07632                         res = read(p->subs[index].dfd, buf, sizeof(buf));
07633                         if (res < 0) {
07634                            if (errno != ELAST) {
07635                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07636                               callerid_free(cs);
07637                               ast_hangup(chan);
07638                               goto quit;
07639                            }
07640                            break;
07641                         }
07642                         if (p->ringt) 
07643                            p->ringt--;
07644                         if (p->ringt == 1) {
07645                            res = -1;
07646                            break;
07647                         }
07648                      }
07649                   }
07650                   if (option_verbose > 2)
07651                      /* this only shows up if you have n of the dring patterns filled in */
07652                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07653    
07654                   for (counter = 0; counter < 3; counter++) {
07655                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07656                      channel */
07657                      distMatches = 0;
07658                      for (counter1 = 0; counter1 < 3; counter1++) {
07659                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07660                         (p->drings.ringnum[counter].ring[counter1]-10)) {
07661                            distMatches++;
07662                         }
07663                      }
07664                      if (distMatches == 3) {
07665                         /* The ring matches, set the context to whatever is for distinctive ring.. */
07666                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07667                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07668                         if (option_verbose > 2)
07669                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07670                         break;
07671                      }
07672                   }
07673                }
07674                /* Restore linear mode (if appropriate) for Caller*ID processing */
07675                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07676 #if 1
07677                restore_gains(p);
07678 #endif            
07679             } else
07680                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
07681          } else {
07682             ast_log(LOG_WARNING, "Channel %s in prering "
07683                "state, but I have nothing to do. "
07684                "Terminating simple switch, should be "
07685                "restarted by the actual ring.\n", 
07686                chan->name);
07687             ast_hangup(chan);
07688             goto quit;
07689          }
07690       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07691          /* FSK Bell202 callerID */
07692          cs = callerid_new(p->cid_signalling);
07693          if (cs) {
07694 #if 1
07695             bump_gains(p);
07696 #endif            
07697             samples = 0;
07698             len = 0;
07699             distMatches = 0;
07700             /* Clear the current ring data array so we dont have old data in it. */
07701             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07702                curRingData[receivedRingT] = 0;
07703             receivedRingT = 0;
07704             counter = 0;
07705             counter1 = 0;
07706             /* Check to see if context is what it should be, if not set to be. */
07707             if (strcmp(p->context,p->defcontext) != 0) {
07708                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07709                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07710             }
07711 
07712             /* Take out of linear mode for Caller*ID processing */
07713             dahdi_setlinear(p->subs[index].dfd, 0);
07714             for (;;) {  
07715                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07716                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07717                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07718                   callerid_free(cs);
07719                   ast_hangup(chan);
07720                   goto quit;
07721                }
07722                if (i & DAHDI_IOMUX_SIGEVENT) {
07723                   res = dahdi_get_event(p->subs[index].dfd);
07724                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07725                   /* If we get a PR event, they hung up while processing calerid */
07726                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07727                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07728                      p->polarity = POLARITY_IDLE;
07729                      callerid_free(cs);
07730                      ast_hangup(chan);
07731                      goto quit;
07732                   }
07733                   res = 0;
07734                   /* Let us detect callerid when the telco uses distinctive ring */
07735 
07736                   curRingData[receivedRingT] = p->ringt;
07737 
07738                   if (p->ringt < p->ringt_base/2)
07739                      break;
07740                   /* Increment the ringT counter so we can match it against
07741                      values in chan_dahdi.conf for distinctive ring */
07742                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07743                      break;
07744                } else if (i & DAHDI_IOMUX_READ) {
07745                   res = read(p->subs[index].dfd, buf, sizeof(buf));
07746                   if (res < 0) {
07747                      if (errno != ELAST) {
07748                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07749                         callerid_free(cs);
07750                         ast_hangup(chan);
07751                         goto quit;
07752                      }
07753                      break;
07754                   }
07755                   if (p->ringt) 
07756                      p->ringt--;
07757                   if (p->ringt == 1) {
07758                      res = -1;
07759                      break;
07760                   }
07761                   samples += res;
07762                   res = callerid_feed(cs, buf, res, AST_LAW(p));
07763                   if (res < 0) {
07764                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07765                      break;
07766                   } else if (res)
07767                      break;
07768                   else if (samples > (8000 * 10))
07769                      break;
07770                }
07771             }
07772             if (res == 1) {
07773                callerid_get(cs, &name, &number, &flags);
07774                if (option_debug)
07775                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07776             }
07777             if (distinctiveringaftercid == 1) {
07778                /* Clear the current ring data array so we dont have old data in it. */
07779                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07780                   curRingData[receivedRingT] = 0;
07781                }
07782                receivedRingT = 0;
07783                if (option_verbose > 2)
07784                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
07785                for (;;) {
07786                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07787                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
07788                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07789                      callerid_free(cs);
07790                      ast_hangup(chan);
07791                      goto quit;
07792                   }
07793                   if (i & DAHDI_IOMUX_SIGEVENT) {
07794                      res = dahdi_get_event(p->subs[index].dfd);
07795                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07796                      res = 0;
07797                      /* Let us detect callerid when the telco uses distinctive ring */
07798 
07799                      curRingData[receivedRingT] = p->ringt;
07800 
07801                      if (p->ringt < p->ringt_base/2)
07802                         break;
07803                      /* Increment the ringT counter so we can match it against
07804                         values in chan_dahdi.conf for distinctive ring */
07805                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07806                         break;
07807                   } else if (i & DAHDI_IOMUX_READ) {
07808                      res = read(p->subs[index].dfd, buf, sizeof(buf));
07809                      if (res < 0) {
07810                         if (errno != ELAST) {
07811                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07812                            callerid_free(cs);
07813                            ast_hangup(chan);
07814                            goto quit;
07815                         }
07816                         break;
07817                      }
07818                   if (p->ringt)
07819                      p->ringt--;
07820                      if (p->ringt == 1) {
07821                         res = -1;
07822                         break;
07823                      }
07824                   }
07825                }
07826             }
07827             if (p->usedistinctiveringdetection) {
07828                if (option_verbose > 2)
07829                   /* this only shows up if you have n of the dring patterns filled in */
07830                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07831 
07832                for (counter = 0; counter < 3; counter++) {
07833                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07834                   channel */
07835                   if (option_verbose > 2)
07836                      /* this only shows up if you have n of the dring patterns filled in */
07837                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
07838                         p->drings.ringnum[counter].ring[0],
07839                         p->drings.ringnum[counter].ring[1],
07840                         p->drings.ringnum[counter].ring[2]);
07841                   distMatches = 0;
07842                   for (counter1 = 0; counter1 < 3; counter1++) {
07843                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07844                      (p->drings.ringnum[counter].ring[counter1]-10)) {
07845                         distMatches++;
07846                      }
07847                   }
07848                   if (distMatches == 3) {
07849                      /* The ring matches, set the context to whatever is for distinctive ring.. */
07850                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07851                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07852                      if (option_verbose > 2)
07853                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07854                      break;
07855                   }
07856                }
07857             }
07858             /* Restore linear mode (if appropriate) for Caller*ID processing */
07859             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07860 #if 1
07861             restore_gains(p);
07862 #endif            
07863             if (res < 0) {
07864                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07865             }
07866          } else
07867             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07868       }
07869       else
07870          cs = NULL;
07871 
07872       if (number)
07873          ast_shrink_phone_number(number);
07874       ast_set_callerid(chan, number, name, number);
07875 
07876       if (smdi_msg)
07877          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07878 
07879       if (cs)
07880          callerid_free(cs);
07881 
07882       ast_setstate(chan, AST_STATE_RING);
07883       chan->rings = 1;
07884       p->ringt = p->ringt_base;
07885       res = ast_pbx_run(chan);
07886       if (res) {
07887          ast_hangup(chan);
07888          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07889       }
07890       goto quit;
07891    default:
07892       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07893       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07894       if (res < 0)
07895             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07896    }
07897    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07898    if (res < 0)
07899          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07900    ast_hangup(chan);
07901 quit:
07902    ast_mutex_lock(&ss_thread_lock);
07903    ss_thread_count--;
07904    ast_cond_signal(&ss_thread_complete);
07905    ast_mutex_unlock(&ss_thread_lock);
07906    return NULL;
07907 }
07908 
07909 /* destroy a DAHDI channel, identified by its number */
07910 static int dahdi_destroy_channel_bynum(int channel)
07911 {
07912    struct dahdi_pvt *tmp = NULL;
07913    struct dahdi_pvt *prev = NULL;
07914 
07915    ast_mutex_lock(&iflock);
07916    tmp = iflist;
07917    while (tmp) {
07918       if (tmp->channel == channel) {
07919          int x = DAHDI_FLASH;
07920          ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
07921          destroy_channel(prev, tmp, 1);
07922          ast_mutex_unlock(&iflock);
07923          ast_module_unref(ast_module_info->self);
07924          return RESULT_SUCCESS;
07925       }
07926       prev = tmp;
07927       tmp = tmp->next;
07928    }
07929    ast_mutex_unlock(&iflock);
07930    return RESULT_FAILURE;
07931 }
07932 
07933 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
07934 {
07935    int res;
07936    pthread_t threadid;
07937    pthread_attr_t attr;
07938    struct ast_channel *chan;
07939    pthread_attr_init(&attr);
07940    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07941    /* Handle an event on a given channel for the monitor thread. */
07942    switch (event) {
07943    case DAHDI_EVENT_NONE:
07944    case DAHDI_EVENT_BITSCHANGED:
07945       break;
07946    case DAHDI_EVENT_WINKFLASH:
07947    case DAHDI_EVENT_RINGOFFHOOK:
07948       if (i->inalarm) break;
07949       if (i->radio) break;
07950       /* Got a ring/answer.  What kind of channel are we? */
07951       switch (i->sig) {
07952       case SIG_FXOLS:
07953       case SIG_FXOGS:
07954       case SIG_FXOKS:
07955          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07956          if (res && (errno == EBUSY))
07957             break;
07958          if (i->cidspill) {
07959             /* Cancel VMWI spill */
07960             free(i->cidspill);
07961             i->cidspill = NULL;
07962          }
07963          if (i->immediate) {
07964             dahdi_enable_ec(i);
07965             /* The channel is immediately up.  Start right away */
07966             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07967             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07968             if (!chan) {
07969                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07970                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07971                if (res < 0)
07972                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07973             }
07974          } else {
07975             /* Check for callerid, digits, etc */
07976             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07977             if (chan) {
07978                if (has_voicemail(i))
07979                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07980                else
07981                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07982                if (res < 0) 
07983                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07984                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07985                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07986                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07987                   if (res < 0)
07988                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07989                   ast_hangup(chan);
07990                }
07991             } else
07992                ast_log(LOG_WARNING, "Unable to create channel\n");
07993          }
07994          break;
07995       case SIG_FXSLS:
07996       case SIG_FXSGS:
07997       case SIG_FXSKS:
07998             i->ringt = i->ringt_base;
07999             /* Fall through */
08000       case SIG_EMWINK:
08001       case SIG_FEATD:
08002       case SIG_FEATDMF:
08003       case SIG_FEATDMF_TA:
08004       case SIG_E911:
08005       case SIG_FGC_CAMA:
08006       case SIG_FGC_CAMAMF:
08007       case SIG_FEATB:
08008       case SIG_EM:
08009       case SIG_EM_E1:
08010       case SIG_SFWINK:
08011       case SIG_SF_FEATD:
08012       case SIG_SF_FEATDMF:
08013       case SIG_SF_FEATB:
08014       case SIG_SF:
08015             /* Check for callerid, digits, etc */
08016             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08017             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08018                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08019                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08020                if (res < 0)
08021                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08022                ast_hangup(chan);
08023             } else if (!chan) {
08024                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08025             }
08026             break;
08027       default:
08028          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08029          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08030          if (res < 0)
08031                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08032          pthread_attr_destroy(&attr);
08033          return NULL;
08034       }
08035       break;
08036    case DAHDI_EVENT_NOALARM:
08037       i->inalarm = 0;
08038       if (!i->unknown_alarm) {
08039          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08040          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08041                   "Channel: %d\r\n", i->channel);
08042       } else {
08043          i->unknown_alarm = 0;
08044       }
08045       break;
08046    case DAHDI_EVENT_ALARM:
08047       i->inalarm = 1;
08048       res = get_alarms(i);
08049       handle_alarms(i, res);
08050       /* fall thru intentionally */
08051    case DAHDI_EVENT_ONHOOK:
08052       if (i->radio)
08053          break;
08054       /* Back on hook.  Hang up. */
08055       switch (i->sig) {
08056       case SIG_FXOLS:
08057       case SIG_FXOGS:
08058       case SIG_FEATD:
08059       case SIG_FEATDMF:
08060       case SIG_FEATDMF_TA:
08061       case SIG_E911:
08062       case SIG_FGC_CAMA:
08063       case SIG_FGC_CAMAMF:
08064       case SIG_FEATB:
08065       case SIG_EM:
08066       case SIG_EM_E1:
08067       case SIG_EMWINK:
08068       case SIG_SF_FEATD:
08069       case SIG_SF_FEATDMF:
08070       case SIG_SF_FEATB:
08071       case SIG_SF:
08072       case SIG_SFWINK:
08073       case SIG_FXSLS:
08074       case SIG_FXSGS:
08075       case SIG_FXSKS:
08076       case SIG_GR303FXSKS:
08077          dahdi_disable_ec(i);
08078          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08079          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08080          break;
08081       case SIG_GR303FXOKS:
08082       case SIG_FXOKS:
08083          dahdi_disable_ec(i);
08084          /* Diddle the battery for the zhone */
08085 #ifdef ZHONE_HACK
08086          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08087          usleep(1);
08088 #endif         
08089          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08090          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08091          break;
08092       case SIG_PRI:
08093          dahdi_disable_ec(i);
08094          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08095          break;
08096       default:
08097          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08098          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08099          pthread_attr_destroy(&attr);
08100          return NULL;
08101       }
08102       break;
08103    case DAHDI_EVENT_POLARITY:
08104       switch (i->sig) {
08105       case SIG_FXSLS:
08106       case SIG_FXSKS:
08107       case SIG_FXSGS:
08108          /* We have already got a PR before the channel was 
08109             created, but it wasn't handled. We need polarity 
08110             to be REV for remote hangup detection to work. 
08111             At least in Spain */
08112          if (i->hanguponpolarityswitch)
08113             i->polarity = POLARITY_REV;
08114 
08115          if (i->cid_start == CID_START_POLARITY) {
08116             i->polarity = POLARITY_REV;
08117             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08118                    "CID detection on channel %d\n",
08119                    i->channel);
08120             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08121             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08122                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08123             }
08124          }
08125          break;
08126       default:
08127          ast_log(LOG_WARNING, "handle_init_event detected "
08128             "polarity reversal on non-FXO (SIG_FXS) "
08129             "interface %d\n", i->channel);
08130       }
08131       break;
08132    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
08133       ast_log(LOG_NOTICE, 
08134             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08135             i->channel);
08136       pthread_attr_destroy(&attr);
08137       return i;
08138    }
08139    pthread_attr_destroy(&attr);
08140    return NULL;
08141 }
08142 
08143 static void *do_monitor(void *data)
08144 {
08145    int count, res, res2, spoint, pollres=0;
08146    struct dahdi_pvt *i;
08147    struct dahdi_pvt *last = NULL;
08148    struct dahdi_pvt *doomed;
08149    time_t thispass = 0, lastpass = 0;
08150    int found;
08151    char buf[1024];
08152    struct pollfd *pfds=NULL;
08153    int lastalloc = -1;
08154    /* This thread monitors all the frame relay interfaces which are not yet in use
08155       (and thus do not have a separate thread) indefinitely */
08156    /* From here on out, we die whenever asked */
08157 #if 0
08158    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08159       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08160       return NULL;
08161    }
08162    ast_log(LOG_DEBUG, "Monitor starting...\n");
08163 #endif
08164    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08165 
08166    for (;;) {
08167       /* Lock the interface list */
08168       ast_mutex_lock(&iflock);
08169       if (!pfds || (lastalloc != ifcount)) {
08170          if (pfds) {
08171             free(pfds);
08172             pfds = NULL;
08173          }
08174          if (ifcount) {
08175             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08176                ast_mutex_unlock(&iflock);
08177                return NULL;
08178             }
08179          }
08180          lastalloc = ifcount;
08181       }
08182       /* Build the stuff we're going to poll on, that is the socket of every
08183          dahdi_pvt that does not have an associated owner channel */
08184       count = 0;
08185       i = iflist;
08186       while (i) {
08187          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08188             if (!i->owner && !i->subs[SUB_REAL].owner) {
08189                /* This needs to be watched, as it lacks an owner */
08190                pfds[count].fd = i->subs[SUB_REAL].dfd;
08191                pfds[count].events = POLLPRI;
08192                pfds[count].revents = 0;
08193                /* Message waiting or r2 channels also get watched for reading */
08194                if (i->cidspill)
08195                   pfds[count].events |= POLLIN;
08196                count++;
08197             }
08198          }
08199          i = i->next;
08200       }
08201       /* Okay, now that we know what to do, release the interface lock */
08202       ast_mutex_unlock(&iflock);
08203       
08204       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08205       pthread_testcancel();
08206       /* Wait at least a second for something to happen */
08207       res = poll(pfds, count, 1000);
08208       pthread_testcancel();
08209       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08210 
08211       /* Okay, poll has finished.  Let's see what happened.  */
08212       if (res < 0) {
08213          if ((errno != EAGAIN) && (errno != EINTR))
08214             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08215          continue;
08216       }
08217       /* Alright, lock the interface list again, and let's look and see what has
08218          happened */
08219       ast_mutex_lock(&iflock);
08220       found = 0;
08221       spoint = 0;
08222       lastpass = thispass;
08223       thispass = time(NULL);
08224       doomed = NULL;
08225       for (i = iflist;; i = i->next) {
08226          if (doomed) {
08227             int res;
08228             res = dahdi_destroy_channel_bynum(doomed->channel);
08229             if (!res) {
08230                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08231             }
08232             doomed = NULL;
08233          }
08234          if (!i) {
08235             break;
08236          }
08237          if (thispass != lastpass) {
08238             if (!found && ((i == last) || ((i == iflist) && !last))) {
08239                last = i;
08240                if (last) {
08241                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08242                      (last->sig & __DAHDI_SIG_FXO)) {
08243                      res = ast_app_has_voicemail(last->mailbox, NULL);
08244                      if (last->msgstate != res) {
08245                         int x;
08246                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08247                         x = DAHDI_FLUSH_BOTH;
08248                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08249                         if (res2)
08250                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08251                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08252                            /* Turn on on hook transfer for 4 seconds */
08253                            x = 4000;
08254                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08255                            last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08256                            last->cidpos = 0;
08257                            last->msgstate = res;
08258                            last->onhooktime = thispass;
08259                         }
08260                         found ++;
08261                      }
08262                   }
08263                   last = last->next;
08264                }
08265             }
08266          }
08267          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08268             if (i->radio && !i->owner)
08269             {
08270                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08271                if (res)
08272                {
08273                   if (option_debug)
08274                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08275                   /* Don't hold iflock while handling init events */
08276                   ast_mutex_unlock(&iflock);
08277                   doomed = handle_init_event(i, res);
08278                   ast_mutex_lock(&iflock);   
08279                }
08280                continue;
08281             }              
08282             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08283             if (pollres & POLLIN) {
08284                if (i->owner || i->subs[SUB_REAL].owner) {
08285 #ifdef HAVE_PRI
08286                   if (!i->pri)
08287 #endif                  
08288                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08289                   continue;
08290                }
08291                if (!i->cidspill) {
08292                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08293                   continue;
08294                }
08295                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08296                if (res > 0) {
08297                   /* We read some number of bytes.  Write an equal amount of data */
08298                   if (res > i->cidlen - i->cidpos) 
08299                      res = i->cidlen - i->cidpos;
08300                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
08301                   if (res2 > 0) {
08302                      i->cidpos += res2;
08303                      if (i->cidpos >= i->cidlen) {
08304                         free(i->cidspill);
08305                         i->cidspill = 0;
08306                         i->cidpos = 0;
08307                         i->cidlen = 0;
08308                      }
08309                   } else {
08310                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
08311                      i->msgstate = -1;
08312                   }
08313                } else {
08314                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08315                }
08316             }
08317             if (pollres & POLLPRI) {
08318                if (i->owner || i->subs[SUB_REAL].owner) {
08319 #ifdef HAVE_PRI
08320                   if (!i->pri)
08321 #endif                  
08322                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08323                   continue;
08324                }
08325                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08326                if (option_debug)
08327                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08328                /* Don't hold iflock while handling init events */
08329                ast_mutex_unlock(&iflock);
08330                doomed = handle_init_event(i, res);
08331                ast_mutex_lock(&iflock);   
08332             }
08333          }
08334       }
08335       ast_mutex_unlock(&iflock);
08336    }
08337    /* Never reached */
08338    return NULL;
08339    
08340 }
08341 
08342 static int restart_monitor(void)
08343 {
08344    pthread_attr_t attr;
08345    pthread_attr_init(&attr);
08346    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08347    /* If we're supposed to be stopped -- stay stopped */
08348    if (monitor_thread == AST_PTHREADT_STOP)
08349       return 0;
08350    ast_mutex_lock(&monlock);
08351    if (monitor_thread == pthread_self()) {
08352       ast_mutex_unlock(&monlock);
08353       ast_log(LOG_WARNING, "Cannot kill myself\n");
08354       return -1;
08355    }
08356    if (monitor_thread != AST_PTHREADT_NULL) {
08357       /* Wake up the thread */
08358       pthread_kill(monitor_thread, SIGURG);
08359    } else {
08360       /* Start a new monitor */
08361       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08362          ast_mutex_unlock(&monlock);
08363          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08364          pthread_attr_destroy(&attr);
08365          return -1;
08366       }
08367    }
08368    ast_mutex_unlock(&monlock);
08369    pthread_attr_destroy(&attr);
08370    return 0;
08371 }
08372 
08373 #ifdef HAVE_OPENR2
08374 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08375 {
08376    if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08377       ast_log(LOG_ERROR, "No more R2 links available!.\n");
08378       return NULL;
08379    }
08380    return &r2links[id];
08381 }
08382 #endif
08383 
08384 #ifdef HAVE_PRI
08385 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08386 {
08387    int x;
08388    int trunkgroup;
08389    /* Get appropriate trunk group if there is one */
08390    trunkgroup = pris[*span].mastertrunkgroup;
08391    if (trunkgroup) {
08392       /* Select a specific trunk group */
08393       for (x = 0; x < NUM_SPANS; x++) {
08394          if (pris[x].trunkgroup == trunkgroup) {
08395             *span = x;
08396             return 0;
08397          }
08398       }
08399       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08400       *span = -1;
08401    } else {
08402       if (pris[*span].trunkgroup) {
08403          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08404          *span = -1;
08405       } else if (pris[*span].mastertrunkgroup) {
08406          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08407          *span = -1;
08408       } else {
08409          if (si->totalchans == 31) {
08410             /* E1 */
08411             pris[*span].dchannels[0] = 16 + offset;
08412          } else if (si->totalchans == 24) {
08413             /* T1 or J1 */
08414             pris[*span].dchannels[0] = 24 + offset;
08415          } else if (si->totalchans == 3) {
08416             /* BRI */
08417             pris[*span].dchannels[0] = 3 + offset;
08418          } else {
08419             ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
08420             *span = -1;
08421             return 0;
08422          }
08423          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08424          pris[*span].offset = offset;
08425          pris[*span].span = *span + 1;
08426       }
08427    }
08428    return 0;
08429 }
08430 
08431 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08432 {
08433    struct dahdi_spaninfo si;
08434    struct dahdi_params p;
08435    int fd;
08436    int span;
08437    int ospan=0;
08438    int x,y;
08439    for (x = 0; x < NUM_SPANS; x++) {
08440       if (pris[x].trunkgroup == trunkgroup) {
08441          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08442          return -1;
08443       }
08444    }
08445    for (y = 0; y < NUM_DCHANS; y++) {
08446       if (!channels[y]) 
08447          break;
08448       memset(&si, 0, sizeof(si));
08449       memset(&p, 0, sizeof(p));
08450       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08451       if (fd < 0) {
08452          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08453          return -1;
08454       }
08455       x = channels[y];
08456       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08457          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08458          close(fd);
08459          return -1;
08460       }
08461       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08462          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08463          return -1;
08464       }
08465       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08466          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08467          close(fd);
08468          return -1;
08469       }
08470       span = p.spanno - 1;
08471       if (pris[span].trunkgroup) {
08472          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08473          close(fd);
08474          return -1;
08475       }
08476       if (pris[span].pvts[0]) {
08477          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08478          close(fd);
08479          return -1;
08480       }
08481       if (!y) {
08482          pris[span].trunkgroup = trunkgroup;
08483          pris[span].offset = channels[y] - p.chanpos;
08484          ospan = span;
08485       }
08486       pris[ospan].dchannels[y] = channels[y];
08487       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08488       pris[span].span = span + 1;
08489       close(fd);
08490    }
08491    return 0;   
08492 }
08493 
08494 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08495 {
08496    if (pris[span].mastertrunkgroup) {
08497       ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
08498       return -1;
08499    }
08500    pris[span].mastertrunkgroup = trunkgroup;
08501    pris[span].prilogicalspan = logicalspan;
08502    return 0;
08503 }
08504 
08505 #endif
08506 
08507 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08508 {
08509    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
08510    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
08511    char fn[80];
08512 #if 1
08513    struct dahdi_bufferinfo bi;
08514 #endif
08515    int res;
08516    int span=0;
08517    int here = 0;
08518    int x;
08519    struct dahdi_pvt **wlist;
08520    struct dahdi_pvt **wend;
08521    struct dahdi_params p;
08522 
08523    wlist = &iflist;
08524    wend = &ifend;
08525 
08526 #ifdef HAVE_PRI
08527    if (pri) {
08528       wlist = &pri->crvs;
08529       wend = &pri->crvend;
08530    }
08531 #endif
08532 
08533    tmp2 = *wlist;
08534    prev = NULL;
08535 
08536    while (tmp2) {
08537       if (!tmp2->destroy) {
08538          if (tmp2->channel == channel) {
08539             tmp = tmp2;
08540             here = 1;
08541             break;
08542          }
08543          if (tmp2->channel > channel) {
08544             break;
08545          }
08546       }
08547       prev = tmp2;
08548       tmp2 = tmp2->next;
08549    }
08550 
08551    if (!here && reloading != 1) {
08552       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08553          if (tmp)
08554             free(tmp);
08555          return NULL;
08556       }
08557       ast_mutex_init(&tmp->lock);
08558       ifcount++;
08559       for (x = 0; x < 3; x++)
08560          tmp->subs[x].dfd = -1;
08561       tmp->channel = channel;
08562       tmp->priindication_oob = conf->chan.priindication_oob;
08563    }
08564 
08565    if (tmp) {
08566       int chan_sig = conf->chan.sig;
08567       if (!here) {
08568          if ((channel != CHAN_PSEUDO) && !pri) {
08569             int count = 0;
08570             snprintf(fn, sizeof(fn), "%d", channel);
08571             /* Open non-blocking */
08572             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08573             while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
08574                usleep(1);
08575                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08576                count++;
08577             }
08578             /* Allocate a DAHDI structure */
08579             if (tmp->subs[SUB_REAL].dfd < 0) {
08580                ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
08581                destroy_dahdi_pvt(&tmp);
08582                return NULL;
08583             }
08584             memset(&p, 0, sizeof(p));
08585             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08586             if (res < 0) {
08587                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08588                destroy_dahdi_pvt(&tmp);
08589                return NULL;
08590             }
08591             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
08592                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
08593                destroy_dahdi_pvt(&tmp);
08594                return NULL;
08595             }
08596             tmp->law = p.curlaw;
08597             tmp->span = p.spanno;
08598             span = p.spanno - 1;
08599          } else {
08600             if (channel == CHAN_PSEUDO)
08601                chan_sig = 0;
08602             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08603                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08604                return NULL;
08605             }
08606          }
08607 #ifdef HAVE_PRI
08608          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08609             int offset;
08610             int myswitchtype;
08611             int matchesdchan;
08612             int x,y;
08613             offset = 0;
08614             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08615                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08616                destroy_dahdi_pvt(&tmp);
08617                return NULL;
08618             }
08619             if (span >= NUM_SPANS) {
08620                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08621                destroy_dahdi_pvt(&tmp);
08622                return NULL;
08623             } else {
08624                struct dahdi_spaninfo si;
08625                si.spanno = 0;
08626                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08627                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08628                   destroy_dahdi_pvt(&tmp);
08629                   return NULL;
08630                }
08631                /* Store the logical span first based upon the real span */
08632                tmp->logicalspan = pris[span].prilogicalspan;
08633                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08634                if (span < 0) {
08635                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08636                   destroy_dahdi_pvt(&tmp);
08637                   return NULL;
08638                }
08639                if (chan_sig == SIG_PRI)
08640                   myswitchtype = conf->pri.switchtype;
08641                else
08642                   myswitchtype = PRI_SWITCH_GR303_TMC;
08643                /* Make sure this isn't a d-channel */
08644                matchesdchan=0;
08645                for (x = 0; x < NUM_SPANS; x++) {
08646                   for (y = 0; y < NUM_DCHANS; y++) {
08647                      if (pris[x].dchannels[y] == tmp->channel) {
08648                         matchesdchan = 1;
08649                         break;
08650                      }
08651                   }
08652                }
08653                offset = p.chanpos;
08654                if (!matchesdchan) {
08655                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08656                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08657                      destroy_dahdi_pvt(&tmp);
08658                      return NULL;
08659                   }
08660                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08661                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08662                      destroy_dahdi_pvt(&tmp);
08663                      return NULL;
08664                   }
08665                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08666                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08667                      destroy_dahdi_pvt(&tmp);
08668                      return NULL;
08669                   }
08670                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08671                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08672                      destroy_dahdi_pvt(&tmp);
08673                      return NULL;
08674                   }
08675                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08676                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08677                      destroy_dahdi_pvt(&tmp);
08678                      return NULL;
08679                   }
08680                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08681                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08682                      destroy_dahdi_pvt(&tmp);
08683                      return NULL;
08684                   }
08685                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08686                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08687                      destroy_dahdi_pvt(&tmp);
08688                      return NULL;
08689                   }
08690                   if (pris[span].numchans >= MAX_CHANNELS) {
08691                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08692                         pris[span].trunkgroup);
08693                      destroy_dahdi_pvt(&tmp);
08694                      return NULL;
08695                   }
08696                   pris[span].nodetype = conf->pri.nodetype;
08697                   pris[span].switchtype = myswitchtype;
08698                   pris[span].nsf = conf->pri.nsf;
08699                   pris[span].dialplan = conf->pri.dialplan;
08700                   pris[span].localdialplan = conf->pri.localdialplan;
08701                   pris[span].pvts[pris[span].numchans++] = tmp;
08702                   pris[span].minunused = conf->pri.minunused;
08703                   pris[span].minidle = conf->pri.minidle;
08704                   pris[span].overlapdial = conf->pri.overlapdial;
08705 #ifdef HAVE_PRI_INBANDDISCONNECT
08706                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08707 #endif
08708                   pris[span].facilityenable = conf->pri.facilityenable;
08709                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08710                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08711                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08712                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08713                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08714                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08715                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08716                   pris[span].resetinterval = conf->pri.resetinterval;
08717                   
08718                   tmp->pri = &pris[span];
08719                   tmp->prioffset = offset;
08720                   tmp->call = NULL;
08721                } else {
08722                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08723                   destroy_dahdi_pvt(&tmp);
08724                   return NULL;
08725                }
08726             }
08727          } else {
08728             tmp->prioffset = 0;
08729          }
08730 #endif
08731 #ifdef HAVE_OPENR2
08732          if (chan_sig == SIG_MFCR2 && reloading != 1) {
08733             char logdir[OR2_MAX_PATH];
08734             struct dahdi_mfcr2 *dahdi_r2;
08735             int threshold = 0;
08736             int snres = 0;
08737             dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
08738             if (!dahdi_r2) {
08739                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
08740             } else if (!dahdi_r2->protocol_context){
08741                char tmplogdir[] = "/tmp";
08742                dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 
08743                      &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
08744                if (!dahdi_r2->protocol_context) {
08745                   ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
08746                   destroy_dahdi_pvt(&tmp);
08747                   return NULL;
08748                } 
08749                openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
08750                openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
08751                openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
08752                openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
08753                openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
08754                openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
08755                openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
08756                openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
08757 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
08758                openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
08759                openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
08760 #endif
08761                if (ast_strlen_zero(mfcr2_cur_logdir)) {
08762                   if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
08763                      ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08764                   }
08765                } else {
08766                   snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
08767                   if (snres >= sizeof(logdir)) {
08768                      ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
08769                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08770                         ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08771                      }
08772                   } else {
08773                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08774                         ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
08775                      }
08776                   }  
08777                }
08778                if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
08779                   if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
08780                      ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
08781                   }
08782                }
08783             } 
08784             if (dahdi_r2) {
08785                /* TODO: should we check numchans overflow, or is it already done by DAHDI? */
08786                dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
08787                tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
08788                      tmp->subs[SUB_REAL].dfd, NULL, NULL);
08789                if (!tmp->r2chan) {
08790                   openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
08791                   ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
08792                   destroy_dahdi_pvt(&tmp);
08793                   return NULL;
08794                }
08795                openr2_chan_set_client_data(tmp->r2chan, tmp);
08796                /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
08797                openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
08798                openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
08799                if (mfcr2_cur_call_files) {
08800                   openr2_chan_enable_call_files(tmp->r2chan);
08801                }
08802                tmp->mfcr2_category = mfcr2_cur_category;
08803                tmp->mfcr2 = dahdi_r2;
08804                tmp->mfcr2call = 0;
08805                tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
08806                tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
08807                tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
08808                tmp->mfcr2_ani_index = 0;
08809                tmp->mfcr2_dnis_index = 0;
08810                tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
08811                tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
08812             }
08813          }
08814 #endif
08815       } else {
08816          chan_sig = tmp->sig;
08817          if (tmp->subs[SUB_REAL].dfd > -1) {
08818             memset(&p, 0, sizeof(p));
08819             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08820          }
08821       }
08822       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
08823       switch (chan_sig) {
08824       case SIG_FXSKS:
08825       case SIG_FXSLS:
08826       case SIG_EM:
08827       case SIG_EM_E1:
08828       case SIG_EMWINK:
08829       case SIG_FEATD:
08830       case SIG_FEATDMF:
08831       case SIG_FEATDMF_TA:
08832       case SIG_FEATB:
08833       case SIG_E911:
08834       case SIG_SF:
08835       case SIG_SFWINK:
08836       case SIG_FGC_CAMA:
08837       case SIG_FGC_CAMAMF:
08838       case SIG_SF_FEATD:
08839       case SIG_SF_FEATDMF:
08840       case SIG_SF_FEATB:
08841          p.starttime = 250;
08842          break;
08843       }
08844 
08845       if (tmp->radio) {
08846          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
08847          p.channo = channel;
08848          p.rxwinktime = 1;
08849          p.rxflashtime = 1;
08850          p.starttime = 1;
08851          p.debouncetime = 5;
08852       }
08853       if (!tmp->radio) {
08854          p.channo = channel;
08855          /* Override timing settings based on config file */
08856          if (conf->timing.prewinktime >= 0)
08857             p.prewinktime = conf->timing.prewinktime;
08858          if (conf->timing.preflashtime >= 0)
08859             p.preflashtime = conf->timing.preflashtime;
08860          if (conf->timing.winktime >= 0)
08861             p.winktime = conf->timing.winktime;
08862          if (conf->timing.flashtime >= 0)
08863             p.flashtime = conf->timing.flashtime;
08864          if (conf->timing.starttime >= 0)
08865             p.starttime = conf->timing.starttime;
08866          if (conf->timing.rxwinktime >= 0)
08867             p.rxwinktime = conf->timing.rxwinktime;
08868          if (conf->timing.rxflashtime >= 0)
08869             p.rxflashtime = conf->timing.rxflashtime;
08870          if (conf->timing.debouncetime >= 0)
08871             p.debouncetime = conf->timing.debouncetime;
08872       }
08873       
08874       /* dont set parms on a pseudo-channel (or CRV) */
08875       if (tmp->subs[SUB_REAL].dfd >= 0)
08876       {
08877          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08878          if (res < 0) {
08879             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08880             destroy_dahdi_pvt(&tmp);
08881             return NULL;
08882          }
08883       }
08884 #if 1
08885       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08886          memset(&bi, 0, sizeof(bi));
08887          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08888          if (!res) {
08889             bi.txbufpolicy = conf->chan.buf_policy;
08890             bi.rxbufpolicy = conf->chan.buf_policy;
08891             bi.numbufs = conf->chan.buf_no;
08892             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08893             if (res < 0) {
08894                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08895             }
08896          } else
08897             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08898       }
08899 #endif
08900       tmp->immediate = conf->chan.immediate;
08901       tmp->transfertobusy = conf->chan.transfertobusy;
08902       tmp->sig = chan_sig;
08903       tmp->outsigmod = conf->chan.outsigmod;
08904       tmp->ringt_base = ringt_base;
08905       tmp->firstradio = 0;
08906       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08907          tmp->permcallwaiting = conf->chan.callwaiting;
08908       else
08909          tmp->permcallwaiting = 0;
08910       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
08911       tmp->destroy = 0;
08912       tmp->drings = drings;
08913       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
08914       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08915       tmp->threewaycalling = conf->chan.threewaycalling;
08916       tmp->adsi = conf->chan.adsi;
08917       tmp->use_smdi = conf->chan.use_smdi;
08918       tmp->permhidecallerid = conf->chan.hidecallerid;
08919       tmp->callreturn = conf->chan.callreturn;
08920       tmp->echocancel = conf->chan.echocancel;
08921       tmp->echotraining = conf->chan.echotraining;
08922       tmp->pulse = conf->chan.pulse;
08923       if (tmp->echocancel)
08924          tmp->echocanbridged = conf->chan.echocanbridged;
08925       else {
08926          if (conf->chan.echocanbridged)
08927             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08928          tmp->echocanbridged = 0;
08929       }
08930       tmp->busydetect = conf->chan.busydetect;
08931       tmp->busycount = conf->chan.busycount;
08932       tmp->busycompare = conf->chan.busycompare;
08933       tmp->busytonelength = conf->chan.busytonelength;
08934       tmp->busyquietlength = conf->chan.busyquietlength;
08935       tmp->busyfuzziness = conf->chan.busyfuzziness;
08936       tmp->silencethreshold = conf->chan.silencethreshold;
08937       tmp->callprogress = conf->chan.callprogress;
08938       tmp->cancallforward = conf->chan.cancallforward;
08939       tmp->dtmfrelax = conf->chan.dtmfrelax;
08940       tmp->callwaiting = tmp->permcallwaiting;
08941       tmp->hidecallerid = tmp->permhidecallerid;
08942       tmp->channel = channel;
08943       tmp->stripmsd = conf->chan.stripmsd;
08944       tmp->use_callerid = conf->chan.use_callerid;
08945       tmp->cid_signalling = conf->chan.cid_signalling;
08946       tmp->cid_start = conf->chan.cid_start;
08947       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
08948       tmp->restrictcid = conf->chan.restrictcid;
08949       tmp->use_callingpres = conf->chan.use_callingpres;
08950       tmp->priexclusive = conf->chan.priexclusive;
08951       if (tmp->usedistinctiveringdetection) {
08952          if (!tmp->use_callerid) {
08953             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
08954             tmp->use_callerid = 1;
08955          }
08956       }
08957 
08958       if (tmp->cid_signalling == CID_SIG_SMDI) {
08959          if (!tmp->use_smdi) {
08960             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
08961             tmp->use_smdi = 1;
08962          }
08963       }
08964       if (tmp->use_smdi) {
08965          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
08966          if (!(tmp->smdi_iface)) {
08967             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
08968             tmp->use_smdi = 0;
08969          }
08970       }
08971 
08972       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
08973       tmp->amaflags = conf->chan.amaflags;
08974       if (!here) {
08975          tmp->confno = -1;
08976          tmp->propconfno = -1;
08977       }
08978       tmp->canpark = conf->chan.canpark;
08979       tmp->transfer = conf->chan.transfer;
08980       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08981       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08982       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08983       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08984       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08985       tmp->cid_ton = 0;
08986       if (chan_sig != SIG_PRI) {
08987          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08988          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08989       } else {
08990          tmp->cid_num[0] = '\0';
08991          tmp->cid_name[0] = '\0';
08992       }
08993       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08994       tmp->msgstate = -1;
08995       tmp->group = conf->chan.group;
08996       tmp->callgroup = conf->chan.callgroup;
08997       tmp->pickupgroup= conf->chan.pickupgroup;
08998       tmp->rxgain = conf->chan.rxgain;
08999       tmp->txgain = conf->chan.txgain;
09000       tmp->tonezone = conf->chan.tonezone;
09001       tmp->onhooktime = time(NULL);
09002       if (tmp->subs[SUB_REAL].dfd > -1) {
09003          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09004          if (tmp->dsp)
09005             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09006          update_conf(tmp);
09007          if (!here) {
09008             if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09009                /* Hang it up to be sure it's good */
09010                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09011          }
09012          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09013 #ifdef HAVE_PRI
09014          /* the dchannel is down so put the channel in alarm */
09015          if (tmp->pri && !pri_is_up(tmp->pri)) {
09016             tmp->inalarm = 1;
09017          }
09018 #endif            
09019          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09020             tmp->inalarm = 1;
09021             handle_alarms(tmp, res);
09022          } else {
09023             /* yes, this looks strange... the unknown_alarm flag is only used to
09024                control whether an 'alarm cleared' message gets generated when we
09025                get an indication that the channel is no longer in alarm status.
09026                however, the channel *could* be in an alarm status that we aren't
09027                aware of (since get_alarms() only reports span alarms, not channel
09028                alarms). setting this flag will cause any potential 'alarm cleared'
09029                message to be suppressed, but if a real alarm occurs before that
09030                happens, this flag will get cleared by it and the situation will
09031                be normal.
09032             */
09033             tmp->unknown_alarm = 1;
09034          }
09035       }
09036 
09037       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09038       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09039       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09040       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09041 
09042    }
09043    if (tmp && !here) {
09044       /* nothing on the iflist */
09045       if (!*wlist) {
09046          *wlist = tmp;
09047          tmp->prev = NULL;
09048          tmp->next = NULL;
09049          *wend = tmp;
09050       } else {
09051          /* at least one member on the iflist */
09052          struct dahdi_pvt *working = *wlist;
09053 
09054          /* check if we maybe have to put it on the begining */
09055          if (working->channel > tmp->channel) {
09056             tmp->next = *wlist;
09057             tmp->prev = NULL;
09058             (*wlist)->prev = tmp;
09059             *wlist = tmp;
09060          } else {
09061          /* go through all the members and put the member in the right place */
09062             while (working) {
09063                /* in the middle */
09064                if (working->next) {
09065                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09066                      tmp->next = working->next;
09067                      tmp->prev = working;
09068                      working->next->prev = tmp;
09069                      working->next = tmp;
09070                      break;
09071                   }
09072                } else {
09073                /* the last */
09074                   if (working->channel < tmp->channel) {
09075                      working->next = tmp;
09076                      tmp->next = NULL;
09077                      tmp->prev = working;
09078                      *wend = tmp;
09079                      break;
09080                   }
09081                }
09082                working = working->next;
09083             }
09084          }
09085       }
09086    }
09087    return tmp;
09088 }
09089 
09090 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09091 {
09092    int res;
09093    struct dahdi_params par;
09094 
09095    /* First, check group matching */
09096    if (groupmatch) {
09097       if ((p->group & groupmatch) != groupmatch)
09098          return 0;
09099       *groupmatched = 1;
09100    }
09101    /* Check to see if we have a channel match */
09102    if (channelmatch != -1) {
09103       if (p->channel != channelmatch)
09104          return 0;
09105       *channelmatched = 1;
09106    }
09107    /* We're at least busy at this point */
09108    if (busy) {
09109       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09110          *busy = 1;
09111    }
09112    /* If do not disturb, definitely not */
09113    if (p->dnd)
09114       return 0;
09115    /* If guard time, definitely not */
09116    if (p->guardtime && (time(NULL) < p->guardtime)) 
09117       return 0;
09118       
09119    /* If no owner definitely available */
09120    if (!p->owner) {
09121 #ifdef HAVE_PRI
09122       /* Trust PRI */
09123       if (p->pri) {
09124          if (p->resetting || p->call)
09125             return 0;
09126          else
09127             return 1;
09128       }
09129 #endif
09130 #ifdef HAVE_OPENR2
09131       /* Trust MFC/R2 */
09132       if (p->mfcr2) {
09133          if (p->mfcr2call || p->mfcr2block)
09134             return 0;
09135          else
09136             return 1;
09137       }
09138 #endif
09139       if (!(p->radio || (p->oprmode < 0)))
09140       {
09141          if (!p->sig || (p->sig == SIG_FXSLS))
09142             return 1;
09143          /* Check hook state */
09144          if (p->subs[SUB_REAL].dfd > -1) {
09145             memset(&par, 0, sizeof(par));
09146             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09147          } else {
09148             /* Assume not off hook on CVRS */
09149             res = 0;
09150             par.rxisoffhook = 0;
09151          }
09152          if (res) {
09153             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09154          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09155             /* When "onhook" that means no battery on the line, and thus
09156               it is out of service..., if it's on a TDM card... If it's a channel
09157               bank, there is no telling... */
09158             if (par.rxbits > -1)
09159                return 1;
09160             if (par.rxisoffhook)
09161                return 1;
09162             else
09163 #ifdef DAHDI_CHECK_HOOKSTATE
09164                return 0;
09165 #else
09166                return 1;
09167 #endif
09168          } else if (par.rxisoffhook) {
09169             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09170             /* Not available when the other end is off hook */
09171             return 0;
09172          }
09173       }
09174       return 1;
09175    }
09176 
09177    /* If it's not an FXO, forget about call wait */
09178    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09179       return 0;
09180 
09181    if (!p->callwaiting) {
09182       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09183       return 0;
09184    }
09185 
09186    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09187       /* If there is already a call waiting call, then we can't take a second one */
09188       return 0;
09189    }
09190    
09191    if ((p->owner->_state != AST_STATE_UP) &&
09192        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09193       /* If the current call is not up, then don't allow the call */
09194       return 0;
09195    }
09196    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09197       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09198       return 0;
09199    }
09200    /* We're cool */
09201    return 1;
09202 }
09203 
09204 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09205 {
09206    struct dahdi_pvt *p;
09207    struct dahdi_bufferinfo bi;
09208    int res;
09209    
09210    if ((p = ast_malloc(sizeof(*p)))) {
09211       memcpy(p, src, sizeof(struct dahdi_pvt));
09212       ast_mutex_init(&p->lock);
09213       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09214       /* Allocate a DAHDI structure */
09215       if (p->subs[SUB_REAL].dfd < 0) {
09216          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09217          destroy_dahdi_pvt(&p);
09218          return NULL;
09219       }
09220       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09221       if (!res) {
09222          bi.txbufpolicy = p->buf_policy;
09223          bi.rxbufpolicy = p->buf_policy;
09224          bi.numbufs = p->buf_no;
09225          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09226          if (res < 0) {
09227             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09228          }
09229       } else
09230          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09231    }
09232    p->destroy = 1;
09233    p->next = iflist;
09234    p->prev = NULL;
09235    iflist = p;
09236    if (iflist->next)
09237       iflist->next->prev = p;
09238    return p;
09239 }
09240    
09241 
09242 #ifdef HAVE_PRI
09243 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09244 {
09245    int x;
09246    if (backwards)
09247       x = pri->numchans;
09248    else
09249       x = 0;
09250    for (;;) {
09251       if (backwards && (x < 0))
09252          break;
09253       if (!backwards && (x >= pri->numchans))
09254          break;
09255       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09256          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
09257             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09258          return x;
09259       }
09260       if (backwards)
09261          x--;
09262       else
09263          x++;
09264    }
09265    return -1;
09266 }
09267 #endif
09268 
09269 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09270 {
09271    ast_group_t groupmatch = 0;
09272    int channelmatch = -1;
09273    int roundrobin = 0;
09274    int callwait = 0;
09275    int busy = 0;
09276    struct dahdi_pvt *p;
09277    struct ast_channel *tmp = NULL;
09278    char *dest=NULL;
09279    int x;
09280    char *s;
09281    char opt=0;
09282    int res=0, y=0;
09283    int backwards = 0;
09284 #ifdef HAVE_PRI
09285    int crv;
09286    int bearer = -1;
09287    int trunkgroup;
09288    struct dahdi_pri *pri=NULL;
09289 #endif   
09290    struct dahdi_pvt *exit, *start, *end;
09291    ast_mutex_t *lock;
09292    int channelmatched = 0;
09293    int groupmatched = 0;
09294    
09295    /*
09296     * data is ---v
09297     * Dial(DAHDI/pseudo[/extension])
09298     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09299     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09300     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09301     *
09302     * g - channel group allocation search forward
09303     * G - channel group allocation search backward
09304     * r - channel group allocation round robin search forward
09305     * R - channel group allocation round robin search backward
09306     *
09307     * c - Wait for DTMF digit to confirm answer
09308     * r<cadance#> - Set distintive ring cadance number
09309     * d - Force bearer capability for ISDN call to digital.
09310     */
09311 
09312    /* Assume we're locking the iflock */
09313    lock = &iflock;
09314    start = iflist;
09315    end = ifend;
09316    if (data) {
09317       dest = ast_strdupa((char *)data);
09318    } else {
09319       ast_log(LOG_WARNING, "Channel requested with no data\n");
09320       return NULL;
09321    }
09322    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09323       /* Retrieve the group number */
09324       char *stringp;
09325 
09326       stringp = dest + 1;
09327       s = strsep(&stringp, "/");
09328       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09329          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09330          return NULL;
09331       }
09332       groupmatch = ((ast_group_t) 1 << x);
09333       if (toupper(dest[0]) == 'G') {
09334          if (dest[0] == 'G') {
09335             backwards = 1;
09336             p = ifend;
09337          } else
09338             p = iflist;
09339       } else {
09340          if (dest[0] == 'R') {
09341             backwards = 1;
09342             p = round_robin[x]?round_robin[x]->prev:ifend;
09343             if (!p)
09344                p = ifend;
09345          } else {
09346             p = round_robin[x]?round_robin[x]->next:iflist;
09347             if (!p)
09348                p = iflist;
09349          }
09350          roundrobin = 1;
09351       }
09352    } else {
09353       char *stringp;
09354 
09355       stringp = dest;
09356       s = strsep(&stringp, "/");
09357       p = iflist;
09358       if (!strcasecmp(s, "pseudo")) {
09359          /* Special case for pseudo */
09360          x = CHAN_PSEUDO;
09361          channelmatch = x;
09362       } 
09363 #ifdef HAVE_PRI
09364       else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09365          if ((trunkgroup < 1) || (crv < 1)) {
09366             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09367             return NULL;
09368          }
09369          res--;
09370          for (x = 0; x < NUM_SPANS; x++) {
09371             if (pris[x].trunkgroup == trunkgroup) {
09372                pri = pris + x;
09373                lock = &pri->lock;
09374                start = pri->crvs;
09375                end = pri->crvend;
09376                break;
09377             }
09378          }
09379          if (!pri) {
09380             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09381             return NULL;
09382          }
09383          channelmatch = crv;
09384          p = pris[x].crvs;
09385       }
09386 #endif   
09387       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09388          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09389          return NULL;
09390       } else {
09391          channelmatch = x;
09392       }
09393    }
09394    /* Search for an unowned channel */
09395    ast_mutex_lock(lock);
09396    exit = p;
09397    while (p && !tmp) {
09398       if (roundrobin)
09399          round_robin[x] = p;
09400 #if 0
09401       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09402 #endif
09403 
09404       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09405          if (option_debug)
09406             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09407             if (p->inalarm) 
09408                goto next;
09409 
09410          callwait = (p->owner != NULL);
09411 #ifdef HAVE_PRI
09412          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09413             if (p->sig != SIG_FXSKS) {
09414                /* Gotta find an actual channel to use for this
09415                   CRV if this isn't a callwait */
09416                bearer = pri_find_empty_chan(pri, 0);
09417                if (bearer < 0) {
09418                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09419                   p = NULL;
09420                   break;
09421                }
09422                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09423             } else {
09424                if (alloc_sub(p, 0)) {
09425                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09426                   p = NULL;
09427                   break;
09428                } else
09429                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09430                p->pri = pri;
09431             }
09432          }
09433 #endif         
09434 #ifdef HAVE_OPENR2
09435          if (p->mfcr2) {
09436             ast_mutex_lock(&p->lock);
09437             if (p->mfcr2call) {
09438                ast_mutex_unlock(&p->lock);
09439                ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09440                goto next;
09441             }
09442             if (p->mfcr2block) {
09443                ast_mutex_unlock(&p->lock);
09444                ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09445                goto next;
09446             }
09447             p->mfcr2call = 1;
09448             ast_mutex_unlock(&p->lock);
09449          }
09450 #endif
09451          if (p->channel == CHAN_PSEUDO) {
09452             p = chandup(p);
09453             if (!p) {
09454                break;
09455             }
09456          }
09457          if (p->owner) {
09458             if (alloc_sub(p, SUB_CALLWAIT)) {
09459                p = NULL;
09460                break;
09461             }
09462          }
09463          p->outgoing = 1;
09464          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09465          if (!tmp) {
09466             p->outgoing = 0;
09467          }
09468 #ifdef HAVE_PRI
09469          if (p->bearer) {
09470             /* Log owner to bearer channel, too */
09471             p->bearer->owner = tmp;
09472          }
09473 #endif         
09474          /* Make special notes */
09475          if (res > 1) {
09476             if (opt == 'c') {
09477                /* Confirm answer */
09478                p->confirmanswer = 1;
09479             } else if (opt == 'r') {
09480                /* Distinctive ring */
09481                if (res < 3)
09482                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09483                else
09484                   p->distinctivering = y;
09485             } else if (opt == 'd') {
09486                /* If this is an ISDN call, make it digital */
09487                p->digital = 1;
09488                if (tmp)
09489                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09490             } else {
09491                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09492             }
09493          }
09494          /* Note if the call is a call waiting call */
09495          if (tmp && callwait)
09496             tmp->cdrflags |= AST_CDR_CALLWAIT;
09497          break;
09498       }
09499 next:
09500       if (backwards) {
09501          p = p->prev;
09502          if (!p)
09503             p = end;
09504       } else {
09505          p = p->next;
09506          if (!p)
09507             p = start;
09508       }
09509       /* stop when you roll to the one that we started from */
09510       if (p == exit)
09511          break;
09512    }
09513    ast_mutex_unlock(lock);
09514    restart_monitor();
09515    if (callwait)
09516       *cause = AST_CAUSE_BUSY;
09517    else if (!tmp) {
09518       if (channelmatched) {
09519          if (busy)
09520             *cause = AST_CAUSE_BUSY;
09521       } else if (groupmatched) {
09522          *cause = AST_CAUSE_CONGESTION;
09523       }
09524    }
09525       
09526    return tmp;
09527 }
09528 
09529 #ifdef HAVE_OPENR2
09530 static void *mfcr2_monitor(void *data)
09531 {
09532    struct dahdi_pvt *p;
09533    struct dahdi_mfcr2 *mfcr2 = data;
09534    /* we should be using pthread_key_create
09535       and allocate pollers dynamically.
09536       I think do_monitor() could be leaking, since it
09537       could be cancelled at any time and is not
09538       using thread keys, why?, */
09539    struct pollfd pollers[sizeof(mfcr2->pvts)];
09540    int maxsleep = 20;
09541    int res = 0;
09542    int i = 0;
09543    int pollsize = 0;
09544    int oldstate = 0;
09545    int was_idle = 0;
09546    int quit_loop = 0;
09547    /* now that we're ready to get calls, unblock our side and
09548       get current line state */
09549    for (i = 0; i < mfcr2->numchans; i++) {
09550       p = mfcr2->pvts[i];
09551       if (openr2_chan_set_idle(p->r2chan)) {
09552          ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09553       } else {
09554          ast_mutex_lock(&p->lock);
09555          mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09556          mfcr2->pvts[i]->mfcr2call = 0;
09557          ast_mutex_unlock(&p->lock);
09558       }
09559       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09560    }
09561    while(1) {
09562       /* we trust here that the mfcr2 channel list will not ever change once
09563          the module is loaded */
09564       pollsize = 0;
09565       for (i = 0; i < mfcr2->numchans; i++) {
09566          pollers[i].revents = 0;
09567          pollers[i].events = 0;
09568          if (mfcr2->pvts[i]->owner) {
09569             continue;
09570          }
09571          if (!mfcr2->pvts[i]->r2chan) {
09572             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09573             quit_loop = 1;
09574             break;
09575          }
09576          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09577          pollers[i].events = POLLIN | POLLPRI;
09578          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09579          pollsize++;
09580       }
09581       if (quit_loop) {
09582          break;
09583       }
09584 
09585       if (pollsize == 0) {
09586          if (!was_idle) {
09587             ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09588             was_idle = 1;
09589          }
09590          poll(NULL, 0, maxsleep);
09591          continue;
09592       }
09593       was_idle = 0;
09594 
09595       /* probably poll() is a valid cancel point, lets just be on the safe side
09596          by calling pthread_testcancel */
09597       pthread_testcancel();
09598       res = poll(pollers, pollsize, maxsleep);
09599       pthread_testcancel();
09600       if ((res < 0) && (errno != EINTR)) {
09601          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09602          break;
09603       } 
09604       /* do we want to allow to cancel while processing events? */
09605       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09606       for (i = 0; i < mfcr2->numchans; i++) {
09607          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
09608             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09609          }
09610       }
09611       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09612    }
09613    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09614    return 0;
09615 }
09616 #endif
09617 
09618 
09619 #ifdef HAVE_PRI
09620 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
09621 {
09622    struct dahdi_pvt *p;
09623    p = pri->crvs;
09624    while (p) {
09625       if (p->channel == crv)
09626          return p;
09627       p = p->next;
09628    }
09629    return NULL;
09630 }
09631 
09632 
09633 static int pri_find_principle(struct dahdi_pri *pri, int channel)
09634 {
09635    int x;
09636    int span = PRI_SPAN(channel);
09637    int spanfd;
09638    struct dahdi_params param;
09639    int principle = -1;
09640    int explicit = PRI_EXPLICIT(channel);
09641    channel = PRI_CHANNEL(channel);
09642 
09643    if (!explicit) {
09644       spanfd = pri_active_dchan_fd(pri);
09645       memset(&param, 0, sizeof(param));
09646       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
09647          return -1;
09648       span = pris[param.spanno - 1].prilogicalspan;
09649    }
09650 
09651    for (x = 0; x < pri->numchans; x++) {
09652       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09653          principle = x;
09654          break;
09655       }
09656    }
09657    
09658    return principle;
09659 }
09660 
09661 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
09662 {
09663    int x;
09664    struct dahdi_pvt *crv;
09665    if (!c) {
09666       if (principle < 0)
09667          return -1;
09668       return principle;
09669    }
09670    if ((principle > -1) && 
09671       (principle < pri->numchans) && 
09672       (pri->pvts[principle]) && 
09673       (pri->pvts[principle]->call == c))
09674       return principle;
09675    /* First, check for other bearers */
09676    for (x = 0; x < pri->numchans; x++) {
09677       if (!pri->pvts[x])
09678          continue;
09679       if (pri->pvts[x]->call == c) {
09680          /* Found our call */
09681          if (principle != x) {
09682             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09683 
09684             if (option_verbose > 2)
09685                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09686                   old->channel, new->channel);
09687             if (new->owner) {
09688                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09689                   old->channel, new->channel, new->channel);
09690                return -1;
09691             }
09692             /* Fix it all up now */
09693             new->owner = old->owner;
09694             old->owner = NULL;
09695             if (new->owner) {
09696                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09697                new->owner->tech_pvt = new;
09698                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09699                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09700                old->subs[SUB_REAL].owner = NULL;
09701             } else
09702                ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
09703             new->call = old->call;
09704             old->call = NULL;
09705 
09706             /* Copy any DSP that may be present */
09707             new->dsp = old->dsp;
09708             new->dsp_features = old->dsp_features;
09709             old->dsp = NULL;
09710             old->dsp_features = 0;
09711          }
09712          return principle;
09713       }
09714    }
09715    /* Now check for a CRV with no bearer */
09716    crv = pri->crvs;
09717    while (crv) {
09718       if (crv->call == c) {
09719          /* This is our match...  Perform some basic checks */
09720          if (crv->bearer)
09721             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09722          else if (pri->pvts[principle]->owner) 
09723             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09724          else {
09725             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
09726                wakeup the potential sleeper */
09727             dahdi_close_sub(crv, SUB_REAL);
09728             pri->pvts[principle]->call = crv->call;
09729             pri_assign_bearer(crv, pri, pri->pvts[principle]);
09730             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09731                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09732                            pri->trunkgroup, crv->channel);
09733             wakeup_sub(crv, SUB_REAL, pri);
09734          }
09735          return principle;
09736       }
09737       crv = crv->next;
09738    }
09739    ast_log(LOG_WARNING, "Call specified, but not found?\n");
09740    return -1;
09741 }
09742 
09743 static void *do_idle_thread(void *vchan)
09744 {
09745    struct ast_channel *chan = vchan;
09746    struct dahdi_pvt *pvt = chan->tech_pvt;
09747    struct ast_frame *f;
09748    char ex[80];
09749    /* Wait up to 30 seconds for an answer */
09750    int newms, ms = 30000;
09751    if (option_verbose > 2) 
09752       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09753    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09754    if (ast_call(chan, ex, 0)) {
09755       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09756       ast_hangup(chan);
09757       return NULL;
09758    }
09759    while ((newms = ast_waitfor(chan, ms)) > 0) {
09760       f = ast_read(chan);
09761       if (!f) {
09762          /* Got hangup */
09763          break;
09764       }
09765       if (f->frametype == AST_FRAME_CONTROL) {
09766          switch (f->subclass) {
09767          case AST_CONTROL_ANSWER:
09768             /* Launch the PBX */
09769             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09770             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09771             chan->priority = 1;
09772             if (option_verbose > 3) 
09773                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09774             ast_pbx_run(chan);
09775             /* It's already hungup, return immediately */
09776             return NULL;
09777          case AST_CONTROL_BUSY:
09778             if (option_verbose > 3) 
09779                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09780             break;
09781          case AST_CONTROL_CONGESTION:
09782             if (option_verbose > 3) 
09783                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09784             break;
09785          };
09786       }
09787       ast_frfree(f);
09788       ms = newms;
09789    }
09790    /* Hangup the channel since nothing happend */
09791    ast_hangup(chan);
09792    return NULL;
09793 }
09794 
09795 #ifndef PRI_RESTART
09796 #error "Upgrade your libpri"
09797 #endif
09798 static void dahdi_pri_message(struct pri *pri, char *s)
09799 {
09800    int x, y;
09801    int dchan = -1, span = -1;
09802    int dchancount = 0;
09803 
09804    if (pri) {
09805       for (x = 0; x < NUM_SPANS; x++) {
09806          for (y = 0; y < NUM_DCHANS; y++) {
09807             if (pris[x].dchans[y])
09808                dchancount++;
09809 
09810             if (pris[x].dchans[y] == pri)
09811                dchan = y;
09812          }
09813          if (dchan >= 0) {
09814             span = x;
09815             break;
09816          }
09817          dchancount = 0;
09818       }
09819       if ((dchan >= 0) && (span >= 0)) {
09820          if (dchancount > 1)
09821             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09822          else
09823             ast_verbose("%s", s);
09824       } else
09825          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09826    } else
09827       ast_verbose("%s", s);
09828 
09829    ast_mutex_lock(&pridebugfdlock);
09830 
09831    if (pridebugfd >= 0) {
09832       if (write(pridebugfd, s, strlen(s)) < 0) {
09833          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09834       }
09835    }
09836 
09837    ast_mutex_unlock(&pridebugfdlock);
09838 }
09839 
09840 static void dahdi_pri_error(struct pri *pri, char *s)
09841 {
09842    int x, y;
09843    int dchan = -1, span = -1;
09844    int dchancount = 0;
09845 
09846    if (pri) {
09847       for (x = 0; x < NUM_SPANS; x++) {
09848          for (y = 0; y < NUM_DCHANS; y++) {
09849             if (pris[x].dchans[y])
09850                dchancount++;
09851 
09852             if (pris[x].dchans[y] == pri)
09853                dchan = y;
09854          }
09855          if (dchan >= 0) {
09856             span = x;
09857             break;
09858          }
09859          dchancount = 0;
09860       }
09861       if ((dchan >= 0) && (span >= 0)) {
09862          if (dchancount > 1)
09863             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09864          else
09865             ast_log(LOG_ERROR, "%s", s);
09866       } else
09867          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09868    } else
09869       ast_log(LOG_ERROR, "%s", s);
09870 
09871    ast_mutex_lock(&pridebugfdlock);
09872 
09873    if (pridebugfd >= 0) {
09874       if (write(pridebugfd, s, strlen(s)) < 0) {
09875          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09876       }
09877    }
09878 
09879    ast_mutex_unlock(&pridebugfdlock);
09880 }
09881 
09882 static int pri_check_restart(struct dahdi_pri *pri)
09883 {
09884    do {
09885       pri->resetpos++;
09886    } while ((pri->resetpos < pri->numchans) &&
09887        (!pri->pvts[pri->resetpos] ||
09888         pri->pvts[pri->resetpos]->call ||
09889         pri->pvts[pri->resetpos]->resetting));
09890    if (pri->resetpos < pri->numchans) {
09891       /* Mark the channel as resetting and restart it */
09892       pri->pvts[pri->resetpos]->resetting = 1;
09893       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09894    } else {
09895       pri->resetting = 0;
09896       time(&pri->lastreset);
09897    }
09898    return 0;
09899 }
09900 
09901 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
09902 {
09903    int x;
09904    int redo;
09905    ast_mutex_unlock(&pri->lock);
09906    ast_mutex_lock(&p->lock);
09907    do {
09908       redo = 0;
09909       for (x = 0; x < 3; x++) {
09910          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
09911             redo++;
09912             DEADLOCK_AVOIDANCE(&p->lock);
09913          }
09914          if (p->subs[x].owner) {
09915             ast_queue_hangup(p->subs[x].owner);
09916             ast_mutex_unlock(&p->subs[x].owner->lock);
09917          }
09918       }
09919    } while (redo);
09920    ast_mutex_unlock(&p->lock);
09921    ast_mutex_lock(&pri->lock);
09922    return 0;
09923 }
09924 
09925 static char * redirectingreason2str(int redirectingreason)
09926 {
09927    switch (redirectingreason) {
09928    case 0:
09929       return "UNKNOWN";
09930    case 1:
09931       return "BUSY";
09932    case 2:
09933       return "NO_REPLY";
09934    case 0xF:
09935       return "UNCONDITIONAL";
09936    default:
09937       return "NOREDIRECT";
09938    }
09939 }
09940 
09941 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
09942 {
09943    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
09944       if (size) {
09945          *buf = '\0';
09946       }
09947       return;
09948    }
09949 
09950    switch (plan) {
09951    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
09952       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
09953       break;
09954    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
09955       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
09956       break;
09957    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
09958       snprintf(buf, size, "%s%s", pri->localprefix, number);
09959       break;
09960    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
09961       snprintf(buf, size, "%s%s", pri->privateprefix, number);
09962       break;
09963    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
09964       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
09965       break;
09966    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
09967       snprintf(buf, size, "%s", number);
09968       break;
09969    }
09970 }
09971 
09972 static int dahdi_setlaw(int dfd, int law)
09973 {
09974    int res;
09975    res = ioctl(dfd, DAHDI_SETLAW, &law);
09976    if (res)
09977       return res;
09978    return 0;
09979 }
09980 
09981 static void *pri_dchannel(void *vpri)
09982 {
09983    struct dahdi_pri *pri = vpri;
09984    pri_event *e;
09985    struct pollfd fds[NUM_DCHANS];
09986    int res;
09987    int chanpos = 0;
09988    int x;
09989    int haveidles;
09990    int activeidles;
09991    int nextidle = -1;
09992    struct ast_channel *c;
09993    struct timeval tv, lowest, *next;
09994    struct timeval lastidle = { 0, 0 };
09995    int doidling=0;
09996    char *cc;
09997    char idlen[80];
09998    struct ast_channel *idle;
09999    pthread_t p;
10000    time_t t;
10001    int i, which=-1;
10002    int numdchans;
10003    int cause=0;
10004    struct dahdi_pvt *crv;
10005    pthread_t threadid;
10006    pthread_attr_t attr;
10007    char ani2str[6];
10008    char plancallingnum[256];
10009    char plancallingani[256];
10010    char calledtonstr[10];
10011    
10012    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10013 
10014    gettimeofday(&lastidle, NULL);
10015    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10016       /* Need to do idle dialing, check to be sure though */
10017       cc = strchr(pri->idleext, '@');
10018       if (cc) {
10019          *cc = '\0';
10020          cc++;
10021          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10022 #if 0
10023          /* Extensions may not be loaded yet */
10024          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10025             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10026          else
10027 #endif
10028             doidling = 1;
10029       } else
10030          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10031    }
10032    for (;;) {
10033       for (i = 0; i < NUM_DCHANS; i++) {
10034          if (!pri->dchannels[i])
10035             break;
10036          fds[i].fd = pri->fds[i];
10037          fds[i].events = POLLIN | POLLPRI;
10038          fds[i].revents = 0;
10039       }
10040       numdchans = i;
10041       time(&t);
10042       ast_mutex_lock(&pri->lock);
10043       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10044          if (pri->resetting && pri_is_up(pri)) {
10045             if (pri->resetpos < 0)
10046                pri_check_restart(pri);
10047          } else {
10048             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
10049                pri->resetting = 1;
10050                pri->resetpos = -1;
10051             }
10052          }
10053       }
10054       /* Look for any idle channels if appropriate */
10055       if (doidling && pri_is_up(pri)) {
10056          nextidle = -1;
10057          haveidles = 0;
10058          activeidles = 0;
10059          for (x = pri->numchans; x >= 0; x--) {
10060             if (pri->pvts[x] && !pri->pvts[x]->owner && 
10061                 !pri->pvts[x]->call) {
10062                if (haveidles < pri->minunused) {
10063                   haveidles++;
10064                } else if (!pri->pvts[x]->resetting) {
10065                   nextidle = x;
10066                   break;
10067                }
10068             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10069                activeidles++;
10070          }
10071          if (nextidle > -1) {
10072             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10073                /* Don't create a new idle call more than once per second */
10074                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10075                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
10076                if (idle) {
10077                   pri->pvts[nextidle]->isidlecall = 1;
10078                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10079                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10080                      dahdi_hangup(idle);
10081                   }
10082                } else
10083                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10084                gettimeofday(&lastidle, NULL);
10085             }
10086          } else if ((haveidles < pri->minunused) &&
10087                (activeidles > pri->minidle)) {
10088             /* Mark something for hangup if there is something 
10089                that can be hungup */
10090             for (x = pri->numchans; x >= 0; x--) {
10091                /* find a candidate channel */
10092                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10093                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10094                   haveidles++;
10095                   /* Stop if we have enough idle channels or
10096                     can't spare any more active idle ones */
10097                   if ((haveidles >= pri->minunused) ||
10098                       (activeidles <= pri->minidle))
10099                      break;
10100                } 
10101             }
10102          }
10103       }
10104       /* Start with reasonable max */
10105       lowest = ast_tv(60, 0);
10106       for (i = 0; i < NUM_DCHANS; i++) {
10107          /* Find lowest available d-channel */
10108          if (!pri->dchannels[i])
10109             break;
10110          if ((next = pri_schedule_next(pri->dchans[i]))) {
10111             /* We need relative time here */
10112             tv = ast_tvsub(*next, ast_tvnow());
10113             if (tv.tv_sec < 0) {
10114                tv = ast_tv(0,0);
10115             }
10116             if (doidling || pri->resetting) {
10117                if (tv.tv_sec > 1) {
10118                   tv = ast_tv(1, 0);
10119                }
10120             } else {
10121                if (tv.tv_sec > 60) {
10122                   tv = ast_tv(60, 0);
10123                }
10124             }
10125          } else if (doidling || pri->resetting) {
10126             /* Make sure we stop at least once per second if we're
10127                monitoring idle channels */
10128             tv = ast_tv(1,0);
10129          } else {
10130             /* Don't poll for more than 60 seconds */
10131             tv = ast_tv(60, 0);
10132          }
10133          if (!i || ast_tvcmp(tv, lowest) < 0) {
10134             lowest = tv;
10135          }
10136       }
10137       ast_mutex_unlock(&pri->lock);
10138 
10139       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10140       pthread_testcancel();
10141       e = NULL;
10142       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10143       pthread_testcancel();
10144       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10145 
10146       ast_mutex_lock(&pri->lock);
10147       if (!res) {
10148          for (which = 0; which < NUM_DCHANS; which++) {
10149             if (!pri->dchans[which])
10150                break;
10151             /* Just a timeout, run the scheduler */
10152             e = pri_schedule_run(pri->dchans[which]);
10153             if (e)
10154                break;
10155          }
10156       } else if (res > -1) {
10157          for (which = 0; which < NUM_DCHANS; which++) {
10158             if (!pri->dchans[which])
10159                break;
10160             if (fds[which].revents & POLLPRI) {
10161                /* Check for an event */
10162                x = 0;
10163                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10164                if (x) 
10165                   ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
10166                /* Keep track of alarm state */  
10167                if (x == DAHDI_EVENT_ALARM) {
10168                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10169                   pri_find_dchan(pri);
10170                } else if (x == DAHDI_EVENT_NOALARM) {
10171                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
10172                   pri_restart(pri->dchans[which]);
10173                }
10174             
10175                if (option_debug)
10176                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10177             } else if (fds[which].revents & POLLIN) {
10178                e = pri_check_event(pri->dchans[which]);
10179             }
10180             if (e)
10181                break;
10182          }
10183       } else if (errno != EINTR)
10184          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10185 
10186       if (e) {
10187          if (pri->debug)
10188             pri_dump_event(pri->dchans[which], e);
10189 
10190          if (e->e != PRI_EVENT_DCHAN_DOWN) {
10191             if (!(pri->dchanavail[which] & DCHAN_UP)) {
10192                if (option_verbose > 1) 
10193                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10194             }
10195             pri->dchanavail[which] |= DCHAN_UP;
10196          } else {
10197             if (pri->dchanavail[which] & DCHAN_UP) {
10198                if (option_verbose > 1) 
10199                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10200             }
10201             pri->dchanavail[which] &= ~DCHAN_UP;
10202          }
10203 
10204          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10205             /* Must be an NFAS group that has the secondary dchan active */
10206             pri->pri = pri->dchans[which];
10207 
10208          switch (e->e) {
10209          case PRI_EVENT_DCHAN_UP:
10210             if (!pri->pri) pri_find_dchan(pri);
10211 
10212             /* Note presense of D-channel */
10213             time(&pri->lastreset);
10214 
10215             /* Restart in 5 seconds */
10216             if (pri->resetinterval > -1) {
10217                pri->lastreset -= pri->resetinterval;
10218                pri->lastreset += 5;
10219             }
10220             pri->resetting = 0;
10221             /* Take the channels from inalarm condition */
10222             for (i = 0; i < pri->numchans; i++)
10223                if (pri->pvts[i]) {
10224                   pri->pvts[i]->inalarm = 0;
10225                }
10226             break;
10227          case PRI_EVENT_DCHAN_DOWN:
10228             pri_find_dchan(pri);
10229             if (!pri_is_up(pri)) {
10230                pri->resetting = 0;
10231                /* Hangup active channels and put them in alarm mode */
10232                for (i = 0; i < pri->numchans; i++) {
10233                   struct dahdi_pvt *p = pri->pvts[i];
10234                   if (p) {
10235                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10236                         /* T309 is not enabled : hangup calls when alarm occurs */
10237                         if (p->call) {
10238                            if (p->pri && p->pri->pri) {
10239                               pri_hangup(p->pri->pri, p->call, -1);
10240                               pri_destroycall(p->pri->pri, p->call);
10241                               p->call = NULL;
10242                            } else
10243                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10244                         }
10245                         if (p->realcall) {
10246                            pri_hangup_all(p->realcall, pri);
10247                         } else if (p->owner)
10248                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10249                      }
10250                      p->inalarm = 1;
10251                   }
10252                }
10253             }
10254             break;
10255          case PRI_EVENT_RESTART:
10256             if (e->restart.channel > -1) {
10257                chanpos = pri_find_principle(pri, e->restart.channel);
10258                if (chanpos < 0)
10259                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
10260                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10261                else {
10262                   if (option_verbose > 2)
10263                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
10264                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10265                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10266                   if (pri->pvts[chanpos]->call) {
10267                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10268                      pri->pvts[chanpos]->call = NULL;
10269                   }
10270                   /* Force soft hangup if appropriate */
10271                   if (pri->pvts[chanpos]->realcall) 
10272                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10273                   else if (pri->pvts[chanpos]->owner)
10274                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10275                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10276                }
10277             } else {
10278                if (option_verbose > 2)
10279                   ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
10280                for (x = 0; x < pri->numchans; x++)
10281                   if (pri->pvts[x]) {
10282                      ast_mutex_lock(&pri->pvts[x]->lock);
10283                      if (pri->pvts[x]->call) {
10284                         pri_destroycall(pri->pri, pri->pvts[x]->call);
10285                         pri->pvts[x]->call = NULL;
10286                      }
10287                      if (pri->pvts[x]->realcall) 
10288                         pri_hangup_all(pri->pvts[x]->realcall, pri);
10289                      else if (pri->pvts[x]->owner)
10290                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10291                      ast_mutex_unlock(&pri->pvts[x]->lock);
10292                   }
10293             }
10294             break;
10295          case PRI_EVENT_KEYPAD_DIGIT:
10296             chanpos = pri_find_principle(pri, e->digit.channel);
10297             if (chanpos < 0) {
10298                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
10299                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10300             } else {
10301                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10302                if (chanpos > -1) {
10303                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10304                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10305                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10306                      /* how to do that */
10307                      int digitlen = strlen(e->digit.digits);
10308                      char digit;
10309                      int i;               
10310                      for (i = 0; i < digitlen; i++) { 
10311                         digit = e->digit.digits[i];
10312                         {
10313                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
10314                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10315                         }
10316                      }
10317                   }
10318                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10319                }
10320             }
10321             break;
10322             
10323          case PRI_EVENT_INFO_RECEIVED:
10324             chanpos = pri_find_principle(pri, e->ring.channel);
10325             if (chanpos < 0) {
10326                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
10327                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10328             } else {
10329                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10330                if (chanpos > -1) {
10331                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10332                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10333                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10334                      /* how to do that */
10335                      int digitlen = strlen(e->ring.callednum);
10336                      char digit;
10337                      int i;               
10338                      for (i = 0; i < digitlen; i++) { 
10339                         digit = e->ring.callednum[i];
10340                         {
10341                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
10342                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10343                         }
10344                      }
10345                   }
10346                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10347                }
10348             }
10349             break;
10350          case PRI_EVENT_RING:
10351             crv = NULL;
10352             if (e->ring.channel == -1)
10353                chanpos = pri_find_empty_chan(pri, 1);
10354             else
10355                chanpos = pri_find_principle(pri, e->ring.channel);
10356             /* if no channel specified find one empty */
10357             if (chanpos < 0) {
10358                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
10359                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10360             } else {
10361                ast_mutex_lock(&pri->pvts[chanpos]->lock);
10362                if (pri->pvts[chanpos]->owner) {
10363                   if (pri->pvts[chanpos]->call == e->ring.call) {
10364                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
10365                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10366                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10367                      break;
10368                   } else {
10369                      /* This is where we handle initial glare */
10370                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
10371                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10372                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10373                      chanpos = -1;
10374                   }
10375                }
10376                if (chanpos > -1)
10377                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10378             }
10379             if ((chanpos < 0) && (e->ring.flexible))
10380                chanpos = pri_find_empty_chan(pri, 1);
10381             if (chanpos > -1) {
10382                ast_mutex_lock(&pri->pvts[chanpos]->lock);
10383                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10384                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
10385                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10386                   if (crv)
10387                      ast_mutex_lock(&crv->lock);
10388                   if (!crv || crv->owner) {
10389                      pri->pvts[chanpos]->call = NULL;
10390                      if (crv) {
10391                         if (crv->owner)
10392                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10393                         ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10394                      } else
10395                         ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10396                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10397                      if (crv)
10398                         ast_mutex_unlock(&crv->lock);
10399                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10400                      break;
10401                   }
10402                }
10403                pri->pvts[chanpos]->call = e->ring.call;
10404                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10405                if (pri->pvts[chanpos]->use_callerid) {
10406                   ast_shrink_phone_number(plancallingnum);
10407                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10408 #ifdef PRI_ANI
10409                   if (!ast_strlen_zero(e->ring.callingani)) {
10410                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10411                      ast_shrink_phone_number(plancallingani);
10412                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10413                   } else {
10414                      pri->pvts[chanpos]->cid_ani[0] = '\0';
10415                   }
10416 #endif
10417                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10418                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10419                } else {
10420                   pri->pvts[chanpos]->cid_num[0] = '\0';
10421                   pri->pvts[chanpos]->cid_ani[0] = '\0';
10422                   pri->pvts[chanpos]->cid_name[0] = '\0';
10423                   pri->pvts[chanpos]->cid_ton = 0;
10424                }
10425                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10426                           e->ring.redirectingnum, e->ring.callingplanrdnis);
10427                /* If immediate=yes go to s|1 */
10428                if (pri->pvts[chanpos]->immediate) {
10429                   if (option_verbose > 2)
10430                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
10431                   pri->pvts[chanpos]->exten[0] = 's';
10432                   pri->pvts[chanpos]->exten[1] = '\0';
10433                }
10434                /* Get called number */
10435                else if (!ast_strlen_zero(e->ring.callednum)) {
10436                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10437                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10438                } else if (pri->overlapdial)
10439                   pri->pvts[chanpos]->exten[0] = '\0';
10440                else {
10441                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
10442                   pri->pvts[chanpos]->exten[0] = 's';
10443                   pri->pvts[chanpos]->exten[1] = '\0';
10444                }
10445                /* Set DNID on all incoming calls -- even immediate */
10446                if (!ast_strlen_zero(e->ring.callednum))
10447                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10448                /* No number yet, but received "sending complete"? */
10449                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10450                   if (option_verbose > 2)
10451                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
10452                   pri->pvts[chanpos]->exten[0] = 's';
10453                   pri->pvts[chanpos]->exten[1] = '\0';
10454                }
10455 
10456                /* Make sure extension exists (or in overlap dial mode, can exist) */
10457                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10458                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10459                   /* Setup law */
10460                   int law;
10461                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10462                      /* Set to audio mode at this point */
10463                      law = 1;
10464                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10465                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10466                   }
10467                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10468                      law = DAHDI_LAW_ALAW;
10469                   else
10470                      law = DAHDI_LAW_MULAW;
10471                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10472                   if (res < 0) 
10473                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10474                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10475                   if (res < 0)
10476                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10477                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10478                      /* Just announce proceeding */
10479                      pri->pvts[chanpos]->proceeding = 1;
10480                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10481                   } else {
10482                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
10483                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10484                      else
10485                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10486                   }
10487                   /* Get the use_callingpres state */
10488                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10489                
10490                   /* Start PBX */
10491                   if (!e->ring.complete
10492                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
10493                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10494                      /*
10495                       * Release the PRI lock while we create the channel
10496                       * so other threads can send D channel messages.
10497                       */
10498                      ast_mutex_unlock(&pri->lock);
10499                      if (crv) {
10500                         /* Set bearer and such */
10501                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10502                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10503                         pri->pvts[chanpos]->owner = &inuse;
10504                         ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10505                      } else {
10506                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10507                      }
10508                      ast_mutex_lock(&pri->lock);
10509                      if (c) {
10510                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10511                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10512                         }
10513                         if (e->ring.ani2 >= 0) {
10514                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10515                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10516                         }
10517 
10518 #ifdef SUPPORT_USERUSER
10519                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
10520                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10521                         }
10522 #endif
10523 
10524                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10525                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10526                         if (e->ring.redirectingreason >= 0)
10527                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10528                      }
10529 
10530                      pthread_attr_init(&attr);
10531                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10532                      if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
10533                         if (option_verbose > 2)
10534                            ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10535                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10536                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10537                      } else {
10538                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10539                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10540                         if (c)
10541                            ast_hangup(c);
10542                         else {
10543                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10544                            pri->pvts[chanpos]->call = NULL;
10545                         }
10546                      }
10547                      pthread_attr_destroy(&attr);
10548                   } else {
10549                      /*
10550                       * Release the PRI lock while we create the channel
10551                       * so other threads can send D channel messages.
10552                       */
10553                      ast_mutex_unlock(&pri->lock);
10554                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
10555                      ast_mutex_lock(&pri->lock);
10556                      if (c) {
10557                         /*
10558                          * It is reasonably safe to set the following
10559                          * channel variables while the PRI and DAHDI private
10560                          * structures are locked.  The PBX has not been
10561                          * started yet and it is unlikely that any other task
10562                          * will do anything with the channel we have just
10563                          * created.
10564                          */
10565                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10566                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10567                         }
10568                         if (e->ring.ani2 >= 0) {
10569                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10570                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10571                         }
10572 
10573 #ifdef SUPPORT_USERUSER
10574                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
10575                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10576                         }
10577 #endif
10578 
10579                         if (e->ring.redirectingreason >= 0)
10580                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10581 
10582                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10583                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10584                      }
10585                      if (c && !ast_pbx_start(c)) {
10586                         if (option_verbose > 2)
10587                            ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10588                               plancallingnum, pri->pvts[chanpos]->exten,
10589                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10590 
10591                         dahdi_enable_ec(pri->pvts[chanpos]);
10592                      } else {
10593                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10594                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10595                         if (c) {
10596                            ast_hangup(c);
10597                         } else {
10598                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10599                            pri->pvts[chanpos]->call = NULL;
10600                         }
10601                      }
10602                   }
10603                } else {
10604                   if (option_verbose > 2)
10605                      ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
10606                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
10607                            pri->pvts[chanpos]->prioffset, pri->span);
10608                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10609                   pri->pvts[chanpos]->call = NULL;
10610                   pri->pvts[chanpos]->exten[0] = '\0';
10611                }
10612                if (crv)
10613                   ast_mutex_unlock(&crv->lock);
10614                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10615             } else {
10616                if (e->ring.flexible)
10617                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10618                else
10619                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10620             }
10621             break;
10622          case PRI_EVENT_RINGING:
10623             chanpos = pri_find_principle(pri, e->ringing.channel);
10624             if (chanpos < 0) {
10625                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
10626                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10627             } else {
10628                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10629                if (chanpos < 0) {
10630                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
10631                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10632                } else {
10633                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10634                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10635                      dahdi_enable_ec(pri->pvts[chanpos]);
10636                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10637                      pri->pvts[chanpos]->alerting = 1;
10638                   } else
10639                      ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
10640 #ifdef PRI_PROGRESS_MASK
10641                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10642 #else
10643                   if (e->ringing.progress == 8) {
10644 #endif
10645                      /* Now we can do call progress detection */
10646                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10647                         /* RINGING detection isn't required because we got ALERTING signal */
10648                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10649                         pri->pvts[chanpos]->dsp_features = 0;
10650                      }
10651                   }
10652 
10653 #ifdef SUPPORT_USERUSER
10654                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10655                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10656                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10657                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10658                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10659                   }
10660 #endif
10661 
10662                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10663                }
10664             }
10665             break;
10666          case PRI_EVENT_PROGRESS:
10667             /* Get chan value if e->e is not PRI_EVNT_RINGING */
10668             chanpos = pri_find_principle(pri, e->proceeding.channel);
10669             if (chanpos > -1) {
10670 #ifdef PRI_PROGRESS_MASK
10671                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10672 #else
10673                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10674 #endif
10675                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10676 
10677                   if (e->proceeding.cause > -1) {
10678                      if (option_verbose > 2)
10679                         ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
10680 
10681                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
10682                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10683                         if (pri->pvts[chanpos]->owner) {
10684                            if (option_verbose > 2)
10685                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10686 
10687                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10688                            f.subclass = AST_CONTROL_BUSY;
10689                         }
10690                      }
10691                   }
10692                   
10693                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10694                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
10695                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10696                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10697 #ifdef PRI_PROGRESS_MASK
10698                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10699 #else
10700                   if (e->proceeding.progress == 8) {
10701 #endif
10702                      /* Now we can do call progress detection */
10703                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10704                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10705                         pri->pvts[chanpos]->dsp_features = 0;
10706                      }
10707                      /* Bring voice path up */
10708                      f.subclass = AST_CONTROL_PROGRESS;
10709                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10710                   }
10711                   pri->pvts[chanpos]->progress = 1;
10712                   pri->pvts[chanpos]->dialing = 0;
10713                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10714                }
10715             }
10716             break;
10717          case PRI_EVENT_PROCEEDING:
10718             chanpos = pri_find_principle(pri, e->proceeding.channel);
10719             if (chanpos > -1) {
10720                if (!pri->pvts[chanpos]->proceeding) {
10721                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10722                   
10723                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10724                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10725                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10726                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10727 #ifdef PRI_PROGRESS_MASK
10728                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10729 #else
10730                   if (e->proceeding.progress == 8) {
10731 #endif
10732                      /* Now we can do call progress detection */
10733                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10734                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10735                         pri->pvts[chanpos]->dsp_features = 0;
10736                      }
10737                      /* Bring voice path up */
10738                      f.subclass = AST_CONTROL_PROGRESS;
10739                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10740                   }
10741                   pri->pvts[chanpos]->proceeding = 1;
10742                   pri->pvts[chanpos]->dialing = 0;
10743                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10744                }
10745             }
10746             break;
10747          case PRI_EVENT_FACNAME:
10748             chanpos = pri_find_principle(pri, e->facname.channel);
10749             if (chanpos < 0) {
10750                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
10751                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10752             } else {
10753                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10754                if (chanpos < 0) {
10755                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
10756                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10757                } else {
10758                   /* Re-use *69 field for PRI */
10759                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10760                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10761                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10762                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10763                   dahdi_enable_ec(pri->pvts[chanpos]);
10764                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10765                }
10766             }
10767             break;            
10768          case PRI_EVENT_ANSWER:
10769             chanpos = pri_find_principle(pri, e->answer.channel);
10770             if (chanpos < 0) {
10771                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
10772                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10773             } else {
10774                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10775                if (chanpos < 0) {
10776                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
10777                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10778                } else {
10779                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10780                   /* Now we can do call progress detection */
10781 
10782                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
10783                    * By this time, we need DTMF detection and other features that were previously disabled
10784                    * -- Matt F */
10785                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10786                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10787                      pri->pvts[chanpos]->dsp_features = 0;
10788                   }
10789                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10790                      ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10791                      x = DAHDI_START;
10792                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10793                      if (res < 0) {
10794                         if (errno != EINPROGRESS) {
10795                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10796                         }
10797                      }
10798                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10799                      pri->pvts[chanpos]->dialing = 1;
10800                      /* Send any "w" waited stuff */
10801                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10802                      if (res < 0) {
10803                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10804                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10805                      } else 
10806                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10807                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10808                   } else if (pri->pvts[chanpos]->confirmanswer) {
10809                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10810                   } else {
10811                      pri->pvts[chanpos]->dialing = 0;
10812                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10813                      /* Enable echo cancellation if it's not on already */
10814                      dahdi_enable_ec(pri->pvts[chanpos]);
10815                   }
10816 
10817 #ifdef SUPPORT_USERUSER
10818                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
10819                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10820                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10821                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10822                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10823                   }
10824 #endif
10825 
10826                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10827                }
10828             }
10829             break;            
10830          case PRI_EVENT_HANGUP:
10831             chanpos = pri_find_principle(pri, e->hangup.channel);
10832             if (chanpos < 0) {
10833                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
10834                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10835             } else {
10836                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10837                if (chanpos > -1) {
10838                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10839                   if (!pri->pvts[chanpos]->alreadyhungup) {
10840                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
10841                      pri->pvts[chanpos]->alreadyhungup = 1;
10842                      if (pri->pvts[chanpos]->realcall) 
10843                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10844                      else if (pri->pvts[chanpos]->owner) {
10845                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
10846                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10847                         switch (pri->pvts[chanpos]->owner->_state) {
10848                         case AST_STATE_BUSY:
10849                         case AST_STATE_UP:
10850                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10851                            break;
10852                         default:
10853                            switch (e->hangup.cause) {
10854                               case PRI_CAUSE_USER_BUSY:
10855                                  pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10856                                  break;
10857                               case PRI_CAUSE_CALL_REJECTED:
10858                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10859                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10860                               case PRI_CAUSE_SWITCH_CONGESTION:
10861                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10862                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10863                                  pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10864                                  break;
10865                               default:
10866                                  pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10867                            }
10868                            break;
10869                         }
10870                      }
10871                      if (option_verbose > 2) 
10872                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
10873                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10874                   } else {
10875                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10876                      pri->pvts[chanpos]->call = NULL;
10877                   }
10878                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10879                      if (option_verbose > 2)
10880                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
10881                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10882                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10883                      pri->pvts[chanpos]->resetting = 1;
10884                   }
10885                   if (e->hangup.aoc_units > -1)
10886                      if (option_verbose > 2)
10887                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10888                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10889 
10890 #ifdef SUPPORT_USERUSER
10891                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10892                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10893                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10894                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10895                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10896                   }
10897 #endif
10898 
10899                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10900                } else {
10901                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
10902                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10903                }
10904             } 
10905             break;
10906 #ifndef PRI_EVENT_HANGUP_REQ
10907 #error please update libpri
10908 #endif
10909          case PRI_EVENT_HANGUP_REQ:
10910             chanpos = pri_find_principle(pri, e->hangup.channel);
10911             if (chanpos < 0) {
10912                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
10913                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10914             } else {
10915                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10916                if (chanpos > -1) {
10917                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10918                   if (pri->pvts[chanpos]->realcall) 
10919                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10920                   else if (pri->pvts[chanpos]->owner) {
10921                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10922                      switch (pri->pvts[chanpos]->owner->_state) {
10923                      case AST_STATE_BUSY:
10924                      case AST_STATE_UP:
10925                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10926                         break;
10927                      default:
10928                         switch (e->hangup.cause) {
10929                            case PRI_CAUSE_USER_BUSY:
10930                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10931                               break;
10932                            case PRI_CAUSE_CALL_REJECTED:
10933                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10934                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10935                            case PRI_CAUSE_SWITCH_CONGESTION:
10936                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10937                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10938                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10939                               break;
10940                            default:
10941                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10942                         }
10943                         break;
10944                      }
10945                      if (option_verbose > 2) 
10946                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
10947                      if (e->hangup.aoc_units > -1)
10948                         if (option_verbose > 2)
10949                            ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10950                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10951                   } else {
10952                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10953                      pri->pvts[chanpos]->call = NULL;
10954                   }
10955                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10956                      if (option_verbose > 2)
10957                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
10958                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10959                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10960                      pri->pvts[chanpos]->resetting = 1;
10961                   }
10962 
10963 #ifdef SUPPORT_USERUSER
10964                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
10965                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10966                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10967                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10968                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10969                   }
10970 #endif
10971 
10972                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10973                } else {
10974                   ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10975                }
10976             } 
10977             break;
10978          case PRI_EVENT_HANGUP_ACK:
10979             chanpos = pri_find_principle(pri, e->hangup.channel);
10980             if (chanpos < 0) {
10981                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
10982                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10983             } else {
10984                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10985                if (chanpos > -1) {
10986                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10987                   pri->pvts[chanpos]->call = NULL;
10988                   pri->pvts[chanpos]->resetting = 0;
10989                   if (pri->pvts[chanpos]->owner) {
10990                      if (option_verbose > 2) 
10991                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10992                   }
10993 
10994 #ifdef SUPPORT_USERUSER
10995                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
10996                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10997                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10998                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10999                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11000                   }
11001 #endif
11002 
11003                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11004                }
11005             }
11006             break;
11007          case PRI_EVENT_CONFIG_ERR:
11008             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11009             break;
11010          case PRI_EVENT_RESTART_ACK:
11011             chanpos = pri_find_principle(pri, e->restartack.channel);
11012             if (chanpos < 0) {
11013                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11014                   channel number, so we have to figure it out...  This must be why
11015                   everybody resets exactly a channel at a time. */
11016                for (x = 0; x < pri->numchans; x++) {
11017                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
11018                      chanpos = x;
11019                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11020                      ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
11021                            pri->pvts[chanpos]->prioffset, pri->span);
11022                      if (pri->pvts[chanpos]->realcall) 
11023                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11024                      else if (pri->pvts[chanpos]->owner) {
11025                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
11026                            pri->pvts[chanpos]->prioffset, pri->span);
11027                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11028                      }
11029                      pri->pvts[chanpos]->resetting = 0;
11030                      if (option_verbose > 2)
11031                         ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
11032                            pri->pvts[chanpos]->prioffset, pri->span);
11033                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11034                      if (pri->resetting)
11035                         pri_check_restart(pri);
11036                      break;
11037                   }
11038                }
11039                if (chanpos < 0) {
11040                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
11041                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11042                }
11043             } else {
11044                if (pri->pvts[chanpos]) {
11045                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11046                   if (pri->pvts[chanpos]->realcall) 
11047                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11048                   else if (pri->pvts[chanpos]->owner) {
11049                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11050                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11051                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11052                   }
11053                   pri->pvts[chanpos]->resetting = 0;
11054                   if (option_verbose > 2)
11055                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
11056                            pri->pvts[chanpos]->prioffset, pri->span);
11057                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11058                   if (pri->resetting)
11059                      pri_check_restart(pri);
11060                }
11061             }
11062             break;
11063          case PRI_EVENT_SETUP_ACK:
11064             chanpos = pri_find_principle(pri, e->setup_ack.channel);
11065             if (chanpos < 0) {
11066                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
11067                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11068             } else {
11069                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11070                if (chanpos > -1) {
11071                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11072                   pri->pvts[chanpos]->setup_ack = 1;
11073                   /* Send any queued digits */
11074                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11075                      ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11076                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
11077                         pri->pvts[chanpos]->dialdest[x]);
11078                   }
11079                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11080                } else
11081                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11082             }
11083             break;
11084          case PRI_EVENT_NOTIFY:
11085             chanpos = pri_find_principle(pri, e->notify.channel);
11086             if (chanpos < 0) {
11087                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11088                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11089             } else {
11090                struct ast_frame f = { AST_FRAME_CONTROL, };
11091                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11092                switch (e->notify.info) {
11093                case PRI_NOTIFY_REMOTE_HOLD:
11094                   f.subclass = AST_CONTROL_HOLD;
11095                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11096                   break;
11097                case PRI_NOTIFY_REMOTE_RETRIEVAL:
11098                   f.subclass = AST_CONTROL_UNHOLD;
11099                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11100                   break;
11101                }
11102                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11103             }
11104             break;
11105          default:
11106             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
11107          }
11108       }  
11109       ast_mutex_unlock(&pri->lock);
11110    }
11111    /* Never reached */
11112    return NULL;
11113 }
11114 
11115 static int start_pri(struct dahdi_pri *pri)
11116 {
11117    int res, x;
11118    struct dahdi_params p;
11119    struct dahdi_bufferinfo bi;
11120    struct dahdi_spaninfo si;
11121    int i;
11122    
11123    for (i = 0; i < NUM_DCHANS; i++) {
11124       if (!pri->dchannels[i])
11125          break;
11126       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11127       x = pri->dchannels[i];
11128       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11129          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11130          return -1;
11131       }
11132       memset(&p, 0, sizeof(p));
11133       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11134       if (res) {
11135          dahdi_close_pri_fd(pri, i);
11136          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11137          return -1;
11138       }
11139       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11140          dahdi_close_pri_fd(pri, i);
11141          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
11142          return -1;
11143       }
11144       memset(&si, 0, sizeof(si));
11145       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11146       if (res) {
11147          dahdi_close_pri_fd(pri, i);
11148          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11149       }
11150       if (!si.alarms)
11151          pri->dchanavail[i] |= DCHAN_NOTINALARM;
11152       else
11153          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11154       memset(&bi, 0, sizeof(bi));
11155       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11156       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11157       bi.numbufs = 32;
11158       bi.bufsize = 1024;
11159       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11160          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11161          dahdi_close_pri_fd(pri, i);
11162          return -1;
11163       }
11164       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11165       /* Force overlap dial if we're doing GR-303! */
11166       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11167          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11168       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11169 #ifdef HAVE_PRI_INBANDDISCONNECT
11170       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11171 #endif
11172       /* Enslave to master if appropriate */
11173       if (i)
11174          pri_enslave(pri->dchans[0], pri->dchans[i]);
11175       if (!pri->dchans[i]) {
11176          dahdi_close_pri_fd(pri, i);
11177          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11178          return -1;
11179       }
11180       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11181       pri_set_nsf(pri->dchans[i], pri->nsf);
11182 #ifdef PRI_GETSET_TIMERS
11183       for (x = 0; x < PRI_MAX_TIMERS; x++) {
11184          if (pritimers[x] != 0)
11185             pri_set_timer(pri->dchans[i], x, pritimers[x]);
11186       }
11187 #endif
11188    }
11189    /* Assume primary is the one we use */
11190    pri->pri = pri->dchans[0];
11191    pri->resetpos = -1;
11192    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11193       for (i = 0; i < NUM_DCHANS; i++) {
11194          if (!pri->dchannels[i])
11195             break;
11196          dahdi_close_pri_fd(pri, i);
11197       }
11198       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11199       return -1;
11200    }
11201    return 0;
11202 }
11203 
11204 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11205 {
11206    int which, span;
11207    char *ret = NULL;
11208 
11209    if (pos != rpos)
11210       return ret;
11211 
11212    for (which = span = 0; span < NUM_SPANS; span++) {
11213       if (pris[span].pri && ++which > state) {
11214          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
11215             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11216          }
11217          break;
11218       }
11219    }
11220    return ret;
11221 }
11222 
11223 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11224 {
11225    return complete_span_helper(line,word,pos,state,3);
11226 }
11227 
11228 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11229 {
11230    return complete_span_helper(line,word,pos,state,4);
11231 }
11232 
11233 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
11234 {
11235    int myfd;
11236 
11237    if (!strncasecmp(argv[1], "set", 3)) {
11238       if (argc < 5) 
11239          return RESULT_SHOWUSAGE;
11240 
11241       if (ast_strlen_zero(argv[4]))
11242          return RESULT_SHOWUSAGE;
11243 
11244       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11245       if (myfd < 0) {
11246          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11247          return RESULT_SUCCESS;
11248       }
11249 
11250       ast_mutex_lock(&pridebugfdlock);
11251 
11252       if (pridebugfd >= 0)
11253          close(pridebugfd);
11254 
11255       pridebugfd = myfd;
11256       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11257       
11258       ast_mutex_unlock(&pridebugfdlock);
11259 
11260       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11261    } else {
11262       /* Assume it is unset */
11263       ast_mutex_lock(&pridebugfdlock);
11264       close(pridebugfd);
11265       pridebugfd = -1;
11266       ast_cli(fd, "PRI debug output to file disabled\n");
11267       ast_mutex_unlock(&pridebugfdlock);
11268    }
11269 
11270    return RESULT_SUCCESS;
11271 }
11272 
11273 #ifdef HAVE_PRI_VERSION
11274 static int handle_pri_version(int fd, int agc, char *argv[]) {
11275    ast_cli(fd, "libpri version: %s\n", pri_get_version());
11276    return RESULT_SUCCESS;
11277 }
11278 #endif
11279 
11280 static int handle_pri_debug(int fd, int argc, char *argv[])
11281 {
11282    int span;
11283    int x;
11284    if (argc < 4) {
11285       return RESULT_SHOWUSAGE;
11286    }
11287    span = atoi(argv[3]);
11288    if ((span < 1) || (span > NUM_SPANS)) {
11289       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11290       return RESULT_SUCCESS;
11291    }
11292    if (!pris[span-1].pri) {
11293       ast_cli(fd, "No PRI running on span %d\n", span);
11294       return RESULT_SUCCESS;
11295    }
11296    for (x = 0; x < NUM_DCHANS; x++) {
11297       if (pris[span-1].dchans[x])
11298          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11299                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11300                                                PRI_DEBUG_Q921_STATE);
11301    }
11302    ast_cli(fd, "Enabled debugging on span %d\n", span);
11303    return RESULT_SUCCESS;
11304 }
11305 
11306 
11307 
11308 static int handle_pri_no_debug(int fd, int argc, char *argv[])
11309 {
11310    int span;
11311    int x;
11312    if (argc < 5)
11313       return RESULT_SHOWUSAGE;
11314    span = atoi(argv[4]);
11315    if ((span < 1) || (span > NUM_SPANS)) {
11316       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11317       return RESULT_SUCCESS;
11318    }
11319    if (!pris[span-1].pri) {
11320       ast_cli(fd, "No PRI running on span %d\n", span);
11321       return RESULT_SUCCESS;
11322    }
11323    for (x = 0; x < NUM_DCHANS; x++) {
11324       if (pris[span-1].dchans[x])
11325          pri_set_debug(pris[span-1].dchans[x], 0);
11326    }
11327    ast_cli(fd, "Disabled debugging on span %d\n", span);
11328    return RESULT_SUCCESS;
11329 }
11330 
11331 static int handle_pri_really_debug(int fd, int argc, char *argv[])
11332 {
11333    int span;
11334    int x;
11335    if (argc < 5)
11336       return RESULT_SHOWUSAGE;
11337    span = atoi(argv[4]);
11338    if ((span < 1) || (span > NUM_SPANS)) {
11339       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11340       return RESULT_SUCCESS;
11341    }
11342    if (!pris[span-1].pri) {
11343       ast_cli(fd, "No PRI running on span %d\n", span);
11344       return RESULT_SUCCESS;
11345    }
11346    for (x = 0; x < NUM_DCHANS; x++) {
11347       if (pris[span-1].dchans[x])
11348          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11349                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11350                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11351    }
11352    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11353    return RESULT_SUCCESS;
11354 }
11355 
11356 static void build_status(char *s, size_t len, int status, int active)
11357 {
11358    if (!s || len < 1) {
11359       return;
11360    }
11361    s[0] = '\0';
11362    if (status & DCHAN_PROVISIONED)
11363       strncat(s, "Provisioned, ", len - strlen(s) - 1);
11364    if (!(status & DCHAN_NOTINALARM))
11365       strncat(s, "In Alarm, ", len - strlen(s) - 1);
11366    if (status & DCHAN_UP)
11367       strncat(s, "Up", len - strlen(s) - 1);
11368    else
11369       strncat(s, "Down", len - strlen(s) - 1);
11370    if (active)
11371       strncat(s, ", Active", len - strlen(s) - 1);
11372    else
11373       strncat(s, ", Standby", len - strlen(s) - 1);
11374    s[len - 1] = '\0';
11375 }
11376 
11377 static int handle_pri_show_spans(int fd, int argc, char *argv[])
11378 {
11379    int span;
11380    int x;
11381    char status[256];
11382    if (argc != 3)
11383       return RESULT_SHOWUSAGE;
11384 
11385    for (span = 0; span < NUM_SPANS; span++) {
11386       if (pris[span].pri) {
11387          for (x = 0; x < NUM_DCHANS; x++) {
11388             if (pris[span].dchannels[x]) {
11389                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11390                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11391             }
11392          }
11393       }
11394    }
11395    return RESULT_SUCCESS;
11396 }
11397 
11398 static int handle_pri_show_span(int fd, int argc, char *argv[])
11399 {
11400    int span;
11401    int x;
11402    char status[256];
11403    if (argc < 4)
11404       return RESULT_SHOWUSAGE;
11405    span = atoi(argv[3]);
11406    if ((span < 1) || (span > NUM_SPANS)) {
11407       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11408       return RESULT_SUCCESS;
11409    }
11410    if (!pris[span-1].pri) {
11411       ast_cli(fd, "No PRI running on span %d\n", span);
11412       return RESULT_SUCCESS;
11413    }
11414    for (x = 0; x < NUM_DCHANS; x++) {
11415       if (pris[span-1].dchannels[x]) {
11416 #ifdef PRI_DUMP_INFO_STR
11417          char *info_str = NULL;
11418 #endif
11419          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11420          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11421          ast_cli(fd, "Status: %s\n", status);
11422 #ifdef PRI_DUMP_INFO_STR
11423          info_str = pri_dump_info_str(pris[span-1].pri);
11424          if (info_str) {
11425             ast_cli(fd, "%s", info_str);
11426             free(info_str);
11427          }
11428 #else
11429          pri_dump_info(pris[span-1].pri);
11430 #endif
11431          ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11432       }
11433    }
11434    return RESULT_SUCCESS;
11435 }
11436 
11437 static int handle_pri_show_debug(int fd, int argc, char *argv[])
11438 {
11439    int x;
11440    int span;
11441    int count=0;
11442    int debug=0;
11443 
11444    for (span = 0; span < NUM_SPANS; span++) {
11445            if (pris[span].pri) {
11446          for (x = 0; x < NUM_DCHANS; x++) {
11447             debug = 0;
11448                if (pris[span].dchans[x]) {
11449                   debug = pri_get_debug(pris[span].dchans[x]);
11450                ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
11451                count++;
11452             }
11453          }
11454       }
11455 
11456    }
11457    ast_mutex_lock(&pridebugfdlock);
11458    if (pridebugfd >= 0) 
11459       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11460    ast_mutex_unlock(&pridebugfdlock);
11461        
11462    if (!count) 
11463       ast_cli(fd, "No debug set or no PRI running\n");
11464    return RESULT_SUCCESS;
11465 }
11466 
11467 static const char pri_debug_help[] = 
11468    "Usage: pri debug span <span>\n"
11469    "       Enables debugging on a given PRI span\n";
11470    
11471 static const char pri_no_debug_help[] = 
11472    "Usage: pri no debug span <span>\n"
11473    "       Disables debugging on a given PRI span\n";
11474 
11475 static const char pri_really_debug_help[] = 
11476    "Usage: pri intensive debug span <span>\n"
11477    "       Enables debugging down to the Q.921 level\n";
11478 
11479 static const char pri_show_span_help[] = 
11480    "Usage: pri show span <span>\n"
11481    "       Displays PRI Information on a given PRI span\n";
11482 
11483 static const char pri_show_spans_help[] = 
11484    "Usage: pri show spans\n"
11485    "       Displays PRI Information\n";
11486 
11487 static struct ast_cli_entry dahdi_pri_cli[] = {
11488    { { "pri", "debug", "span", NULL },
11489    handle_pri_debug, "Enables PRI debugging on a span",
11490    pri_debug_help, complete_span_4 },
11491 
11492    { { "pri", "no", "debug", "span", NULL },
11493    handle_pri_no_debug, "Disables PRI debugging on a span",
11494    pri_no_debug_help, complete_span_5 },
11495 
11496    { { "pri", "intense", "debug", "span", NULL },
11497    handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
11498    pri_really_debug_help, complete_span_5 },
11499 
11500    { { "pri", "show", "spans", NULL },
11501    handle_pri_show_spans, "Displays PRI Information",
11502    pri_show_spans_help },
11503 
11504    { { "pri", "show", "span", NULL },
11505    handle_pri_show_span, "Displays PRI Information",
11506    pri_show_span_help, complete_span_4 },
11507 
11508    { { "pri", "show", "debug", NULL },
11509    handle_pri_show_debug, "Displays current PRI debug settings" },
11510 
11511    { { "pri", "set", "debug", "file", NULL },
11512    handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
11513 
11514    { { "pri", "unset", "debug", "file", NULL },
11515    handle_pri_set_debug_file, "Ends PRI debug output to file" },
11516 
11517 #ifdef HAVE_PRI_VERSION
11518    { { "pri", "show", "version", NULL },
11519    handle_pri_version, "Displays version of libpri" },
11520 #endif
11521 };
11522 
11523 #endif /* HAVE_PRI */
11524 
11525 #ifdef HAVE_OPENR2
11526 
11527 static int handle_mfcr2_version(int fd, int argc, char *argv[])
11528 {
11529    ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11530    return RESULT_SUCCESS;
11531 }
11532 
11533 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[]) 
11534 {
11535 #define FORMAT "%4s %40s\n"
11536    int numvariants = 0;
11537    int i;
11538    const openr2_variant_entry_t *variants;
11539    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11540       ast_cli(fd, "Failed to get list of variants.\n");
11541       return RESULT_FAILURE;
11542    }
11543    ast_cli(fd, FORMAT, "Variant Code", "Country");
11544    for (i = 0; i < numvariants; i++) {
11545       ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11546    }
11547    return RESULT_SUCCESS;
11548 #undef FORMAT
11549 }  
11550 
11551 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
11552 {
11553 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11554    int filtertype = 0;
11555    int targetnum = 0;
11556    char channo[5];
11557    char anino[5];
11558    char dnisno[5];
11559    struct dahdi_pvt *p;
11560    openr2_context_t *r2context;
11561    openr2_variant_t r2variant;
11562    if (!((argc == 3) || (argc == 5))) {
11563       return RESULT_SHOWUSAGE;
11564    }
11565    if (argc == 5) {
11566       if (!strcasecmp(argv[3], "group")) {
11567          targetnum = atoi(argv[4]);
11568          if ((targetnum < 0) || (targetnum > 63))
11569             return RESULT_SHOWUSAGE;
11570          targetnum = 1 << targetnum;
11571          filtertype = 1;
11572       } else if (!strcasecmp(argv[3], "context")) {
11573          filtertype = 2;
11574       } else {
11575          return RESULT_SHOWUSAGE;
11576       }
11577    }
11578    ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11579    ast_mutex_lock(&iflock);
11580    p = iflist;
11581    while (p) {
11582       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11583          p = p->next;
11584          continue;
11585       }
11586       if (filtertype) {
11587          switch(filtertype) {
11588          case 1: /* mfcr2 show channels group <group> */
11589             if (p->group != targetnum) {
11590                p = p->next;
11591                continue;
11592             }
11593             break;
11594          case 2: /* mfcr2 show channels context <context> */
11595             if (strcasecmp(p->context, argv[4])) {
11596                p= p->next;
11597                continue;
11598             }
11599             break;
11600          default:
11601             ;
11602          }
11603       }
11604       r2context = openr2_chan_get_context(p->r2chan);
11605       r2variant = openr2_context_get_variant(r2context);
11606       snprintf(channo, sizeof(channo), "%d", p->channel);
11607       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11608       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11609       ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 
11610             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",  
11611             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11612             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11613       p = p->next;
11614    }
11615    ast_mutex_unlock(&iflock);
11616    return RESULT_SUCCESS;
11617 #undef FORMAT
11618 }
11619 
11620 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
11621 {
11622    struct dahdi_pvt *p = NULL;
11623    int channo = 0;
11624    char *toklevel = NULL;
11625    char *saveptr = NULL;
11626    char *logval = NULL;
11627    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11628    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11629    if (argc < 4) {
11630       return RESULT_SHOWUSAGE;
11631    }
11632    channo = (argc == 5) ? atoi(argv[4]) : -1;
11633    logval = ast_strdupa(argv[3]);
11634    toklevel = strtok_r(logval, ",", &saveptr);
11635    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11636       ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11637       return RESULT_FAILURE;
11638    } else if (OR2_LOG_NOTHING == tmplevel) {
11639       loglevel = tmplevel;
11640    } else {
11641       loglevel |= tmplevel;
11642       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11643          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11644             ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11645             continue;
11646          }
11647          loglevel |= tmplevel;
11648       }
11649    }
11650    ast_mutex_lock(&iflock);
11651    p = iflist;
11652    while (p) {
11653       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11654          p = p->next;
11655          continue;
11656       }
11657       if ((channo != -1) && (p->channel != channo )) {
11658          p = p->next;
11659          continue;
11660       }
11661       openr2_chan_set_log_level(p->r2chan, loglevel);
11662       if (channo != -1) {
11663          ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11664          break;
11665       } else {
11666          p = p->next;
11667       }
11668    }
11669    if ((channo != -1) && !p) {
11670       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11671    }
11672    if (channo == -1) {
11673       ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11674    }
11675    ast_mutex_unlock(&iflock);
11676    return RESULT_SUCCESS;
11677 }
11678 
11679 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
11680 {
11681    struct dahdi_pvt *p = NULL;
11682    int channo = 0;
11683    if (argc < 4) {
11684       return RESULT_SHOWUSAGE;
11685    }
11686    channo = (argc == 5) ? atoi(argv[4]) : -1;
11687    ast_mutex_lock(&iflock);
11688    p = iflist;
11689    while (p) {
11690       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11691          p = p->next;
11692          continue;
11693       }
11694       if ((channo != -1) && (p->channel != channo )) {
11695          p = p->next;
11696          continue;
11697       }
11698       if (ast_true(argv[3])) {
11699          openr2_chan_enable_call_files(p->r2chan);
11700       } else {
11701          openr2_chan_disable_call_files(p->r2chan);
11702       }
11703       if (channo != -1) {
11704          if (ast_true(argv[3])) {
11705             ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11706          } else {
11707             ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11708          }
11709          break;
11710       } else {
11711          p = p->next;
11712       }
11713    }
11714    if ((channo != -1) && !p) {
11715       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11716    }
11717    if (channo == -1) {
11718       if (ast_true(argv[3])) {
11719          ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11720       } else {
11721          ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11722       }  
11723    }
11724    ast_mutex_unlock(&iflock);
11725    return RESULT_SUCCESS;
11726 }  
11727 
11728 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
11729 {
11730    struct dahdi_pvt *p = NULL;
11731    int channo = 0;
11732    channo = (argc == 4) ? atoi(argv[3]) : -1;
11733    ast_mutex_lock(&iflock);
11734    p = iflist;
11735    while (p) {
11736       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11737          p = p->next;
11738          continue;
11739       }
11740       if ((channo != -1) && (p->channel != channo )) {
11741          p = p->next;
11742          continue;
11743       }
11744       if (!openr2_chan_set_idle(p->r2chan)) {
11745          ast_mutex_lock(&p->lock);
11746          p->mfcr2call = 0;
11747          p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11748          ast_mutex_unlock(&p->lock);
11749       }
11750       if (channo != -1) {
11751          break;
11752       } else {
11753          p = p->next;
11754       }
11755    }
11756    if ((channo != -1) && !p) {
11757       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11758    }
11759    ast_mutex_unlock(&iflock);
11760    return RESULT_SUCCESS;
11761 }
11762 
11763 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
11764 {
11765    struct dahdi_pvt *p = NULL;
11766    int channo = 0;
11767    channo = (argc == 4) ? atoi(argv[3]) : -1;
11768    ast_mutex_lock(&iflock);
11769    p = iflist;
11770    while (p) {
11771       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11772          p = p->next;
11773          continue;
11774       }
11775       if ((channo != -1) && (p->channel != channo )) {
11776          p = p->next;
11777          continue;
11778       }
11779       if (!openr2_chan_set_blocked(p->r2chan)) {
11780          ast_mutex_lock(&p->lock);
11781          p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11782          ast_mutex_unlock(&p->lock);
11783       } else {
11784          ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11785       }
11786       if (channo != -1) {
11787          break;
11788       } else {
11789          p = p->next;
11790       }
11791    }
11792    if ((channo != -1) && !p) {
11793       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11794    }
11795    ast_mutex_unlock(&iflock);
11796    return RESULT_SUCCESS;
11797 }
11798 
11799 static const char dahdi_r2_version_help[] = 
11800          "Usage: mfcr2 show version\n"
11801          "       Shows the version of the OpenR2 library being used.\n";
11802 static const char dahdi_r2_variants_help[] = 
11803          "Usage: mfcr2 show variants\n"
11804          "       Show supported MFC/R2 variants.\n";
11805 static const char dahdi_r2_showchannels_help[] =
11806          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
11807          "       Shows the zap channels configured with MFC/R2 signaling.\n";
11808 static const char dahdi_r2_setdebug_help[] =
11809          "Usage: mfcr2 set debug <loglevel> <channel>\n"
11810          "       Set a new logging level for the specified channel.\n"
11811          "       If no channel is specified the logging level will be applied to all channels.\n";
11812 static const char dahdi_r2_callfiles_help[] =
11813          "Usage: mfcr2 call files [on|off] <channel>\n"
11814          "       Enable call files creation on the specified channel.\n"
11815          "       If no channel is specified call files creation policy will be applied to all channels.\n";
11816 static const char dahdi_r2_setidle_help[] =
11817          "Usage: mfcr2 set idle <channel>\n"
11818          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11819          "       Force the given channel into IDLE state.\n"
11820          "       If no channel is specified, all channels will be set to IDLE.\n";
11821 static const char dahdi_r2_setblocked_help[] =
11822          "Usage: mfcr2 set blocked <channel>\n"
11823          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11824          "       Force the given channel into BLOCKED state.\n"
11825          "       If no channel is specified, all channels will be set to BLOCKED.\n";
11826 
11827 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
11828    { { "mfcr2", "show", "version", NULL },
11829    handle_mfcr2_version, "Show OpenR2 library version",
11830    dahdi_r2_version_help },
11831 
11832    { { "mfcr2", "show", "variants", NULL },
11833    handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
11834    dahdi_r2_variants_help },
11835 
11836    { { "mfcr2", "show", "channels", NULL },
11837    handle_mfcr2_show_channels, "Show MFC/R2 channels",
11838    dahdi_r2_showchannels_help },
11839 
11840    { { "mfcr2", "set", "debug", NULL },
11841    handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
11842    dahdi_r2_setdebug_help },
11843 
11844    { { "mfcr2", "call", "files", NULL },
11845    handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
11846    dahdi_r2_callfiles_help },
11847 
11848    { { "mfcr2", "set", "idle", NULL },
11849    handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
11850    dahdi_r2_setidle_help },
11851 
11852    { { "mfcr2", "set", "blocked", NULL },
11853    handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
11854    dahdi_r2_setblocked_help }
11855 
11856 };
11857 
11858 #endif /* HAVE_OPENR2 */
11859 
11860 static int dahdi_destroy_channel(int fd, int argc, char **argv)
11861 {
11862    int channel;
11863    
11864    if (argc != 4)
11865       return RESULT_SHOWUSAGE;
11866    
11867    channel = atoi(argv[3]);
11868 
11869    return dahdi_destroy_channel_bynum(channel);
11870 }
11871 
11872 static void dahdi_softhangup_all(void)
11873 {
11874    struct dahdi_pvt *p;
11875 retry:
11876    ast_mutex_lock(&iflock);
11877     for (p = iflist; p; p = p->next) {
11878       ast_mutex_lock(&p->lock);
11879         if (p->owner && !p->restartpending) {
11880          if (ast_channel_trylock(p->owner)) {
11881             if (option_debug > 2)
11882                ast_verbose("Avoiding deadlock\n");
11883             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11884             ast_mutex_unlock(&p->lock);
11885             ast_mutex_unlock(&iflock);
11886             goto retry;
11887          }
11888          if (option_debug > 2)
11889             ast_verbose("Softhanging up on %s\n", p->owner->name);
11890          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11891          p->restartpending = 1;
11892          num_restart_pending++;
11893          ast_channel_unlock(p->owner);
11894       }
11895       ast_mutex_unlock(&p->lock);
11896     }
11897    ast_mutex_unlock(&iflock);
11898 }
11899 
11900 static int setup_dahdi(int reload);
11901 static int dahdi_restart(void)
11902 {
11903 #ifdef HAVE_OPENR2
11904    int r;
11905 #endif
11906 #if defined(HAVE_PRI)
11907    int i, j;
11908 #endif
11909    int cancel_code;
11910    struct dahdi_pvt *p;
11911 
11912    ast_mutex_lock(&restart_lock);
11913  
11914    if (option_verbose)
11915       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11916    dahdi_softhangup_all();
11917    if (option_verbose > 3)
11918       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11919 
11920 #ifdef HAVE_OPENR2
11921    for (r = 0; r < NUM_SPANS; r++) {
11922       if (r2links[r].master != AST_PTHREADT_NULL) {
11923          ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
11924          pthread_cancel(r2links[r].master);
11925          pthread_join(r2links[r].master, NULL);
11926          openr2_context_delete(r2links[r].protocol_context);
11927       }
11928    }
11929    init_mfcr2_globals();
11930 #endif
11931 
11932    #if defined(HAVE_PRI)
11933    for (i = 0; i < NUM_SPANS; i++) {
11934       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11935          cancel_code = pthread_cancel(pris[i].master);
11936          pthread_kill(pris[i].master, SIGURG);
11937          if (option_debug > 3)
11938             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
11939             pthread_join(pris[i].master, NULL);
11940          if (option_debug > 3)
11941             ast_verbose("Joined thread of span %d\n", i);
11942       }
11943     }
11944    #endif
11945 
11946     ast_mutex_lock(&monlock);
11947     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11948       cancel_code = pthread_cancel(monitor_thread);
11949       pthread_kill(monitor_thread, SIGURG);
11950       if (option_debug > 3)
11951          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
11952         pthread_join(monitor_thread, NULL);
11953       if (option_debug > 3)
11954          ast_verbose("Joined monitor thread\n");
11955     }
11956    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
11957 
11958    ast_mutex_lock(&ss_thread_lock);
11959    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
11960       int x = DAHDI_FLASH;
11961       if (option_debug > 2)
11962          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
11963 
11964       for (p = iflist; p; p = p->next) {
11965          if (p->owner)
11966             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */    
11967       }
11968       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
11969    }
11970 
11971    /* ensure any created channels before monitor threads were stopped are hungup */
11972    dahdi_softhangup_all();
11973    if (option_verbose > 3)
11974       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
11975    destroy_all_channels();
11976    if (option_debug)
11977       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
11978 
11979     ast_mutex_unlock(&monlock);
11980 
11981    #ifdef HAVE_PRI
11982    for (i = 0; i < NUM_SPANS; i++) {
11983       for (j = 0; j < NUM_DCHANS; j++)
11984             dahdi_close_pri_fd(&(pris[i]), j);
11985    }
11986 
11987    memset(pris, 0, sizeof(pris));
11988    for (i = 0; i < NUM_SPANS; i++) {
11989       ast_mutex_init(&pris[i].lock);
11990       pris[i].offset = -1;
11991       pris[i].master = AST_PTHREADT_NULL;
11992       for (j = 0; j < NUM_DCHANS; j++)
11993          pris[i].fds[j] = -1;
11994    }
11995    pri_set_error(dahdi_pri_error);
11996    pri_set_message(dahdi_pri_message);
11997    #endif
11998 
11999    if (setup_dahdi(2) != 0) {
12000       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12001       ast_mutex_unlock(&ss_thread_lock);
12002       return 1;
12003    }
12004    ast_mutex_unlock(&ss_thread_lock);
12005    ast_mutex_unlock(&restart_lock);
12006    return 0;
12007 }
12008 
12009 static int dahdi_restart_cmd(int fd, int argc, char **argv)
12010 {
12011    if (argc != 2) {
12012       return RESULT_SHOWUSAGE;
12013    }
12014 
12015    if (dahdi_restart() != 0)
12016       return RESULT_FAILURE;
12017    return RESULT_SUCCESS;
12018 }
12019 
12020 static int dahdi_show_channels(int fd, int argc, char **argv)
12021 {
12022 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12023 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12024    struct dahdi_pvt *tmp = NULL;
12025    char tmps[20] = "";
12026    ast_mutex_t *lock;
12027    struct dahdi_pvt *start;
12028 #ifdef HAVE_PRI
12029    int trunkgroup;
12030    struct dahdi_pri *pri = NULL;
12031    int x;
12032 #endif
12033 
12034    lock = &iflock;
12035    start = iflist;
12036 
12037 #ifdef HAVE_PRI
12038    if (argc == 4) {
12039       if ((trunkgroup = atoi(argv[3])) < 1)
12040          return RESULT_SHOWUSAGE;
12041       for (x = 0; x < NUM_SPANS; x++) {
12042          if (pris[x].trunkgroup == trunkgroup) {
12043             pri = pris + x;
12044             break;
12045          }
12046       }
12047       if (pri) {
12048          start = pri->crvs;
12049          lock = &pri->lock;
12050       } else {
12051          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12052          return RESULT_FAILURE;
12053       }
12054    } else
12055 #endif
12056    if (argc != 3)
12057       return RESULT_SHOWUSAGE;
12058 
12059    ast_mutex_lock(lock);
12060 #ifdef HAVE_PRI
12061    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12062 #else
12063    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12064 #endif   
12065    
12066    tmp = start;
12067    while (tmp) {
12068       if (tmp->channel > 0) {
12069          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12070       } else
12071          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12072       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12073       tmp = tmp->next;
12074    }
12075    ast_mutex_unlock(lock);
12076    return RESULT_SUCCESS;
12077 #undef FORMAT
12078 #undef FORMAT2
12079 }
12080 
12081 static int dahdi_show_channel(int fd, int argc, char **argv)
12082 {
12083    int channel;
12084    struct dahdi_pvt *tmp = NULL;
12085    struct dahdi_confinfo ci;
12086    struct dahdi_params ps;
12087    int x;
12088    ast_mutex_t *lock;
12089    struct dahdi_pvt *start;
12090 #ifdef HAVE_PRI
12091    char *c;
12092    int trunkgroup;
12093    struct dahdi_pri *pri=NULL;
12094 #endif
12095 
12096    lock = &iflock;
12097    start = iflist;
12098 
12099    if (argc != 4)
12100       return RESULT_SHOWUSAGE;
12101 #ifdef HAVE_PRI
12102    if ((c = strchr(argv[3], ':'))) {
12103       if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12104          return RESULT_SHOWUSAGE;
12105       if ((trunkgroup < 1) || (channel < 1))
12106          return RESULT_SHOWUSAGE;
12107       for (x = 0; x < NUM_SPANS; x++) {
12108          if (pris[x].trunkgroup == trunkgroup) {
12109             pri = pris + x;
12110             break;
12111          }
12112       }
12113       if (pri) {
12114          start = pri->crvs;
12115          lock = &pri->lock;
12116       } else {
12117          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12118          return RESULT_FAILURE;
12119       }
12120    } else
12121 #endif
12122       channel = atoi(argv[3]);
12123 
12124    ast_mutex_lock(lock);
12125    tmp = start;
12126    while (tmp) {
12127       if (tmp->channel == channel) {
12128 #ifdef HAVE_PRI
12129          if (pri) 
12130             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12131          else
12132 #endif         
12133          ast_cli(fd, "Channel: %d\n", tmp->channel);
12134          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12135          ast_cli(fd, "Span: %d\n", tmp->span);
12136          ast_cli(fd, "Extension: %s\n", tmp->exten);
12137          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12138          ast_cli(fd, "Context: %s\n", tmp->context);
12139          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12140          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12141          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12142          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12143          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12144          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12145          ast_cli(fd, "Radio: %d\n", tmp->radio);
12146          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12147          ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
12148          ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
12149          ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
12150          ast_cli(fd, "Confno: %d\n", tmp->confno);
12151          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12152          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12153          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12154          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12155          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12156          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12157          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12158          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12159          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12160          if (tmp->master)
12161             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12162          for (x = 0; x < MAX_SLAVES; x++) {
12163             if (tmp->slaves[x])
12164                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12165          }
12166 #ifdef HAVE_OPENR2
12167          if (tmp->mfcr2) {
12168             char calldir[OR2_MAX_PATH];
12169             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12170             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12171             ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12172             ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12173             ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12174             ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12175             ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12176             ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12177             ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12178             ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12179             ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12180             ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12181 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12182             ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12183             ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12184 #endif
12185             ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12186             ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12187             ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12188             ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12189             ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12190             ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12191             ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12192             ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12193             ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12194             ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12195             ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12196             ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12197             ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12198             ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12199          }
12200 #endif
12201 #ifdef HAVE_PRI
12202          if (tmp->pri) {
12203             ast_cli(fd, "PRI Flags: ");
12204             if (tmp->resetting)
12205                ast_cli(fd, "Resetting ");
12206             if (tmp->call)
12207                ast_cli(fd, "Call ");
12208             if (tmp->bearer)
12209                ast_cli(fd, "Bearer ");
12210             ast_cli(fd, "\n");
12211             if (tmp->logicalspan) 
12212                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12213             else
12214                ast_cli(fd, "PRI Logical Span: Implicit\n");
12215          }
12216             
12217 #endif
12218          memset(&ci, 0, sizeof(ci));
12219          ps.channo = tmp->channel;
12220          if (tmp->subs[SUB_REAL].dfd > -1) {
12221             memset(&ci, 0, sizeof(ci));
12222             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12223                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12224             }
12225 #ifdef DAHDI_GETCONFMUTE
12226             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12227                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12228             }
12229 #endif
12230             memset(&ps, 0, sizeof(ps));
12231             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12232                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12233             } else {
12234                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12235             }
12236          }
12237          if (ISTRUNK(tmp)) {
12238             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
12239             if (!ast_strlen_zero(progzone))
12240                ast_cli(fd, "Progress Zone: %s\n", progzone);
12241             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
12242             if(tmp->busydetect) {
12243                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12244                if(tmp->busytonelength > 0) {
12245                   ast_cli(fd, "Busy Pattern:\n");
12246                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12247                   if (tmp->busyquietlength > 0) 
12248                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12249                   else 
12250                      ast_cli(fd, " -- Detect Tone Only\n");
12251                   if(tmp->busyfuzziness > 0)
12252                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12253                }
12254             }
12255          }
12256          ast_mutex_unlock(lock);
12257          return RESULT_SUCCESS;
12258       }
12259       tmp = tmp->next;
12260    }
12261    
12262    ast_cli(fd, "Unable to find given channel %d\n", channel);
12263    ast_mutex_unlock(lock);
12264    return RESULT_FAILURE;
12265 }
12266 
12267 static char dahdi_show_cadences_usage[] =
12268 "Usage: dahdi show cadences\n"
12269 "       Shows all cadences currently defined\n";
12270 
12271 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
12272 {
12273    int i, j;
12274    for (i = 0; i < num_cadence; i++) {
12275       char output[1024];
12276       char tmp[16], tmp2[64];
12277       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12278       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12279 
12280       for (j = 0; j < 16; j++) {
12281          if (cadences[i].ringcadence[j] == 0)
12282             break;
12283          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12284          if (cidrings[i] * 2 - 1 == j)
12285             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12286          else
12287             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12288          if (j != 0)
12289             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12290          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12291       }
12292       ast_cli(fd,"%s\n",output);
12293    }
12294    return 0;
12295 }
12296 
12297 /* Based on irqmiss.c */
12298 static int dahdi_show_status(int fd, int argc, char *argv[]) {
12299    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12300    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12301 
12302    int span;
12303    int res;
12304    char alarms[50];
12305 
12306    int ctl;
12307    struct dahdi_spaninfo s;
12308 
12309    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12310       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12311       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12312       return RESULT_FAILURE;
12313    }
12314    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12315 
12316    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12317       s.spanno = span;
12318       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12319       if (res) {
12320          continue;
12321       }
12322       alarms[0] = '\0';
12323       if (s.alarms > 0) {
12324          if (s.alarms & DAHDI_ALARM_BLUE)
12325             strcat(alarms, "BLU/");
12326          if (s.alarms & DAHDI_ALARM_YELLOW)
12327             strcat(alarms, "YEL/");
12328          if (s.alarms & DAHDI_ALARM_RED)
12329             strcat(alarms, "RED/");
12330          if (s.alarms & DAHDI_ALARM_LOOPBACK)
12331             strcat(alarms, "LB/");
12332          if (s.alarms & DAHDI_ALARM_RECOVER)
12333             strcat(alarms, "REC/");
12334          if (s.alarms & DAHDI_ALARM_NOTOPEN)
12335             strcat(alarms, "NOP/");
12336          if (!strlen(alarms))
12337             strcat(alarms, "UUU/");
12338          if (strlen(alarms)) {
12339             /* Strip trailing / */
12340             alarms[strlen(alarms) - 1] = '\0';
12341          }
12342       } else {
12343          if (s.numchans)
12344             strcpy(alarms, "OK");
12345          else
12346             strcpy(alarms, "UNCONFIGURED");
12347       }
12348 
12349       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12350    }
12351    close(ctl);
12352 
12353    return RESULT_SUCCESS;
12354 #undef FORMAT
12355 #undef FORMAT2
12356 }
12357 
12358 static char show_channels_usage[] =
12359    "Usage: dahdi show channels\n"
12360    "  Shows a list of available channels\n";
12361 
12362 static char show_channel_usage[] =
12363    "Usage: dahdi show channel <chan num>\n"
12364    "  Detailed information about a given channel\n";
12365 
12366 static char dahdi_show_status_usage[] =
12367    "Usage: dahdi show status\n"
12368    "       Shows a list of DAHDI cards with status\n";
12369 
12370 static char destroy_channel_usage[] =
12371    "Usage: dahdi destroy channel <chan num>\n"
12372    "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12373 
12374 static char dahdi_restart_usage[] =
12375    "Usage: dahdi restart\n"
12376    "  Restarts the DAHDI channels: destroys them all and then\n"
12377    "  re-reads them from chan_dahdi.conf.\n"
12378    "  Note that this will STOP any running CALL on DAHDI channels.\n"
12379    "";
12380 
12381 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
12382    { "zap", "show", "cadences", NULL },
12383    handle_dahdi_show_cadences, NULL,
12384    NULL };
12385 
12386 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
12387    { "zap", "show", "channels", NULL },
12388    dahdi_show_channels, NULL,
12389    NULL };
12390 
12391 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
12392    { "zap", "show", "channel", NULL },
12393    dahdi_show_channel, NULL,
12394    NULL };
12395 
12396 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
12397    { "zap", "destroy", "channel", NULL },
12398    dahdi_destroy_channel, NULL,
12399    NULL };
12400 
12401 static struct ast_cli_entry cli_zap_restart_deprecated = {
12402    { "zap", "restart", NULL },
12403    dahdi_restart_cmd, NULL,
12404    NULL };
12405 
12406 static struct ast_cli_entry cli_zap_show_status_deprecated = {
12407    { "zap", "show", "status", NULL },
12408    dahdi_show_status, NULL,
12409    NULL };
12410 
12411 static struct ast_cli_entry dahdi_cli[] = {
12412    { { "dahdi", "show", "cadences", NULL },
12413    handle_dahdi_show_cadences, "List cadences",
12414    dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
12415 
12416    { { "dahdi", "show", "channels", NULL},
12417    dahdi_show_channels, "Show active DAHDI channels",
12418    show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
12419 
12420    { { "dahdi", "show", "channel", NULL},
12421    dahdi_show_channel, "Show information on a channel",
12422    show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
12423 
12424    { { "dahdi", "destroy", "channel", NULL},
12425    dahdi_destroy_channel, "Destroy a channel",
12426    destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
12427 
12428    { { "dahdi", "restart", NULL},
12429    dahdi_restart_cmd, "Fully restart DAHDI channels",
12430    dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
12431 
12432    { { "dahdi", "show", "status", NULL},
12433    dahdi_show_status, "Show all DAHDI cards status",
12434    dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
12435 };
12436 
12437 #define TRANSFER  0
12438 #define HANGUP    1
12439 
12440 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12441 {
12442    if (p) {
12443       switch (mode) {
12444          case TRANSFER:
12445             p->fake_event = DAHDI_EVENT_WINKFLASH;
12446             break;
12447          case HANGUP:
12448             p->fake_event = DAHDI_EVENT_ONHOOK;
12449             break;
12450          default:
12451             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
12452       }
12453    }
12454    return 0;
12455 }
12456 static struct dahdi_pvt *find_channel(int channel)
12457 {
12458    struct dahdi_pvt *p = iflist;
12459    while (p) {
12460       if (p->channel == channel) {
12461          break;
12462       }
12463       p = p->next;
12464    }
12465    return p;
12466 }
12467 
12468 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
12469 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12470 
12471 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
12472 {
12473    struct dahdi_pvt *p = NULL;
12474    const char *channel = local_astman_header(m, "Channel", zap_mode);
12475 
12476    if (ast_strlen_zero(channel)) {
12477       astman_send_error(s, m, "No channel specified");
12478       return 0;
12479    }
12480    if (!(p = find_channel(atoi(channel)))) {
12481       astman_send_error(s, m, "No such channel");
12482       return 0;
12483    }
12484    p->dnd = dnd;
12485    local_astman_ack(s, m, "DND", zap_mode);
12486 
12487    return 0;
12488 }
12489 
12490 static int zap_action_dndon(struct mansession *s, const struct message *m)
12491 {
12492    return __action_dnd(s, m, 1, 1);
12493 }
12494 
12495 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
12496 {
12497    return __action_dnd(s, m, 0, 1);
12498 }
12499 
12500 static int zap_action_dndoff(struct mansession *s, const struct message *m)
12501 {
12502    return __action_dnd(s, m, 1, 0);
12503 }
12504 
12505 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
12506 {
12507    return __action_dnd(s, m, 0, 0);
12508 }
12509 
12510 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
12511 {
12512    struct dahdi_pvt *p = NULL;
12513    const char *channel = local_astman_header(m, "Channel", zap_mode);
12514 
12515    if (ast_strlen_zero(channel)) {
12516       astman_send_error(s, m, "No channel specified");
12517       return 0;
12518    }
12519    if (!(p = find_channel(atoi(channel)))) {
12520       astman_send_error(s, m, "No such channel");
12521       return 0;
12522    }
12523    dahdi_fake_event(p,TRANSFER);
12524    local_astman_ack(s, m, "Transfer", zap_mode);
12525 
12526    return 0;
12527 }
12528 
12529 static int zap_action_transfer(struct mansession *s, const struct message *m)
12530 {
12531    return __action_transfer(s, m, 1);
12532 }
12533 
12534 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
12535 {
12536    return __action_transfer(s, m, 0);
12537 }
12538 
12539 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
12540 {
12541    struct dahdi_pvt *p = NULL;
12542    const char *channel = local_astman_header(m, "Channel", zap_mode);
12543 
12544    if (ast_strlen_zero(channel)) {
12545       astman_send_error(s, m, "No channel specified");
12546       return 0;
12547    }
12548    if (!(p = find_channel(atoi(channel)))) {
12549       astman_send_error(s, m, "No such channel");
12550       return 0;
12551    }
12552    dahdi_fake_event(p, HANGUP);
12553    local_astman_ack(s, m, "Hangup", zap_mode);
12554    return 0;
12555 }
12556 
12557 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
12558 {
12559    return __action_transferhangup(s, m, 1);
12560 }
12561 
12562 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
12563 {
12564    return __action_transferhangup(s, m, 0);
12565 }
12566 
12567 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
12568 {
12569    struct dahdi_pvt *p = NULL;
12570    const char *channel = local_astman_header(m, "Channel", zap_mode);
12571    const char *number = astman_get_header(m, "Number");
12572    int i;
12573 
12574    if (ast_strlen_zero(channel)) {
12575       astman_send_error(s, m, "No channel specified");
12576       return 0;
12577    }
12578    if (ast_strlen_zero(number)) {
12579       astman_send_error(s, m, "No number specified");
12580       return 0;
12581    }
12582    if (!(p = find_channel(atoi(channel)))) {
12583       astman_send_error(s, m, "No such channel");
12584       return 0;
12585    }
12586    if (!p->owner) {
12587       astman_send_error(s, m, "Channel does not have an owner");
12588       return 0;
12589    }
12590    for (i = 0; i < strlen(number); i++) {
12591       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12592 
12593       dahdi_queue_frame(p, &f, NULL); 
12594    }
12595    local_astman_ack(s, m, "DialOffHook", zap_mode);
12596 
12597    return 0;
12598 }
12599 
12600 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
12601 {
12602    return __action_dialoffhook(s, m, 1);
12603 }
12604 
12605 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
12606 {
12607    return __action_dialoffhook(s, m, 0);
12608 }
12609 
12610 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
12611 {
12612    struct dahdi_pvt *tmp = NULL;
12613    const char *id = astman_get_header(m, "ActionID");
12614    char idText[256] = "";
12615 
12616    local_astman_ack(s, m, " channel status will follow", zap_mode);
12617    if (!ast_strlen_zero(id))
12618       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12619 
12620    ast_mutex_lock(&iflock);
12621    
12622    tmp = iflist;
12623    while (tmp) {
12624       if (tmp->channel > 0) {
12625          int alarm = get_alarms(tmp);
12626          astman_append(s,
12627                   "Event: %sShowChannels\r\n"
12628                   "Channel: %d\r\n"
12629                   "Signalling: %s\r\n"
12630                   "Context: %s\r\n"
12631                   "DND: %s\r\n"
12632                   "Alarm: %s\r\n"
12633                   "%s"
12634                   "\r\n",
12635                   dahdi_chan_name,
12636                   tmp->channel, sig2str(tmp->sig), tmp->context, 
12637                   tmp->dnd ? "Enabled" : "Disabled",
12638                   alarm2str(alarm), idText);
12639       } 
12640 
12641       tmp = tmp->next;
12642    }
12643 
12644    ast_mutex_unlock(&iflock);
12645    
12646    astman_append(s, 
12647             "Event: %sShowChannelsComplete\r\n"
12648             "%s"
12649             "\r\n",
12650             dahdi_chan_name,
12651             idText);
12652    return 0;
12653 }
12654 
12655 static int zap_action_showchannels(struct mansession *s, const struct message *m)
12656 {
12657    return __action_showchannels(s, m, 1);
12658 }
12659 
12660 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
12661 {
12662    return __action_showchannels(s, m, 0);
12663 }
12664 
12665 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
12666 {
12667    if (dahdi_restart() != 0) {
12668       if (zap_mode) {
12669          astman_send_error(s, m, "Failed to restart Zap");
12670       } else {
12671          astman_send_error(s, m, "Failed to restart DAHDI");
12672       }
12673       return 1;
12674    }
12675    local_astman_ack(s, m, "Restart: Success", zap_mode);
12676    return 0;
12677 }
12678 
12679 static int zap_action_restart(struct mansession *s, const struct message *m)
12680 {
12681    return __action_restart(s, m, 1);
12682 }
12683 
12684 static int dahdi_action_restart(struct mansession *s, const struct message *m)
12685 {
12686    return __action_restart(s, m, 0);
12687 }
12688 
12689 #define local_astman_unregister(a) do { \
12690                if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12691                   ast_manager_unregister("DAHDI" a); \
12692                } \
12693                ast_manager_unregister("Zap" a); \
12694                } while (0)
12695 
12696 static int __unload_module(void)
12697 {
12698    struct dahdi_pvt *p;
12699 #ifdef HAVE_OPENR2
12700    int r;
12701 #endif
12702 #ifdef HAVE_PRI
12703    int i, j;
12704    for (i = 0; i < NUM_SPANS; i++) {
12705       if (pris[i].master != AST_PTHREADT_NULL) 
12706          pthread_cancel(pris[i].master);
12707    }
12708    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12709 
12710    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12711       ast_unregister_application(dahdi_send_keypad_facility_app);
12712    }
12713    ast_unregister_application(zap_send_keypad_facility_app);
12714 #endif
12715 #ifdef HAVE_OPENR2
12716    for (r = 0; r < NUM_SPANS; r++) {
12717       if (r2links[r].master != AST_PTHREADT_NULL) {
12718          pthread_cancel(r2links[r].master);
12719          pthread_join(r2links[r].master, NULL);
12720       }
12721    }
12722    ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12723    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12724       ast_unregister_application(dahdi_accept_r2_call_app);
12725    }
12726    ast_unregister_application(zap_accept_r2_call_app);
12727 #endif
12728    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12729    local_astman_unregister("DialOffHook");
12730    local_astman_unregister("Hangup");
12731    local_astman_unregister("Transfer");
12732    local_astman_unregister("DNDoff");
12733    local_astman_unregister("DNDon");
12734    local_astman_unregister("ShowChannels");
12735    local_astman_unregister("Restart");
12736    ast_channel_unregister(chan_tech);
12737    ast_mutex_lock(&iflock);
12738    /* Hangup all interfaces if they have an owner */
12739    p = iflist;
12740    while (p) {
12741       if (p->owner)
12742          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12743       p = p->next;
12744    }
12745    ast_mutex_unlock(&iflock);
12746    ast_mutex_lock(&monlock);
12747    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12748       pthread_cancel(monitor_thread);
12749       pthread_kill(monitor_thread, SIGURG);
12750       pthread_join(monitor_thread, NULL);
12751    }
12752    monitor_thread = AST_PTHREADT_STOP;
12753    ast_mutex_unlock(&monlock);
12754 
12755    destroy_all_channels();
12756 #ifdef HAVE_PRI      
12757    for (i = 0; i < NUM_SPANS; i++) {
12758       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12759          pthread_join(pris[i].master, NULL);
12760       for (j = 0; j < NUM_DCHANS; j++) {
12761          dahdi_close_pri_fd(&(pris[i]), j);
12762       }
12763    }
12764 #endif
12765 #ifdef HAVE_OPENR2
12766    for (r = 0; r < NUM_SPANS; r++) {
12767       if (r2links[r].protocol_context) {
12768          openr2_context_delete(r2links[r].protocol_context);
12769       }
12770    }
12771 #endif
12772    ast_cond_destroy(&ss_thread_complete);
12773    return 0;
12774 }
12775 
12776 static int unload_module(void)
12777 {
12778 #ifdef HAVE_PRI      
12779    int y;
12780    for (y = 0; y < NUM_SPANS; y++)
12781       ast_mutex_destroy(&pris[y].lock);
12782 #endif
12783    return __unload_module();
12784 }
12785 
12786 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
12787 {
12788    char *c, *chan;
12789    int x, start, finish;
12790    struct dahdi_pvt *tmp;
12791 #ifdef HAVE_PRI
12792    struct dahdi_pri *pri;
12793    int trunkgroup, y;
12794 #endif
12795    
12796    if ((reload == 0) && (conf->chan.sig < 0)) {
12797       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12798       return -1;
12799    }
12800 
12801    c = ast_strdupa(value);
12802 
12803 #ifdef HAVE_PRI
12804    pri = NULL;
12805    if (iscrv) {
12806       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12807          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12808          return -1;
12809       }
12810       if (trunkgroup < 1) {
12811          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12812          return -1;
12813       }
12814       c += y;
12815       for (y = 0; y < NUM_SPANS; y++) {
12816          if (pris[y].trunkgroup == trunkgroup) {
12817             pri = pris + y;
12818             break;
12819          }
12820       }
12821       if (!pri) {
12822          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12823          return -1;
12824       }
12825    }
12826 #endif         
12827 
12828    while ((chan = strsep(&c, ","))) {
12829       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12830          /* Range */
12831       } else if (sscanf(chan, "%30d", &start)) {
12832          /* Just one */
12833          finish = start;
12834       } else if (!strcasecmp(chan, "pseudo")) {
12835          finish = start = CHAN_PSEUDO;
12836          if (found_pseudo)
12837             *found_pseudo = 1;
12838       } else {
12839          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12840          return -1;
12841       }
12842       if (finish < start) {
12843          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12844          x = finish;
12845          finish = start;
12846          start = x;
12847       }
12848 
12849       for (x = start; x <= finish; x++) {
12850 #ifdef HAVE_PRI
12851          tmp = mkintf(x, conf, pri, reload);
12852 #else       
12853          tmp = mkintf(x, conf, NULL, reload);
12854 #endif         
12855 
12856          if (tmp) {
12857             if (option_verbose > 2) {
12858 #ifdef HAVE_PRI
12859                if (pri)
12860                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12861                else
12862 #endif
12863                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12864             }
12865          } else {
12866             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12867                (reload == 1) ? "reconfigure" : "register", value);
12868             return -1;
12869          }
12870       }
12871 #ifdef HAVE_OPENR2
12872       if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12873          mfcr2_cur_context_index++;
12874       }  
12875 #endif
12876    }
12877 
12878    return 0;
12879 }
12880 
12881 /** The length of the parameters list of 'dahdichan'. 
12882  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
12883 #define MAX_CHANLIST_LEN 80
12884 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
12885 {
12886    struct dahdi_pvt *tmp;
12887    int y;
12888    int found_pseudo = 0;
12889         char dahdichan[MAX_CHANLIST_LEN] = {};
12890 
12891    for (; v; v = v->next) {
12892       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12893          continue;
12894 
12895       /* Create the interface list */
12896       if (!strcasecmp(v->name, "channel")
12897 #ifdef HAVE_PRI
12898           || !strcasecmp(v->name, "crv")
12899 #endif         
12900          ) {
12901          int iscrv;
12902          if (skipchannels)
12903             continue;
12904          iscrv = !strcasecmp(v->name, "crv");
12905          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12906                return -1;
12907       } else if (!strcasecmp(v->name, "buffers")) {
12908          int res;
12909          char policy[21] = "";
12910 
12911          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
12912          if (res != 2) {
12913             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
12914             confp->chan.buf_no = numbufs;
12915             continue;
12916          }
12917          if (confp->chan.buf_no < 0)
12918             confp->chan.buf_no = numbufs;
12919          if (!strcasecmp(policy, "full")) {
12920             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
12921          } else if (!strcasecmp(policy, "immediate")) {
12922             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
12923          } else {
12924             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
12925          }
12926       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
12927          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
12928          if (v->name[0] == 'z' || v->name[0] == 'Z') {
12929             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
12930          }
12931       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12932          if (ast_true(v->value))
12933             confp->chan.usedistinctiveringdetection = 1;
12934       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12935          if (ast_true(v->value))
12936             distinctiveringaftercid = 1;
12937       } else if (!strcasecmp(v->name, "dring1context")) {
12938          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
12939       } else if (!strcasecmp(v->name, "dring2context")) {
12940          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
12941       } else if (!strcasecmp(v->name, "dring3context")) {
12942          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
12943       } else if (!strcasecmp(v->name, "dring1")) {
12944          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
12945       } else if (!strcasecmp(v->name, "dring2")) {
12946          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
12947       } else if (!strcasecmp(v->name, "dring3")) {
12948          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
12949       } else if (!strcasecmp(v->name, "usecallerid")) {
12950          confp->chan.use_callerid = ast_true(v->value);
12951       } else if (!strcasecmp(v->name, "cidsignalling")) {
12952          if (!strcasecmp(v->value, "bell"))
12953             confp->chan.cid_signalling = CID_SIG_BELL;
12954          else if (!strcasecmp(v->value, "v23"))
12955             confp->chan.cid_signalling = CID_SIG_V23;
12956          else if (!strcasecmp(v->value, "dtmf"))
12957             confp->chan.cid_signalling = CID_SIG_DTMF;
12958          else if (!strcasecmp(v->value, "smdi"))
12959             confp->chan.cid_signalling = CID_SIG_SMDI;
12960          else if (!strcasecmp(v->value, "v23_jp"))
12961             confp->chan.cid_signalling = CID_SIG_V23_JP;
12962          else if (ast_true(v->value))
12963             confp->chan.cid_signalling = CID_SIG_BELL;
12964       } else if (!strcasecmp(v->name, "cidstart")) {
12965          if (!strcasecmp(v->value, "ring"))
12966             confp->chan.cid_start = CID_START_RING;
12967          else if (!strcasecmp(v->value, "polarity"))
12968             confp->chan.cid_start = CID_START_POLARITY;
12969          else if (ast_true(v->value))
12970             confp->chan.cid_start = CID_START_RING;
12971       } else if (!strcasecmp(v->name, "threewaycalling")) {
12972          confp->chan.threewaycalling = ast_true(v->value);
12973       } else if (!strcasecmp(v->name, "cancallforward")) {
12974          confp->chan.cancallforward = ast_true(v->value);
12975       } else if (!strcasecmp(v->name, "relaxdtmf")) {
12976          if (ast_true(v->value)) 
12977             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
12978          else
12979             confp->chan.dtmfrelax = 0;
12980       } else if (!strcasecmp(v->name, "mailbox")) {
12981          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
12982       } else if (!strcasecmp(v->name, "hasvoicemail")) {
12983          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
12984             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
12985          }
12986       } else if (!strcasecmp(v->name, "adsi")) {
12987          confp->chan.adsi = ast_true(v->value);
12988       } else if (!strcasecmp(v->name, "usesmdi")) {
12989          confp->chan.use_smdi = ast_true(v->value);
12990       } else if (!strcasecmp(v->name, "smdiport")) {
12991          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
12992       } else if (!strcasecmp(v->name, "transfer")) {
12993          confp->chan.transfer = ast_true(v->value);
12994       } else if (!strcasecmp(v->name, "canpark")) {
12995          confp->chan.canpark = ast_true(v->value);
12996       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
12997          confp->chan.echocanbridged = ast_true(v->value);
12998       } else if (!strcasecmp(v->name, "busydetect")) {
12999          confp->chan.busydetect = ast_true(v->value);
13000       } else if (!strcasecmp(v->name, "busycount")) {
13001          confp->chan.busycount = atoi(v->value);
13002       } else if (!strcasecmp(v->name, "silencethreshold")) {
13003             confp->chan.silencethreshold = atoi(v->value);
13004       } else if (!strcasecmp(v->name, "busycompare")) {
13005             confp->chan.busycompare = ast_true(v->value);
13006       } else if (!strcasecmp(v->name, "busypattern")) {
13007          int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
13008          if (count == 1)
13009             confp->chan.busyquietlength = 0;
13010          else if (count < 1)
13011                ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
13012       } else if (!strcasecmp(v->name, "busyfuzziness")) {
13013             confp->chan.busyfuzziness = atoi(v->value);
13014       } else if (!strcasecmp(v->name, "callprogress")) {
13015          if (ast_true(v->value))
13016             confp->chan.callprogress |= 1;
13017          else
13018             confp->chan.callprogress &= ~1;
13019       } else if (!strcasecmp(v->name, "faxdetect")) {
13020          if (!strcasecmp(v->value, "incoming")) {
13021             confp->chan.callprogress |= 4;
13022             confp->chan.callprogress &= ~2;
13023          } else if (!strcasecmp(v->value, "outgoing")) {
13024             confp->chan.callprogress &= ~4;
13025             confp->chan.callprogress |= 2;
13026          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13027             confp->chan.callprogress |= 6;
13028          else
13029             confp->chan.callprogress &= ~6;
13030       } else if (!strcasecmp(v->name, "echocancel")) {
13031          if (!ast_strlen_zero(v->value)) {
13032             y = atoi(v->value);
13033          } else
13034             y = 0;
13035          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
13036             confp->chan.echocancel = y;
13037          else {
13038             confp->chan.echocancel = ast_true(v->value);
13039             if (confp->chan.echocancel)
13040                confp->chan.echocancel=128;
13041          }
13042       } else if (!strcasecmp(v->name, "echotraining")) {
13043          if (sscanf(v->value, "%30d", &y) == 1) {
13044             if ((y < 10) || (y > 4000)) {
13045                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
13046             } else {
13047                confp->chan.echotraining = y;
13048             }
13049          } else if (ast_true(v->value)) {
13050             confp->chan.echotraining = 400;
13051          } else
13052             confp->chan.echotraining = 0;
13053       } else if (!strcasecmp(v->name, "hidecallerid")) {
13054          confp->chan.hidecallerid = ast_true(v->value);
13055       } else if (!strcasecmp(v->name, "hidecalleridname")) {
13056          confp->chan.hidecalleridname = ast_true(v->value);
13057       } else if (!strcasecmp(v->name, "pulsedial")) {
13058          confp->chan.pulse = ast_true(v->value);
13059       } else if (!strcasecmp(v->name, "callreturn")) {
13060          confp->chan.callreturn = ast_true(v->value);
13061       } else if (!strcasecmp(v->name, "callwaiting")) {
13062          confp->chan.callwaiting = ast_true(v->value);
13063       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13064          confp->chan.callwaitingcallerid = ast_true(v->value);
13065       } else if (!strcasecmp(v->name, "context")) {
13066          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13067       } else if (!strcasecmp(v->name, "language")) {
13068          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13069       } else if (!strcasecmp(v->name, "progzone")) {
13070          ast_copy_string(progzone, v->value, sizeof(progzone));
13071       } else if (!strcasecmp(v->name, "mohinterpret") 
13072          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13073          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13074       } else if (!strcasecmp(v->name, "mohsuggest")) {
13075          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13076       } else if (!strcasecmp(v->name, "stripmsd")) {
13077          confp->chan.stripmsd = atoi(v->value);
13078       } else if (!strcasecmp(v->name, "jitterbuffers")) {
13079          numbufs = atoi(v->value);
13080       } else if (!strcasecmp(v->name, "group")) {
13081          confp->chan.group = ast_get_group(v->value);
13082       } else if (!strcasecmp(v->name, "callgroup")) {
13083          confp->chan.callgroup = ast_get_group(v->value);
13084       } else if (!strcasecmp(v->name, "pickupgroup")) {
13085          confp->chan.pickupgroup = ast_get_group(v->value);
13086       } else if (!strcasecmp(v->name, "immediate")) {
13087          confp->chan.immediate = ast_true(v->value);
13088       } else if (!strcasecmp(v->name, "transfertobusy")) {
13089          confp->chan.transfertobusy = ast_true(v->value);
13090       } else if (!strcasecmp(v->name, "rxgain")) {
13091          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
13092             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
13093          }
13094       } else if (!strcasecmp(v->name, "txgain")) {
13095          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
13096             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
13097          }
13098       } else if (!strcasecmp(v->name, "tonezone")) {
13099          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
13100             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
13101          }
13102       } else if (!strcasecmp(v->name, "callerid")) {
13103          if (!strcasecmp(v->value, "asreceived")) {
13104             confp->chan.cid_num[0] = '\0';
13105             confp->chan.cid_name[0] = '\0';
13106          } else {
13107             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13108          } 
13109       } else if (!strcasecmp(v->name, "fullname")) {
13110          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13111       } else if (!strcasecmp(v->name, "cid_number")) {
13112          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13113       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
13114          confp->chan.dahditrcallerid = ast_true(v->value);
13115          if (strstr(v->name, "zap")) {
13116             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
13117          }
13118       } else if (!strcasecmp(v->name, "restrictcid")) {
13119          confp->chan.restrictcid = ast_true(v->value);
13120       } else if (!strcasecmp(v->name, "usecallingpres")) {
13121          confp->chan.use_callingpres = ast_true(v->value);
13122       } else if (!strcasecmp(v->name, "accountcode")) {
13123          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13124       } else if (!strcasecmp(v->name, "amaflags")) {
13125          y = ast_cdr_amaflags2int(v->value);
13126          if (y < 0) 
13127             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
13128          else
13129             confp->chan.amaflags = y;
13130       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13131          confp->chan.polarityonanswerdelay = atoi(v->value);
13132       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13133          confp->chan.answeronpolarityswitch = ast_true(v->value);
13134       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13135          confp->chan.hanguponpolarityswitch = ast_true(v->value);
13136       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13137          confp->chan.sendcalleridafter = atoi(v->value);
13138       } else if (reload != 1) {
13139           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13140             confp->chan.outsigmod = -1;
13141             if (!strcasecmp(v->value, "em")) {
13142                confp->chan.sig = SIG_EM;
13143             } else if (!strcasecmp(v->value, "em_e1")) {
13144                confp->chan.sig = SIG_EM_E1;
13145             } else if (!strcasecmp(v->value, "em_w")) {
13146                confp->chan.sig = SIG_EMWINK;
13147                confp->chan.radio = 0;
13148             } else if (!strcasecmp(v->value, "fxs_ls")) {
13149                confp->chan.sig = SIG_FXSLS;
13150                confp->chan.radio = 0;
13151             } else if (!strcasecmp(v->value, "fxs_gs")) {
13152                confp->chan.sig = SIG_FXSGS;
13153                confp->chan.radio = 0;
13154             } else if (!strcasecmp(v->value, "fxs_ks")) {
13155                confp->chan.sig = SIG_FXSKS;
13156                confp->chan.radio = 0;
13157             } else if (!strcasecmp(v->value, "fxo_ls")) {
13158                confp->chan.sig = SIG_FXOLS;
13159                confp->chan.radio = 0;
13160             } else if (!strcasecmp(v->value, "fxo_gs")) {
13161                confp->chan.sig = SIG_FXOGS;
13162                confp->chan.radio = 0;
13163             } else if (!strcasecmp(v->value, "fxo_ks")) {
13164                confp->chan.sig = SIG_FXOKS;
13165                confp->chan.radio = 0;
13166             } else if (!strcasecmp(v->value, "fxs_rx")) {
13167                confp->chan.sig = SIG_FXSKS;
13168                confp->chan.radio = 1;
13169             } else if (!strcasecmp(v->value, "fxo_rx")) {
13170                confp->chan.sig = SIG_FXOLS;
13171                confp->chan.radio = 1;
13172             } else if (!strcasecmp(v->value, "fxs_tx")) {
13173                confp->chan.sig = SIG_FXSLS;
13174                confp->chan.radio = 1;
13175             } else if (!strcasecmp(v->value, "fxo_tx")) {
13176                confp->chan.sig = SIG_FXOGS;
13177                confp->chan.radio = 1;
13178             } else if (!strcasecmp(v->value, "em_rx")) {
13179                confp->chan.sig = SIG_EM;
13180                confp->chan.radio = 1;
13181             } else if (!strcasecmp(v->value, "em_tx")) {
13182                confp->chan.sig = SIG_EM;
13183                confp->chan.radio = 1;
13184             } else if (!strcasecmp(v->value, "em_rxtx")) {
13185                confp->chan.sig = SIG_EM;
13186                confp->chan.radio = 2;
13187             } else if (!strcasecmp(v->value, "em_txrx")) {
13188                confp->chan.sig = SIG_EM;
13189                confp->chan.radio = 2;
13190             } else if (!strcasecmp(v->value, "sf")) {
13191                confp->chan.sig = SIG_SF;
13192                confp->chan.radio = 0;
13193             } else if (!strcasecmp(v->value, "sf_w")) {
13194                confp->chan.sig = SIG_SFWINK;
13195                confp->chan.radio = 0;
13196             } else if (!strcasecmp(v->value, "sf_featd")) {
13197                confp->chan.sig = SIG_FEATD;
13198                confp->chan.radio = 0;
13199             } else if (!strcasecmp(v->value, "sf_featdmf")) {
13200                confp->chan.sig = SIG_FEATDMF;
13201                confp->chan.radio = 0;
13202             } else if (!strcasecmp(v->value, "sf_featb")) {
13203                confp->chan.sig = SIG_SF_FEATB;
13204                confp->chan.radio = 0;
13205             } else if (!strcasecmp(v->value, "sf")) {
13206                confp->chan.sig = SIG_SF;
13207                confp->chan.radio = 0;
13208             } else if (!strcasecmp(v->value, "sf_rx")) {
13209                confp->chan.sig = SIG_SF;
13210                confp->chan.radio = 1;
13211             } else if (!strcasecmp(v->value, "sf_tx")) {
13212                confp->chan.sig = SIG_SF;
13213                confp->chan.radio = 1;
13214             } else if (!strcasecmp(v->value, "sf_rxtx")) {
13215                confp->chan.sig = SIG_SF;
13216                confp->chan.radio = 2;
13217             } else if (!strcasecmp(v->value, "sf_txrx")) {
13218                confp->chan.sig = SIG_SF;
13219                confp->chan.radio = 2;
13220             } else if (!strcasecmp(v->value, "featd")) {
13221                confp->chan.sig = SIG_FEATD;
13222                confp->chan.radio = 0;
13223             } else if (!strcasecmp(v->value, "featdmf")) {
13224                confp->chan.sig = SIG_FEATDMF;
13225                confp->chan.radio = 0;
13226             } else if (!strcasecmp(v->value, "featdmf_ta")) {
13227                confp->chan.sig = SIG_FEATDMF_TA;
13228                confp->chan.radio = 0;
13229             } else if (!strcasecmp(v->value, "e911")) {
13230                confp->chan.sig = SIG_E911;
13231                confp->chan.radio = 0;
13232             } else if (!strcasecmp(v->value, "fgccama")) {
13233                confp->chan.sig = SIG_FGC_CAMA;
13234                confp->chan.radio = 0;
13235             } else if (!strcasecmp(v->value, "fgccamamf")) {
13236                confp->chan.sig = SIG_FGC_CAMAMF;
13237                confp->chan.radio = 0;
13238             } else if (!strcasecmp(v->value, "featb")) {
13239                confp->chan.sig = SIG_FEATB;
13240                confp->chan.radio = 0;
13241 #ifdef HAVE_OPENR2
13242             } else if (!strcasecmp(v->value, "mfcr2")) {
13243                confp->chan.sig = SIG_MFCR2;
13244 #endif
13245 #ifdef HAVE_PRI
13246             } else if (!strcasecmp(v->value, "pri_net")) {
13247                confp->chan.radio = 0;
13248                confp->chan.sig = SIG_PRI;
13249                confp->pri.nodetype = PRI_NETWORK;
13250             } else if (!strcasecmp(v->value, "pri_cpe")) {
13251                confp->chan.sig = SIG_PRI;
13252                confp->chan.radio = 0;
13253                confp->pri.nodetype = PRI_CPE;
13254             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13255                confp->chan.sig = SIG_GR303FXOKS;
13256                confp->chan.radio = 0;
13257                confp->pri.nodetype = PRI_NETWORK;
13258             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13259                confp->chan.sig = SIG_GR303FXSKS;
13260                confp->chan.radio = 0;
13261                confp->pri.nodetype = PRI_CPE;
13262 #endif
13263             } else {
13264                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13265             }
13266           } else if (!strcasecmp(v->name, "outsignalling")) {
13267             if (!strcasecmp(v->value, "em")) {
13268                confp->chan.outsigmod = SIG_EM;
13269             } else if (!strcasecmp(v->value, "em_e1")) {
13270                confp->chan.outsigmod = SIG_EM_E1;
13271             } else if (!strcasecmp(v->value, "em_w")) {
13272                confp->chan.outsigmod = SIG_EMWINK;
13273             } else if (!strcasecmp(v->value, "sf")) {
13274                confp->chan.outsigmod = SIG_SF;
13275             } else if (!strcasecmp(v->value, "sf_w")) {
13276                confp->chan.outsigmod = SIG_SFWINK;
13277             } else if (!strcasecmp(v->value, "sf_featd")) {
13278                confp->chan.outsigmod = SIG_FEATD;
13279             } else if (!strcasecmp(v->value, "sf_featdmf")) {
13280                confp->chan.outsigmod = SIG_FEATDMF;
13281             } else if (!strcasecmp(v->value, "sf_featb")) {
13282                confp->chan.outsigmod = SIG_SF_FEATB;
13283             } else if (!strcasecmp(v->value, "sf")) {
13284                confp->chan.outsigmod = SIG_SF;
13285             } else if (!strcasecmp(v->value, "featd")) {
13286                confp->chan.outsigmod = SIG_FEATD;
13287             } else if (!strcasecmp(v->value, "featdmf")) {
13288                confp->chan.outsigmod = SIG_FEATDMF;
13289             } else if (!strcasecmp(v->value, "featdmf_ta")) {
13290                confp->chan.outsigmod = SIG_FEATDMF_TA;
13291             } else if (!strcasecmp(v->value, "e911")) {
13292                confp->chan.outsigmod = SIG_E911;
13293             } else if (!strcasecmp(v->value, "fgccama")) {
13294                confp->chan.outsigmod = SIG_FGC_CAMA;
13295             } else if (!strcasecmp(v->value, "fgccamamf")) {
13296                confp->chan.outsigmod = SIG_FGC_CAMAMF;
13297             } else if (!strcasecmp(v->value, "featb")) {
13298                confp->chan.outsigmod = SIG_FEATB;
13299             } else {
13300                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13301             }
13302 #ifdef HAVE_PRI
13303          } else if (!strcasecmp(v->name, "pridialplan")) {
13304             if (!strcasecmp(v->value, "national")) {
13305                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13306             } else if (!strcasecmp(v->value, "unknown")) {
13307                confp->pri.dialplan = PRI_UNKNOWN + 1;
13308             } else if (!strcasecmp(v->value, "private")) {
13309                confp->pri.dialplan = PRI_PRIVATE + 1;
13310             } else if (!strcasecmp(v->value, "international")) {
13311                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13312             } else if (!strcasecmp(v->value, "local")) {
13313                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13314             } else if (!strcasecmp(v->value, "dynamic")) {
13315                confp->pri.dialplan = -1;
13316             } else {
13317                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13318             }
13319          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13320             if (!strcasecmp(v->value, "national")) {
13321                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13322             } else if (!strcasecmp(v->value, "unknown")) {
13323                confp->pri.localdialplan = PRI_UNKNOWN + 1;
13324             } else if (!strcasecmp(v->value, "private")) {
13325                confp->pri.localdialplan = PRI_PRIVATE + 1;
13326             } else if (!strcasecmp(v->value, "international")) {
13327                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13328             } else if (!strcasecmp(v->value, "local")) {
13329                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13330             } else if (!strcasecmp(v->value, "dynamic")) {
13331                confp->pri.localdialplan = -1;
13332             } else {
13333                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13334             }
13335          } else if (!strcasecmp(v->name, "switchtype")) {
13336             if (!strcasecmp(v->value, "national")) 
13337                confp->pri.switchtype = PRI_SWITCH_NI2;
13338             else if (!strcasecmp(v->value, "ni1"))
13339                confp->pri.switchtype = PRI_SWITCH_NI1;
13340             else if (!strcasecmp(v->value, "dms100"))
13341                confp->pri.switchtype = PRI_SWITCH_DMS100;
13342             else if (!strcasecmp(v->value, "4ess"))
13343                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
13344             else if (!strcasecmp(v->value, "5ess"))
13345                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13346             else if (!strcasecmp(v->value, "euroisdn"))
13347                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13348             else if (!strcasecmp(v->value, "qsig"))
13349                confp->pri.switchtype = PRI_SWITCH_QSIG;
13350             else {
13351                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13352                return -1;
13353             }
13354          } else if (!strcasecmp(v->name, "nsf")) {
13355             if (!strcasecmp(v->value, "sdn"))
13356                confp->pri.nsf = PRI_NSF_SDN;
13357             else if (!strcasecmp(v->value, "megacom"))
13358                confp->pri.nsf = PRI_NSF_MEGACOM;
13359             else if (!strcasecmp(v->value, "tollfreemegacom"))
13360                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
13361             else if (!strcasecmp(v->value, "accunet"))
13362                confp->pri.nsf = PRI_NSF_ACCUNET;
13363             else if (!strcasecmp(v->value, "none"))
13364                confp->pri.nsf = PRI_NSF_NONE;
13365             else {
13366                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13367                confp->pri.nsf = PRI_NSF_NONE;
13368             }
13369          } else if (!strcasecmp(v->name, "priindication")) {
13370             if (!strcasecmp(v->value, "outofband"))
13371                confp->chan.priindication_oob = 1;
13372             else if (!strcasecmp(v->value, "inband"))
13373                confp->chan.priindication_oob = 0;
13374             else
13375                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
13376                   v->value, v->lineno);
13377          } else if (!strcasecmp(v->name, "priexclusive")) {
13378             confp->chan.priexclusive = ast_true(v->value);
13379          } else if (!strcasecmp(v->name, "internationalprefix")) {
13380             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13381          } else if (!strcasecmp(v->name, "nationalprefix")) {
13382             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13383          } else if (!strcasecmp(v->name, "localprefix")) {
13384             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13385          } else if (!strcasecmp(v->name, "privateprefix")) {
13386             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13387          } else if (!strcasecmp(v->name, "unknownprefix")) {
13388             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13389          } else if (!strcasecmp(v->name, "resetinterval")) {
13390             if (!strcasecmp(v->value, "never"))
13391                confp->pri.resetinterval = -1;
13392             else if (atoi(v->value) >= 60)
13393                confp->pri.resetinterval = atoi(v->value);
13394             else
13395                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13396                   v->value, v->lineno);
13397          } else if (!strcasecmp(v->name, "minunused")) {
13398             confp->pri.minunused = atoi(v->value);
13399          } else if (!strcasecmp(v->name, "minidle")) {
13400             confp->pri.minidle = atoi(v->value); 
13401          } else if (!strcasecmp(v->name, "idleext")) {
13402             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13403          } else if (!strcasecmp(v->name, "idledial")) {
13404             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13405          } else if (!strcasecmp(v->name, "overlapdial")) {
13406             if (ast_true(v->value)) {
13407                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13408             } else if (!strcasecmp(v->value, "incoming")) {
13409                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
13410             } else if (!strcasecmp(v->value, "outgoing")) {
13411                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
13412             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
13413                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13414             } else {
13415                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
13416             }
13417 #ifdef HAVE_PRI_INBANDDISCONNECT
13418          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13419             confp->pri.inbanddisconnect = ast_true(v->value);
13420 #endif
13421          } else if (!strcasecmp(v->name, "pritimer")) {
13422 #ifdef PRI_GETSET_TIMERS
13423             char tmp[20];
13424             char *timerc;
13425             char *c;
13426             int timer;
13427             int timeridx;
13428 
13429             ast_copy_string(tmp, v->value, sizeof(tmp));
13430             c = tmp;
13431             timerc = strsep(&c, ",");
13432             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
13433                timeridx = pri_timer2idx(timerc);
13434                timer = atoi(c);
13435                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
13436                   ast_log(LOG_WARNING,
13437                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
13438                      v->lineno);
13439                } else if (!timer) {
13440                   ast_log(LOG_WARNING,
13441                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
13442                      c, timerc, v->lineno);
13443                } else {
13444                   pritimers[timeridx] = timer;
13445                }
13446             } else {
13447                ast_log(LOG_WARNING,
13448                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
13449                   v->value, v->lineno);
13450             }
13451 #endif /* PRI_GETSET_TIMERS */
13452          } else if (!strcasecmp(v->name, "facilityenable")) {
13453             confp->pri.facilityenable = ast_true(v->value);
13454 #endif /* HAVE_PRI */
13455 #ifdef HAVE_OPENR2
13456          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
13457             ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
13458             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY  KNOW WHAT YOU ARE DOING*.\n", mfcr2_cur_r2proto_file);
13459          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
13460             ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
13461          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
13462             mfcr2_cur_variant = openr2_proto_get_variant(v->value);
13463             if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
13464                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
13465             }
13466          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
13467             mfcr2_cur_mfback_timeout = atoi(v->value);
13468             if (!mfcr2_cur_mfback_timeout) {
13469                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
13470                mfcr2_cur_mfback_timeout = -1;
13471             } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
13472                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
13473             }
13474          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
13475             mfcr2_cur_metering_pulse_timeout = atoi(v->value);
13476             if (mfcr2_cur_metering_pulse_timeout > 500) {
13477                ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
13478             }
13479 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13480          } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
13481             mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
13482          } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
13483             mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
13484          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
13485             mfcr2_cur_dtmf_time_on = atoi(v->value);
13486          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
13487             mfcr2_cur_dtmf_time_off = atoi(v->value);
13488 #endif
13489          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
13490             mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
13491          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
13492             mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
13493          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
13494             mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
13495          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
13496             mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
13497          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
13498             mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
13499          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
13500             mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
13501          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
13502             mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
13503          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
13504             mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
13505          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
13506             mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
13507          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
13508             mfcr2_cur_max_ani = atoi(v->value);
13509             if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
13510                mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
13511             }
13512          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
13513             mfcr2_cur_max_dnis = atoi(v->value);
13514             if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
13515                mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
13516             }
13517          } else if (!strcasecmp(v->name, "mfcr2_category")) {
13518             mfcr2_cur_category = openr2_proto_get_category(v->value);
13519             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
13520                mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
13521                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 
13522                      v->value, v->lineno);
13523             }
13524          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
13525             openr2_log_level_t tmplevel;
13526             char *toklevel = NULL;
13527             char *saveptr = NULL;
13528             char *logval = ast_strdupa(v->value);
13529             toklevel = strtok_r(logval, ",", &saveptr);
13530             if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13531                ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
13532             } else if (OR2_LOG_NOTHING == tmplevel) {
13533                mfcr2_cur_loglevel = tmplevel;
13534             } else {
13535                mfcr2_cur_loglevel |= tmplevel;
13536                while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
13537                   if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13538                      ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
13539                      continue;
13540                   }
13541                   mfcr2_cur_loglevel |= tmplevel;
13542                }
13543             }
13544 #endif /* HAVE_OPENR2 */
13545 
13546          } else if (!strcasecmp(v->name, "cadence")) {
13547             /* setup to scan our argument */
13548             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13549             int i;
13550             struct dahdi_ring_cadence new_cadence;
13551             int cid_location = -1;
13552             int firstcadencepos = 0;
13553             char original_args[80];
13554             int cadence_is_ok = 1;
13555 
13556             ast_copy_string(original_args, v->value, sizeof(original_args));
13557             /* 16 cadences allowed (8 pairs) */
13558             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
13559    
13560             /* Cadence must be even (on/off) */
13561             if (element_count % 2 == 1) {
13562                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13563                cadence_is_ok = 0;
13564             }
13565    
13566             /* Ring cadences cannot be negative */
13567             for (i = 0; i < element_count; i++) {
13568                if (c[i] == 0) {
13569                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13570                   cadence_is_ok = 0;
13571                   break;
13572                } else if (c[i] < 0) {
13573                   if (i % 2 == 1) {
13574                      /* Silence duration, negative possibly okay */
13575                      if (cid_location == -1) {
13576                         cid_location = i;
13577                         c[i] *= -1;
13578                      } else {
13579                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13580                         cadence_is_ok = 0;
13581                         break;
13582                      }
13583                   } else {
13584                      if (firstcadencepos == 0) {
13585                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
13586                                  /* duration will be passed negative to the DAHDI driver */
13587                      } else {
13588                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13589                         cadence_is_ok = 0;
13590                         break;
13591                      }
13592                   }
13593                }
13594             }
13595    
13596             /* Substitute our scanned cadence */
13597             for (i = 0; i < 16; i++) {
13598                new_cadence.ringcadence[i] = c[i];
13599             }
13600    
13601             if (cadence_is_ok) {
13602                /* ---we scanned it without getting annoyed; now some sanity checks--- */
13603                if (element_count < 2) {
13604                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13605                } else {
13606                   if (cid_location == -1) {
13607                      /* user didn't say; default to first pause */
13608                      cid_location = 1;
13609                   } else {
13610                      /* convert element_index to cidrings value */
13611                      cid_location = (cid_location + 1) / 2;
13612                   }
13613                   /* ---we like their cadence; try to install it--- */
13614                   if (!user_has_defined_cadences++)
13615                      /* this is the first user-defined cadence; clear the default user cadences */
13616                      num_cadence = 0;
13617                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
13618                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13619                   else {
13620                      cadences[num_cadence] = new_cadence;
13621                      cidrings[num_cadence++] = cid_location;
13622                      if (option_verbose > 2)
13623                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13624                   }
13625                }
13626             }
13627          } else if (!strcasecmp(v->name, "ringtimeout")) {
13628             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13629          } else if (!strcasecmp(v->name, "prewink")) {
13630             confp->timing.prewinktime = atoi(v->value);
13631          } else if (!strcasecmp(v->name, "preflash")) {
13632             confp->timing.preflashtime = atoi(v->value);
13633          } else if (!strcasecmp(v->name, "wink")) {
13634             confp->timing.winktime = atoi(v->value);
13635          } else if (!strcasecmp(v->name, "flash")) {
13636             confp->timing.flashtime = atoi(v->value);
13637          } else if (!strcasecmp(v->name, "start")) {
13638             confp->timing.starttime = atoi(v->value);
13639          } else if (!strcasecmp(v->name, "rxwink")) {
13640             confp->timing.rxwinktime = atoi(v->value);
13641          } else if (!strcasecmp(v->name, "rxflash")) {
13642             confp->timing.rxflashtime = atoi(v->value);
13643          } else if (!strcasecmp(v->name, "debounce")) {
13644             confp->timing.debouncetime = atoi(v->value);
13645          } else if (!strcasecmp(v->name, "toneduration")) {
13646             int toneduration;
13647             int ctlfd;
13648             int res;
13649             struct dahdi_dialparams dps;
13650 
13651             ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
13652 
13653             if (ctlfd == -1) {
13654                ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
13655                return -1;
13656             }
13657 
13658             toneduration = atoi(v->value);
13659             if (toneduration > -1) {
13660                memset(&dps, 0, sizeof(dps));
13661 
13662                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13663                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13664                if (res < 0) {
13665                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13666                   return -1;
13667                }
13668             }
13669             close(ctlfd);
13670          } else if (!strcasecmp(v->name, "defaultcic")) {
13671             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13672          } else if (!strcasecmp(v->name, "defaultozz")) {
13673             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13674          } 
13675       } else if (!skipchannels)
13676          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
13677    }
13678    if (dahdichan[0]) { 
13679       /* The user has set 'dahdichan' */
13680       /*< \todo pass proper line number instead of 0 */
13681       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13682          return -1;
13683       }
13684    }
13685    /*< \todo why check for the pseudo in the per-channel section.
13686     * Any actual use for manual setup of the pseudo channel? */
13687    if (!found_pseudo && reload != 1) {
13688       /* use the default configuration for a channel, so
13689          that any settings from real configured channels
13690          don't "leak" into the pseudo channel config
13691       */
13692       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13693 
13694       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
13695 
13696       if (tmp) {
13697          if (option_verbose > 2)
13698             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13699       } else {
13700          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13701       }
13702    }
13703    return 0;
13704 }
13705       
13706 static int setup_dahdi(int reload)
13707 {
13708    struct ast_config *cfg;
13709    struct ast_variable *v;
13710    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13711    int res;
13712 
13713 #ifdef HAVE_PRI
13714    char *c;
13715    int spanno;
13716    int i, x;
13717    int logicalspan;
13718    int trunkgroup;
13719    int dchannels[NUM_DCHANS];
13720 #endif
13721 
13722 #ifdef HAVE_ZAPTEL
13723    int load_from_zapata_conf = 1;
13724 #else
13725    int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13726 #endif
13727 
13728    if (load_from_zapata_conf) {
13729       if (!(cfg = ast_config_load("zapata.conf"))) {
13730          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13731          return 0;
13732       }
13733    } else {
13734       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13735          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13736          return 0;
13737       }
13738    }
13739 
13740    /* It's a little silly to lock it, but we mind as well just to be sure */
13741    ast_mutex_lock(&iflock);
13742 #ifdef HAVE_PRI
13743    if (reload != 1) {
13744       /* Process trunkgroups first */
13745       v = ast_variable_browse(cfg, "trunkgroups");
13746       while (v) {
13747          if (!strcasecmp(v->name, "trunkgroup")) {
13748             trunkgroup = atoi(v->value);
13749             if (trunkgroup > 0) {
13750                if ((c = strchr(v->value, ','))) {
13751                   i = 0;
13752                   memset(dchannels, 0, sizeof(dchannels));
13753                   while (c && (i < NUM_DCHANS)) {
13754                      dchannels[i] = atoi(c + 1);
13755                      if (dchannels[i] < 0) {
13756                         ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13757                      } else
13758                         i++;
13759                      c = strchr(c + 1, ',');
13760                   }
13761                   if (i) {
13762                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13763                         ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
13764                      } else if (option_verbose > 1)
13765                         ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
13766                   } else
13767                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13768                } else
13769                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13770             } else
13771                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13772          } else if (!strcasecmp(v->name, "spanmap")) {
13773             spanno = atoi(v->value);
13774             if (spanno > 0) {
13775                if ((c = strchr(v->value, ','))) {
13776                   trunkgroup = atoi(c + 1);
13777                   if (trunkgroup > 0) {
13778                      if ((c = strchr(c + 1, ','))) 
13779                         logicalspan = atoi(c + 1);
13780                      else
13781                         logicalspan = 0;
13782                      if (logicalspan >= 0) {
13783                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13784                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13785                         } else if (option_verbose > 1) 
13786                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13787                      } else
13788                         ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
13789                   } else
13790                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13791                } else
13792                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13793             } else
13794                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13795          } else {
13796             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13797          }
13798          v = v->next;
13799       }
13800    }
13801 #endif
13802    
13803    /* Copy the default jb config over global_jbconf */
13804    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13805 
13806    v = ast_variable_browse(cfg, "channels");
13807    res = process_dahdi(&conf, "", v, reload, 0);
13808    ast_mutex_unlock(&iflock);
13809    ast_config_destroy(cfg);
13810    if (res)
13811       return res;
13812    cfg = ast_config_load("users.conf");
13813    if (cfg) {
13814       char *cat;
13815       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13816       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13817          if (!strcasecmp(cat, "general"))
13818             continue;
13819          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13820             struct dahdi_chan_conf sect_conf;
13821             memcpy(&sect_conf, &conf, sizeof(sect_conf));
13822 
13823             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13824          }
13825       }
13826       ast_config_destroy(cfg);
13827    }
13828 #ifdef HAVE_PRI
13829    if (reload != 1) {
13830       for (x = 0; x < NUM_SPANS; x++) {
13831          if (pris[x].pvts[0]) {
13832             if (start_pri(pris + x)) {
13833                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13834                return -1;
13835             } else if (option_verbose > 1)
13836                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13837          }
13838       }
13839    }
13840 #endif
13841 #ifdef HAVE_OPENR2
13842    if (reload != 1) {
13843       int x;
13844       for (x = 0; x < NUM_SPANS; x++) {
13845          if (r2links[x].protocol_context) {
13846             if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13847                ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13848                return -1;
13849             } else {
13850                ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13851             }
13852          }
13853       }
13854    }
13855 #endif
13856    /* And start the monitor for the first time */
13857    restart_monitor();
13858    return 0;
13859 }
13860 
13861 #define local_astman_register(a, b, c, d) do { \
13862                   if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13863                      ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13864                   } \
13865                   ast_manager_register("Zap" a, b, zap_ ## c, d); \
13866                  } while (0)
13867 
13868 static int load_module(void)
13869 {
13870    int res;
13871 
13872 #ifdef HAVE_PRI
13873    int y,i;
13874    memset(pris, 0, sizeof(pris));
13875    for (y = 0; y < NUM_SPANS; y++) {
13876       ast_mutex_init(&pris[y].lock);
13877       pris[y].offset = -1;
13878       pris[y].master = AST_PTHREADT_NULL;
13879       for (i = 0; i < NUM_DCHANS; i++)
13880          pris[y].fds[i] = -1;
13881    }
13882    pri_set_error(dahdi_pri_error);
13883    pri_set_message(dahdi_pri_message);
13884    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13885       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13886          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13887    }
13888    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13889       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13890 #endif
13891 #ifdef HAVE_OPENR2
13892    init_mfcr2_globals();
13893    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13894       ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
13895          dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
13896    }
13897    ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
13898       zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
13899 #endif
13900    if ((res = setup_dahdi(0))) {
13901       return AST_MODULE_LOAD_DECLINE;
13902    }
13903    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13904       chan_tech = &dahdi_tech;
13905    } else {
13906       chan_tech = &zap_tech;
13907    }
13908    if (ast_channel_register(chan_tech)) {
13909       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13910       __unload_module();
13911       return -1;
13912    }
13913 #ifdef HAVE_PRI
13914    ast_string_field_init(&inuse, 16);
13915    ast_string_field_set(&inuse, name, "GR-303InUse");
13916    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13917 #endif   
13918 #ifdef HAVE_OPENR2
13919    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
13920 #endif
13921    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13922    
13923    memset(round_robin, 0, sizeof(round_robin));
13924    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13925    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13926    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13927    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13928    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13929    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13930    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13931 
13932    ast_cond_init(&ss_thread_complete, NULL);
13933 
13934    return res;
13935 }
13936 
13937 static int dahdi_sendtext(struct ast_channel *c, const char *text)
13938 {
13939 #define  END_SILENCE_LEN 400
13940 #define  HEADER_MS 50
13941 #define  TRAILER_MS 5
13942 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
13943 #define  ASCII_BYTES_PER_CHAR 80
13944 
13945    unsigned char *buf,*mybuf;
13946    struct dahdi_pvt *p = c->tech_pvt;
13947    struct pollfd fds[1];
13948    int size,res,fd,len,x;
13949    int bytes=0;
13950    /* Initial carrier (imaginary) */
13951    float cr = 1.0;
13952    float ci = 0.0;
13953    float scont = 0.0;
13954    int index;
13955 
13956    index = dahdi_get_index(c, p, 0);
13957    if (index < 0) {
13958       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
13959       return -1;
13960    }
13961    if (!text[0]) return(0); /* if nothing to send, dont */
13962    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
13963    if (p->mate) 
13964       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
13965    else
13966       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
13967    if (!buf)
13968       return -1;
13969    mybuf = buf;
13970    if (p->mate) {
13971       int codec = AST_LAW(p);
13972       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
13973          PUT_CLID_MARKMS;
13974       }
13975       /* Put actual message */
13976       for (x = 0; text[x]; x++) {
13977          PUT_CLID(text[x]);
13978       }
13979       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
13980          PUT_CLID_MARKMS;
13981       }
13982       len = bytes;
13983       buf = mybuf;
13984    } else {
13985       len = tdd_generate(p->tdd, buf, text);
13986       if (len < 1) {
13987          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
13988          free(mybuf);
13989          return -1;
13990       }
13991    }
13992    memset(buf + len, 0x7f, END_SILENCE_LEN);
13993    len += END_SILENCE_LEN;
13994    fd = p->subs[index].dfd;
13995    while (len) {
13996       if (ast_check_hangup(c)) {
13997          free(mybuf);
13998          return -1;
13999       }
14000       size = len;
14001       if (size > READ_SIZE)
14002          size = READ_SIZE;
14003       fds[0].fd = fd;
14004       fds[0].events = POLLOUT | POLLPRI;
14005       fds[0].revents = 0;
14006       res = poll(fds, 1, -1);
14007       if (!res) {
14008          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14009          continue;
14010       }
14011         /* if got exception */
14012       if (fds[0].revents & POLLPRI) {
14013          ast_free(mybuf);
14014          return -1;
14015       }
14016       if (!(fds[0].revents & POLLOUT)) {
14017          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14018          continue;
14019       }
14020       res = write(fd, buf, size);
14021       if (res != size) {
14022          if (res == -1) {
14023             free(mybuf);
14024             return -1;
14025          }
14026          if (option_debug)
14027             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14028          break;
14029       }
14030       len -= size;
14031       buf += size;
14032    }
14033    free(mybuf);
14034    return(0);
14035 }
14036 
14037 
14038 static int reload(void)
14039 {
14040    int res = 0;
14041 
14042    res = setup_dahdi(1);
14043    if (res) {
14044       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14045       return -1;
14046    }
14047    return 0;
14048 }
14049 
14050 /* This is a workaround so that menuselect displays a proper description
14051  * AST_MODULE_INFO(, , "DAHDI Telephony"
14052  */
14053 
14054 #ifdef HAVE_PRI
14055 #define tdesc "DAHDI Telephony w/PRI"
14056 #else
14057 #define tdesc "DAHDI Telephony"
14058 #endif
14059 
14060 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14061       .load = load_module,
14062       .unload = unload_module,
14063       .reload = reload,
14064           );
14065 
14066 

Generated on Thu Dec 17 13:33:30 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7