Thu May 14 14:48:51 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  ***/
00047 
00048 #include "asterisk.h"
00049 
00050 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 180010 $")
00051 
00052 #include <stdio.h>
00053 #include <string.h>
00054 #ifdef __NetBSD__
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <errno.h>
00061 #include <stdlib.h>
00062 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00063 #include <stdint.h>
00064 #endif
00065 #include <unistd.h>
00066 #include <sys/ioctl.h>
00067 #include <math.h>
00068 #include <ctype.h>
00069 
00070 #ifdef HAVE_PRI
00071 #include <libpri.h>
00072 #endif
00073 
00074 #include "asterisk/lock.h"
00075 #include "asterisk/channel.h"
00076 #include "asterisk/config.h"
00077 #include "asterisk/logger.h"
00078 #include "asterisk/module.h"
00079 #include "asterisk/pbx.h"
00080 #include "asterisk/options.h"
00081 #include "asterisk/file.h"
00082 #include "asterisk/ulaw.h"
00083 #include "asterisk/alaw.h"
00084 #include "asterisk/callerid.h"
00085 #include "asterisk/adsi.h"
00086 #include "asterisk/cli.h"
00087 #include "asterisk/cdr.h"
00088 #include "asterisk/features.h"
00089 #include "asterisk/musiconhold.h"
00090 #include "asterisk/say.h"
00091 #include "asterisk/tdd.h"
00092 #include "asterisk/app.h"
00093 #include "asterisk/dsp.h"
00094 #include "asterisk/astdb.h"
00095 #include "asterisk/manager.h"
00096 #include "asterisk/causes.h"
00097 #include "asterisk/term.h"
00098 #include "asterisk/utils.h"
00099 #include "asterisk/transcap.h"
00100 #include "asterisk/stringfields.h"
00101 #include "asterisk/abstract_jb.h"
00102 #include "asterisk/smdi.h"
00103 #include "asterisk/astobj.h"
00104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00105 
00106 #include "asterisk/dahdi_compat.h"
00107 #include "asterisk/tonezone_compat.h"
00108 
00109 /*! Global jitterbuffer configuration - by default, jb is disabled */
00110 static struct ast_jb_conf default_jbconf =
00111 {
00112    .flags = 0,
00113    .max_size = -1,
00114    .resync_threshold = -1,
00115    .impl = ""
00116 };
00117 static struct ast_jb_conf global_jbconf;
00118 
00119 #ifndef DAHDI_TONEDETECT
00120 /* Work around older code with no tone detect */
00121 #define DAHDI_EVENT_DTMFDOWN 0
00122 #define DAHDI_EVENT_DTMFUP 0
00123 #endif
00124 
00125 /* define this to send PRI user-user information elements */
00126 #undef SUPPORT_USERUSER
00127 
00128 /*! 
00129  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00130  * the user hangs up to reset the state machine so ring works properly.
00131  * This is used to be able to support kewlstart by putting the zhone in
00132  * groundstart mode since their forward disconnect supervision is entirely
00133  * broken even though their documentation says it isn't and their support
00134  * is entirely unwilling to provide any assistance with their channel banks
00135  * even though their web site says they support their products for life.
00136  */
00137 /* #define ZHONE_HACK */
00138 
00139 /*! \note
00140  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00141  * before dialing on it.  Certain FXO interfaces always think they're out of
00142  * service with this method however.
00143  */
00144 /* #define DAHDI_CHECK_HOOKSTATE */
00145 
00146 /*! \brief Typically, how many rings before we should send Caller*ID */
00147 #define DEFAULT_CIDRINGS 1
00148 
00149 #define CHANNEL_PSEUDO -12
00150 
00151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00152 
00153 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00154 #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)) 
00155 
00156 static const char tdesc[] = "DAHDI Telephony Driver"
00157 #ifdef HAVE_PRI
00158                " w/PRI"
00159 #endif
00160 ;
00161 
00162 #define SIG_EM    DAHDI_SIG_EM
00163 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00165 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00166 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00167 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00168 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00169 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00170 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00171 #define SIG_FXSLS DAHDI_SIG_FXSLS
00172 #define SIG_FXSGS DAHDI_SIG_FXSGS
00173 #define SIG_FXSKS DAHDI_SIG_FXSKS
00174 #define SIG_FXOLS DAHDI_SIG_FXOLS
00175 #define SIG_FXOGS DAHDI_SIG_FXOGS
00176 #define SIG_FXOKS DAHDI_SIG_FXOKS
00177 #define SIG_PRI      DAHDI_SIG_CLEAR
00178 #define  SIG_SF      DAHDI_SIG_SF
00179 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00181 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00182 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00184 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00185 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00186 
00187 #define NUM_SPANS       32
00188 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00189 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00190 
00191 #define CHAN_PSEUDO  -2
00192 
00193 #define DCHAN_PROVISIONED (1 << 0)
00194 #define DCHAN_NOTINALARM  (1 << 1)
00195 #define DCHAN_UP          (1 << 2)
00196 
00197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00198 
00199 static char defaultcic[64] = "";
00200 static char defaultozz[64] = "";
00201 
00202 static char progzone[10] = "";
00203 
00204 static int distinctiveringaftercid = 0;
00205 
00206 static int numbufs = 4;
00207 
00208 #ifdef HAVE_PRI
00209 static struct ast_channel inuse;
00210 #ifdef PRI_GETSET_TIMERS
00211 static int pritimers[PRI_MAX_TIMERS];
00212 #endif
00213 static int pridebugfd = -1;
00214 static char pridebugfilename[1024] = "";
00215 #endif
00216 
00217 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00218 static int firstdigittimeout = 16000;
00219 
00220 /*! \brief How long to wait for following digits (FXO logic) */
00221 static int gendigittimeout = 8000;
00222 
00223 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00224 static int matchdigittimeout = 3000;
00225 
00226 /*! \brief Protect the interface list (of dahdi_pvt's) */
00227 AST_MUTEX_DEFINE_STATIC(iflock);
00228 
00229 
00230 static int ifcount = 0;
00231 
00232 #ifdef HAVE_PRI
00233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00234 #endif
00235 
00236 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00237    when it's doing something critical. */
00238 AST_MUTEX_DEFINE_STATIC(monlock);
00239 
00240 /*! \brief This is the thread for the monitor which checks for input on the channels
00241    which are not currently in use. */
00242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00243 static ast_cond_t ss_thread_complete;
00244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00245 AST_MUTEX_DEFINE_STATIC(restart_lock);
00246 static int ss_thread_count = 0;
00247 static int num_restart_pending = 0;
00248 
00249 static int restart_monitor(void);
00250 
00251 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);
00252 
00253 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00254 
00255 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00256 static inline int dahdi_get_event(int fd)
00257 {
00258    int j;
00259    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00260       return -1;
00261    return j;
00262 }
00263 
00264 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00265 static inline int dahdi_wait_event(int fd)
00266 {
00267    int i, j = 0;
00268    i = DAHDI_IOMUX_SIGEVENT;
00269    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00270       return -1;
00271    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00272       return -1;
00273    return j;
00274 }
00275 
00276 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00277 #define READ_SIZE 160
00278 
00279 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00280 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00281 
00282 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00283 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00284 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00285 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00286 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00287 
00288 struct dahdi_pvt;
00289 
00290 /*!
00291  * \brief Configured ring timeout base.
00292  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00293  */
00294 static int ringt_base = DEFAULT_RINGT;
00295 
00296 #ifdef HAVE_PRI
00297 
00298 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00299 #define PRI_CHANNEL(p) ((p) & 0xff)
00300 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00301 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00302 
00303 struct dahdi_pri {
00304    pthread_t master;                /*!< Thread of master */
00305    ast_mutex_t lock;                /*!< Mutex */
00306    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00307    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00308    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00309    int minunused;                   /*!< Min # of channels to keep empty */
00310    int minidle;                     /*!< Min # of "idling" calls to keep active */
00311    int nodetype;                    /*!< Node type */
00312    int switchtype;                     /*!< Type of switch to emulate */
00313    int nsf;                   /*!< Network-Specific Facilities */
00314    int dialplan;                    /*!< Dialing plan */
00315    int localdialplan;                  /*!< Local dialing plan */
00316    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00317    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00318    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00319    char privateprefix[20];                /*!< for private dialplans */
00320    char unknownprefix[20];                /*!< for unknown dialplans */
00321    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00322    int trunkgroup;                     /*!< What our trunkgroup is */
00323    int mastertrunkgroup;                  /*!< What trunk group is our master */
00324    int prilogicalspan;                 /*!< Logical span number within trunk group */
00325    int numchans;                    /*!< Num of channels we represent */
00326    int overlapdial;                 /*!< In overlap dialing mode */
00327    int facilityenable;                 /*!< Enable facility IEs */
00328    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00329    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00330    struct pri *pri;                 /*!< Currently active D-channel */
00331    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00332    int debug;
00333    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00334    /*! \brief Value set but not used */
00335    int offset;
00336    /*! \brief Span number put into user output messages */
00337    int span;
00338    /*! \brief TRUE if span is being reset/restarted */
00339    int resetting;
00340    /*! \brief Current position during a reset (-1 if not started) */
00341    int resetpos;
00342 #ifdef HAVE_PRI_INBANDDISCONNECT
00343    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00344 #endif
00345    time_t lastreset;                /*!< time when unused channels were last reset */
00346    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00347    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00348    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00349    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00350 };
00351 
00352 
00353 static struct dahdi_pri pris[NUM_SPANS];
00354 
00355 #if 0
00356 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00357 #else
00358 #define DEFAULT_PRI_DEBUG 0
00359 #endif
00360 
00361 static inline void pri_rel(struct dahdi_pri *pri)
00362 {
00363    ast_mutex_unlock(&pri->lock);
00364 }
00365 
00366 #else
00367 /*! Shut up the compiler */
00368 struct dahdi_pri;
00369 #endif
00370 
00371 #define SUB_REAL  0        /*!< Active call */
00372 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00373 #define SUB_THREEWAY 2        /*!< Three-way call */
00374 
00375 /* Polarity states */
00376 #define POLARITY_IDLE   0
00377 #define POLARITY_REV    1
00378 
00379 
00380 static struct dahdi_distRings drings;
00381 
00382 struct distRingData {
00383    int ring[3];
00384 };
00385 struct ringContextData {
00386    char contextData[AST_MAX_CONTEXT];
00387 };
00388 struct dahdi_distRings {
00389    struct distRingData ringnum[3];
00390    struct ringContextData ringContext[3];
00391 };
00392 
00393 static char *subnames[] = {
00394    "Real",
00395    "Callwait",
00396    "Threeway"
00397 };
00398 
00399 struct dahdi_subchannel {
00400    int dfd;
00401    struct ast_channel *owner;
00402    int chan;
00403    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00404    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00405    unsigned int needringing:1;
00406    unsigned int needbusy:1;
00407    unsigned int needcongestion:1;
00408    unsigned int needcallerid:1;
00409    unsigned int needanswer:1;
00410    unsigned int needflash:1;
00411    unsigned int needhold:1;
00412    unsigned int needunhold:1;
00413    unsigned int linear:1;
00414    unsigned int inthreeway:1;
00415    struct dahdi_confinfo curconf;
00416 };
00417 
00418 #define CONF_USER_REAL     (1 << 0)
00419 #define CONF_USER_THIRDCALL   (1 << 1)
00420 
00421 #define MAX_SLAVES   4
00422 
00423 static struct dahdi_pvt {
00424    ast_mutex_t lock;
00425    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00426                      /*!< Up to three channels can be associated with this call */
00427       
00428    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00429    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00430    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00431 
00432    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00433    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00434    int inconference;          /*!< If our real should be in the conference */
00435    
00436    int buf_no;             /*!< Number of buffers */
00437    int buf_policy;            /*!< Buffer policy */
00438    int sig;             /*!< Signalling style */
00439    /*!
00440     * \brief Nonzero if the signaling type is sent over a radio.
00441     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00442     */
00443    int radio;
00444    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00445    int oprmode;               /*!< "Operator Services" mode */
00446    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00447    /*! \brief Rx gain set by chan_dahdi.conf */
00448    float rxgain;
00449    /*! \brief Tx gain set by chan_dahdi.conf */
00450    float txgain;
00451    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00452    struct dahdi_pvt *next;          /*!< Next channel in list */
00453    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00454 
00455    /* flags */
00456 
00457    /*!
00458     * \brief TRUE if ADSI (Analog Display Services Interface) available
00459     * \note Set from the "adsi" value read in from chan_dahdi.conf
00460     */
00461    unsigned int adsi:1;
00462    /*!
00463     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00464     * call is answered by the remote party.
00465     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00466     */
00467    unsigned int answeronpolarityswitch:1;
00468    /*!
00469     * \brief TRUE if busy detection is enabled.
00470     * (Listens for the beep-beep busy pattern.)
00471     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00472     */
00473    unsigned int busydetect:1;
00474    /*!
00475     * \brief TRUE if call return is enabled.
00476     * (*69, if your dialplan doesn't catch this first)
00477     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00478     */
00479    unsigned int callreturn:1;
00480    /*!
00481     * \brief TRUE if busy extensions will hear the call-waiting tone
00482     * and can use hook-flash to switch between callers.
00483     * \note Can be disabled by dialing *70.
00484     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00485     */
00486    unsigned int callwaiting:1;
00487    /*!
00488     * \brief TRUE if send caller ID for Call Waiting
00489     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00490     */
00491    unsigned int callwaitingcallerid:1;
00492    /*!
00493     * \brief TRUE if support for call forwarding enabled.
00494     * Dial *72 to enable call forwarding.
00495     * Dial *73 to disable call forwarding.
00496     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00497     */
00498    unsigned int cancallforward:1;
00499    /*!
00500     * \brief TRUE if support for call parking is enabled.
00501     * \note Set from the "canpark" value read in from chan_dahdi.conf
00502     */
00503    unsigned int canpark:1;
00504    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00505    unsigned int confirmanswer:1;
00506    /*!
00507     * \brief TRUE if the channel is to be destroyed on hangup.
00508     * (Used by pseudo channels.)
00509     */
00510    unsigned int destroy:1;
00511    unsigned int didtdd:1;           /*!< flag to say its done it once */
00512    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00513    unsigned int dialednone:1;
00514    /*! \brief TRUE if in the process of dialing digits or sending something. */
00515    unsigned int dialing:1;
00516    /*! \brief TRUE if the transfer capability of the call is digital. */
00517    unsigned int digital:1;
00518    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00519    unsigned int dnd:1;
00520    /*! \brief XXX BOOLEAN Purpose??? */
00521    unsigned int echobreak:1;
00522    /*!
00523     * \brief TRUE if echo cancellation enabled when bridged.
00524     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00525     * \note Disabled if the echo canceller is not setup.
00526     */
00527    unsigned int echocanbridged:1;
00528    /*! \brief TRUE if echo cancellation is turned on. */
00529    unsigned int echocanon:1;
00530    /*! \brief TRUE if a fax tone has already been handled. */
00531    unsigned int faxhandled:1;
00532    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00533    unsigned int firstradio:1;
00534    /*!
00535     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00536     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00537     */
00538    unsigned int hanguponpolarityswitch:1;
00539    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00540    unsigned int hardwaredtmf:1;
00541    /*!
00542     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00543     * \note Caller ID can be disabled by dialing *67.
00544     * \note Caller ID can be enabled by dialing *82.
00545     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00546     */
00547    unsigned int hidecallerid:1;
00548    /*!
00549     * \brief TRUE if hide just the name not the number for legacy PBX use.
00550     * \note Only applies to PRI channels.
00551     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00552     */
00553    unsigned int hidecalleridname:1;
00554    /*! \brief TRUE if DTMF detection is disabled. */
00555    unsigned int ignoredtmf:1;
00556    /*!
00557     * \brief TRUE if the channel should be answered immediately
00558     * without attempting to gather any digits.
00559     * \note Set from the "immediate" value read in from chan_dahdi.conf
00560     */
00561    unsigned int immediate:1;
00562    /*! \brief TRUE if in an alarm condition. */
00563    unsigned int inalarm:1;
00564    unsigned int unknown_alarm:1;
00565    /*! \brief TRUE if TDD in MATE mode */
00566    unsigned int mate:1;
00567    /*! \brief TRUE if we originated the call leg. */
00568    unsigned int outgoing:1;
00569    /* unsigned int overlapdial:1;         unused and potentially confusing */
00570    /*!
00571     * \brief TRUE if busy extensions will hear the call-waiting tone
00572     * and can use hook-flash to switch between callers.
00573     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00574     */
00575    unsigned int permcallwaiting:1;
00576    /*!
00577     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00578     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00579     */
00580    unsigned int permhidecallerid:1;
00581    /*!
00582     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00583     * \note Set from the "priindication" value read in from chan_dahdi.conf
00584     */
00585    unsigned int priindication_oob:1;
00586    /*!
00587     * \brief TRUE if PRI B channels are always exclusively selected.
00588     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00589     */
00590    unsigned int priexclusive:1;
00591    /*!
00592     * \brief TRUE if we will pulse dial.
00593     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00594     */
00595    unsigned int pulse:1;
00596    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00597    unsigned int pulsedial:1;
00598    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00599    /*!
00600     * \brief TRUE if caller ID is restricted.
00601     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00602     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00603     */
00604    unsigned int restrictcid:1;
00605    /*!
00606     * \brief TRUE if three way calling is enabled
00607     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00608     */
00609    unsigned int threewaycalling:1;
00610    /*!
00611     * \brief TRUE if call transfer is enabled
00612     * \note For FXS ports (either direct analog or over T1/E1):
00613     *   Support flash-hook call transfer
00614     * \note For digital ports using ISDN PRI protocols:
00615     *   Support switch-side transfer (called 2BCT, RLT or other names)
00616     * \note Set from the "transfer" value read in from chan_dahdi.conf
00617     */
00618    unsigned int transfer:1;
00619    /*!
00620     * \brief TRUE if caller ID is used on this channel.
00621     * \note PRI spans will save caller ID from the networking peer.
00622     * \note FXS ports will generate the caller ID spill.
00623     * \note FXO ports will listen for the caller ID spill.
00624     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00625     */
00626    unsigned int use_callerid:1;
00627    /*!
00628     * \brief TRUE if we will use the calling presentation setting
00629     * from the Asterisk channel for outgoing calls.
00630     * \note Only applies to PRI channels.
00631     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00632     */
00633    unsigned int use_callingpres:1;
00634    /*!
00635     * \brief TRUE if distinctive rings are to be detected.
00636     * \note For FXO lines
00637     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00638     */
00639    unsigned int usedistinctiveringdetection:1;
00640    /*!
00641     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00642     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00643     */
00644    unsigned int dahditrcallerid:1;
00645    /*!
00646     * \brief TRUE if allowed to flash-transfer to busy channels.
00647     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00648     */
00649    unsigned int transfertobusy:1;
00650 #if defined(HAVE_PRI)
00651    /*! \brief TRUE if channel is alerting/ringing */
00652    unsigned int alerting:1;
00653    /*! \brief TRUE if the call has already gone/hungup */
00654    unsigned int alreadyhungup:1;
00655    /*!
00656     * \brief TRUE if this is an idle call
00657     * \note Applies to PRI channels.
00658     */
00659    unsigned int isidlecall:1;
00660    /*!
00661     * \brief TRUE if call is in a proceeding state.
00662     * The call has started working its way through the network.
00663     */
00664    unsigned int proceeding:1;
00665    /*! \brief TRUE if the call has seen progress through the network. */
00666    unsigned int progress:1;
00667    /*!
00668     * \brief TRUE if this channel is being reset/restarted
00669     * \note Applies to PRI channels.
00670     */
00671    unsigned int resetting:1;
00672    /*!
00673     * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
00674     * \note Applies to PRI channels.
00675     */
00676    unsigned int setup_ack:1;
00677 #endif
00678    /*!
00679     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00680     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00681     */
00682    unsigned int use_smdi:1;
00683    /*! \brief The serial port to listen for SMDI data on */
00684    struct ast_smdi_interface *smdi_iface;
00685 
00686    /*! \brief Distinctive Ring data */
00687    struct dahdi_distRings drings;
00688 
00689    /*!
00690     * \brief The configured context for incoming calls.
00691     * \note The "context" string read in from chan_dahdi.conf
00692     */
00693    char context[AST_MAX_CONTEXT];
00694    /*!
00695     * \brief Saved context string.
00696     */
00697    char defcontext[AST_MAX_CONTEXT];
00698    /*! \brief Extension to use in the dialplan. */
00699    char exten[AST_MAX_EXTENSION];
00700    /*!
00701     * \brief Language configured for calls.
00702     * \note The "language" string read in from chan_dahdi.conf
00703     */
00704    char language[MAX_LANGUAGE];
00705    /*!
00706     * \brief The configured music-on-hold class to use for calls.
00707     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00708     */
00709    char mohinterpret[MAX_MUSICCLASS];
00710    /*!
00711     * \brief Sugggested music-on-hold class for peer channel to use for calls.
00712     * \note The "mohsuggest" string read in from chan_dahdi.conf
00713     */
00714    char mohsuggest[MAX_MUSICCLASS];
00715 #ifdef PRI_ANI
00716    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
00717    char cid_ani[AST_MAX_EXTENSION];
00718 #endif
00719    /*! \brief Caller ID number from an incoming call. */
00720    char cid_num[AST_MAX_EXTENSION];
00721    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
00722    int cid_ton;
00723    /*! \brief Caller ID name from an incoming call. */
00724    char cid_name[AST_MAX_EXTENSION];
00725    /*! \brief Last Caller ID number from an incoming call. */
00726    char lastcid_num[AST_MAX_EXTENSION];
00727    /*! \brief Last Caller ID name from an incoming call. */
00728    char lastcid_name[AST_MAX_EXTENSION];
00729    char *origcid_num;            /*!< malloced original callerid */
00730    char *origcid_name;           /*!< malloced original callerid */
00731    /*! \brief Call waiting number. */
00732    char callwait_num[AST_MAX_EXTENSION];
00733    /*! \brief Call waiting name. */
00734    char callwait_name[AST_MAX_EXTENSION];
00735    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
00736    char rdnis[AST_MAX_EXTENSION];
00737    /*! \brief Dialed Number Identifier */
00738    char dnid[AST_MAX_EXTENSION];
00739    /*!
00740     * \brief Bitmapped groups this belongs to.
00741     * \note The "group" bitmapped group string read in from chan_dahdi.conf
00742     */
00743    ast_group_t group;
00744    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
00745    int law;
00746    int confno;             /*!< Our conference */
00747    int confusers;             /*!< Who is using our conference */
00748    int propconfno;               /*!< Propagated conference number */
00749    /*!
00750     * \brief Bitmapped call groups this belongs to.
00751     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
00752     */
00753    ast_group_t callgroup;
00754    /*!
00755     * \brief Bitmapped pickup groups this belongs to.
00756     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
00757     */
00758    ast_group_t pickupgroup;
00759    int channel;               /*!< Channel Number or CRV */
00760    int span;               /*!< Span number */
00761    time_t guardtime;          /*!< Must wait this much time before using for new call */
00762    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
00763    int cid_start;             /*!< CID start indicator, polarity or ring */
00764    int callingpres;           /*!< The value of callling presentation that we're going to use when placing a PRI call */
00765    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
00766    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
00767    /*! \brief Analog caller ID waveform sample buffer */
00768    unsigned char *cidspill;
00769    /*! \brief Position in the cidspill buffer to send out next. */
00770    int cidpos;
00771    /*! \brief Length of the cidspill buffer containing samples. */
00772    int cidlen;
00773    /*! \brief Ring timeout timer?? */
00774    int ringt;
00775    /*!
00776     * \brief Ring timeout base.
00777     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
00778     */
00779    int ringt_base;
00780    /*!
00781     * \brief Number of most significant digits/characters to strip from the dialed number.
00782     * \note Feature is deprecated.  Use dialplan logic.
00783     * \note The characters are stripped before the PRI TON/NPI prefix
00784     * characters are processed.
00785     */
00786    int stripmsd;
00787    /*! \brief BOOLEAN. XXX Meaning what?? */
00788    int callwaitcas;
00789    /*! \brief Number of call waiting rings. */
00790    int callwaitrings;
00791    /*! \brief Number of echo cancel taps.  0 if echo canceller not requested. */
00792    int echocancel;
00793    /*!
00794     * \brief Echo training time. 0 = disabled
00795     * \note Set from the "echotraining" value read in from chan_dahdi.conf
00796     */
00797    int echotraining;
00798    /*! \brief Filled with 'w'.  XXX Purpose?? */
00799    char echorest[20];
00800    /*!
00801     * \brief Number of times to see "busy" tone before hanging up.
00802     * \note Set from the "busycount" value read in from chan_dahdi.conf
00803     */
00804    int busycount;
00805    /*!
00806     * \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
00807     * \note Set from the "busycompare" value read in from chan_dahdi.conf
00808     */
00809    int busycompare;
00810    /*!
00811     * \brief Lenght of "tone" in ms.
00812     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00813     */
00814    int busytonelength;
00815    /*!
00816     * \brief Lenght of "silence" in ms.
00817     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00818     */
00819    int busyquietlength;
00820    /*!
00821     * \brief  Maximun percentage difference allowed between measured and actual pattern
00822     * \note Set from the "busyfuzziness" value read in from chan_dahdi.conf
00823     */
00824    int busyfuzziness;
00825    /*!
00826     * \brief Maximun signal average level considered as silence in this channel
00827     * \note Set from the "silencethreshold" value read in from chan_dahdi.conf
00828     */
00829    int silencethreshold;
00830    /*!
00831     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
00832     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
00833     */
00834    int callprogress;
00835    struct timeval flashtime;        /*!< Last flash-hook time */
00836    /*! \brief Opaque DSP configuration structure. */
00837    struct ast_dsp *dsp;
00838    //int cref;             /*!< Call reference number (Not used) */
00839    /*! \brief DAHDI dial operation command struct for ioctl() call. */
00840    struct dahdi_dialoperation dop;
00841    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
00842    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
00843    char finaldial[64];
00844    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
00845    int amaflags;              /*!< AMA Flags */
00846    struct tdd_state *tdd;           /*!< TDD flag */
00847    /*! \brief Accumulated call forwarding number. */
00848    char call_forward[AST_MAX_EXTENSION];
00849    /*!
00850     * \brief Voice mailbox location.
00851     * \note Set from the "mailbox" string read in from chan_dahdi.conf
00852     */
00853    char mailbox[AST_MAX_EXTENSION];
00854    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
00855    char dialdest[256];
00856    /*! \brief Time the interface went on-hook. */
00857    int onhooktime;
00858    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
00859    int msgstate;
00860    int distinctivering;          /*!< Which distinctivering to use */
00861    int cidrings;              /*!< Which ring to deliver CID on */
00862    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
00863    /*! \brief Holding place for event injected from outside normal operation. */
00864    int fake_event;
00865    /*!
00866     * \brief Minimal time period (ms) between the answer polarity
00867     * switch and hangup polarity switch.
00868     */
00869    int polarityonanswerdelay;
00870    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
00871    struct timeval polaritydelaytv;
00872    /*!
00873     * \brief Send caller ID after this many rings.
00874     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
00875     */
00876    int sendcalleridafter;
00877 #ifdef HAVE_PRI
00878    /*! \brief DAHDI PRI control parameters */
00879    struct dahdi_pri *pri;
00880    /*! \brief XXX Purpose??? */
00881    struct dahdi_pvt *bearer;
00882    /*! \brief XXX Purpose??? */
00883    struct dahdi_pvt *realcall;
00884    /*! \brief Opaque libpri call control structure */
00885    q931_call *call;
00886    /*! \brief Channel number in span. */
00887    int prioffset;
00888    /*! \brief Logical span number within trunk group */
00889    int logicalspan;
00890 #endif   
00891    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
00892    int polarity;
00893    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
00894    int dsp_features;
00895    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
00896    char begindigit;
00897 } *iflist = NULL, *ifend = NULL;
00898 
00899 /*! \brief Channel configuration from chan_dahdi.conf .
00900  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
00901  * Generally there is a field here for every possible configuration item.
00902  *
00903  * The state of fields is saved along the parsing and whenever a 'channel'
00904  * statement is reached, the current dahdi_chan_conf is used to configure the 
00905  * channel (struct dahdi_pvt)
00906  *
00907  * @seealso dahdi_chan_init for the default values.
00908  */
00909 struct dahdi_chan_conf {
00910    struct dahdi_pvt chan;
00911 #ifdef HAVE_PRI
00912    struct dahdi_pri pri;
00913 #endif
00914    struct dahdi_params timing;
00915 
00916    /*!
00917     * \brief The serial port to listen for SMDI data on
00918     * \note Set from the "smdiport" string read in from chan_dahdi.conf
00919     */
00920    char smdi_port[SMDI_MAX_FILENAME_LEN];
00921 };
00922 
00923 /** returns a new dahdi_chan_conf with default values (by-value) */
00924 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00925    /* recall that if a field is not included here it is initialized
00926     * to 0 or equivalent
00927     */
00928    struct dahdi_chan_conf conf = {
00929 #ifdef HAVE_PRI
00930       .pri = {
00931          .nsf = PRI_NSF_NONE,
00932          .switchtype = PRI_SWITCH_NI2,
00933          .dialplan = PRI_NATIONAL_ISDN + 1,
00934          .localdialplan = PRI_NATIONAL_ISDN + 1,
00935          .nodetype = PRI_CPE,
00936 
00937          .minunused = 2,
00938          .idleext = "",
00939          .idledial = "",
00940          .internationalprefix = "",
00941          .nationalprefix = "",
00942          .localprefix = "",
00943          .privateprefix = "",
00944          .unknownprefix = "",
00945 
00946          .resetinterval = 3600
00947       },
00948 #endif
00949       .chan = {
00950          .context = "default",
00951          .cid_num = "",
00952          .cid_name = "",
00953          .mohinterpret = "default",
00954          .mohsuggest = "",
00955          .transfertobusy = 1,
00956 
00957          .cid_signalling = CID_SIG_BELL,
00958          .cid_start = CID_START_RING,
00959          .dahditrcallerid = 0,
00960          .use_callerid = 1,
00961          .sig = -1,
00962          .outsigmod = -1,
00963 
00964          .tonezone = -1,
00965 
00966          .echocancel = 1,
00967 
00968          .busycount = 3,
00969          .busycompare = 0,
00970          .busytonelength = 0,
00971          .busyquietlength = 0,
00972          .busyfuzziness = 0,
00973          .silencethreshold = 0,
00974 
00975          .accountcode = "",
00976 
00977          .mailbox = "",
00978 
00979 
00980          .polarityonanswerdelay = 600,
00981 
00982          .sendcalleridafter = DEFAULT_CIDRINGS,
00983 
00984          .buf_policy = DAHDI_POLICY_IMMEDIATE,
00985          .buf_no = numbufs
00986       },
00987       .timing = {
00988          .prewinktime = -1,
00989          .preflashtime = -1,
00990          .winktime = -1,
00991          .flashtime = -1,
00992          .starttime = -1,
00993          .rxwinktime = -1,
00994          .rxflashtime = -1,
00995          .debouncetime = -1
00996       },
00997       .smdi_port = "/dev/ttyS0",
00998    };
00999 
01000    return conf;
01001 }
01002 
01003 
01004 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01005 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01006 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01007 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01008 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01009 static int dahdi_hangup(struct ast_channel *ast);
01010 static int dahdi_answer(struct ast_channel *ast);
01011 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01012 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01013 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01014 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01015 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01016 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01017 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
01018 
01019 static const struct ast_channel_tech dahdi_tech = {
01020    .type = "DAHDI",
01021    .description = tdesc,
01022    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01023    .requester = dahdi_request,
01024    .send_digit_begin = dahdi_digit_begin,
01025    .send_digit_end = dahdi_digit_end,
01026    .send_text = dahdi_sendtext,
01027    .call = dahdi_call,
01028    .hangup = dahdi_hangup,
01029    .answer = dahdi_answer,
01030    .read = dahdi_read,
01031    .write = dahdi_write,
01032    .bridge = dahdi_bridge,
01033    .exception = dahdi_exception,
01034    .indicate = dahdi_indicate,
01035    .fixup = dahdi_fixup,
01036    .setoption = dahdi_setoption,
01037    .func_channel_read = dahdi_func_read,
01038 };
01039 
01040 static const struct ast_channel_tech zap_tech = {
01041    .type = "Zap",
01042    .description = tdesc,
01043    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01044    .requester = dahdi_request,
01045    .send_digit_begin = dahdi_digit_begin,
01046    .send_digit_end = dahdi_digit_end,
01047    .send_text = dahdi_sendtext,
01048    .call = dahdi_call,
01049    .hangup = dahdi_hangup,
01050    .answer = dahdi_answer,
01051    .read = dahdi_read,
01052    .write = dahdi_write,
01053    .bridge = dahdi_bridge,
01054    .exception = dahdi_exception,
01055    .indicate = dahdi_indicate,
01056    .fixup = dahdi_fixup,
01057    .setoption = dahdi_setoption,
01058    .func_channel_read = dahdi_func_read,
01059 };
01060 
01061 static const struct ast_channel_tech *chan_tech;
01062 
01063 #ifdef HAVE_PRI
01064 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01065 #else
01066 #define GET_CHANNEL(p) ((p)->channel)
01067 #endif
01068 
01069 struct dahdi_pvt *round_robin[32];
01070 
01071 #ifdef HAVE_PRI
01072 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01073 {
01074    int res;
01075    /* Grab the lock first */
01076    do {
01077       res = ast_mutex_trylock(&pri->lock);
01078       if (res) {
01079          DEADLOCK_AVOIDANCE(&pvt->lock);
01080       }
01081    } while (res);
01082    /* Then break the poll */
01083    if (pri->master != AST_PTHREADT_NULL)
01084       pthread_kill(pri->master, SIGURG);
01085    return 0;
01086 }
01087 #endif
01088 
01089 #define NUM_CADENCE_MAX 25
01090 static int num_cadence = 4;
01091 static int user_has_defined_cadences = 0;
01092 
01093 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01094    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01095    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01096    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01097    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01098 };
01099 
01100 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01101  * is 1, the second pause is 2 and so on.
01102  */
01103 
01104 static int cidrings[NUM_CADENCE_MAX] = {
01105    2,                            /*!< Right after first long ring */
01106    4,                            /*!< Right after long part */
01107    3,                            /*!< After third chirp */
01108    2,                            /*!< Second spell */
01109 };
01110 
01111 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01112          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01113 
01114 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01115 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01116 
01117 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01118 {
01119    int res;
01120    if (p->subs[SUB_REAL].owner == ast)
01121       res = 0;
01122    else if (p->subs[SUB_CALLWAIT].owner == ast)
01123       res = 1;
01124    else if (p->subs[SUB_THREEWAY].owner == ast)
01125       res = 2;
01126    else {
01127       res = -1;
01128       if (!nullok)
01129          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01130    }
01131    return res;
01132 }
01133 
01134 #ifdef HAVE_PRI
01135 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01136 #else
01137 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01138 #endif
01139 {
01140 #ifdef HAVE_PRI
01141    if (pri)
01142       ast_mutex_unlock(&pri->lock);
01143 #endif         
01144    for (;;) {
01145       if (p->subs[a].owner) {
01146          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01147             DEADLOCK_AVOIDANCE(&p->lock);
01148          } else {
01149             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01150             ast_mutex_unlock(&p->subs[a].owner->lock);
01151             break;
01152          }
01153       } else
01154          break;
01155    }
01156 #ifdef HAVE_PRI
01157    if (pri)
01158       ast_mutex_lock(&pri->lock);
01159 #endif         
01160 }
01161 
01162 #ifdef HAVE_PRI
01163 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01164 #else
01165 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01166 #endif
01167 {
01168    /* We must unlock the PRI to avoid the possibility of a deadlock */
01169 #ifdef HAVE_PRI
01170    if (pri)
01171       ast_mutex_unlock(&pri->lock);
01172 #endif      
01173    for (;;) {
01174       if (p->owner) {
01175          if (ast_mutex_trylock(&p->owner->lock)) {
01176             DEADLOCK_AVOIDANCE(&p->lock);
01177          } else {
01178             ast_queue_frame(p->owner, f);
01179             ast_mutex_unlock(&p->owner->lock);
01180             break;
01181          }
01182       } else
01183          break;
01184    }
01185 #ifdef HAVE_PRI
01186    if (pri)
01187       ast_mutex_lock(&pri->lock);
01188 #endif      
01189 }
01190 
01191 static int restore_gains(struct dahdi_pvt *p);
01192 
01193 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01194 {
01195    int tchan;
01196    int tinthreeway;
01197    struct ast_channel *towner;
01198 
01199    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01200 
01201    tchan = p->subs[a].chan;
01202    towner = p->subs[a].owner;
01203    tinthreeway = p->subs[a].inthreeway;
01204 
01205    p->subs[a].chan = p->subs[b].chan;
01206    p->subs[a].owner = p->subs[b].owner;
01207    p->subs[a].inthreeway = p->subs[b].inthreeway;
01208 
01209    p->subs[b].chan = tchan;
01210    p->subs[b].owner = towner;
01211    p->subs[b].inthreeway = tinthreeway;
01212 
01213    if (p->subs[a].owner) 
01214       p->subs[a].owner->fds[0] = p->subs[a].dfd;
01215    if (p->subs[b].owner) 
01216       p->subs[b].owner->fds[0] = p->subs[b].dfd;
01217    wakeup_sub(p, a, NULL);
01218    wakeup_sub(p, b, NULL);
01219 }
01220 
01221 static int dahdi_open(char *fn)
01222 {
01223    int fd;
01224    int isnum;
01225    int chan = 0;
01226    int bs;
01227    int x;
01228    isnum = 1;
01229    for (x = 0; x < strlen(fn); x++) {
01230       if (!isdigit(fn[x])) {
01231          isnum = 0;
01232          break;
01233       }
01234    }
01235    if (isnum) {
01236       chan = atoi(fn);
01237       if (chan < 1) {
01238          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01239          return -1;
01240       }
01241       fn = DAHDI_FILE_CHANNEL;
01242    }
01243    fd = open(fn, O_RDWR | O_NONBLOCK);
01244    if (fd < 0) {
01245       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01246       return -1;
01247    }
01248    if (chan) {
01249       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01250          x = errno;
01251          close(fd);
01252          errno = x;
01253          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01254          return -1;
01255       }
01256    }
01257    bs = READ_SIZE;
01258    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01259       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01260       x = errno;
01261       close(fd);
01262       errno = x;
01263       return -1;
01264    }
01265    return fd;
01266 }
01267 
01268 static void dahdi_close(int fd)
01269 {
01270    if (fd > 0)
01271       close(fd);
01272 }
01273 
01274 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01275 {
01276    dahdi_close(chan_pvt->subs[sub_num].dfd);
01277    chan_pvt->subs[sub_num].dfd = -1;
01278 }
01279  
01280 #ifdef HAVE_PRI
01281 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01282 {
01283    dahdi_close(pri->fds[fd_num]);
01284    pri->fds[fd_num] = -1;
01285 }
01286 #endif
01287 
01288 static int dahdi_setlinear(int dfd, int linear)
01289 {
01290    int res;
01291    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01292    if (res)
01293       return res;
01294    return 0;
01295 }
01296 
01297 
01298 static int alloc_sub(struct dahdi_pvt *p, int x)
01299 {
01300    struct dahdi_bufferinfo bi;
01301    int res;
01302    if (p->subs[x].dfd < 0) {
01303       p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01304       if (p->subs[x].dfd > -1) {
01305          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01306          if (!res) {
01307             bi.txbufpolicy = p->buf_policy;
01308             bi.rxbufpolicy = p->buf_policy;
01309             bi.numbufs = p->buf_no;
01310             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01311             if (res < 0) {
01312                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01313             }
01314          } else 
01315             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01316          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01317             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01318             dahdi_close_sub(p, x);
01319             return -1;
01320          }
01321          if (option_debug)
01322             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01323          return 0;
01324       } else
01325          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01326       return -1;
01327    }
01328    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01329    return -1;
01330 }
01331 
01332 static int unalloc_sub(struct dahdi_pvt *p, int x)
01333 {
01334    if (!x) {
01335       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01336       return -1;
01337    }
01338    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01339    dahdi_close_sub(p, x);
01340    p->subs[x].linear = 0;
01341    p->subs[x].chan = 0;
01342    p->subs[x].owner = NULL;
01343    p->subs[x].inthreeway = 0;
01344    p->polarity = POLARITY_IDLE;
01345    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01346    return 0;
01347 }
01348 
01349 static int digit_to_dtmfindex(char digit)
01350 {
01351    if (isdigit(digit))
01352       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01353    else if (digit >= 'A' && digit <= 'D')
01354       return DAHDI_TONE_DTMF_A + (digit - 'A');
01355    else if (digit >= 'a' && digit <= 'd')
01356       return DAHDI_TONE_DTMF_A + (digit - 'a');
01357    else if (digit == '*')
01358       return DAHDI_TONE_DTMF_s;
01359    else if (digit == '#')
01360       return DAHDI_TONE_DTMF_p;
01361    else
01362       return -1;
01363 }
01364 
01365 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01366 {
01367    struct dahdi_pvt *pvt;
01368    int index;
01369    int dtmf = -1;
01370    
01371    pvt = chan->tech_pvt;
01372 
01373    ast_mutex_lock(&pvt->lock);
01374 
01375    index = dahdi_get_index(chan, pvt, 0);
01376 
01377    if ((index != SUB_REAL) || !pvt->owner)
01378       goto out;
01379 
01380 #ifdef HAVE_PRI
01381    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01382       if (pvt->setup_ack) {
01383          if (!pri_grab(pvt, pvt->pri)) {
01384             pri_information(pvt->pri->pri, pvt->call, digit);
01385             pri_rel(pvt->pri);
01386          } else
01387             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01388       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01389          int res;
01390          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01391          res = strlen(pvt->dialdest);
01392          pvt->dialdest[res++] = digit;
01393          pvt->dialdest[res] = '\0';
01394       }
01395       goto out;
01396    }
01397 #endif
01398    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01399       goto out;
01400 
01401    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01402       int res;
01403       struct dahdi_dialoperation zo = {
01404          .op = DAHDI_DIAL_OP_APPEND,
01405          .dialstr[0] = 'T',
01406          .dialstr[1] = digit,
01407          .dialstr[2] = 0,
01408       };
01409       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01410          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01411       else
01412          pvt->dialing = 1;
01413    } else {
01414       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01415       pvt->dialing = 1;
01416       pvt->begindigit = digit;
01417    }
01418 
01419 out:
01420    ast_mutex_unlock(&pvt->lock);
01421 
01422    return 0;
01423 }
01424 
01425 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01426 {
01427    struct dahdi_pvt *pvt;
01428    int res = 0;
01429    int index;
01430    int x;
01431    
01432    pvt = chan->tech_pvt;
01433 
01434    ast_mutex_lock(&pvt->lock);
01435    
01436    index = dahdi_get_index(chan, pvt, 0);
01437 
01438    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01439       goto out;
01440 
01441 #ifdef HAVE_PRI
01442    /* This means that the digit was already sent via PRI signalling */
01443    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01444       goto out;
01445 #endif
01446 
01447    if (pvt->begindigit) {
01448       x = -1;
01449       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01450       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01451       pvt->dialing = 0;
01452       pvt->begindigit = 0;
01453    }
01454 
01455 out:
01456    ast_mutex_unlock(&pvt->lock);
01457 
01458    return res;
01459 }
01460 
01461 static char *events[] = {
01462    "No event",
01463    "On hook",
01464    "Ring/Answered",
01465    "Wink/Flash",
01466    "Alarm",
01467    "No more alarm",
01468    "HDLC Abort",
01469    "HDLC Overrun",
01470    "HDLC Bad FCS",
01471    "Dial Complete",
01472    "Ringer On",
01473    "Ringer Off",
01474    "Hook Transition Complete",
01475    "Bits Changed",
01476    "Pulse Start",
01477    "Timer Expired",
01478    "Timer Ping",
01479    "Polarity Reversal",
01480    "Ring Begin",
01481 };
01482 
01483 static struct {
01484    int alarm;
01485    char *name;
01486 } alarms[] = {
01487    { DAHDI_ALARM_RED, "Red Alarm" },
01488    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01489    { DAHDI_ALARM_BLUE, "Blue Alarm" },
01490    { DAHDI_ALARM_RECOVER, "Recovering" },
01491    { DAHDI_ALARM_LOOPBACK, "Loopback" },
01492    { DAHDI_ALARM_NOTOPEN, "Not Open" },
01493    { DAHDI_ALARM_NONE, "None" },
01494 };
01495 
01496 static char *alarm2str(int alarm)
01497 {
01498    int x;
01499    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01500       if (alarms[x].alarm & alarm)
01501          return alarms[x].name;
01502    }
01503    return alarm ? "Unknown Alarm" : "No Alarm";
01504 }
01505 
01506 static char *event2str(int event)
01507 {
01508    static char buf[256];
01509    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01510       return events[event];
01511    sprintf(buf, "Event %d", event); /* safe */
01512    return buf;
01513 }
01514 
01515 #ifdef HAVE_PRI
01516 static char *dialplan2str(int dialplan)
01517 {
01518    if (dialplan == -1) {
01519       return("Dynamically set dialplan in ISDN");
01520    }
01521    return (pri_plan2str(dialplan));
01522 }
01523 #endif
01524 
01525 static char *dahdi_sig2str(int sig)
01526 {
01527    static char buf[256];
01528    switch (sig) {
01529    case SIG_EM:
01530       return "E & M Immediate";
01531    case SIG_EMWINK:
01532       return "E & M Wink";
01533    case SIG_EM_E1:
01534       return "E & M E1";
01535    case SIG_FEATD:
01536       return "Feature Group D (DTMF)";
01537    case SIG_FEATDMF:
01538       return "Feature Group D (MF)";
01539    case SIG_FEATDMF_TA:
01540       return "Feature Groud D (MF) Tandem Access";
01541    case SIG_FEATB:
01542       return "Feature Group B (MF)";
01543    case SIG_E911:
01544       return "E911 (MF)";
01545    case SIG_FGC_CAMA:
01546       return "FGC/CAMA (Dialpulse)";
01547    case SIG_FGC_CAMAMF:
01548       return "FGC/CAMA (MF)";
01549    case SIG_FXSLS:
01550       return "FXS Loopstart";
01551    case SIG_FXSGS:
01552       return "FXS Groundstart";
01553    case SIG_FXSKS:
01554       return "FXS Kewlstart";
01555    case SIG_FXOLS:
01556       return "FXO Loopstart";
01557    case SIG_FXOGS:
01558       return "FXO Groundstart";
01559    case SIG_FXOKS:
01560       return "FXO Kewlstart";
01561    case SIG_PRI:
01562       return "ISDN PRI";
01563    case SIG_SF:
01564       return "SF (Tone) Immediate";
01565    case SIG_SFWINK:
01566       return "SF (Tone) Wink";
01567    case SIG_SF_FEATD:
01568       return "SF (Tone) with Feature Group D (DTMF)";
01569    case SIG_SF_FEATDMF:
01570       return "SF (Tone) with Feature Group D (MF)";
01571    case SIG_SF_FEATB:
01572       return "SF (Tone) with Feature Group B (MF)";
01573    case SIG_GR303FXOKS:
01574       return "GR-303 with FXOKS";
01575    case SIG_GR303FXSKS:
01576       return "GR-303 with FXSKS";
01577    case 0:
01578       return "Pseudo";
01579    default:
01580       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01581       return buf;
01582    }
01583 }
01584 
01585 #define sig2str dahdi_sig2str
01586 
01587 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
01588 {
01589    /* If the conference already exists, and we're already in it
01590       don't bother doing anything */
01591    struct dahdi_confinfo zi;
01592    
01593    memset(&zi, 0, sizeof(zi));
01594    zi.chan = 0;
01595 
01596    if (slavechannel > 0) {
01597       /* If we have only one slave, do a digital mon */
01598       zi.confmode = DAHDI_CONF_DIGITALMON;
01599       zi.confno = slavechannel;
01600    } else {
01601       if (!index) {
01602          /* Real-side and pseudo-side both participate in conference */
01603          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01604             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01605       } else
01606          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01607       zi.confno = p->confno;
01608    }
01609    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01610       return 0;
01611    if (c->dfd < 0)
01612       return 0;
01613    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01614       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01615       return -1;
01616    }
01617    if (slavechannel < 1) {
01618       p->confno = zi.confno;
01619    }
01620    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01621    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01622    return 0;
01623 }
01624 
01625 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01626 {
01627    /* If they're listening to our channel, they're ours */  
01628    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01629       return 1;
01630    /* If they're a talker on our (allocated) conference, they're ours */
01631    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01632       return 1;
01633    return 0;
01634 }
01635 
01636 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
01637 {
01638    struct dahdi_confinfo zi;
01639    if (/* Can't delete if there's no dfd */
01640       (c->dfd < 0) ||
01641       /* Don't delete from the conference if it's not our conference */
01642       !isourconf(p, c)
01643       /* Don't delete if we don't think it's conferenced at all (implied) */
01644       ) return 0;
01645    memset(&zi, 0, sizeof(zi));
01646    zi.chan = 0;
01647    zi.confno = 0;
01648    zi.confmode = 0;
01649    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01650       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01651       return -1;
01652    }
01653    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01654    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01655    return 0;
01656 }
01657 
01658 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01659 {
01660    int x;
01661    int useslavenative;
01662    struct dahdi_pvt *slave = NULL;
01663    /* Start out optimistic */
01664    useslavenative = 1;
01665    /* Update conference state in a stateless fashion */
01666    for (x = 0; x < 3; x++) {
01667       /* Any three-way calling makes slave native mode *definitely* out
01668          of the question */
01669       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01670          useslavenative = 0;
01671    }
01672    /* If we don't have any 3-way calls, check to see if we have
01673       precisely one slave */
01674    if (useslavenative) {
01675       for (x = 0; x < MAX_SLAVES; x++) {
01676          if (p->slaves[x]) {
01677             if (slave) {
01678                /* Whoops already have a slave!  No 
01679                   slave native and stop right away */
01680                slave = NULL;
01681                useslavenative = 0;
01682                break;
01683             } else {
01684                /* We have one slave so far */
01685                slave = p->slaves[x];
01686             }
01687          }
01688       }
01689    }
01690    /* If no slave, slave native definitely out */
01691    if (!slave)
01692       useslavenative = 0;
01693    else if (slave->law != p->law) {
01694       useslavenative = 0;
01695       slave = NULL;
01696    }
01697    if (out)
01698       *out = slave;
01699    return useslavenative;
01700 }
01701 
01702 static int reset_conf(struct dahdi_pvt *p)
01703 {
01704    struct dahdi_confinfo zi;
01705    memset(&zi, 0, sizeof(zi));
01706    p->confno = -1;
01707    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01708    if (p->subs[SUB_REAL].dfd > -1) {
01709       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01710          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01711    }
01712    return 0;
01713 }
01714 
01715 static int update_conf(struct dahdi_pvt *p)
01716 {
01717    int needconf = 0;
01718    int x;
01719    int useslavenative;
01720    struct dahdi_pvt *slave = NULL;
01721 
01722    useslavenative = isslavenative(p, &slave);
01723    /* Start with the obvious, general stuff */
01724    for (x = 0; x < 3; x++) {
01725       /* Look for three way calls */
01726       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01727          conf_add(p, &p->subs[x], x, 0);
01728          needconf++;
01729       } else {
01730          conf_del(p, &p->subs[x], x);
01731       }
01732    }
01733    /* If we have a slave, add him to our conference now. or DAX
01734       if this is slave native */
01735    for (x = 0; x < MAX_SLAVES; x++) {
01736       if (p->slaves[x]) {
01737          if (useslavenative)
01738             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01739          else {
01740             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01741             needconf++;
01742          }
01743       }
01744    }
01745    /* If we're supposed to be in there, do so now */
01746    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01747       if (useslavenative)
01748          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01749       else {
01750          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01751          needconf++;
01752       }
01753    }
01754    /* If we have a master, add ourselves to his conference */
01755    if (p->master) {
01756       if (isslavenative(p->master, NULL)) {
01757          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01758       } else {
01759          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01760       }
01761    }
01762    if (!needconf) {
01763       /* Nobody is left (or should be left) in our conference.
01764          Kill it. */
01765       p->confno = -1;
01766    }
01767    if (option_debug)
01768       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01769    return 0;
01770 }
01771 
01772 static void dahdi_enable_ec(struct dahdi_pvt *p)
01773 {
01774    int x;
01775    int res;
01776    if (!p)
01777       return;
01778    if (p->echocanon) {
01779       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01780       return;
01781    }
01782    if (p->digital) {
01783       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01784       return;
01785    }
01786    if (p->echocancel) {
01787       if (p->sig == SIG_PRI) {
01788          x = 1;
01789          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01790          if (res)
01791             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01792       }
01793       x = p->echocancel;
01794       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01795       if (res) 
01796          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01797       else {
01798          p->echocanon = 1;
01799          if (option_debug)
01800             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01801       }
01802    } else if (option_debug)
01803       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01804 }
01805 
01806 static void dahdi_train_ec(struct dahdi_pvt *p)
01807 {
01808    int x;
01809    int res;
01810    if (p && p->echocancel && p->echotraining) {
01811       x = p->echotraining;
01812       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01813       if (res)
01814          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01815       else {
01816          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01817       }
01818    } else
01819       ast_log(LOG_DEBUG, "No echo training requested\n");
01820 }
01821 
01822 static void dahdi_disable_ec(struct dahdi_pvt *p)
01823 {
01824    int x;
01825    int res;
01826    if (p->echocancel) {
01827       x = 0;
01828       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01829       if (res)
01830          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01831       else if (option_debug)
01832          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01833    }
01834    p->echocanon = 0;
01835 }
01836 
01837 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
01838 {
01839    int j;
01840    int k;
01841    float linear_gain = pow(10.0, gain / 20.0);
01842 
01843    switch (law) {
01844    case DAHDI_LAW_ALAW:
01845       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01846          if (gain) {
01847             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01848             if (k > 32767) k = 32767;
01849             if (k < -32767) k = -32767;
01850             g->txgain[j] = AST_LIN2A(k);
01851          } else {
01852             g->txgain[j] = j;
01853          }
01854       }
01855       break;
01856    case DAHDI_LAW_MULAW:
01857       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01858          if (gain) {
01859             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01860             if (k > 32767) k = 32767;
01861             if (k < -32767) k = -32767;
01862             g->txgain[j] = AST_LIN2MU(k);
01863          } else {
01864             g->txgain[j] = j;
01865          }
01866       }
01867       break;
01868    }
01869 }
01870 
01871 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
01872 {
01873    int j;
01874    int k;
01875    float linear_gain = pow(10.0, gain / 20.0);
01876 
01877    switch (law) {
01878    case DAHDI_LAW_ALAW:
01879       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01880          if (gain) {
01881             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01882             if (k > 32767) k = 32767;
01883             if (k < -32767) k = -32767;
01884             g->rxgain[j] = AST_LIN2A(k);
01885          } else {
01886             g->rxgain[j] = j;
01887          }
01888       }
01889       break;
01890    case DAHDI_LAW_MULAW:
01891       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01892          if (gain) {
01893             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01894             if (k > 32767) k = 32767;
01895             if (k < -32767) k = -32767;
01896             g->rxgain[j] = AST_LIN2MU(k);
01897          } else {
01898             g->rxgain[j] = j;
01899          }
01900       }
01901       break;
01902    }
01903 }
01904 
01905 static int set_actual_txgain(int fd, int chan, float gain, int law)
01906 {
01907    struct dahdi_gains g;
01908    int res;
01909 
01910    memset(&g, 0, sizeof(g));
01911    g.chan = chan;
01912    res = ioctl(fd, DAHDI_GETGAINS, &g);
01913    if (res) {
01914       if (option_debug)
01915          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01916       return res;
01917    }
01918 
01919    fill_txgain(&g, gain, law);
01920 
01921    return ioctl(fd, DAHDI_SETGAINS, &g);
01922 }
01923 
01924 static int set_actual_rxgain(int fd, int chan, float gain, int law)
01925 {
01926    struct dahdi_gains g;
01927    int res;
01928 
01929    memset(&g, 0, sizeof(g));
01930    g.chan = chan;
01931    res = ioctl(fd, DAHDI_GETGAINS, &g);
01932    if (res) {
01933       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01934       return res;
01935    }
01936 
01937    fill_rxgain(&g, gain, law);
01938 
01939    return ioctl(fd, DAHDI_SETGAINS, &g);
01940 }
01941 
01942 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
01943 {
01944    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01945 }
01946 
01947 static int bump_gains(struct dahdi_pvt *p)
01948 {
01949    int res;
01950 
01951    /* Bump receive gain by 5.0db */
01952    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01953    if (res) {
01954       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01955       return -1;
01956    }
01957 
01958    return 0;
01959 }
01960 
01961 static int restore_gains(struct dahdi_pvt *p)
01962 {
01963    int res;
01964 
01965    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01966    if (res) {
01967       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01968       return -1;
01969    }
01970 
01971    return 0;
01972 }
01973 
01974 static inline int dahdi_set_hook(int fd, int hs)
01975 {
01976    int x, res;
01977 
01978    x = hs;
01979    res = ioctl(fd, DAHDI_HOOK, &x);
01980 
01981    if (res < 0) {
01982       if (errno == EINPROGRESS)
01983          return 0;
01984       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01985       /* will expectedly fail if phone is off hook during operation, such as during a restart */
01986    }
01987 
01988    return res;
01989 }
01990 
01991 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
01992 {
01993    int x, y, res;
01994    x = muted;
01995    if (p->sig == SIG_PRI) {
01996       y = 1;
01997       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01998       if (res)
01999          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02000    }
02001    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02002    if (res < 0)
02003       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02004    return res;
02005 }
02006 
02007 static int save_conference(struct dahdi_pvt *p)
02008 {
02009    struct dahdi_confinfo c;
02010    int res;
02011    if (p->saveconf.confmode) {
02012       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02013       return -1;
02014    }
02015    p->saveconf.chan = 0;
02016    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02017    if (res) {
02018       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02019       p->saveconf.confmode = 0;
02020       return -1;
02021    }
02022    c.chan = 0;
02023    c.confno = 0;
02024    c.confmode = DAHDI_CONF_NORMAL;
02025    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02026    if (res) {
02027       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02028       return -1;
02029    }
02030    if (option_debug)
02031       ast_log(LOG_DEBUG, "Disabled conferencing\n");
02032    return 0;
02033 }
02034 
02035 static int restore_conference(struct dahdi_pvt *p)
02036 {
02037    int res;
02038    if (p->saveconf.confmode) {
02039       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02040       p->saveconf.confmode = 0;
02041       if (res) {
02042          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02043          return -1;
02044       }
02045    }
02046    if (option_debug)
02047       ast_log(LOG_DEBUG, "Restored conferencing\n");
02048    return 0;
02049 }
02050 
02051 static int send_callerid(struct dahdi_pvt *p);
02052 
02053 static int send_cwcidspill(struct dahdi_pvt *p)
02054 {
02055    p->callwaitcas = 0;
02056    p->cidcwexpire = 0;
02057    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02058       return -1;
02059    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02060    /* Make sure we account for the end */
02061    p->cidlen += READ_SIZE * 4;
02062    p->cidpos = 0;
02063    send_callerid(p);
02064    if (option_verbose > 2)
02065       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02066    return 0;
02067 }
02068 
02069 static int has_voicemail(struct dahdi_pvt *p)
02070 {
02071 
02072    return ast_app_has_voicemail(p->mailbox, NULL);
02073 }
02074 
02075 static int send_callerid(struct dahdi_pvt *p)
02076 {
02077    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02078    int res;
02079    /* Take out of linear mode if necessary */
02080    if (p->subs[SUB_REAL].linear) {
02081       p->subs[SUB_REAL].linear = 0;
02082       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02083    }
02084    while (p->cidpos < p->cidlen) {
02085       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02086       if (res < 0) {
02087          if (errno == EAGAIN)
02088             return 0;
02089          else {
02090             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02091             return -1;
02092          }
02093       }
02094       if (!res)
02095          return 0;
02096       p->cidpos += res;
02097    }
02098    free(p->cidspill);
02099    p->cidspill = NULL;
02100    if (p->callwaitcas) {
02101       /* Wait for CID/CW to expire */
02102       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02103    } else
02104       restore_conference(p);
02105    return 0;
02106 }
02107 
02108 static int dahdi_callwait(struct ast_channel *ast)
02109 {
02110    struct dahdi_pvt *p = ast->tech_pvt;
02111    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02112    if (p->cidspill) {
02113       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02114       free(p->cidspill);
02115    }
02116    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02117       return -1;
02118    save_conference(p);
02119    /* Silence */
02120    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02121    if (!p->callwaitrings && p->callwaitingcallerid) {
02122       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02123       p->callwaitcas = 1;
02124       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02125    } else {
02126       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02127       p->callwaitcas = 0;
02128       p->cidlen = 2400 + READ_SIZE * 4;
02129    }
02130    p->cidpos = 0;
02131    send_callerid(p);
02132    
02133    return 0;
02134 }
02135 
02136 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02137 {
02138    struct dahdi_pvt *p = ast->tech_pvt;
02139    int x, res, index,mysig;
02140    char *c, *n, *l;
02141 #ifdef HAVE_PRI
02142    char *s = NULL;
02143 #endif
02144    char dest[256]; /* must be same length as p->dialdest */
02145    ast_mutex_lock(&p->lock);
02146    ast_copy_string(dest, rdest, sizeof(dest));
02147    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02148    if ((ast->_state == AST_STATE_BUSY)) {
02149       p->subs[SUB_REAL].needbusy = 1;
02150       ast_mutex_unlock(&p->lock);
02151       return 0;
02152    }
02153    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02154       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02155       ast_mutex_unlock(&p->lock);
02156       return -1;
02157    }
02158    p->dialednone = 0;
02159    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02160    {
02161       /* Special pseudo -- automatically up */
02162       ast_setstate(ast, AST_STATE_UP); 
02163       ast_mutex_unlock(&p->lock);
02164       return 0;
02165    }
02166    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02167    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02168    if (res)
02169       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02170    p->outgoing = 1;
02171 
02172    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02173 
02174    mysig = p->sig;
02175    if (p->outsigmod > -1)
02176       mysig = p->outsigmod;
02177 
02178    switch (mysig) {
02179    case SIG_FXOLS:
02180    case SIG_FXOGS:
02181    case SIG_FXOKS:
02182       if (p->owner == ast) {
02183          /* Normal ring, on hook */
02184          
02185          /* Don't send audio while on hook, until the call is answered */
02186          p->dialing = 1;
02187          if (p->use_callerid) {
02188             /* Generate the Caller-ID spill if desired */
02189             if (p->cidspill) {
02190                ast_log(LOG_WARNING, "cidspill already exists??\n");
02191                free(p->cidspill);
02192             }
02193             p->callwaitcas = 0;
02194             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02195                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02196                p->cidpos = 0;
02197                send_callerid(p);
02198             }
02199          }
02200          /* Choose proper cadence */
02201          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02202             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02203                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02204             p->cidrings = cidrings[p->distinctivering - 1];
02205          } else {
02206             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02207                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02208             p->cidrings = p->sendcalleridafter;
02209          }
02210 
02211          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02212          c = strchr(dest, '/');
02213          if (c)
02214             c++;
02215          if (c && (strlen(c) < p->stripmsd)) {
02216             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02217             c = NULL;
02218          }
02219          if (c) {
02220             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02221             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02222             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02223          } else {
02224             p->dop.dialstr[0] = '\0';
02225          }
02226          x = DAHDI_RING;
02227          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02228             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02229             ast_mutex_unlock(&p->lock);
02230             return -1;
02231          }
02232          p->dialing = 1;
02233       } else {
02234          /* Call waiting call */
02235          p->callwaitrings = 0;
02236          if (ast->cid.cid_num)
02237             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02238          else
02239             p->callwait_num[0] = '\0';
02240          if (ast->cid.cid_name)
02241             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02242          else
02243             p->callwait_name[0] = '\0';
02244          /* Call waiting tone instead */
02245          if (dahdi_callwait(ast)) {
02246             ast_mutex_unlock(&p->lock);
02247             return -1;
02248          }
02249          /* Make ring-back */
02250          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02251             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02252             
02253       }
02254       n = ast->cid.cid_name;
02255       l = ast->cid.cid_num;
02256       if (l)
02257          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02258       else
02259          p->lastcid_num[0] = '\0';
02260       if (n)
02261          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02262       else
02263          p->lastcid_name[0] = '\0';
02264       ast_setstate(ast, AST_STATE_RINGING);
02265       index = dahdi_get_index(ast, p, 0);
02266       if (index > -1) {
02267          p->subs[index].needringing = 1;
02268       }
02269       break;
02270    case SIG_FXSLS:
02271    case SIG_FXSGS:
02272    case SIG_FXSKS:
02273    case SIG_EMWINK:
02274    case SIG_EM:
02275    case SIG_EM_E1:
02276    case SIG_FEATD:
02277    case SIG_FEATDMF:
02278    case SIG_E911:
02279    case SIG_FGC_CAMA:
02280    case SIG_FGC_CAMAMF:
02281    case SIG_FEATB:
02282    case SIG_SFWINK:
02283    case SIG_SF:
02284    case SIG_SF_FEATD:
02285    case SIG_SF_FEATDMF:
02286    case SIG_FEATDMF_TA:
02287    case SIG_SF_FEATB:
02288       c = strchr(dest, '/');
02289       if (c)
02290          c++;
02291       else
02292          c = "";
02293       if (strlen(c) < p->stripmsd) {
02294          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02295          ast_mutex_unlock(&p->lock);
02296          return -1;
02297       }
02298 #ifdef HAVE_PRI
02299       /* Start the trunk, if not GR-303 */
02300       if (!p->pri) {
02301 #endif
02302          x = DAHDI_START;
02303          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02304          if (res < 0) {
02305             if (errno != EINPROGRESS) {
02306                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02307                ast_mutex_unlock(&p->lock);
02308                return -1;
02309             }
02310          }
02311 #ifdef HAVE_PRI
02312       }
02313 #endif
02314       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02315       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02316 
02317       c += p->stripmsd;
02318 
02319       switch (mysig) {
02320       case SIG_FEATD:
02321          l = ast->cid.cid_num;
02322          if (l) 
02323             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02324          else
02325             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02326          break;
02327       case SIG_FEATDMF:
02328          l = ast->cid.cid_num;
02329          if (l) 
02330             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02331          else
02332             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02333          break;
02334       case SIG_FEATDMF_TA:
02335       {
02336          const char *cic, *ozz;
02337 
02338          /* If you have to go through a Tandem Access point you need to use this */
02339          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02340          if (!ozz)
02341             ozz = defaultozz;
02342          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02343          if (!cic)
02344             cic = defaultcic;
02345          if (!ozz || !cic) {
02346             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02347             ast_mutex_unlock(&p->lock);
02348             return -1;
02349          }
02350          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02351          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02352          p->whichwink = 0;
02353       }
02354          break;
02355       case SIG_E911:
02356          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02357          break;
02358       case SIG_FGC_CAMA:
02359          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02360          break;
02361       case SIG_FGC_CAMAMF:
02362       case SIG_FEATB:
02363          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02364          break;
02365       default:
02366          if (p->pulse)
02367             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02368          else
02369             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02370          break;
02371       }
02372 
02373       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02374          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02375          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02376          p->echorest[sizeof(p->echorest) - 1] = '\0';
02377          p->echobreak = 1;
02378          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02379       } else
02380          p->echobreak = 0;
02381       if (!res) {
02382          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02383             int saveerr = errno;
02384 
02385             x = DAHDI_ONHOOK;
02386             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02387             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02388             ast_mutex_unlock(&p->lock);
02389             return -1;
02390          }
02391       } else
02392          ast_log(LOG_DEBUG, "Deferring dialing...\n");
02393       p->dialing = 1;
02394       if (ast_strlen_zero(c))
02395          p->dialednone = 1;
02396       ast_setstate(ast, AST_STATE_DIALING);
02397       break;
02398    case 0:
02399       /* Special pseudo -- automatically up*/
02400       ast_setstate(ast, AST_STATE_UP);
02401       break;      
02402    case SIG_PRI:
02403       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02404       p->dialdest[0] = '\0';
02405       break;
02406    default:
02407       ast_log(LOG_DEBUG, "not yet implemented\n");
02408       ast_mutex_unlock(&p->lock);
02409       return -1;
02410    }
02411 #ifdef HAVE_PRI
02412    if (p->pri) {
02413       struct pri_sr *sr;
02414 #ifdef SUPPORT_USERUSER
02415       const char *useruser;
02416 #endif
02417       int pridialplan;
02418       int dp_strip;
02419       int prilocaldialplan;
02420       int ldp_strip;
02421       int exclusive;
02422       const char *rr_str;
02423       int redirect_reason;
02424 
02425       c = strchr(dest, '/');
02426       if (c) {
02427          c++;
02428       } else {
02429          c = "";
02430       }
02431 
02432       l = NULL;
02433       n = NULL;
02434       if (!p->hidecallerid) {
02435          l = ast->cid.cid_num;
02436          if (!p->hidecalleridname) {
02437             n = ast->cid.cid_name;
02438          }
02439       }
02440 
02441 
02442       if (strlen(c) < p->stripmsd) {
02443          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02444          ast_mutex_unlock(&p->lock);
02445          return -1;
02446       }
02447       if (mysig != SIG_FXSKS) {
02448          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02449          s = strchr(c + p->stripmsd, 'w');
02450          if (s) {
02451             if (strlen(s) > 1)
02452                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02453             else
02454                p->dop.dialstr[0] = '\0';
02455             *s = '\0';
02456          } else {
02457             p->dop.dialstr[0] = '\0';
02458          }
02459       }
02460       if (pri_grab(p, p->pri)) {
02461          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02462          ast_mutex_unlock(&p->lock);
02463          return -1;
02464       }
02465       if (!(p->call = pri_new_call(p->pri->pri))) {
02466          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02467          pri_rel(p->pri);
02468          ast_mutex_unlock(&p->lock);
02469          return -1;
02470       }
02471       if (!(sr = pri_sr_new())) {
02472          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02473          pri_destroycall(p->pri->pri, p->call);
02474          p->call = NULL;
02475          pri_rel(p->pri);
02476          ast_mutex_unlock(&p->lock);
02477          return -1;
02478       }
02479       if (p->bearer || (mysig == SIG_FXSKS)) {
02480          if (p->bearer) {
02481             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);
02482             p->bearer->call = p->call;
02483          } else
02484             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02485          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02486       }
02487       p->digital = IS_DIGITAL(ast->transfercapability);
02488       /* Add support for exclusive override */
02489       if (p->priexclusive)
02490          exclusive = 1;
02491       else {
02492       /* otherwise, traditional behavior */
02493          if (p->pri->nodetype == PRI_NETWORK)
02494             exclusive = 0;
02495          else
02496             exclusive = 1;
02497       }
02498       
02499       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02500       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02501                (p->digital ? -1 : 
02502                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02503       if (p->pri->facilityenable)
02504          pri_facility_enable(p->pri->pri);
02505 
02506       if (option_verbose > 2)
02507          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02508       dp_strip = 0;
02509       pridialplan = p->pri->dialplan - 1;
02510       if (pridialplan == -2) { /* compute dynamically */
02511          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02512             dp_strip = strlen(p->pri->internationalprefix);
02513             pridialplan = PRI_INTERNATIONAL_ISDN;
02514          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02515             dp_strip = strlen(p->pri->nationalprefix);
02516             pridialplan = PRI_NATIONAL_ISDN;
02517          } else {
02518             pridialplan = PRI_LOCAL_ISDN;
02519          }
02520       }
02521       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02522 
02523       ldp_strip = 0;
02524       prilocaldialplan = p->pri->localdialplan - 1;
02525       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
02526          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02527             ldp_strip = strlen(p->pri->internationalprefix);
02528             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02529          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02530             ldp_strip = strlen(p->pri->nationalprefix);
02531             prilocaldialplan = PRI_NATIONAL_ISDN;
02532          } else {
02533             prilocaldialplan = PRI_LOCAL_ISDN;
02534          }
02535       }
02536       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02537          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02538       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02539          if (!strcasecmp(rr_str, "UNKNOWN"))
02540             redirect_reason = 0;
02541          else if (!strcasecmp(rr_str, "BUSY"))
02542             redirect_reason = 1;
02543          else if (!strcasecmp(rr_str, "NO_REPLY"))
02544             redirect_reason = 2;
02545          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02546             redirect_reason = 15;
02547          else
02548             redirect_reason = PRI_REDIR_UNCONDITIONAL;
02549       } else
02550          redirect_reason = PRI_REDIR_UNCONDITIONAL;
02551       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02552 
02553 #ifdef SUPPORT_USERUSER
02554       /* User-user info */
02555       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02556 
02557       if (useruser)
02558          pri_sr_set_useruser(sr, useruser);
02559 #endif
02560 
02561       if (pri_setup(p->pri->pri, p->call, sr)) {
02562          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
02563             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02564          pri_rel(p->pri);
02565          ast_mutex_unlock(&p->lock);
02566          pri_sr_free(sr);
02567          return -1;
02568       }
02569       pri_sr_free(sr);
02570       ast_setstate(ast, AST_STATE_DIALING);
02571       pri_rel(p->pri);
02572    }
02573 #endif      
02574    ast_mutex_unlock(&p->lock);
02575    return 0;
02576 }
02577 
02578 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
02579 {
02580    struct dahdi_pvt *p = *pvt;
02581    /* Remove channel from the list */
02582    if (p->prev)
02583       p->prev->next = p->next;
02584    if (p->next)
02585       p->next->prev = p->prev;
02586    if (p->use_smdi)
02587       ast_smdi_interface_unref(p->smdi_iface);
02588    ast_mutex_destroy(&p->lock);
02589    dahdi_close_sub(p, SUB_REAL);
02590    if (p->owner)
02591       p->owner->tech_pvt = NULL;
02592    free(p);
02593    *pvt = NULL;
02594 }
02595 
02596 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
02597 {
02598    int owned = 0;
02599    int i = 0;
02600 
02601    if (!now) {
02602       if (cur->owner) {
02603          owned = 1;
02604       }
02605 
02606       for (i = 0; i < 3; i++) {
02607          if (cur->subs[i].owner) {
02608             owned = 1;
02609          }
02610       }
02611       if (!owned) {
02612          if (prev) {
02613             prev->next = cur->next;
02614             if (prev->next)
02615                prev->next->prev = prev;
02616             else
02617                ifend = prev;
02618          } else {
02619             iflist = cur->next;
02620             if (iflist)
02621                iflist->prev = NULL;
02622             else
02623                ifend = NULL;
02624          }
02625          destroy_dahdi_pvt(&cur);
02626       }
02627    } else {
02628       if (prev) {
02629          prev->next = cur->next;
02630          if (prev->next)
02631             prev->next->prev = prev;
02632          else
02633             ifend = prev;
02634       } else {
02635          iflist = cur->next;
02636          if (iflist)
02637             iflist->prev = NULL;
02638          else
02639             ifend = NULL;
02640       }
02641       destroy_dahdi_pvt(&cur);
02642    }
02643    return 0;
02644 }
02645 
02646 static void destroy_all_channels(void)
02647 {
02648    int x;
02649    struct dahdi_pvt *p, *pl;
02650 
02651    while (num_restart_pending) {
02652       usleep(1);
02653    }
02654 
02655    ast_mutex_lock(&iflock);
02656    /* Destroy all the interfaces and free their memory */
02657    p = iflist;
02658    while (p) {
02659       /* Free any callerid */
02660       if (p->cidspill)
02661          ast_free(p->cidspill);
02662       pl = p;
02663       p = p->next;
02664       x = pl->channel;
02665       /* Free associated memory */
02666       if (pl)
02667          destroy_dahdi_pvt(&pl);
02668       if (option_verbose > 2) 
02669          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02670    }
02671    iflist = NULL;
02672    ifcount = 0;
02673    ast_mutex_unlock(&iflock);
02674 }
02675 
02676 #ifdef HAVE_PRI
02677 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
02678 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
02679 
02680 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02681 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02682 
02683 static char *dahdi_send_keypad_facility_descrip = 
02684 "  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02685 "  IE over the current channel.\n";
02686 static char *zap_send_keypad_facility_descrip = 
02687 "  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02688 "  IE over the current channel.\n";
02689 
02690 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
02691 {
02692    /* Data will be our digit string */
02693    struct dahdi_pvt *p;
02694    char *digits = (char *) data;
02695 
02696    if (ast_strlen_zero(digits)) {
02697       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02698       return -1;
02699    }
02700 
02701    p = (struct dahdi_pvt *)chan->tech_pvt;
02702 
02703    if (!p) {
02704       ast_log(LOG_DEBUG, "Unable to find technology private\n");
02705       return -1;
02706    }
02707 
02708    ast_mutex_lock(&p->lock);
02709 
02710    if (!p->pri || !p->call) {
02711       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02712       ast_mutex_unlock(&p->lock);
02713       return -1;
02714    }
02715 
02716    if (!pri_grab(p, p->pri)) {
02717       pri_keypad_facility(p->pri->pri, p->call, digits);
02718       pri_rel(p->pri);
02719    } else {
02720       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02721       ast_mutex_unlock(&p->lock);
02722       return -1;
02723    }
02724 
02725    ast_mutex_unlock(&p->lock);
02726 
02727    return 0;
02728 }
02729 
02730 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02731 {
02732    return send_keypad_facility_exec(chan, data);
02733 }
02734 
02735 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02736 {
02737    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);  
02738    return send_keypad_facility_exec(chan, data);
02739 }
02740 
02741 static int pri_is_up(struct dahdi_pri *pri)
02742 {
02743    int x;
02744    for (x = 0; x < NUM_DCHANS; x++) {
02745       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02746          return 1;
02747    }
02748    return 0;
02749 }
02750 
02751 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
02752 {
02753    bearer->owner = &inuse;
02754    bearer->realcall = crv;
02755    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02756    if (crv->subs[SUB_REAL].owner)
02757       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02758    crv->bearer = bearer;
02759    crv->call = bearer->call;
02760    crv->pri = pri;
02761    return 0;
02762 }
02763 
02764 static char *pri_order(int level)
02765 {
02766    switch (level) {
02767    case 0:
02768       return "Primary";
02769    case 1:
02770       return "Secondary";
02771    case 2:
02772       return "Tertiary";
02773    case 3:
02774       return "Quaternary";
02775    default:
02776       return "<Unknown>";
02777    }     
02778 }
02779 
02780 /* Returns fd of the active dchan */
02781 static int pri_active_dchan_fd(struct dahdi_pri *pri)
02782 {
02783    int x = -1;
02784 
02785    for (x = 0; x < NUM_DCHANS; x++) {
02786       if ((pri->dchans[x] == pri->pri))
02787          break;
02788    }
02789 
02790    return pri->fds[x];
02791 }
02792 
02793 static int pri_find_dchan(struct dahdi_pri *pri)
02794 {
02795    int oldslot = -1;
02796    struct pri *old;
02797    int newslot = -1;
02798    int x;
02799    old = pri->pri;
02800    for (x = 0; x < NUM_DCHANS; x++) {
02801       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02802          newslot = x;
02803       if (pri->dchans[x] == old) {
02804          oldslot = x;
02805       }
02806    }
02807    if (newslot < 0) {
02808       newslot = 0;
02809       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
02810          pri->dchannels[newslot]);
02811    }
02812    if (old && (oldslot != newslot))
02813       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02814          pri->dchannels[oldslot], pri->dchannels[newslot]);
02815    pri->pri = pri->dchans[newslot];
02816    return 0;
02817 }
02818 #endif
02819 
02820 static int dahdi_hangup(struct ast_channel *ast)
02821 {
02822    int res;
02823    int index,x, law;
02824    /*static int restore_gains(struct dahdi_pvt *p);*/
02825    struct dahdi_pvt *p = ast->tech_pvt;
02826    struct dahdi_pvt *tmp = NULL;
02827    struct dahdi_pvt *prev = NULL;
02828    struct dahdi_params par;
02829 
02830    if (option_debug)
02831       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02832    if (!ast->tech_pvt) {
02833       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02834       return 0;
02835    }
02836    
02837    ast_mutex_lock(&p->lock);
02838    
02839    index = dahdi_get_index(ast, p, 1);
02840 
02841    if (p->sig == SIG_PRI) {
02842       x = 1;
02843       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02844    }
02845 
02846    x = 0;
02847    dahdi_confmute(p, 0);
02848    restore_gains(p);
02849    if (p->origcid_num) {
02850       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02851       free(p->origcid_num);
02852       p->origcid_num = NULL;
02853    }  
02854    if (p->origcid_name) {
02855       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02856       free(p->origcid_name);
02857       p->origcid_name = NULL;
02858    }  
02859    if (p->dsp)
02860       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02861    p->exten[0] = '\0';
02862 
02863    if (option_debug)
02864       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02865       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02866    p->ignoredtmf = 0;
02867    
02868    if (index > -1) {
02869       /* Real channel, do some fixup */
02870       p->subs[index].owner = NULL;
02871       p->subs[index].needanswer = 0;
02872       p->subs[index].needflash = 0;
02873       p->subs[index].needringing = 0;
02874       p->subs[index].needbusy = 0;
02875       p->subs[index].needcongestion = 0;
02876       p->subs[index].linear = 0;
02877       p->subs[index].needcallerid = 0;
02878       p->polarity = POLARITY_IDLE;
02879       dahdi_setlinear(p->subs[index].dfd, 0);
02880       if (index == SUB_REAL) {
02881          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02882             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02883             if (p->subs[SUB_CALLWAIT].inthreeway) {
02884                /* We had flipped over to answer a callwait and now it's gone */
02885                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02886                /* Move to the call-wait, but un-own us until they flip back. */
02887                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02888                unalloc_sub(p, SUB_CALLWAIT);
02889                p->owner = NULL;
02890             } else {
02891                /* The three way hung up, but we still have a call wait */
02892                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02893                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02894                unalloc_sub(p, SUB_THREEWAY);
02895                if (p->subs[SUB_REAL].inthreeway) {
02896                   /* This was part of a three way call.  Immediately make way for
02897                      another call */
02898                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02899                   p->owner = p->subs[SUB_REAL].owner;
02900                } else {
02901                   /* This call hasn't been completed yet...  Set owner to NULL */
02902                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02903                   p->owner = NULL;
02904                }
02905                p->subs[SUB_REAL].inthreeway = 0;
02906             }
02907          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02908             /* Move to the call-wait and switch back to them. */
02909             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02910             unalloc_sub(p, SUB_CALLWAIT);
02911             p->owner = p->subs[SUB_REAL].owner;
02912             if (p->owner->_state != AST_STATE_UP)
02913                p->subs[SUB_REAL].needanswer = 1;
02914             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02915                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02916          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02917             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02918             unalloc_sub(p, SUB_THREEWAY);
02919             if (p->subs[SUB_REAL].inthreeway) {
02920                /* This was part of a three way call.  Immediately make way for
02921                   another call */
02922                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02923                p->owner = p->subs[SUB_REAL].owner;
02924             } else {
02925                /* This call hasn't been completed yet...  Set owner to NULL */
02926                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02927                p->owner = NULL;
02928             }
02929             p->subs[SUB_REAL].inthreeway = 0;
02930          }
02931       } else if (index == SUB_CALLWAIT) {
02932          /* Ditch the holding callwait call, and immediately make it availabe */
02933          if (p->subs[SUB_CALLWAIT].inthreeway) {
02934             /* This is actually part of a three way, placed on hold.  Place the third part
02935                on music on hold now */
02936             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02937                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02938                   S_OR(p->mohsuggest, NULL),
02939                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02940             }
02941             p->subs[SUB_THREEWAY].inthreeway = 0;
02942             /* Make it the call wait now */
02943             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02944             unalloc_sub(p, SUB_THREEWAY);
02945          } else
02946             unalloc_sub(p, SUB_CALLWAIT);
02947       } else if (index == SUB_THREEWAY) {
02948          if (p->subs[SUB_CALLWAIT].inthreeway) {
02949             /* The other party of the three way call is currently in a call-wait state.
02950                Start music on hold for them, and take the main guy out of the third call */
02951             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02952                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02953                   S_OR(p->mohsuggest, NULL),
02954                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02955             }
02956             p->subs[SUB_CALLWAIT].inthreeway = 0;
02957          }
02958          p->subs[SUB_REAL].inthreeway = 0;
02959          /* If this was part of a three way call index, let us make
02960             another three way call */
02961          unalloc_sub(p, SUB_THREEWAY);
02962       } else {
02963          /* This wasn't any sort of call, but how are we an index? */
02964          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02965       }
02966    }
02967 
02968    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02969       p->owner = NULL;
02970       p->ringt = 0;
02971       p->distinctivering = 0;
02972       p->confirmanswer = 0;
02973       p->cidrings = 1;
02974       p->outgoing = 0;
02975       p->digital = 0;
02976       p->faxhandled = 0;
02977       p->pulsedial = 0;
02978       p->onhooktime = time(NULL);
02979 #ifdef HAVE_PRI
02980       p->proceeding = 0;
02981       p->progress = 0;
02982       p->alerting = 0;
02983       p->setup_ack = 0;
02984 #endif      
02985       if (p->dsp) {
02986          ast_dsp_free(p->dsp);
02987          p->dsp = NULL;
02988       }
02989 
02990       law = DAHDI_LAW_DEFAULT;
02991       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02992       if (res < 0) 
02993          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02994       /* Perform low level hangup if no owner left */
02995 #ifdef HAVE_PRI
02996       if (p->pri) {
02997 #ifdef SUPPORT_USERUSER
02998          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02999 #endif
03000 
03001          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03002          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03003             if (!pri_grab(p, p->pri)) {
03004                if (p->alreadyhungup) {
03005                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
03006 
03007 #ifdef SUPPORT_USERUSER
03008                   pri_call_set_useruser(p->call, useruser);
03009 #endif
03010 
03011                   pri_hangup(p->pri->pri, p->call, -1);
03012                   p->call = NULL;
03013                   if (p->bearer) 
03014                      p->bearer->call = NULL;
03015                } else {
03016                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03017                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03018                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03019 
03020 #ifdef SUPPORT_USERUSER
03021                   pri_call_set_useruser(p->call, useruser);
03022 #endif
03023 
03024                   p->alreadyhungup = 1;
03025                   if (p->bearer)
03026                      p->bearer->alreadyhungup = 1;
03027                   if (cause) {
03028                      if (atoi(cause))
03029                         icause = atoi(cause);
03030                   }
03031                   pri_hangup(p->pri->pri, p->call, icause);
03032                }
03033                if (res < 0) 
03034                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03035                pri_rel(p->pri);        
03036             } else {
03037                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03038                res = -1;
03039             }
03040          } else {
03041             if (p->bearer)
03042                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03043             p->call = NULL;
03044             res = 0;
03045          }
03046       }
03047 #endif
03048       if (p->sig && (p->sig != SIG_PRI))
03049          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03050       if (res < 0) {
03051          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03052       }
03053       switch (p->sig) {
03054       case SIG_FXOGS:
03055       case SIG_FXOLS:
03056       case SIG_FXOKS:
03057          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03058          if (!res) {
03059 #if 0
03060             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03061 #endif
03062             /* If they're off hook, try playing congestion */
03063             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03064                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03065             else
03066                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03067          }
03068          break;
03069       case SIG_FXSGS:
03070       case SIG_FXSLS:
03071       case SIG_FXSKS:
03072          /* Make sure we're not made available for at least two seconds assuming
03073             we were actually used for an inbound or outbound call. */
03074          if (ast->_state != AST_STATE_RESERVED) {
03075             time(&p->guardtime);
03076             p->guardtime += 2;
03077          }
03078          break;
03079       default:
03080          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03081       }
03082       if (p->cidspill)
03083          free(p->cidspill);
03084       if (p->sig)
03085          dahdi_disable_ec(p);
03086       x = 0;
03087       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03088       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03089       p->didtdd = 0;
03090       p->cidspill = NULL;
03091       p->callwaitcas = 0;
03092       p->callwaiting = p->permcallwaiting;
03093       p->hidecallerid = p->permhidecallerid;
03094       p->dialing = 0;
03095       p->rdnis[0] = '\0';
03096       update_conf(p);
03097       reset_conf(p);
03098       /* Restore data mode */
03099       if (p->sig == SIG_PRI) {
03100          x = 0;
03101          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03102       }
03103 #ifdef HAVE_PRI
03104       if (p->bearer) {
03105          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03106          /* Free up the bearer channel as well, and
03107             don't use its file descriptor anymore */
03108          update_conf(p->bearer);
03109          reset_conf(p->bearer);
03110          p->bearer->owner = NULL;
03111          p->bearer->realcall = NULL;
03112          p->bearer = NULL;
03113          p->subs[SUB_REAL].dfd = -1;
03114          p->pri = NULL;
03115       }
03116 #endif
03117       if (num_restart_pending == 0)
03118          restart_monitor();
03119    }
03120 
03121    p->callwaitingrepeat = 0;
03122    p->cidcwexpire = 0;
03123    p->oprmode = 0;
03124    ast->tech_pvt = NULL;
03125    ast_mutex_unlock(&p->lock);
03126    ast_module_unref(ast_module_info->self);
03127    if (option_verbose > 2) 
03128       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03129 
03130    ast_mutex_lock(&iflock);
03131 
03132    if (p->restartpending) {
03133       num_restart_pending--;
03134    }
03135 
03136    tmp = iflist;
03137    prev = NULL;
03138    if (p->destroy) {
03139       while (tmp) {
03140          if (tmp == p) {
03141             destroy_channel(prev, tmp, 0);
03142             break;
03143          } else {
03144             prev = tmp;
03145             tmp = tmp->next;
03146          }
03147       }
03148    }
03149    ast_mutex_unlock(&iflock);
03150    return 0;
03151 }
03152 
03153 static int dahdi_answer(struct ast_channel *ast)
03154 {
03155    struct dahdi_pvt *p = ast->tech_pvt;
03156    int res = 0;
03157    int index;
03158    int oldstate = ast->_state;
03159    ast_setstate(ast, AST_STATE_UP);
03160    ast_mutex_lock(&p->lock);
03161    index = dahdi_get_index(ast, p, 0);
03162    if (index < 0)
03163       index = SUB_REAL;
03164    /* nothing to do if a radio channel */
03165    if ((p->radio || (p->oprmode < 0))) {
03166       ast_mutex_unlock(&p->lock);
03167       return 0;
03168    }
03169    switch (p->sig) {
03170    case SIG_FXSLS:
03171    case SIG_FXSGS:
03172    case SIG_FXSKS:
03173       p->ringt = 0;
03174       /* Fall through */
03175    case SIG_EM:
03176    case SIG_EM_E1:
03177    case SIG_EMWINK:
03178    case SIG_FEATD:
03179    case SIG_FEATDMF:
03180    case SIG_FEATDMF_TA:
03181    case SIG_E911:
03182    case SIG_FGC_CAMA:
03183    case SIG_FGC_CAMAMF:
03184    case SIG_FEATB:
03185    case SIG_SF:
03186    case SIG_SFWINK:
03187    case SIG_SF_FEATD:
03188    case SIG_SF_FEATDMF:
03189    case SIG_SF_FEATB:
03190    case SIG_FXOLS:
03191    case SIG_FXOGS:
03192    case SIG_FXOKS:
03193       /* Pick up the line */
03194       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03195       if (p->hanguponpolarityswitch) {
03196          gettimeofday(&p->polaritydelaytv, NULL);
03197       }
03198       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03199       tone_zone_play_tone(p->subs[index].dfd, -1);
03200       p->dialing = 0;
03201       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03202          if (oldstate == AST_STATE_RINGING) {
03203             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03204             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03205             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03206             p->owner = p->subs[SUB_REAL].owner;
03207          }
03208       }
03209       if (p->sig & __DAHDI_SIG_FXS) {
03210          dahdi_enable_ec(p);
03211          dahdi_train_ec(p);
03212       }
03213       break;
03214 #ifdef HAVE_PRI
03215    case SIG_PRI:
03216       /* Send a pri acknowledge */
03217       if (!pri_grab(p, p->pri)) {
03218          p->proceeding = 1;
03219          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03220          pri_rel(p->pri);
03221       } else {
03222          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03223          res = -1;
03224       }
03225       break;
03226 #endif
03227    case 0:
03228       ast_mutex_unlock(&p->lock);
03229       return 0;
03230    default:
03231       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03232       res = -1;
03233    }
03234    ast_mutex_unlock(&p->lock);
03235    return res;
03236 }
03237 
03238 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03239 {
03240    char *cp;
03241    signed char *scp;
03242    int x;
03243    int index;
03244    struct dahdi_pvt *p = chan->tech_pvt, *pp;
03245    struct oprmode *oprmode;
03246    
03247 
03248    /* all supported options require data */
03249    if (!data || (datalen < 1)) {
03250       errno = EINVAL;
03251       return -1;
03252    }
03253 
03254    switch (option) {
03255    case AST_OPTION_TXGAIN:
03256       scp = (signed char *) data;
03257       index = dahdi_get_index(chan, p, 0);
03258       if (index < 0) {
03259          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03260          return -1;
03261       }
03262       if (option_debug)
03263          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03264       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
03265    case AST_OPTION_RXGAIN:
03266       scp = (signed char *) data;
03267       index = dahdi_get_index(chan, p, 0);
03268       if (index < 0) {
03269          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03270          return -1;
03271       }
03272       if (option_debug)
03273          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03274       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
03275    case AST_OPTION_TONE_VERIFY:
03276       if (!p->dsp)
03277          break;
03278       cp = (char *) data;
03279       switch (*cp) {
03280       case 1:
03281          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03282          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
03283          break;
03284       case 2:
03285          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03286          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
03287          break;
03288       default:
03289          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03290          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
03291          break;
03292       }
03293       break;
03294    case AST_OPTION_TDD:
03295       /* turn on or off TDD */
03296       cp = (char *) data;
03297       p->mate = 0;
03298       if (!*cp) { /* turn it off */
03299          if (option_debug)
03300             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03301          if (p->tdd)
03302             tdd_free(p->tdd);
03303          p->tdd = 0;
03304          break;
03305       }
03306       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03307          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03308       dahdi_disable_ec(p);
03309       /* otherwise, turn it on */
03310       if (!p->didtdd) { /* if havent done it yet */
03311          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
03312          unsigned char *buf;
03313          int size, res, fd, len;
03314          struct pollfd fds[1];
03315 
03316          buf = mybuf;
03317          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03318          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03319          len = 40000;
03320          index = dahdi_get_index(chan, p, 0);
03321          if (index < 0) {
03322             ast_log(LOG_WARNING, "No index in TDD?\n");
03323             return -1;
03324          }
03325          fd = p->subs[index].dfd;
03326          while (len) {
03327             if (ast_check_hangup(chan))
03328                return -1;
03329             size = len;
03330             if (size > READ_SIZE)
03331                size = READ_SIZE;
03332             fds[0].fd = fd;
03333             fds[0].events = POLLPRI | POLLOUT;
03334             fds[0].revents = 0;
03335             res = poll(fds, 1, -1);
03336             if (!res) {
03337                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03338                continue;
03339             }
03340             /* if got exception */
03341             if (fds[0].revents & POLLPRI)
03342                return -1;
03343             if (!(fds[0].revents & POLLOUT)) {
03344                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03345                continue;
03346             }
03347             res = write(fd, buf, size);
03348             if (res != size) {
03349                if (res == -1) return -1;
03350                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03351                break;
03352             }
03353             len -= size;
03354             buf += size;
03355          }
03356          p->didtdd = 1; /* set to have done it now */    
03357       }
03358       if (*cp == 2) { /* Mate mode */
03359          if (p->tdd)
03360             tdd_free(p->tdd);
03361          p->tdd = 0;
03362          p->mate = 1;
03363          break;
03364       }     
03365       if (!p->tdd) { /* if we dont have one yet */
03366          p->tdd = tdd_new(); /* allocate one */
03367       }     
03368       break;
03369    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03370       if (!p->dsp)
03371          break;
03372       cp = (char *) data;
03373       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03374          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03375                 p->dtmfrelax = 0;
03376                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03377                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03378       break;
03379    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03380       cp = (char *) data;
03381       if (!*cp) {    
03382          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03383          x = 0;
03384          dahdi_disable_ec(p);
03385       } else {    
03386          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03387          x = 1;
03388       }
03389       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03390          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03391       break;
03392    case AST_OPTION_OPRMODE:  /* Operator services mode */
03393       oprmode = (struct oprmode *) data;
03394       pp = oprmode->peer->tech_pvt;
03395       p->oprmode = pp->oprmode = 0;
03396       /* setup peers */
03397       p->oprpeer = pp;
03398       pp->oprpeer = p;
03399       /* setup modes, if any */
03400       if (oprmode->mode) 
03401       {
03402          pp->oprmode = oprmode->mode;
03403          p->oprmode = -oprmode->mode;
03404       }
03405       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03406          oprmode->mode, chan->name,oprmode->peer->name);;
03407       break;
03408    case AST_OPTION_ECHOCAN:
03409       cp = (char *) data;
03410       if (*cp) {
03411          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03412          dahdi_enable_ec(p);
03413       } else {
03414          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03415          dahdi_disable_ec(p);
03416       }
03417       break;
03418    }
03419    errno = 0;
03420 
03421    return 0;
03422 }
03423 
03424 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
03425 {
03426    struct dahdi_pvt *p = chan->tech_pvt;
03427    
03428    if (!strcasecmp(data, "rxgain")) {
03429       ast_mutex_lock(&p->lock);
03430       snprintf(buf, len, "%f", p->rxgain);
03431       ast_mutex_unlock(&p->lock);   
03432    } else if (!strcasecmp(data, "txgain")) {
03433       ast_mutex_lock(&p->lock);
03434       snprintf(buf, len, "%f", p->txgain);
03435       ast_mutex_unlock(&p->lock);   
03436    } else {
03437       ast_copy_string(buf, "", len);
03438    }
03439    return 0;
03440 }
03441 
03442 
03443 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
03444 {
03445    /* Unlink a specific slave or all slaves/masters from a given master */
03446    int x;
03447    int hasslaves;
03448    if (!master)
03449       return;
03450    if (needlock) {
03451       ast_mutex_lock(&master->lock);
03452       if (slave) {
03453          while (ast_mutex_trylock(&slave->lock)) {
03454             DEADLOCK_AVOIDANCE(&master->lock);
03455          }
03456       }
03457    }
03458    hasslaves = 0;
03459    for (x = 0; x < MAX_SLAVES; x++) {
03460       if (master->slaves[x]) {
03461          if (!slave || (master->slaves[x] == slave)) {
03462             /* Take slave out of the conference */
03463             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03464             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03465             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03466             master->slaves[x]->master = NULL;
03467             master->slaves[x] = NULL;
03468          } else
03469             hasslaves = 1;
03470       }
03471       if (!hasslaves)
03472          master->inconference = 0;
03473    }
03474    if (!slave) {
03475       if (master->master) {
03476          /* Take master out of the conference */
03477          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03478          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03479          hasslaves = 0;
03480          for (x = 0; x < MAX_SLAVES; x++) {
03481             if (master->master->slaves[x] == master)
03482                master->master->slaves[x] = NULL;
03483             else if (master->master->slaves[x])
03484                hasslaves = 1;
03485          }
03486          if (!hasslaves)
03487             master->master->inconference = 0;
03488       }
03489       master->master = NULL;
03490    }
03491    update_conf(master);
03492    if (needlock) {
03493       if (slave)
03494          ast_mutex_unlock(&slave->lock);
03495       ast_mutex_unlock(&master->lock);
03496    }
03497 }
03498 
03499 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
03500    int x;
03501    if (!slave || !master) {
03502       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03503       return;
03504    }
03505    for (x = 0; x < MAX_SLAVES; x++) {
03506       if (!master->slaves[x]) {
03507          master->slaves[x] = slave;
03508          break;
03509       }
03510    }
03511    if (x >= MAX_SLAVES) {
03512       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03513       master->slaves[MAX_SLAVES - 1] = slave;
03514    }
03515    if (slave->master) 
03516       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03517    slave->master = master;
03518    
03519    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03520 }
03521 
03522 static void disable_dtmf_detect(struct dahdi_pvt *p)
03523 {
03524 #ifdef DAHDI_TONEDETECT
03525    int val;
03526 #endif
03527 
03528    p->ignoredtmf = 1;
03529 
03530 #ifdef DAHDI_TONEDETECT
03531    val = 0;
03532    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03533 #endif      
03534    if (!p->hardwaredtmf && p->dsp) {
03535       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03536       ast_dsp_set_features(p->dsp, p->dsp_features);
03537    }
03538 }
03539 
03540 static void enable_dtmf_detect(struct dahdi_pvt *p)
03541 {
03542 #ifdef DAHDI_TONEDETECT
03543    int val;
03544 #endif
03545 
03546    if (p->channel == CHAN_PSEUDO)
03547       return;
03548 
03549    p->ignoredtmf = 0;
03550 
03551 #ifdef DAHDI_TONEDETECT
03552    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03553    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03554 #endif      
03555    if (!p->hardwaredtmf && p->dsp) {
03556       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03557       ast_dsp_set_features(p->dsp, p->dsp_features);
03558    }
03559 }
03560 
03561 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)
03562 {
03563    struct ast_channel *who;
03564    struct dahdi_pvt *p0, *p1, *op0, *op1;
03565    struct dahdi_pvt *master = NULL, *slave = NULL;
03566    struct ast_frame *f;
03567    int inconf = 0;
03568    int nothingok = 1;
03569    int ofd0, ofd1;
03570    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03571    int os0 = -1, os1 = -1;
03572    int priority = 0;
03573    struct ast_channel *oc0, *oc1;
03574    enum ast_bridge_result res;
03575 
03576 #ifdef PRI_2BCT
03577    int triedtopribridge = 0;
03578    q931_call *q931c0 = NULL, *q931c1 = NULL;
03579 #endif
03580 
03581    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03582       There is code below to handle it properly until DTMF is actually seen,
03583       but due to currently unresolved issues it's ignored...
03584    */
03585 
03586    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03587       return AST_BRIDGE_FAILED_NOWARN;
03588 
03589    ast_mutex_lock(&c0->lock);
03590    while (ast_mutex_trylock(&c1->lock)) {
03591       DEADLOCK_AVOIDANCE(&c0->lock);
03592    }
03593 
03594    p0 = c0->tech_pvt;
03595    p1 = c1->tech_pvt;
03596    /* cant do pseudo-channels here */
03597    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03598       ast_mutex_unlock(&c0->lock);
03599       ast_mutex_unlock(&c1->lock);
03600       return AST_BRIDGE_FAILED_NOWARN;
03601    }
03602 
03603    oi0 = dahdi_get_index(c0, p0, 0);
03604    oi1 = dahdi_get_index(c1, p1, 0);
03605    if ((oi0 < 0) || (oi1 < 0)) {
03606       ast_mutex_unlock(&c0->lock);
03607       ast_mutex_unlock(&c1->lock);
03608       return AST_BRIDGE_FAILED;
03609    }
03610 
03611    op0 = p0 = c0->tech_pvt;
03612    op1 = p1 = c1->tech_pvt;
03613    ofd0 = c0->fds[0];
03614    ofd1 = c1->fds[0];
03615    oc0 = p0->owner;
03616    oc1 = p1->owner;
03617 
03618    if (ast_mutex_trylock(&p0->lock)) {
03619       /* Don't block, due to potential for deadlock */
03620       ast_mutex_unlock(&c0->lock);
03621       ast_mutex_unlock(&c1->lock);
03622       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03623       return AST_BRIDGE_RETRY;
03624    }
03625    if (ast_mutex_trylock(&p1->lock)) {
03626       /* Don't block, due to potential for deadlock */
03627       ast_mutex_unlock(&p0->lock);
03628       ast_mutex_unlock(&c0->lock);
03629       ast_mutex_unlock(&c1->lock);
03630       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03631       return AST_BRIDGE_RETRY;
03632    }
03633 
03634    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03635       if (p0->owner && p1->owner) {
03636          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03637          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03638             master = p0;
03639             slave = p1;
03640             inconf = 1;
03641          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03642             master = p1;
03643             slave = p0;
03644             inconf = 1;
03645          } else {
03646             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03647             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03648                p0->channel,
03649                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03650                p0->subs[SUB_REAL].inthreeway, p0->channel,
03651                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03652                p1->subs[SUB_REAL].inthreeway);
03653          }
03654          nothingok = 0;
03655       }
03656    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03657       if (p1->subs[SUB_THREEWAY].inthreeway) {
03658          master = p1;
03659          slave = p0;
03660          nothingok = 0;
03661       }
03662    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03663       if (p0->subs[SUB_THREEWAY].inthreeway) {
03664          master = p0;
03665          slave = p1;
03666          nothingok = 0;
03667       }
03668    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03669       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03670          don't put us in anything */
03671       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03672          master = p1;
03673          slave = p0;
03674          nothingok = 0;
03675       }
03676    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03677       /* Same as previous */
03678       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03679          master = p0;
03680          slave = p1;
03681          nothingok = 0;
03682       }
03683    }
03684    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03685       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03686    if (master && slave) {
03687       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03688          in an active threeway call with a channel that is ringing, we should
03689          indicate ringing. */
03690       if ((oi1 == SUB_THREEWAY) && 
03691           p1->subs[SUB_THREEWAY].inthreeway && 
03692           p1->subs[SUB_REAL].owner && 
03693           p1->subs[SUB_REAL].inthreeway && 
03694           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03695          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03696          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03697          os1 = p1->subs[SUB_REAL].owner->_state;
03698       } else {
03699          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03700          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03701       }
03702       if ((oi0 == SUB_THREEWAY) && 
03703           p0->subs[SUB_THREEWAY].inthreeway && 
03704           p0->subs[SUB_REAL].owner && 
03705           p0->subs[SUB_REAL].inthreeway && 
03706           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03707          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03708          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03709          os0 = p0->subs[SUB_REAL].owner->_state;
03710       } else {
03711          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03712          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03713       }
03714       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03715          if (!p0->echocanbridged || !p1->echocanbridged) {
03716             /* Disable echo cancellation if appropriate */
03717             dahdi_disable_ec(p0);
03718             dahdi_disable_ec(p1);
03719          }
03720       }
03721       dahdi_link(slave, master);
03722       master->inconference = inconf;
03723    } else if (!nothingok)
03724       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03725 
03726    update_conf(p0);
03727    update_conf(p1);
03728    t0 = p0->subs[SUB_REAL].inthreeway;
03729    t1 = p1->subs[SUB_REAL].inthreeway;
03730 
03731    ast_mutex_unlock(&p0->lock);
03732    ast_mutex_unlock(&p1->lock);
03733 
03734    ast_mutex_unlock(&c0->lock);
03735    ast_mutex_unlock(&c1->lock);
03736 
03737    /* Native bridge failed */
03738    if ((!master || !slave) && !nothingok) {
03739       dahdi_enable_ec(p0);
03740       dahdi_enable_ec(p1);
03741       return AST_BRIDGE_FAILED;
03742    }
03743    
03744    if (option_verbose > 2) 
03745       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03746 
03747    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03748       disable_dtmf_detect(op0);
03749 
03750    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03751       disable_dtmf_detect(op1);
03752 
03753    for (;;) {
03754       struct ast_channel *c0_priority[2] = {c0, c1};
03755       struct ast_channel *c1_priority[2] = {c1, c0};
03756 
03757       /* Here's our main loop...  Start by locking things, looking for private parts, 
03758          and then balking if anything is wrong */
03759       ast_mutex_lock(&c0->lock);
03760       while (ast_mutex_trylock(&c1->lock)) {
03761          DEADLOCK_AVOIDANCE(&c0->lock);
03762       }
03763 
03764       p0 = c0->tech_pvt;
03765       p1 = c1->tech_pvt;
03766 
03767       if (op0 == p0)
03768          i0 = dahdi_get_index(c0, p0, 1);
03769       if (op1 == p1)
03770          i1 = dahdi_get_index(c1, p1, 1);
03771       ast_mutex_unlock(&c0->lock);
03772       ast_mutex_unlock(&c1->lock);
03773 
03774       if (!timeoutms || 
03775           (op0 != p0) ||
03776           (op1 != p1) || 
03777           (ofd0 != c0->fds[0]) || 
03778           (ofd1 != c1->fds[0]) ||
03779           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03780           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03781           (oc0 != p0->owner) || 
03782           (oc1 != p1->owner) ||
03783           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03784           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03785           (oi0 != i0) ||
03786           (oi1 != i1)) {
03787          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03788             op0->channel, oi0, op1->channel, oi1);
03789          res = AST_BRIDGE_RETRY;
03790          goto return_from_bridge;
03791       }
03792 
03793 #ifdef PRI_2BCT
03794       q931c0 = p0->call;
03795       q931c1 = p1->call;
03796       if (p0->transfer && p1->transfer 
03797           && q931c0 && q931c1 
03798           && !triedtopribridge) {
03799          pri_channel_bridge(q931c0, q931c1);
03800          triedtopribridge = 1;
03801       }
03802 #endif
03803 
03804       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03805       if (!who) {
03806          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03807          continue;
03808       }
03809       f = ast_read(who);
03810       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03811          *fo = f;
03812          *rc = who;
03813          res = AST_BRIDGE_COMPLETE;
03814          goto return_from_bridge;
03815       }
03816       if (f->frametype == AST_FRAME_DTMF) {
03817          if ((who == c0) && p0->pulsedial) {
03818             ast_write(c1, f);
03819          } else if ((who == c1) && p1->pulsedial) {
03820             ast_write(c0, f);
03821          } else {
03822             *fo = f;
03823             *rc = who;
03824             res = AST_BRIDGE_COMPLETE;
03825             goto return_from_bridge;
03826          }
03827       }
03828       ast_frfree(f);
03829       
03830       /* Swap who gets priority */
03831       priority = !priority;
03832    }
03833 
03834 return_from_bridge:
03835    if (op0 == p0)
03836       dahdi_enable_ec(p0);
03837 
03838    if (op1 == p1)
03839       dahdi_enable_ec(p1);
03840 
03841    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03842       enable_dtmf_detect(op0);
03843 
03844    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03845       enable_dtmf_detect(op1);
03846 
03847    dahdi_unlink(slave, master, 1);
03848 
03849    return res;
03850 }
03851 
03852 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
03853 {
03854    struct dahdi_pvt *p = newchan->tech_pvt;
03855    int x;
03856    ast_mutex_lock(&p->lock);
03857    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03858    if (p->owner == oldchan) {
03859       p->owner = newchan;
03860    }
03861    for (x = 0; x < 3; x++)
03862       if (p->subs[x].owner == oldchan) {
03863          if (!x)
03864             dahdi_unlink(NULL, p, 0);
03865          p->subs[x].owner = newchan;
03866       }
03867    if (newchan->_state == AST_STATE_RINGING) 
03868       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03869    update_conf(p);
03870    ast_mutex_unlock(&p->lock);
03871    return 0;
03872 }
03873 
03874 static int dahdi_ring_phone(struct dahdi_pvt *p)
03875 {
03876    int x;
03877    int res;
03878    /* Make sure our transmit state is on hook */
03879    x = 0;
03880    x = DAHDI_ONHOOK;
03881    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03882    do {
03883       x = DAHDI_RING;
03884       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03885       if (res) {
03886          switch (errno) {
03887          case EBUSY:
03888          case EINTR:
03889             /* Wait just in case */
03890             usleep(10000);
03891             continue;
03892          case EINPROGRESS:
03893             res = 0;
03894             break;
03895          default:
03896             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03897             res = 0;
03898          }
03899       }
03900    } while (res);
03901    return res;
03902 }
03903 
03904 static void *ss_thread(void *data);
03905 
03906 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
03907 
03908 static int attempt_transfer(struct dahdi_pvt *p)
03909 {
03910    /* In order to transfer, we need at least one of the channels to
03911       actually be in a call bridge.  We can't conference two applications
03912       together (but then, why would we want to?) */
03913    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03914       /* The three-way person we're about to transfer to could still be in MOH, so
03915          stop if now if appropriate */
03916       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03917          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03918       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03919          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03920       }
03921       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03922          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03923       }
03924        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03925          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03926                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03927          return -1;
03928       }
03929       /* Orphan the channel after releasing the lock */
03930       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03931       unalloc_sub(p, SUB_THREEWAY);
03932    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03933       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03934       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03935          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03936       }
03937       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03938          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03939       }
03940       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03941          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03942                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03943          return -1;
03944       }
03945       /* Three-way is now the REAL */
03946       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03947       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03948       unalloc_sub(p, SUB_THREEWAY);
03949       /* Tell the caller not to hangup */
03950       return 1;
03951    } else {
03952       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03953                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03954       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03955       return -1;
03956    }
03957    return 0;
03958 }
03959 
03960 static int check_for_conference(struct dahdi_pvt *p)
03961 {
03962    struct dahdi_confinfo ci;
03963    /* Fine if we already have a master, etc */
03964    if (p->master || (p->confno > -1))
03965       return 0;
03966    memset(&ci, 0, sizeof(ci));
03967    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03968       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03969       return 0;
03970    }
03971    /* If we have no master and don't have a confno, then 
03972       if we're in a conference, it's probably a MeetMe room or
03973       some such, so don't let us 3-way out! */
03974    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03975       if (option_verbose > 2) 
03976          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03977       return 1;
03978    }
03979    return 0;
03980 }
03981 
03982 static int get_alarms(struct dahdi_pvt *p)
03983 {
03984    int res;
03985    struct dahdi_spaninfo zi;
03986 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03987    /*
03988     * The conditional compilation is needed only in asterisk-1.4 for
03989     * backward compatibility with old zaptel drivers that don't have
03990     * a DAHDI_PARAMS.chan_alarms field.
03991     */
03992    struct dahdi_params params;
03993 #endif
03994 
03995    memset(&zi, 0, sizeof(zi));
03996    zi.spanno = p->span;
03997 
03998    /* First check for span alarms */
03999    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04000       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04001       return 0;
04002    }
04003    if (zi.alarms != DAHDI_ALARM_NONE)
04004       return zi.alarms;
04005 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04006    /* No alarms on the span. Check for channel alarms. */
04007    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04008       return params.chan_alarms;
04009    /* ioctl failed */
04010    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04011 #endif
04012    return DAHDI_ALARM_NONE;
04013 }
04014 
04015 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04016 {
04017    struct dahdi_pvt *p = ast->tech_pvt;
04018    struct ast_frame *f = *dest;
04019 
04020    if (option_debug)
04021       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04022 
04023    if (p->confirmanswer) {
04024       if (option_debug)
04025          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04026       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04027          of a DTMF digit */
04028       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04029       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04030       *dest = &p->subs[index].f;
04031       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04032       p->confirmanswer = 0;
04033    } else if (p->callwaitcas) {
04034       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04035          if (option_debug)
04036             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04037          if (p->cidspill)
04038             free(p->cidspill);
04039          send_cwcidspill(p);
04040       }
04041       if ((f->subclass != 'm') && (f->subclass != 'u')) 
04042          p->callwaitcas = 0;
04043       p->subs[index].f.frametype = AST_FRAME_NULL;
04044       p->subs[index].f.subclass = 0;
04045       *dest = &p->subs[index].f;
04046    } else if (f->subclass == 'f') {
04047       /* Fax tone -- Handle and return NULL */
04048       if ((p->callprogress & 0x6) && !p->faxhandled) {
04049          p->faxhandled = 1;
04050          if (strcmp(ast->exten, "fax")) {
04051             const char *target_context = S_OR(ast->macrocontext, ast->context);
04052 
04053             /* We need to unlock 'ast' here because ast_exists_extension has the
04054              * potential to start autoservice on the channel. Such action is prone
04055              * to deadlock.
04056              */
04057             ast_mutex_unlock(&p->lock);
04058             ast_channel_unlock(ast);
04059             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04060                ast_channel_lock(ast);
04061                ast_mutex_lock(&p->lock);
04062                if (option_verbose > 2)
04063                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04064                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04065                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04066                if (ast_async_goto(ast, target_context, "fax", 1))
04067                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04068             } else {
04069                ast_channel_lock(ast);
04070                ast_mutex_lock(&p->lock);
04071                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04072             }
04073          } else if (option_debug)
04074             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04075       } else if (option_debug)
04076             ast_log(LOG_DEBUG, "Fax already handled\n");
04077       dahdi_confmute(p, 0);
04078       p->subs[index].f.frametype = AST_FRAME_NULL;
04079       p->subs[index].f.subclass = 0;
04080       *dest = &p->subs[index].f;
04081    } else if (f->subclass == 'm') {
04082       /* Confmute request */
04083       dahdi_confmute(p, 1);
04084       p->subs[index].f.frametype = AST_FRAME_NULL;
04085       p->subs[index].f.subclass = 0;
04086       *dest = &p->subs[index].f;    
04087    } else if (f->subclass == 'u') {
04088       /* Unmute */
04089       dahdi_confmute(p, 0);
04090       p->subs[index].f.frametype = AST_FRAME_NULL;
04091       p->subs[index].f.subclass = 0;
04092       *dest = &p->subs[index].f;    
04093    } else
04094       dahdi_confmute(p, 0);
04095 }
04096          
04097 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04098 {
04099    const char *alarm_str = alarm2str(alarms);
04100    
04101    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
04102     * doesn't know what to do with it.  Don't confuse users with log messages. */
04103    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04104       p->unknown_alarm = 1;
04105       return;
04106    } else {
04107       p->unknown_alarm = 0;
04108    }
04109    
04110    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04111    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04112             "Alarm: %s\r\n"
04113             "Channel: %d\r\n",
04114             alarm_str, p->channel);
04115 }
04116 
04117 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04118 {
04119    int res, x;
04120    int index, mysig;
04121    char *c;
04122    struct dahdi_pvt *p = ast->tech_pvt;
04123    pthread_t threadid;
04124    pthread_attr_t attr;
04125    struct ast_channel *chan;
04126    struct ast_frame *f;
04127 
04128    index = dahdi_get_index(ast, p, 0);
04129    mysig = p->sig;
04130    if (p->outsigmod > -1)
04131       mysig = p->outsigmod;
04132    p->subs[index].f.frametype = AST_FRAME_NULL;
04133    p->subs[index].f.subclass = 0;
04134    p->subs[index].f.datalen = 0;
04135    p->subs[index].f.samples = 0;
04136    p->subs[index].f.mallocd = 0;
04137    p->subs[index].f.offset = 0;
04138    p->subs[index].f.src = "dahdi_handle_event";
04139    p->subs[index].f.data = NULL;
04140    f = &p->subs[index].f;
04141 
04142    if (index < 0)
04143       return &p->subs[index].f;
04144    if (p->fake_event) {
04145       res = p->fake_event;
04146       p->fake_event = 0;
04147    } else
04148       res = dahdi_get_event(p->subs[index].dfd);
04149 
04150    if (option_debug)
04151       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04152 
04153    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04154       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04155 
04156       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04157 #ifdef HAVE_PRI
04158       if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
04159          /* absorb event */
04160       } else {
04161 #endif
04162          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04163          p->subs[index].f.subclass = res & 0xff;
04164 #ifdef HAVE_PRI
04165       }
04166 #endif
04167       dahdi_handle_dtmfup(ast, index, &f);
04168       return f;
04169    }
04170 
04171    if (res & DAHDI_EVENT_DTMFDOWN) {
04172       if (option_debug)
04173          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04174       /* Mute conference */
04175       dahdi_confmute(p, 1);
04176       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04177       p->subs[index].f.subclass = res & 0xff;
04178       return &p->subs[index].f;
04179    }
04180 
04181    switch (res) {
04182 #ifdef DAHDI_EVENT_EC_DISABLED
04183       case DAHDI_EVENT_EC_DISABLED:
04184          if (option_verbose > 2) 
04185             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04186          p->echocanon = 0;
04187          break;
04188 #endif
04189       case DAHDI_EVENT_BITSCHANGED:
04190          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04191       case DAHDI_EVENT_PULSE_START:
04192          /* Stop tone if there's a pulse start and the PBX isn't started */
04193          if (!ast->pbx)
04194             tone_zone_play_tone(p->subs[index].dfd, -1);
04195          break;   
04196       case DAHDI_EVENT_DIALCOMPLETE:
04197          if (p->inalarm) break;
04198          if ((p->radio || (p->oprmode < 0))) break;
04199          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
04200             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04201             return NULL;
04202          }
04203          if (!x) { /* if not still dialing in driver */
04204             dahdi_enable_ec(p);
04205             if (p->echobreak) {
04206                dahdi_train_ec(p);
04207                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04208                p->dop.op = DAHDI_DIAL_OP_REPLACE;
04209                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04210                p->echobreak = 0;
04211             } else {
04212                p->dialing = 0;
04213                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04214                   /* if thru with dialing after offhook */
04215                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04216                      ast_setstate(ast, AST_STATE_UP);
04217                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
04218                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04219                      break;
04220                   } else { /* if to state wait for offhook to dial rest */
04221                      /* we now wait for off hook */
04222                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04223                   }
04224                }
04225                if (ast->_state == AST_STATE_DIALING) {
04226                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04227                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
04228                   } 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)))) {
04229                      ast_setstate(ast, AST_STATE_RINGING);
04230                   } else if (!p->answeronpolarityswitch) {
04231                      ast_setstate(ast, AST_STATE_UP);
04232                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
04233                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04234                      /* If aops=0 and hops=1, this is necessary */
04235                      p->polarity = POLARITY_REV;
04236                   } else {
04237                      /* Start clean, so we can catch the change to REV polarity when party answers */
04238                      p->polarity = POLARITY_IDLE;
04239                   }
04240                }
04241             }
04242          }
04243          break;
04244       case DAHDI_EVENT_ALARM:
04245 #ifdef HAVE_PRI
04246          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04247             /* T309 is not enabled : hangup calls when alarm occurs */
04248             if (p->call) {
04249                if (p->pri && p->pri->pri) {
04250                   if (!pri_grab(p, p->pri)) {
04251                      pri_hangup(p->pri->pri, p->call, -1);
04252                      pri_destroycall(p->pri->pri, p->call);
04253                      p->call = NULL;
04254                      pri_rel(p->pri);
04255                   } else
04256                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04257                } else
04258                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04259             }
04260             if (p->owner)
04261                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04262          }
04263          if (p->bearer)
04264             p->bearer->inalarm = 1;
04265          else
04266 #endif
04267          p->inalarm = 1;
04268          res = get_alarms(p);
04269          handle_alarms(p, res);
04270 #ifdef HAVE_LIBPRI
04271          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04272             /* fall through intentionally */
04273          } else {
04274             break;
04275          }
04276 #endif
04277       case DAHDI_EVENT_ONHOOK:
04278          if (p->radio) {
04279             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04280             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04281             break;
04282          }
04283          if (p->oprmode < 0)
04284          {
04285             if (p->oprmode != -1) break;
04286             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04287             {
04288                /* Make sure it starts ringing */
04289                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04290                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04291                save_conference(p->oprpeer);
04292                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04293             }
04294             break;
04295          }
04296          switch (p->sig) {
04297          case SIG_FXOLS:
04298          case SIG_FXOGS:
04299          case SIG_FXOKS:
04300             p->onhooktime = time(NULL);
04301             p->msgstate = -1;
04302             /* Check for some special conditions regarding call waiting */
04303             if (index == SUB_REAL) {
04304                /* The normal line was hung up */
04305                if (p->subs[SUB_CALLWAIT].owner) {
04306                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
04307                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04308                   if (option_verbose > 2) 
04309                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04310                   unalloc_sub(p, SUB_CALLWAIT); 
04311 #if 0
04312                   p->subs[index].needanswer = 0;
04313                   p->subs[index].needringing = 0;
04314 #endif                  
04315                   p->callwaitingrepeat = 0;
04316                   p->cidcwexpire = 0;
04317                   p->owner = NULL;
04318                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04319                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04320                      p->dialing = 1;
04321                   dahdi_ring_phone(p);
04322                } else if (p->subs[SUB_THREEWAY].owner) {
04323                   unsigned int mssinceflash;
04324                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04325                      the private structure -- not especially easy or clean */
04326                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04327                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04328                      ast_mutex_unlock(&p->lock);
04329                      DEADLOCK_AVOIDANCE(&ast->lock);
04330                      /* We can grab ast and p in that order, without worry.  We should make sure
04331                         nothing seriously bad has happened though like some sort of bizarre double
04332                         masquerade! */
04333                      ast_mutex_lock(&p->lock);
04334                      if (p->owner != ast) {
04335                         ast_log(LOG_WARNING, "This isn't good...\n");
04336                         return NULL;
04337                      }
04338                   }
04339                   if (!p->subs[SUB_THREEWAY].owner) {
04340                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04341                      return NULL;
04342                   }
04343                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04344                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04345                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04346                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04347                         hanging up.  Hangup both channels now */
04348                      if (p->subs[SUB_THREEWAY].owner)
04349                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04350                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04351                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04352                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04353                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04354                      if (p->transfer) {
04355                         /* In any case this isn't a threeway call anymore */
04356                         p->subs[SUB_REAL].inthreeway = 0;
04357                         p->subs[SUB_THREEWAY].inthreeway = 0;
04358                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04359                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04360                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04361                            /* Swap subs and dis-own channel */
04362                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04363                            p->owner = NULL;
04364                            /* Ring the phone */
04365                            dahdi_ring_phone(p);
04366                         } else {
04367                            if ((res = attempt_transfer(p)) < 0) {
04368                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04369                               if (p->subs[SUB_THREEWAY].owner)
04370                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04371                            } else if (res) {
04372                               /* Don't actually hang up at this point */
04373                               if (p->subs[SUB_THREEWAY].owner)
04374                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04375                               break;
04376                            }
04377                         }
04378                      } else {
04379                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04380                         if (p->subs[SUB_THREEWAY].owner)
04381                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04382                      }
04383                   } else {
04384                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04385                      /* Swap subs and dis-own channel */
04386                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04387                      p->owner = NULL;
04388                      /* Ring the phone */
04389                      dahdi_ring_phone(p);
04390                   }
04391                }
04392             } else {
04393                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04394             }
04395             /* Fall through */
04396          default:
04397             dahdi_disable_ec(p);
04398             return NULL;
04399          }
04400          break;
04401       case DAHDI_EVENT_RINGOFFHOOK:
04402          if (p->inalarm) break;
04403          if (p->oprmode < 0)
04404          {
04405             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04406             {
04407                /* Make sure it stops ringing */
04408                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04409                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04410                restore_conference(p->oprpeer);
04411             }
04412             break;
04413          }
04414          if (p->radio)
04415          {
04416             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04417             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04418             break;
04419          }
04420          /* for E911, its supposed to wait for offhook then dial
04421             the second half of the dial string */
04422          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04423             c = strchr(p->dialdest, '/');
04424             if (c)
04425                c++;
04426             else
04427                c = p->dialdest;
04428             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04429             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04430             if (strlen(p->dop.dialstr) > 4) {
04431                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04432                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04433                p->echorest[sizeof(p->echorest) - 1] = '\0';
04434                p->echobreak = 1;
04435                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04436             } else
04437                p->echobreak = 0;
04438             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04439                int saveerr = errno;
04440 
04441                x = DAHDI_ONHOOK;
04442                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04443                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04444                return NULL;
04445                }
04446             p->dialing = 1;
04447             return &p->subs[index].f;
04448          }
04449          switch (p->sig) {
04450          case SIG_FXOLS:
04451          case SIG_FXOGS:
04452          case SIG_FXOKS:
04453             switch (ast->_state) {
04454             case AST_STATE_RINGING:
04455                dahdi_enable_ec(p);
04456                dahdi_train_ec(p);
04457                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04458                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04459                /* Make sure it stops ringing */
04460                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04461                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04462                if (p->cidspill) {
04463                   /* Cancel any running CallerID spill */
04464                   free(p->cidspill);
04465                   p->cidspill = NULL;
04466                }
04467                p->dialing = 0;
04468                p->callwaitcas = 0;
04469                if (p->confirmanswer) {
04470                   /* Ignore answer if "confirm answer" is enabled */
04471                   p->subs[index].f.frametype = AST_FRAME_NULL;
04472                   p->subs[index].f.subclass = 0;
04473                } else if (!ast_strlen_zero(p->dop.dialstr)) {
04474                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
04475                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04476                   if (res < 0) {
04477                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04478                      p->dop.dialstr[0] = '\0';
04479                      return NULL;
04480                   } else {
04481                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04482                      p->subs[index].f.frametype = AST_FRAME_NULL;
04483                      p->subs[index].f.subclass = 0;
04484                      p->dialing = 1;
04485                   }
04486                   p->dop.dialstr[0] = '\0';
04487                   ast_setstate(ast, AST_STATE_DIALING);
04488                } else
04489                   ast_setstate(ast, AST_STATE_UP);
04490                return &p->subs[index].f;
04491             case AST_STATE_DOWN:
04492                ast_setstate(ast, AST_STATE_RING);
04493                ast->rings = 1;
04494                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04495                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04496                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04497                return &p->subs[index].f;
04498             case AST_STATE_UP:
04499                /* Make sure it stops ringing */
04500                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04501                /* Okay -- probably call waiting*/
04502                if (ast_bridged_channel(p->owner))
04503                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04504                p->subs[index].needunhold = 1;
04505                break;
04506             case AST_STATE_RESERVED:
04507                /* Start up dialtone */
04508                if (has_voicemail(p))
04509                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04510                else
04511                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04512                break;
04513             default:
04514                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04515             }
04516             break;
04517          case SIG_FXSLS:
04518          case SIG_FXSGS:
04519          case SIG_FXSKS:
04520             if (ast->_state == AST_STATE_RING) {
04521                p->ringt = p->ringt_base;
04522             }
04523 
04524             /* Fall through */
04525          case SIG_EM:
04526          case SIG_EM_E1:
04527          case SIG_EMWINK:
04528          case SIG_FEATD:
04529          case SIG_FEATDMF:
04530          case SIG_FEATDMF_TA:
04531          case SIG_E911:
04532          case SIG_FGC_CAMA:
04533          case SIG_FGC_CAMAMF:
04534          case SIG_FEATB:
04535          case SIG_SF:
04536          case SIG_SFWINK:
04537          case SIG_SF_FEATD:
04538          case SIG_SF_FEATDMF:
04539          case SIG_SF_FEATB:
04540             if (ast->_state == AST_STATE_PRERING)
04541                ast_setstate(ast, AST_STATE_RING);
04542             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04543                if (option_debug)
04544                   ast_log(LOG_DEBUG, "Ring detected\n");
04545                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04546                p->subs[index].f.subclass = AST_CONTROL_RING;
04547             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04548                if (option_debug)
04549                   ast_log(LOG_DEBUG, "Line answered\n");
04550                if (p->confirmanswer) {
04551                   p->subs[index].f.frametype = AST_FRAME_NULL;
04552                   p->subs[index].f.subclass = 0;
04553                } else {
04554                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
04555                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04556                   ast_setstate(ast, AST_STATE_UP);
04557                }
04558             } else if (ast->_state != AST_STATE_RING)
04559                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04560             break;
04561          default:
04562             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04563          }
04564          break;
04565 #ifdef DAHDI_EVENT_RINGBEGIN
04566       case DAHDI_EVENT_RINGBEGIN:
04567          switch (p->sig) {
04568          case SIG_FXSLS:
04569          case SIG_FXSGS:
04570          case SIG_FXSKS:
04571             if (ast->_state == AST_STATE_RING) {
04572                p->ringt = p->ringt_base;
04573             }
04574             break;
04575          }
04576          break;
04577 #endif         
04578       case DAHDI_EVENT_RINGEROFF:
04579          if (p->inalarm) break;
04580          if ((p->radio || (p->oprmode < 0))) break;
04581          ast->rings++;
04582          if ((ast->rings > p->cidrings) && (p->cidspill)) {
04583             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
04584             free(p->cidspill);
04585             p->cidspill = NULL;
04586             p->callwaitcas = 0;
04587          }
04588          p->subs[index].f.frametype = AST_FRAME_CONTROL;
04589          p->subs[index].f.subclass = AST_CONTROL_RINGING;
04590          break;
04591       case DAHDI_EVENT_RINGERON:
04592          break;
04593       case DAHDI_EVENT_NOALARM:
04594          p->inalarm = 0;
04595 #ifdef HAVE_PRI
04596          /* Extremely unlikely but just in case */
04597          if (p->bearer)
04598             p->bearer->inalarm = 0;
04599 #endif            
04600          if (!p->unknown_alarm) {
04601             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04602             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04603                "Channel: %d\r\n", p->channel);
04604          } else {
04605             p->unknown_alarm = 0;
04606          }
04607          break;
04608       case DAHDI_EVENT_WINKFLASH:
04609          if (p->inalarm) break;
04610          if (p->radio) break;
04611          if (p->oprmode < 0) break;
04612          if (p->oprmode > 1)
04613          {
04614             struct dahdi_params par;
04615 
04616             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04617             {
04618                if (!par.rxisoffhook)
04619                {
04620                   /* Make sure it stops ringing */
04621                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04622                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04623                   save_conference(p);
04624                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04625                }
04626             }
04627             break;
04628          }
04629          /* Remember last time we got a flash-hook */
04630          gettimeofday(&p->flashtime, NULL);
04631          switch (mysig) {
04632          case SIG_FXOLS:
04633          case SIG_FXOGS:
04634          case SIG_FXOKS:
04635             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04636                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04637             p->callwaitcas = 0;
04638 
04639             if (index != SUB_REAL) {
04640                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04641                goto winkflashdone;
04642             }
04643             
04644             if (p->subs[SUB_CALLWAIT].owner) {
04645                /* Swap to call-wait */
04646                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04647                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04648                p->owner = p->subs[SUB_REAL].owner;
04649                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04650                if (p->owner->_state == AST_STATE_RINGING) {
04651                   ast_setstate(p->owner, AST_STATE_UP);
04652                   p->subs[SUB_REAL].needanswer = 1;
04653                }
04654                p->callwaitingrepeat = 0;
04655                p->cidcwexpire = 0;
04656                /* Start music on hold if appropriate */
04657                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04658                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04659                      S_OR(p->mohsuggest, NULL),
04660                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04661                }
04662                p->subs[SUB_CALLWAIT].needhold = 1;
04663                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04664                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04665                      S_OR(p->mohsuggest, NULL),
04666                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04667                }
04668                p->subs[SUB_REAL].needunhold = 1;
04669             } else if (!p->subs[SUB_THREEWAY].owner) {
04670                if (!p->threewaycalling) {
04671                   /* Just send a flash if no 3-way calling */
04672                   p->subs[SUB_REAL].needflash = 1;
04673                   goto winkflashdone;
04674                } else if (!check_for_conference(p)) {
04675                   char cid_num[256];
04676                   char cid_name[256];
04677 
04678                   cid_num[0] = 0;
04679                   cid_name[0] = 0;
04680                   if (p->dahditrcallerid && p->owner) {
04681                      if (p->owner->cid.cid_num)
04682                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04683                      if (p->owner->cid.cid_name)
04684                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04685                   }
04686                   /* XXX This section needs much more error checking!!! XXX */
04687                   /* Start a 3-way call if feasible */
04688                   if (!((ast->pbx) ||
04689                         (ast->_state == AST_STATE_UP) ||
04690                         (ast->_state == AST_STATE_RING))) {
04691                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04692                         goto winkflashdone;
04693                   }
04694                   if (alloc_sub(p, SUB_THREEWAY)) {
04695                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04696                      goto winkflashdone;
04697                   }
04698                   /* Make new channel */
04699                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04700                   if (p->dahditrcallerid) {
04701                      if (!p->origcid_num)
04702                         p->origcid_num = ast_strdup(p->cid_num);
04703                      if (!p->origcid_name)
04704                         p->origcid_name = ast_strdup(p->cid_name);
04705                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04706                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04707                   }
04708                   /* Swap things around between the three-way and real call */
04709                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
04710                   /* Disable echo canceller for better dialing */
04711                   dahdi_disable_ec(p);
04712                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04713                   if (res)
04714                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04715                   p->owner = chan;
04716                   pthread_attr_init(&attr);
04717                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04718                   if (!chan) {
04719                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04720                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04721                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04722                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04723                      dahdi_enable_ec(p);
04724                      ast_hangup(chan);
04725                   } else {
04726                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04727                      int way3bridge = 0, cdr3way = 0;
04728                      
04729                      if (!other) {
04730                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04731                      } else
04732                         way3bridge = 1;
04733                      
04734                      if (p->subs[SUB_THREEWAY].owner->cdr)
04735                         cdr3way = 1;
04736                      
04737                      if (option_verbose > 2) 
04738                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04739                      /* Start music on hold if appropriate */
04740                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04741                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04742                            S_OR(p->mohsuggest, NULL),
04743                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04744                      }
04745                      p->subs[SUB_THREEWAY].needhold = 1;
04746                   }
04747                   pthread_attr_destroy(&attr);
04748                }
04749             } else {
04750                /* Already have a 3 way call */
04751                if (p->subs[SUB_THREEWAY].inthreeway) {
04752                   /* Call is already up, drop the last person */
04753                   if (option_debug)
04754                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04755                   /* If the primary call isn't answered yet, use it */
04756                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04757                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
04758                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04759                      p->owner = p->subs[SUB_REAL].owner;
04760                   }
04761                   /* Drop the last call and stop the conference */
04762                   if (option_verbose > 2)
04763                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04764                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04765                   p->subs[SUB_REAL].inthreeway = 0;
04766                   p->subs[SUB_THREEWAY].inthreeway = 0;
04767                } else {
04768                   /* Lets see what we're up to */
04769                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
04770                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04771                      int otherindex = SUB_THREEWAY;
04772                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04773                      int way3bridge = 0, cdr3way = 0;
04774                      
04775                      if (!other) {
04776                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04777                      } else
04778                         way3bridge = 1;
04779                      
04780                      if (p->subs[SUB_THREEWAY].owner->cdr)
04781                         cdr3way = 1;
04782 
04783                      if (option_verbose > 2)
04784                         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);
04785                      /* Put them in the threeway, and flip */
04786                      p->subs[SUB_THREEWAY].inthreeway = 1;
04787                      p->subs[SUB_REAL].inthreeway = 1;
04788                      if (ast->_state == AST_STATE_UP) {
04789                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
04790                         otherindex = SUB_REAL;
04791                      }
04792                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04793                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04794                      p->subs[otherindex].needunhold = 1;
04795                      p->owner = p->subs[SUB_REAL].owner;
04796                      if (ast->_state == AST_STATE_RINGING) {
04797                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04798                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04799                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04800                      }
04801                   } else {
04802                      if (option_verbose > 2)
04803                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04804                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04805                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04806                      p->owner = p->subs[SUB_REAL].owner;
04807                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04808                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04809                      p->subs[SUB_REAL].needunhold = 1;
04810                      dahdi_enable_ec(p);
04811                   }
04812                      
04813                }
04814             }
04815          winkflashdone:              
04816             update_conf(p);
04817             break;
04818          case SIG_EM:
04819          case SIG_EM_E1:
04820          case SIG_EMWINK:
04821          case SIG_FEATD:
04822          case SIG_SF:
04823          case SIG_SFWINK:
04824          case SIG_SF_FEATD:
04825          case SIG_FXSLS:
04826          case SIG_FXSGS:
04827             if (p->dialing)
04828                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04829             else
04830                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04831             break;
04832          case SIG_FEATDMF_TA:
04833             switch (p->whichwink) {
04834             case 0:
04835                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04836                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04837                break;
04838             case 1:
04839                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04840                break;
04841             case 2:
04842                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04843                return NULL;
04844             }
04845             p->whichwink++;
04846             /* Fall through */
04847          case SIG_FEATDMF:
04848          case SIG_E911:
04849          case SIG_FGC_CAMAMF:
04850          case SIG_FGC_CAMA:
04851          case SIG_FEATB:
04852          case SIG_SF_FEATDMF:
04853          case SIG_SF_FEATB:
04854             /* FGD MF *Must* wait for wink */
04855             if (!ast_strlen_zero(p->dop.dialstr)) {
04856                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04857                if (res < 0) {
04858                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04859                   p->dop.dialstr[0] = '\0';
04860                   return NULL;
04861                } else 
04862                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04863             }
04864             p->dop.dialstr[0] = '\0';
04865             break;
04866          default:
04867             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04868          }
04869          break;
04870       case DAHDI_EVENT_HOOKCOMPLETE:
04871          if (p->inalarm) break;
04872          if ((p->radio || (p->oprmode < 0))) break;
04873          switch (mysig) {
04874          case SIG_FXSLS:  /* only interesting for FXS */
04875          case SIG_FXSGS:
04876          case SIG_FXSKS:
04877          case SIG_EM:
04878          case SIG_EM_E1:
04879          case SIG_EMWINK:
04880          case SIG_FEATD:
04881          case SIG_SF:
04882          case SIG_SFWINK:
04883          case SIG_SF_FEATD:
04884             if (!ast_strlen_zero(p->dop.dialstr)) {
04885                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04886                if (res < 0) {
04887                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04888                   p->dop.dialstr[0] = '\0';
04889                   return NULL;
04890                } else 
04891                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04892             }
04893             p->dop.dialstr[0] = '\0';
04894             p->dop.op = DAHDI_DIAL_OP_REPLACE;
04895             break;
04896          case SIG_FEATDMF:
04897          case SIG_FEATDMF_TA:
04898          case SIG_E911:
04899          case SIG_FGC_CAMA:
04900          case SIG_FGC_CAMAMF:
04901          case SIG_FEATB:
04902          case SIG_SF_FEATDMF:
04903          case SIG_SF_FEATB:
04904             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04905             break;
04906          default:
04907             break;
04908          }
04909          break;
04910       case DAHDI_EVENT_POLARITY:
04911          /*
04912           * If we get a Polarity Switch event, check to see
04913           * if we should change the polarity state and
04914           * mark the channel as UP or if this is an indication
04915           * of remote end disconnect.
04916           */
04917          if (p->polarity == POLARITY_IDLE) {
04918             p->polarity = POLARITY_REV;
04919             if (p->answeronpolarityswitch &&
04920                 ((ast->_state == AST_STATE_DIALING) ||
04921                 (ast->_state == AST_STATE_RINGING))) {
04922                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04923                ast_setstate(p->owner, AST_STATE_UP);
04924                if (p->hanguponpolarityswitch) {
04925                   gettimeofday(&p->polaritydelaytv, NULL);
04926                }
04927             } else
04928                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04929          } 
04930          /* Removed else statement from here as it was preventing hangups from ever happening*/
04931          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
04932          if (p->hanguponpolarityswitch &&
04933             (p->polarityonanswerdelay > 0) &&
04934                 (p->polarity == POLARITY_REV) &&
04935             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04936                                 /* Added log_debug information below to provide a better indication of what is going on */
04937             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) );
04938          
04939             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04940                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04941                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04942                p->polarity = POLARITY_IDLE;
04943             } else {
04944                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);
04945             }
04946          } else {
04947             p->polarity = POLARITY_IDLE;
04948             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04949          }
04950                         /* Added more log_debug information below to provide a better indication of what is going on */
04951          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) );
04952          break;
04953       default:
04954          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04955    }
04956    return &p->subs[index].f;
04957 }
04958 
04959 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
04960 {
04961    struct dahdi_pvt *p = ast->tech_pvt;
04962    int res;
04963    int usedindex=-1;
04964    int index;
04965    struct ast_frame *f;
04966 
04967 
04968    index = dahdi_get_index(ast, p, 1);
04969    
04970    p->subs[index].f.frametype = AST_FRAME_NULL;
04971    p->subs[index].f.datalen = 0;
04972    p->subs[index].f.samples = 0;
04973    p->subs[index].f.mallocd = 0;
04974    p->subs[index].f.offset = 0;
04975    p->subs[index].f.subclass = 0;
04976    p->subs[index].f.delivery = ast_tv(0,0);
04977    p->subs[index].f.src = "dahdi_exception";
04978    p->subs[index].f.data = NULL;
04979    
04980    
04981    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04982       /* If nobody owns us, absorb the event appropriately, otherwise
04983          we loop indefinitely.  This occurs when, during call waiting, the
04984          other end hangs up our channel so that it no longer exists, but we
04985          have neither FLASH'd nor ONHOOK'd to signify our desire to
04986          change to the other channel. */
04987       if (p->fake_event) {
04988          res = p->fake_event;
04989          p->fake_event = 0;
04990       } else
04991          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04992       /* Switch to real if there is one and this isn't something really silly... */
04993       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04994          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04995          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04996          p->owner = p->subs[SUB_REAL].owner;
04997          if (p->owner && ast_bridged_channel(p->owner))
04998             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04999          p->subs[SUB_REAL].needunhold = 1;
05000       }
05001       switch (res) {
05002       case DAHDI_EVENT_ONHOOK:
05003          dahdi_disable_ec(p);
05004          if (p->owner) {
05005             if (option_verbose > 2) 
05006                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05007             dahdi_ring_phone(p);
05008             p->callwaitingrepeat = 0;
05009             p->cidcwexpire = 0;
05010          } else
05011             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05012          update_conf(p);
05013          break;
05014       case DAHDI_EVENT_RINGOFFHOOK:
05015          dahdi_enable_ec(p);
05016          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05017          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05018             p->subs[SUB_REAL].needanswer = 1;
05019             p->dialing = 0;
05020          }
05021          break;
05022       case DAHDI_EVENT_HOOKCOMPLETE:
05023       case DAHDI_EVENT_RINGERON:
05024       case DAHDI_EVENT_RINGEROFF:
05025          /* Do nothing */
05026          break;
05027       case DAHDI_EVENT_WINKFLASH:
05028          gettimeofday(&p->flashtime, NULL);
05029          if (p->owner) {
05030             if (option_verbose > 2) 
05031                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05032             if (p->owner->_state != AST_STATE_UP) {
05033                /* Answer if necessary */
05034                usedindex = dahdi_get_index(p->owner, p, 0);
05035                if (usedindex > -1) {
05036                   p->subs[usedindex].needanswer = 1;
05037                }
05038                ast_setstate(p->owner, AST_STATE_UP);
05039             }
05040             p->callwaitingrepeat = 0;
05041             p->cidcwexpire = 0;
05042             if (ast_bridged_channel(p->owner))
05043                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05044             p->subs[SUB_REAL].needunhold = 1;
05045          } else
05046             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05047          update_conf(p);
05048          break;
05049       default:
05050          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05051       }
05052       f = &p->subs[index].f;
05053       return f;
05054    }
05055    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
05056       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05057    /* If it's not us, return NULL immediately */
05058    if (ast != p->owner) {
05059       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05060       f = &p->subs[index].f;
05061       return f;
05062    }
05063    f = dahdi_handle_event(ast);
05064    return f;
05065 }
05066 
05067 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05068 {
05069    struct dahdi_pvt *p = ast->tech_pvt;
05070    struct ast_frame *f;
05071    ast_mutex_lock(&p->lock);
05072    f = __dahdi_exception(ast);
05073    ast_mutex_unlock(&p->lock);
05074    return f;
05075 }
05076 
05077 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
05078 {
05079    struct dahdi_pvt *p = ast->tech_pvt;
05080    int res;
05081    int index;
05082    void *readbuf;
05083    struct ast_frame *f;
05084 
05085    while (ast_mutex_trylock(&p->lock)) {
05086       DEADLOCK_AVOIDANCE(&ast->lock);
05087    }
05088 
05089    index = dahdi_get_index(ast, p, 0);
05090    
05091    /* Hang up if we don't really exist */
05092    if (index < 0) {
05093       ast_log(LOG_WARNING, "We dont exist?\n");
05094       ast_mutex_unlock(&p->lock);
05095       return NULL;
05096    }
05097    
05098    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05099 
05100    p->subs[index].f.frametype = AST_FRAME_NULL;
05101    p->subs[index].f.datalen = 0;
05102    p->subs[index].f.samples = 0;
05103    p->subs[index].f.mallocd = 0;
05104    p->subs[index].f.offset = 0;
05105    p->subs[index].f.subclass = 0;
05106    p->subs[index].f.delivery = ast_tv(0,0);
05107    p->subs[index].f.src = "dahdi_read";
05108    p->subs[index].f.data = NULL;
05109    
05110    /* make sure it sends initial key state as first frame */
05111    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05112    {
05113       struct dahdi_params ps;
05114 
05115       ps.channo = p->channel;
05116       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05117          ast_mutex_unlock(&p->lock);
05118          return NULL;
05119       }
05120       p->firstradio = 1;
05121       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05122       if (ps.rxisoffhook)
05123       {
05124          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05125       }
05126       else
05127       {
05128          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05129       }
05130       ast_mutex_unlock(&p->lock);
05131       return &p->subs[index].f;
05132    }
05133    if (p->ringt == 1) {
05134       ast_mutex_unlock(&p->lock);
05135       return NULL;
05136    }
05137    else if (p->ringt > 0) 
05138       p->ringt--;
05139 
05140    if (p->subs[index].needringing) {
05141       /* Send ringing frame if requested */
05142       p->subs[index].needringing = 0;
05143       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05144       p->subs[index].f.subclass = AST_CONTROL_RINGING;
05145       ast_setstate(ast, AST_STATE_RINGING);
05146       ast_mutex_unlock(&p->lock);
05147       return &p->subs[index].f;
05148    }
05149 
05150    if (p->subs[index].needbusy) {
05151       /* Send busy frame if requested */
05152       p->subs[index].needbusy = 0;
05153       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05154       p->subs[index].f.subclass = AST_CONTROL_BUSY;
05155       ast_mutex_unlock(&p->lock);
05156       return &p->subs[index].f;
05157    }
05158 
05159    if (p->subs[index].needcongestion) {
05160       /* Send congestion frame if requested */
05161       p->subs[index].needcongestion = 0;
05162       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05163       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05164       ast_mutex_unlock(&p->lock);
05165       return &p->subs[index].f;
05166    }
05167 
05168    if (p->subs[index].needcallerid) {
05169       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05170                      S_OR(p->lastcid_name, NULL),
05171                      S_OR(p->lastcid_num, NULL)
05172                      );
05173       p->subs[index].needcallerid = 0;
05174    }
05175    
05176    if (p->subs[index].needanswer) {
05177       /* Send answer frame if requested */
05178       p->subs[index].needanswer = 0;
05179       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05180       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05181       ast_mutex_unlock(&p->lock);
05182       return &p->subs[index].f;
05183    }  
05184    
05185    if (p->subs[index].needflash) {
05186       /* Send answer frame if requested */
05187       p->subs[index].needflash = 0;
05188       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05189       p->subs[index].f.subclass = AST_CONTROL_FLASH;
05190       ast_mutex_unlock(&p->lock);
05191       return &p->subs[index].f;
05192    }  
05193    
05194    if (p->subs[index].needhold) {
05195       /* Send answer frame if requested */
05196       p->subs[index].needhold = 0;
05197       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05198       p->subs[index].f.subclass = AST_CONTROL_HOLD;
05199       ast_mutex_unlock(&p->lock);
05200       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
05201       return &p->subs[index].f;
05202    }  
05203    
05204    if (p->subs[index].needunhold) {
05205       /* Send answer frame if requested */
05206       p->subs[index].needunhold = 0;
05207       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05208       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
05209       ast_mutex_unlock(&p->lock);
05210       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
05211       return &p->subs[index].f;
05212    }  
05213    
05214    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05215       if (!p->subs[index].linear) {
05216          p->subs[index].linear = 1;
05217          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05218          if (res) 
05219             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
05220       }
05221    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05222          (ast->rawreadformat == AST_FORMAT_ALAW)) {
05223       if (p->subs[index].linear) {
05224          p->subs[index].linear = 0;
05225          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05226          if (res) 
05227             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
05228       }
05229    } else {
05230       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05231       ast_mutex_unlock(&p->lock);
05232       return NULL;
05233    }
05234    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
05235    CHECK_BLOCKING(ast);
05236    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05237    ast_clear_flag(ast, AST_FLAG_BLOCKING);
05238    /* Check for hangup */
05239    if (res < 0) {
05240       f = NULL;
05241       if (res == -1)  {
05242          if (errno == EAGAIN) {
05243             /* Return "NULL" frame if there is nobody there */
05244             ast_mutex_unlock(&p->lock);
05245             return &p->subs[index].f;
05246          } else if (errno == ELAST) {
05247             f = __dahdi_exception(ast);
05248          } else
05249             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05250       }
05251       ast_mutex_unlock(&p->lock);
05252       return f;
05253    }
05254    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
05255       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05256       f = __dahdi_exception(ast);
05257       ast_mutex_unlock(&p->lock);
05258       return f;
05259    }
05260    if (p->tdd) { /* if in TDD mode, see if we receive that */
05261       int c;
05262 
05263       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05264       if (c < 0) {
05265          ast_log(LOG_DEBUG,"tdd_feed failed\n");
05266          ast_mutex_unlock(&p->lock);
05267          return NULL;
05268       }
05269       if (c) { /* if a char to return */
05270          p->subs[index].f.subclass = 0;
05271          p->subs[index].f.frametype = AST_FRAME_TEXT;
05272          p->subs[index].f.mallocd = 0;
05273          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05274          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
05275          p->subs[index].f.datalen = 1;
05276          *((char *) p->subs[index].f.data) = c;
05277          ast_mutex_unlock(&p->lock);
05278          return &p->subs[index].f;
05279       }
05280    }
05281    /* Ensure the CW timer decrements only on a single subchannel */
05282    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05283       p->callwaitingrepeat--;
05284    }
05285    if (p->cidcwexpire)
05286       p->cidcwexpire--;
05287    /* Repeat callwaiting */
05288    if (p->callwaitingrepeat == 1) {
05289       p->callwaitrings++;
05290       dahdi_callwait(ast);
05291    }
05292    /* Expire CID/CW */
05293    if (p->cidcwexpire == 1) {
05294       if (option_verbose > 2)
05295          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
05296       restore_conference(p);
05297    }
05298    if (p->subs[index].linear) {
05299       p->subs[index].f.datalen = READ_SIZE * 2;
05300    } else 
05301       p->subs[index].f.datalen = READ_SIZE;
05302 
05303    /* Handle CallerID Transmission */
05304    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05305       send_callerid(p);
05306    }
05307 
05308    p->subs[index].f.frametype = AST_FRAME_VOICE;
05309    p->subs[index].f.subclass = ast->rawreadformat;
05310    p->subs[index].f.samples = READ_SIZE;
05311    p->subs[index].f.mallocd = 0;
05312    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05313    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05314 #if 0
05315    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05316 #endif   
05317    if (p->dialing || /* Transmitting something */
05318       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05319       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05320       ) {
05321       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05322          don't send anything */
05323       p->subs[index].f.frametype = AST_FRAME_NULL;
05324       p->subs[index].f.subclass = 0;
05325       p->subs[index].f.samples = 0;
05326       p->subs[index].f.mallocd = 0;
05327       p->subs[index].f.offset = 0;
05328       p->subs[index].f.data = NULL;
05329       p->subs[index].f.datalen= 0;
05330    }
05331    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
05332       /* Perform busy detection. etc on the dahdi line */
05333       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05334       if (f) {
05335          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05336             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05337                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05338                   a busy  */
05339                f = NULL;
05340             }
05341          } else if (f->frametype == AST_FRAME_DTMF) {
05342 #ifdef HAVE_PRI
05343             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05344                /* Don't accept in-band DTMF when in overlap dial mode */
05345                f->frametype = AST_FRAME_NULL;
05346                f->subclass = 0;
05347             }
05348 #endif            
05349             /* DSP clears us of being pulse */
05350             p->pulsedial = 0;
05351          }
05352       }
05353    } else 
05354       f = &p->subs[index].f; 
05355 
05356    if (f && (f->frametype == AST_FRAME_DTMF))
05357       dahdi_handle_dtmfup(ast, index, &f);
05358 
05359    /* If we have a fake_event, trigger exception to handle it */
05360    if (p->fake_event)
05361       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05362 
05363    ast_mutex_unlock(&p->lock);
05364    return f;
05365 }
05366 
05367 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05368 {
05369    int sent=0;
05370    int size;
05371    int res;
05372    int fd;
05373    fd = p->subs[index].dfd;
05374    while (len) {
05375       size = len;
05376       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05377          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05378       res = write(fd, buf, size);
05379       if (res != size) {
05380          if (option_debug)
05381             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05382          return sent;
05383       }
05384       len -= size;
05385       buf += size;
05386    }
05387    return sent;
05388 }
05389 
05390 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05391 {
05392    struct dahdi_pvt *p = ast->tech_pvt;
05393    int res;
05394    int index;
05395    index = dahdi_get_index(ast, p, 0);
05396    if (index < 0) {
05397       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05398       return -1;
05399    }
05400 
05401 #if 0
05402 #ifdef HAVE_PRI
05403    ast_mutex_lock(&p->lock);
05404    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05405       if (p->pri->pri) {      
05406          if (!pri_grab(p, p->pri)) {
05407                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05408                pri_rel(p->pri);
05409          } else
05410                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05411       }
05412       p->proceeding=1;
05413    }
05414    ast_mutex_unlock(&p->lock);
05415 #endif
05416 #endif
05417    /* Write a frame of (presumably voice) data */
05418    if (frame->frametype != AST_FRAME_VOICE) {
05419       if (frame->frametype != AST_FRAME_IMAGE)
05420          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05421       return 0;
05422    }
05423    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
05424        (frame->subclass != AST_FORMAT_ULAW) &&
05425        (frame->subclass != AST_FORMAT_ALAW)) {
05426       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05427       return -1;
05428    }
05429    if (p->dialing) {
05430       if (option_debug)
05431          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05432       return 0;
05433    }
05434    if (!p->owner) {
05435       if (option_debug)
05436          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05437       return 0;
05438    }
05439    if (p->cidspill) {
05440       if (option_debug)
05441          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05442       return 0;
05443    }
05444    /* Return if it's not valid data */
05445    if (!frame->data || !frame->datalen)
05446       return 0;
05447 
05448    if (frame->subclass == AST_FORMAT_SLINEAR) {
05449       if (!p->subs[index].linear) {
05450          p->subs[index].linear = 1;
05451          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05452          if (res)
05453             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05454       }
05455       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05456    } else {
05457       /* x-law already */
05458       if (p->subs[index].linear) {
05459          p->subs[index].linear = 0;
05460          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05461          if (res)
05462             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05463       }
05464       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05465    }
05466    if (res < 0) {
05467       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05468       return -1;
05469    } 
05470    return 0;
05471 }
05472 
05473 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
05474 {
05475    struct dahdi_pvt *p = chan->tech_pvt;
05476    int res=-1;
05477    int index;
05478    int func = DAHDI_FLASH;
05479    ast_mutex_lock(&p->lock);
05480    index = dahdi_get_index(chan, p, 0);
05481    if (option_debug)
05482       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05483    if (index == SUB_REAL) {
05484       switch (condition) {
05485       case AST_CONTROL_BUSY:
05486 #ifdef HAVE_PRI
05487          if (p->priindication_oob && p->sig == SIG_PRI) {
05488             chan->hangupcause = AST_CAUSE_USER_BUSY;
05489             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05490             res = 0;
05491          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05492             if (p->pri->pri) {      
05493                if (!pri_grab(p, p->pri)) {
05494                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05495                   pri_rel(p->pri);
05496                }
05497                else
05498                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05499             }
05500             p->progress = 1;
05501             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05502          } else
05503 #endif
05504             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05505          break;
05506       case AST_CONTROL_RINGING:
05507 #ifdef HAVE_PRI
05508          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05509             if (p->pri->pri) {      
05510                if (!pri_grab(p, p->pri)) {
05511                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05512                   pri_rel(p->pri);
05513                }
05514                else
05515                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05516             }
05517             p->alerting = 1;
05518          }
05519 #endif
05520          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05521          if (chan->_state != AST_STATE_UP) {
05522             if ((chan->_state != AST_STATE_RING) ||
05523                ((p->sig != SIG_FXSKS) &&
05524                 (p->sig != SIG_FXSLS) &&
05525                 (p->sig != SIG_FXSGS)))
05526                ast_setstate(chan, AST_STATE_RINGING);
05527          }
05528          break;
05529       case AST_CONTROL_PROCEEDING:
05530          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05531 #ifdef HAVE_PRI
05532          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05533             if (p->pri->pri) {      
05534                if (!pri_grab(p, p->pri)) {
05535                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05536                   pri_rel(p->pri);
05537                }
05538                else
05539                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05540             }
05541             p->proceeding = 1;
05542          }
05543 #endif
05544          /* don't continue in ast_indicate */
05545          res = 0;
05546          break;
05547       case AST_CONTROL_PROGRESS:
05548          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05549 #ifdef HAVE_PRI
05550          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05551          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05552             if (p->pri->pri) {      
05553                if (!pri_grab(p, p->pri)) {
05554                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05555                   pri_rel(p->pri);
05556                }
05557                else
05558                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05559             }
05560             p->progress = 1;
05561          }
05562 #endif
05563          /* don't continue in ast_indicate */
05564          res = 0;
05565          break;
05566       case AST_CONTROL_CONGESTION:
05567          chan->hangupcause = AST_CAUSE_CONGESTION;
05568 #ifdef HAVE_PRI
05569          if (p->priindication_oob && p->sig == SIG_PRI) {
05570             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05571             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05572             res = 0;
05573          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05574             if (p->pri) {     
05575                if (!pri_grab(p, p->pri)) {
05576                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05577                   pri_rel(p->pri);
05578                } else
05579                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05580             }
05581             p->progress = 1;
05582             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05583          } else
05584 #endif
05585             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05586          break;
05587       case AST_CONTROL_HOLD:
05588 #ifdef HAVE_PRI
05589          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05590             if (!pri_grab(p, p->pri)) {
05591                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05592                pri_rel(p->pri);
05593             } else
05594                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05595          } else
05596 #endif
05597             ast_moh_start(chan, data, p->mohinterpret);
05598          break;
05599       case AST_CONTROL_UNHOLD:
05600 #ifdef HAVE_PRI
05601          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05602             if (!pri_grab(p, p->pri)) {
05603                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05604                pri_rel(p->pri);
05605             } else
05606                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05607          } else
05608 #endif
05609             ast_moh_stop(chan);
05610          break;
05611       case AST_CONTROL_RADIO_KEY:
05612          if (p->radio) 
05613              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05614          res = 0;
05615          break;
05616       case AST_CONTROL_RADIO_UNKEY:
05617          if (p->radio)
05618              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05619          res = 0;
05620          break;
05621       case AST_CONTROL_FLASH:
05622          /* flash hookswitch */
05623          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05624             /* Clear out the dial buffer */
05625             p->dop.dialstr[0] = '\0';
05626             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05627                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05628                   chan->name, strerror(errno));
05629             } else
05630                res = 0;
05631          } else
05632             res = 0;
05633          break;
05634       case AST_CONTROL_SRCUPDATE:
05635          res = 0;
05636          break;
05637       case -1:
05638          res = tone_zone_play_tone(p->subs[index].dfd, -1);
05639          break;
05640       }
05641    } else
05642       res = 0;
05643    ast_mutex_unlock(&p->lock);
05644    return res;
05645 }
05646 
05647 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
05648 {
05649    struct ast_channel *tmp;
05650    int deflaw;
05651    int res;
05652    int x,y;
05653    int features;
05654    char *b2 = NULL;
05655    struct dahdi_params ps;
05656    char chanprefix[*dahdi_chan_name_len + 4];
05657 
05658    if (i->subs[index].owner) {
05659       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05660       return NULL;
05661    }
05662    y = 1;
05663    do {
05664       if (b2)
05665          free(b2);
05666 #ifdef HAVE_PRI
05667       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05668          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05669       else
05670 #endif
05671       if (i->channel == CHAN_PSEUDO)
05672          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05673       else  
05674          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05675       for (x = 0; x < 3; x++) {
05676          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05677             break;
05678       }
05679       y++;
05680    } while (x < 3);
05681    strcpy(chanprefix, dahdi_chan_name);
05682    strcat(chanprefix, "/%s");
05683    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05684    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05685       free(b2);
05686    if (!tmp)
05687       return NULL;
05688    tmp->tech = chan_tech;
05689    ps.channo = i->channel;
05690    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05691    if (res) {
05692       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05693       ps.curlaw = DAHDI_LAW_MULAW;
05694    }
05695    if (ps.curlaw == DAHDI_LAW_ALAW)
05696       deflaw = AST_FORMAT_ALAW;
05697    else
05698       deflaw = AST_FORMAT_ULAW;
05699    if (law) {
05700       if (law == DAHDI_LAW_ALAW)
05701          deflaw = AST_FORMAT_ALAW;
05702       else
05703          deflaw = AST_FORMAT_ULAW;
05704    }
05705    tmp->fds[0] = i->subs[index].dfd;
05706    tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05707    /* Start out assuming ulaw since it's smaller :) */
05708    tmp->rawreadformat = deflaw;
05709    tmp->readformat = deflaw;
05710    tmp->rawwriteformat = deflaw;
05711    tmp->writeformat = deflaw;
05712    i->subs[index].linear = 0;
05713    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05714    features = 0;
05715    if (index == SUB_REAL) {
05716       if (i->busydetect && CANBUSYDETECT(i))
05717          features |= DSP_FEATURE_BUSY_DETECT;
05718       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05719          features |= DSP_FEATURE_CALL_PROGRESS;
05720       if ((!i->outgoing && (i->callprogress & 4)) || 
05721           (i->outgoing && (i->callprogress & 2))) {
05722          features |= DSP_FEATURE_FAX_DETECT;
05723       }
05724 #ifdef DAHDI_TONEDETECT
05725       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05726       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05727 #endif      
05728          i->hardwaredtmf = 0;
05729          features |= DSP_FEATURE_DTMF_DETECT;
05730 #ifdef DAHDI_TONEDETECT
05731       } else if (NEED_MFDETECT(i)) {
05732          i->hardwaredtmf = 1;
05733          features |= DSP_FEATURE_DTMF_DETECT;
05734       }
05735 #endif
05736    }
05737    if (features) {
05738       if (i->dsp) {
05739          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05740       } else {
05741          if (i->channel != CHAN_PSEUDO)
05742             i->dsp = ast_dsp_new();
05743          else
05744             i->dsp = NULL;
05745          if (i->dsp) {
05746             i->dsp_features = features;
05747 #ifdef HAVE_PRI
05748             /* We cannot do progress detection until receives PROGRESS message */
05749             if (i->outgoing && (i->sig == SIG_PRI)) {
05750                /* Remember requested DSP features, don't treat
05751                   talking as ANSWER */
05752                i->dsp_features = features & ~DSP_PROGRESS_TALK;
05753                features = 0;
05754             }
05755 #endif
05756             ast_dsp_set_features(i->dsp, features);
05757             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05758             if (!ast_strlen_zero(progzone))
05759                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05760             if (i->busydetect && CANBUSYDETECT(i)) {
05761                if(i->silencethreshold > 0)
05762                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05763                ast_dsp_set_busy_count(i->dsp, i->busycount);
05764                if(i->busytonelength > 0)
05765                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05766                if((i->busytonelength == i->busyquietlength) && i->busycompare)
05767                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05768             }
05769          }
05770       }
05771    }
05772       
05773    if (state == AST_STATE_RING)
05774       tmp->rings = 1;
05775    tmp->tech_pvt = i;
05776    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05777       /* Only FXO signalled stuff can be picked up */
05778       tmp->callgroup = i->callgroup;
05779       tmp->pickupgroup = i->pickupgroup;
05780    }
05781    if (!ast_strlen_zero(i->language))
05782       ast_string_field_set(tmp, language, i->language);
05783    if (!i->owner)
05784       i->owner = tmp;
05785    if (!ast_strlen_zero(i->accountcode))
05786       ast_string_field_set(tmp, accountcode, i->accountcode);
05787    if (i->amaflags)
05788       tmp->amaflags = i->amaflags;
05789    i->subs[index].owner = tmp;
05790    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05791    ast_string_field_set(tmp, call_forward, i->call_forward);
05792    /* If we've been told "no ADSI" then enforce it */
05793    if (!i->adsi)
05794       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05795    if (!ast_strlen_zero(i->exten))
05796       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05797    if (!ast_strlen_zero(i->rdnis))
05798       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05799    if (!ast_strlen_zero(i->dnid))
05800       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05801 
05802    /* Don't use ast_set_callerid() here because it will
05803     * generate a needless NewCallerID event */
05804 #ifdef PRI_ANI
05805    if (!ast_strlen_zero(i->cid_ani))
05806       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05807    else  
05808       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05809 #else
05810    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05811 #endif
05812    tmp->cid.cid_pres = i->callingpres;
05813    tmp->cid.cid_ton = i->cid_ton;
05814 #ifdef HAVE_PRI
05815    tmp->transfercapability = transfercapability;
05816    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05817    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05818       i->digital = 1;
05819    /* Assume calls are not idle calls unless we're told differently */
05820    i->isidlecall = 0;
05821    i->alreadyhungup = 0;
05822 #endif
05823    /* clear the fake event in case we posted one before we had ast_channel */
05824    i->fake_event = 0;
05825    /* Assure there is no confmute on this channel */
05826    dahdi_confmute(i, 0);
05827    /* Configure the new channel jb */
05828    ast_jb_configure(tmp, &global_jbconf);
05829    if (startpbx) {
05830       if (ast_pbx_start(tmp)) {
05831          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05832          ast_hangup(tmp);
05833          i->owner = NULL;
05834          return NULL;
05835       }
05836    }
05837 
05838    ast_module_ref(ast_module_info->self);
05839    
05840    return tmp;
05841 }
05842 
05843 
05844 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
05845 {
05846    char c;
05847 
05848    *str = 0; /* start with empty output buffer */
05849    for (;;)
05850    {
05851       /* Wait for the first digit (up to specified ms). */
05852       c = ast_waitfordigit(chan, ms);
05853       /* if timeout, hangup or error, return as such */
05854       if (c < 1)
05855          return c;
05856       *str++ = c;
05857       *str = 0;
05858       if (strchr(term, c))
05859          return 1;
05860    }
05861 }
05862 
05863 static int dahdi_wink(struct dahdi_pvt *p, int index)
05864 {
05865    int j;
05866    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05867    for (;;)
05868    {
05869          /* set bits of interest */
05870       j = DAHDI_IOMUX_SIGEVENT;
05871           /* wait for some happening */
05872       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05873          /* exit loop if we have it */
05874       if (j & DAHDI_IOMUX_SIGEVENT) break;
05875    }
05876      /* get the event info */
05877    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05878    return 0;
05879 }
05880 
05881 static void *ss_thread(void *data)
05882 {
05883    struct ast_channel *chan = data;
05884    struct dahdi_pvt *p = chan->tech_pvt;
05885    char exten[AST_MAX_EXTENSION] = "";
05886    char exten2[AST_MAX_EXTENSION] = "";
05887    unsigned char buf[256];
05888    char dtmfcid[300];
05889    char dtmfbuf[300];
05890    struct callerid_state *cs = NULL;
05891    char *name = NULL, *number = NULL;
05892    int distMatches;
05893    int curRingData[3];
05894    int receivedRingT;
05895    int counter1;
05896    int counter;
05897    int samples = 0;
05898    struct ast_smdi_md_message *smdi_msg = NULL;
05899    int flags;
05900    int i;
05901    int timeout;
05902    int getforward = 0;
05903    char *s1, *s2;
05904    int len = 0;
05905    int res;
05906    int index;
05907 
05908    ast_mutex_lock(&ss_thread_lock);
05909    ss_thread_count++;
05910    ast_mutex_unlock(&ss_thread_lock);
05911    /* in the bizarre case where the channel has become a zombie before we
05912       even get started here, abort safely
05913    */
05914    if (!p) {
05915       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05916       ast_hangup(chan);
05917       goto quit;
05918    }
05919    if (option_verbose > 2) 
05920       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05921    index = dahdi_get_index(chan, p, 1);
05922    if (index < 0) {
05923       ast_log(LOG_WARNING, "Huh?\n");
05924       ast_hangup(chan);
05925       goto quit;
05926    }
05927    if (p->dsp)
05928       ast_dsp_digitreset(p->dsp);
05929    switch (p->sig) {
05930 #ifdef HAVE_PRI
05931    case SIG_PRI:
05932       /* Now loop looking for an extension */
05933       ast_copy_string(exten, p->exten, sizeof(exten));
05934       len = strlen(exten);
05935       res = 0;
05936       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05937          if (len && !ast_ignore_pattern(chan->context, exten))
05938             tone_zone_play_tone(p->subs[index].dfd, -1);
05939          else
05940             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05941          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05942             timeout = matchdigittimeout;
05943          else
05944             timeout = gendigittimeout;
05945          res = ast_waitfordigit(chan, timeout);
05946          if (res < 0) {
05947             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05948             ast_hangup(chan);
05949             goto quit;
05950          } else if (res) {
05951             exten[len++] = res;
05952             exten[len] = '\0';
05953          } else
05954             break;
05955       }
05956       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
05957       if (ast_strlen_zero(exten)) {
05958          if (option_verbose > 2)
05959             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05960          exten[0] = 's';
05961          exten[1] = '\0';
05962       }
05963       tone_zone_play_tone(p->subs[index].dfd, -1);
05964       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05965          /* Start the real PBX */
05966          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05967          if (p->dsp) ast_dsp_digitreset(p->dsp);
05968          dahdi_enable_ec(p);
05969          ast_setstate(chan, AST_STATE_RING);
05970          res = ast_pbx_run(chan);
05971          if (res) {
05972             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05973          }
05974       } else {
05975          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05976          chan->hangupcause = AST_CAUSE_UNALLOCATED;
05977          ast_hangup(chan);
05978          p->exten[0] = '\0';
05979          /* Since we send release complete here, we won't get one */
05980          p->call = NULL;
05981       }
05982       goto quit;
05983       break;
05984 #endif
05985    case SIG_FEATD:
05986    case SIG_FEATDMF:
05987    case SIG_FEATDMF_TA:
05988    case SIG_E911:
05989    case SIG_FGC_CAMAMF:
05990    case SIG_FEATB:
05991    case SIG_EMWINK:
05992    case SIG_SF_FEATD:
05993    case SIG_SF_FEATDMF:
05994    case SIG_SF_FEATB:
05995    case SIG_SFWINK:
05996       if (dahdi_wink(p, index))  
05997          goto quit;
05998       /* Fall through */
05999    case SIG_EM:
06000    case SIG_EM_E1:
06001    case SIG_SF:
06002    case SIG_FGC_CAMA:
06003       res = tone_zone_play_tone(p->subs[index].dfd, -1);
06004       if (p->dsp)
06005          ast_dsp_digitreset(p->dsp);
06006       /* set digit mode appropriately */
06007       if (p->dsp) {
06008          if (NEED_MFDETECT(p))
06009             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
06010          else 
06011             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06012       }
06013       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06014       /* Wait for the first digit only if immediate=no */
06015       if (!p->immediate)
06016          /* Wait for the first digit (up to 5 seconds). */
06017          res = ast_waitfordigit(chan, 5000);
06018       else
06019          res = 0;
06020       if (res > 0) {
06021          /* save first char */
06022          dtmfbuf[0] = res;
06023          switch (p->sig) {
06024          case SIG_FEATD:
06025          case SIG_SF_FEATD:
06026             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06027             if (res > 0)
06028                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06029             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06030             break;
06031          case SIG_FEATDMF_TA:
06032             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06033             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06034             if (dahdi_wink(p, index)) goto quit;
06035             dtmfbuf[0] = 0;
06036             /* Wait for the first digit (up to 5 seconds). */
06037             res = ast_waitfordigit(chan, 5000);
06038             if (res <= 0) break;
06039             dtmfbuf[0] = res;
06040             /* fall through intentionally */
06041          case SIG_FEATDMF:
06042          case SIG_E911:
06043          case SIG_FGC_CAMAMF:
06044          case SIG_SF_FEATDMF:
06045             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06046             /* if international caca, do it again to get real ANO */
06047             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06048             {
06049                if (dahdi_wink(p, index)) goto quit;
06050                dtmfbuf[0] = 0;
06051                /* Wait for the first digit (up to 5 seconds). */
06052                res = ast_waitfordigit(chan, 5000);
06053                if (res <= 0) break;
06054                dtmfbuf[0] = res;
06055                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06056             }
06057             if (res > 0) {
06058                /* if E911, take off hook */
06059                if (p->sig == SIG_E911)
06060                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06061                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06062             }
06063             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06064             break;
06065          case SIG_FEATB:
06066          case SIG_SF_FEATB:
06067             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06068             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06069             break;
06070          case SIG_EMWINK:
06071             /* if we received a '*', we are actually receiving Feature Group D
06072                dial syntax, so use that mode; otherwise, fall through to normal
06073                mode
06074             */
06075             if (res == '*') {
06076                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06077                if (res > 0)
06078                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06079                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06080                break;
06081             }
06082          default:
06083             /* If we got the first digit, get the rest */
06084             len = 1;
06085             dtmfbuf[len] = '\0';
06086             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06087                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06088                   timeout = matchdigittimeout;
06089                } else {
06090                   timeout = gendigittimeout;
06091                }
06092                res = ast_waitfordigit(chan, timeout);
06093                if (res < 0) {
06094                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06095                   ast_hangup(chan);
06096                   goto quit;
06097                } else if (res) {
06098                   dtmfbuf[len++] = res;
06099                   dtmfbuf[len] = '\0';
06100                } else {
06101                   break;
06102                }
06103             }
06104             break;
06105          }
06106       }
06107       if (res == -1) {
06108          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06109          ast_hangup(chan);
06110          goto quit;
06111       } else if (res < 0) {
06112          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06113          ast_hangup(chan);
06114          goto quit;
06115       }
06116 
06117       if (p->sig == SIG_FGC_CAMA) {
06118          char anibuf[100];
06119 
06120          if (ast_safe_sleep(chan,1000) == -1) {
06121                            ast_hangup(chan);
06122                            goto quit;
06123          }
06124                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06125                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06126                         res = my_getsigstr(chan, anibuf, "#", 10000);
06127                         if ((res > 0) && (strlen(anibuf) > 2)) {
06128             if (anibuf[strlen(anibuf) - 1] == '#')
06129                anibuf[strlen(anibuf) - 1] = 0;
06130             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06131          }
06132                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06133       }
06134 
06135       ast_copy_string(exten, dtmfbuf, sizeof(exten));
06136       if (ast_strlen_zero(exten))
06137          ast_copy_string(exten, "s", sizeof(exten));
06138       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06139          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
06140          if (exten[0] == '*') {
06141             char *stringp=NULL;
06142             ast_copy_string(exten2, exten, sizeof(exten2));
06143             /* Parse out extension and callerid */
06144             stringp=exten2 +1;
06145             s1 = strsep(&stringp, "*");
06146             s2 = strsep(&stringp, "*");
06147             if (s2) {
06148                if (!ast_strlen_zero(p->cid_num))
06149                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06150                else
06151                   ast_set_callerid(chan, s1, NULL, s1);
06152                ast_copy_string(exten, s2, sizeof(exten));
06153             } else
06154                ast_copy_string(exten, s1, sizeof(exten));
06155          } else if (p->sig == SIG_FEATD)
06156             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06157       }
06158       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06159          if (exten[0] == '*') {
06160             char *stringp=NULL;
06161             ast_copy_string(exten2, exten, sizeof(exten2));
06162             /* Parse out extension and callerid */
06163             stringp=exten2 +1;
06164             s1 = strsep(&stringp, "#");
06165             s2 = strsep(&stringp, "#");
06166             if (s2) {
06167                if (!ast_strlen_zero(p->cid_num))
06168                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06169                else
06170                   if (*(s1 + 2))
06171                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06172                ast_copy_string(exten, s2 + 1, sizeof(exten));
06173             } else
06174                ast_copy_string(exten, s1 + 2, sizeof(exten));
06175          } else
06176             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06177       }
06178       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06179          if (exten[0] == '*') {
06180             char *stringp=NULL;
06181             ast_copy_string(exten2, exten, sizeof(exten2));
06182             /* Parse out extension and callerid */
06183             stringp=exten2 +1;
06184             s1 = strsep(&stringp, "#");
06185             s2 = strsep(&stringp, "#");
06186             if (s2 && (*(s2 + 1) == '0')) {
06187                if (*(s2 + 2))
06188                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06189             }
06190             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
06191             else ast_copy_string(exten, "911", sizeof(exten));
06192          } else
06193             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06194       }
06195       if (p->sig == SIG_FEATB) {
06196          if (exten[0] == '*') {
06197             char *stringp=NULL;
06198             ast_copy_string(exten2, exten, sizeof(exten2));
06199             /* Parse out extension and callerid */
06200             stringp=exten2 +1;
06201             s1 = strsep(&stringp, "#");
06202             ast_copy_string(exten, exten2 + 1, sizeof(exten));
06203          } else
06204             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06205       }
06206       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06207          dahdi_wink(p, index);
06208                         /* some switches require a minimum guard time between
06209                            the last FGD wink and something that answers
06210                            immediately. This ensures it */
06211                         if (ast_safe_sleep(chan,100)) goto quit;
06212       }
06213       dahdi_enable_ec(p);
06214       if (NEED_MFDETECT(p)) {
06215          if (p->dsp) {
06216             if (!p->hardwaredtmf)
06217                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
06218             else {
06219                ast_dsp_free(p->dsp);
06220                p->dsp = NULL;
06221             }
06222          }
06223       }
06224 
06225       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06226          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06227          if (p->dsp) ast_dsp_digitreset(p->dsp);
06228          res = ast_pbx_run(chan);
06229          if (res) {
06230             ast_log(LOG_WARNING, "PBX exited non-zero\n");
06231             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06232          }
06233          goto quit;
06234       } else {
06235          if (option_verbose > 2)
06236             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06237          sleep(2);
06238          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
06239          if (res < 0)
06240             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06241          else
06242             sleep(1);
06243          res = ast_streamfile(chan, "ss-noservice", chan->language);
06244          if (res >= 0)
06245             ast_waitstream(chan, "");
06246          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06247          ast_hangup(chan);
06248          goto quit;
06249       }
06250       break;
06251    case SIG_FXOLS:
06252    case SIG_FXOGS:
06253    case SIG_FXOKS:
06254       /* Read the first digit */
06255       timeout = firstdigittimeout;
06256       /* If starting a threeway call, never timeout on the first digit so someone
06257          can use flash-hook as a "hold" feature */
06258       if (p->subs[SUB_THREEWAY].owner) 
06259          timeout = 999999;
06260       while (len < AST_MAX_EXTENSION-1) {
06261          /* Read digit unless it's supposed to be immediate, in which case the
06262             only answer is 's' */
06263          if (p->immediate) 
06264             res = 's';
06265          else
06266             res = ast_waitfordigit(chan, timeout);
06267          timeout = 0;
06268          if (res < 0) {
06269             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06270             res = tone_zone_play_tone(p->subs[index].dfd, -1);
06271             ast_hangup(chan);
06272             goto quit;
06273          } else if (res)  {
06274             exten[len++]=res;
06275             exten[len] = '\0';
06276          }
06277          if (!ast_ignore_pattern(chan->context, exten))
06278             tone_zone_play_tone(p->subs[index].dfd, -1);
06279          else
06280             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06281          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06282             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06283                if (getforward) {
06284                   /* Record this as the forwarding extension */
06285                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
06286                   if (option_verbose > 2)
06287                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06288                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06289                   if (res)
06290                      break;
06291                   usleep(500000);
06292                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
06293                   sleep(1);
06294                   memset(exten, 0, sizeof(exten));
06295                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06296                   len = 0;
06297                   getforward = 0;
06298                } else  {
06299                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
06300                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06301                   if (!ast_strlen_zero(p->cid_num)) {
06302                      if (!p->hidecallerid)
06303                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
06304                      else
06305                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
06306                   }
06307                   if (!ast_strlen_zero(p->cid_name)) {
06308                      if (!p->hidecallerid)
06309                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
06310                   }
06311                   ast_setstate(chan, AST_STATE_RING);
06312                   dahdi_enable_ec(p);
06313                   res = ast_pbx_run(chan);
06314                   if (res) {
06315                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
06316                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06317                   }
06318                   goto quit;
06319                }
06320             } else {
06321                /* It's a match, but they just typed a digit, and there is an ambiguous match,
06322                   so just set the timeout to matchdigittimeout and wait some more */
06323                timeout = matchdigittimeout;
06324             }
06325          } else if (res == 0) {
06326             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06327             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06328             dahdi_wait_event(p->subs[index].dfd);
06329             ast_hangup(chan);
06330             goto quit;
06331          } else if (p->callwaiting && !strcmp(exten, "*70")) {
06332             if (option_verbose > 2) 
06333                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06334             /* Disable call waiting if enabled */
06335             p->callwaiting = 0;
06336             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06337             if (res) {
06338                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06339                   chan->name, strerror(errno));
06340             }
06341             len = 0;
06342             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06343             memset(exten, 0, sizeof(exten));
06344             timeout = firstdigittimeout;
06345                
06346          } else if (!strcmp(exten,ast_pickup_ext())) {
06347             /* Scan all channels and see if there are any
06348              * ringing channels that have call groups
06349              * that equal this channels pickup group  
06350              */
06351             if (index == SUB_REAL) {
06352                /* Switch us from Third call to Call Wait */
06353                if (p->subs[SUB_THREEWAY].owner) {
06354                   /* If you make a threeway call and the *8# a call, it should actually 
06355                      look like a callwait */
06356                   alloc_sub(p, SUB_CALLWAIT);   
06357                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06358                   unalloc_sub(p, SUB_THREEWAY);
06359                }
06360                dahdi_enable_ec(p);
06361                if (ast_pickup_call(chan)) {
06362                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
06363                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06364                   dahdi_wait_event(p->subs[index].dfd);
06365                }
06366                ast_hangup(chan);
06367                goto quit;
06368             } else {
06369                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
06370                ast_hangup(chan);
06371                goto quit;
06372             }
06373             
06374          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06375             if (option_verbose > 2) 
06376                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06377             /* Disable Caller*ID if enabled */
06378             p->hidecallerid = 1;
06379             if (chan->cid.cid_num)
06380                free(chan->cid.cid_num);
06381             chan->cid.cid_num = NULL;
06382             if (chan->cid.cid_name)
06383                free(chan->cid.cid_name);
06384             chan->cid.cid_name = NULL;
06385             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06386             if (res) {
06387                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06388                   chan->name, strerror(errno));
06389             }
06390             len = 0;
06391             memset(exten, 0, sizeof(exten));
06392             timeout = firstdigittimeout;
06393          } else if (p->callreturn && !strcmp(exten, "*69")) {
06394             res = 0;
06395             if (!ast_strlen_zero(p->lastcid_num)) {
06396                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06397             }
06398             if (!res)
06399                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06400             break;
06401          } else if (!strcmp(exten, "*78")) {
06402             /* Do not disturb */
06403             if (option_verbose > 2)
06404                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06405             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06406                      "Channel: %s/%d\r\n"
06407                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
06408             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06409             p->dnd = 1;
06410             getforward = 0;
06411             memset(exten, 0, sizeof(exten));
06412             len = 0;
06413          } else if (!strcmp(exten, "*79")) {
06414             /* Do not disturb */
06415             if (option_verbose > 2)
06416                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06417             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06418                      "Channel: %s/%d\r\n"
06419                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
06420             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06421             p->dnd = 0;
06422             getforward = 0;
06423             memset(exten, 0, sizeof(exten));
06424             len = 0;
06425          } else if (p->cancallforward && !strcmp(exten, "*72")) {
06426             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06427             getforward = 1;
06428             memset(exten, 0, sizeof(exten));
06429             len = 0;
06430          } else if (p->cancallforward && !strcmp(exten, "*73")) {
06431             if (option_verbose > 2)
06432                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06433             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06434             memset(p->call_forward, 0, sizeof(p->call_forward));
06435             getforward = 0;
06436             memset(exten, 0, sizeof(exten));
06437             len = 0;
06438          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
06439                   p->subs[SUB_THREEWAY].owner &&
06440                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06441             /* This is a three way call, the main call being a real channel, 
06442                and we're parking the first call. */
06443             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06444             if (option_verbose > 2)
06445                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06446             break;
06447          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06448             if (option_verbose > 2)
06449                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06450             res = ast_db_put("blacklist", p->lastcid_num, "1");
06451             if (!res) {
06452                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06453                memset(exten, 0, sizeof(exten));
06454                len = 0;
06455             }
06456          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06457             if (option_verbose > 2) 
06458                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06459             /* Enable Caller*ID if enabled */
06460             p->hidecallerid = 0;
06461             if (chan->cid.cid_num)
06462                free(chan->cid.cid_num);
06463             chan->cid.cid_num = NULL;
06464             if (chan->cid.cid_name)
06465                free(chan->cid.cid_name);
06466             chan->cid.cid_name = NULL;
06467             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06468             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06469             if (res) {
06470                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06471                   chan->name, strerror(errno));
06472             }
06473             len = 0;
06474             memset(exten, 0, sizeof(exten));
06475             timeout = firstdigittimeout;
06476          } else if (!strcmp(exten, "*0")) {
06477             struct ast_channel *nbridge = 
06478                p->subs[SUB_THREEWAY].owner;
06479             struct dahdi_pvt *pbridge = NULL;
06480               /* set up the private struct of the bridged one, if any */
06481             if (nbridge && ast_bridged_channel(nbridge)) 
06482                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06483             if (nbridge && pbridge && 
06484                 (nbridge->tech == chan_tech) && 
06485                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06486                 ISTRUNK(pbridge)) {
06487                int func = DAHDI_FLASH;
06488                /* Clear out the dial buffer */
06489                p->dop.dialstr[0] = '\0';
06490                /* flash hookswitch */
06491                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06492                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06493                      nbridge->name, strerror(errno));
06494                }
06495                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06496                unalloc_sub(p, SUB_THREEWAY);
06497                p->owner = p->subs[SUB_REAL].owner;
06498                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06499                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06500                ast_hangup(chan);
06501                goto quit;
06502             } else {
06503                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06504                dahdi_wait_event(p->subs[index].dfd);
06505                tone_zone_play_tone(p->subs[index].dfd, -1);
06506                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06507                unalloc_sub(p, SUB_THREEWAY);
06508                p->owner = p->subs[SUB_REAL].owner;
06509                ast_hangup(chan);
06510                goto quit;
06511             }              
06512          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06513                      ((exten[0] != '*') || (strlen(exten) > 2))) {
06514             if (option_debug)
06515                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);
06516             break;
06517          }
06518          if (!timeout)
06519             timeout = gendigittimeout;
06520          if (len && !ast_ignore_pattern(chan->context, exten))
06521             tone_zone_play_tone(p->subs[index].dfd, -1);
06522       }
06523       break;
06524    case SIG_FXSLS:
06525    case SIG_FXSGS:
06526    case SIG_FXSKS:
06527 #ifdef HAVE_PRI
06528       if (p->pri) {
06529          /* This is a GR-303 trunk actually.  Wait for the first ring... */
06530          struct ast_frame *f;
06531          int res;
06532          time_t start;
06533 
06534          time(&start);
06535          ast_setstate(chan, AST_STATE_RING);
06536          while (time(NULL) < start + 3) {
06537             res = ast_waitfor(chan, 1000);
06538             if (res) {
06539                f = ast_read(chan);
06540                if (!f) {
06541                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06542                   ast_hangup(chan);
06543                   goto quit;
06544                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06545                   res = 1;
06546                } else
06547                   res = 0;
06548                ast_frfree(f);
06549                if (res) {
06550                   ast_log(LOG_DEBUG, "Got ring!\n");
06551                   res = 0;
06552                   break;
06553                }
06554             }
06555          }
06556       }
06557 #endif
06558       /* check for SMDI messages */
06559       if (p->use_smdi && p->smdi_iface) {
06560          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06561 
06562          if (smdi_msg != NULL) {
06563             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06564 
06565             if (smdi_msg->type == 'B')
06566                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06567             else if (smdi_msg->type == 'N')
06568                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06569 
06570             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06571          } else {
06572             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06573          }
06574       }
06575 
06576       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06577             number = smdi_msg->calling_st;
06578 
06579       /* If we want caller id, we're in a prering state due to a polarity reversal
06580        * and we're set to use a polarity reversal to trigger the start of caller id,
06581        * grab the caller id and wait for ringing to start... */
06582       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06583          /* If set to use DTMF CID signalling, listen for DTMF */
06584          if (p->cid_signalling == CID_SIG_DTMF) {
06585             int i = 0;
06586             cs = NULL;
06587             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06588                "channel %s\n", chan->name);
06589             dahdi_setlinear(p->subs[index].dfd, 0);
06590             res = 2000;
06591             for (;;) {
06592                struct ast_frame *f;
06593                res = ast_waitfor(chan, res);
06594                if (res <= 0) {
06595                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06596                      "Exiting simple switch\n");
06597                   ast_hangup(chan);
06598                   goto quit;
06599                } 
06600                f = ast_read(chan);
06601                if (!f)
06602                   break;
06603                if (f->frametype == AST_FRAME_DTMF) {
06604                   dtmfbuf[i++] = f->subclass;
06605                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06606                   res = 2000;
06607                }
06608                ast_frfree(f);
06609                if (chan->_state == AST_STATE_RING ||
06610                    chan->_state == AST_STATE_RINGING) 
06611                   break; /* Got ring */
06612             }
06613             dtmfbuf[i] = '\0';
06614             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06615             /* Got cid and ring. */
06616             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06617             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06618             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
06619                dtmfcid, flags);
06620             /* If first byte is NULL, we have no cid */
06621             if (!ast_strlen_zero(dtmfcid)) 
06622                number = dtmfcid;
06623             else
06624                number = NULL;
06625          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
06626          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06627             cs = callerid_new(p->cid_signalling);
06628             if (cs) {
06629                samples = 0;
06630 #if 1
06631                bump_gains(p);
06632 #endif            
06633                /* Take out of linear mode for Caller*ID processing */
06634                dahdi_setlinear(p->subs[index].dfd, 0);
06635                
06636                /* First we wait and listen for the Caller*ID */
06637                for (;;) {  
06638                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06639                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06640                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06641                      callerid_free(cs);
06642                      ast_hangup(chan);
06643                      goto quit;
06644                   }
06645                   if (i & DAHDI_IOMUX_SIGEVENT) {
06646                      res = dahdi_get_event(p->subs[index].dfd);
06647                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06648 
06649                      if (p->cid_signalling == CID_SIG_V23_JP) {
06650 #ifdef DAHDI_EVENT_RINGBEGIN
06651                         if (res == DAHDI_EVENT_RINGBEGIN) {
06652                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06653                            usleep(1);
06654                         }
06655 #endif
06656                      } else {
06657                         res = 0;
06658                         break;
06659                      }
06660                   } else if (i & DAHDI_IOMUX_READ) {
06661                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06662                      if (res < 0) {
06663                         if (errno != ELAST) {
06664                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06665                            callerid_free(cs);
06666                            ast_hangup(chan);
06667                            goto quit;
06668                         }
06669                         break;
06670                      }
06671                      samples += res;
06672 
06673                      if  (p->cid_signalling == CID_SIG_V23_JP) {
06674                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06675                      } else {
06676                         res = callerid_feed(cs, buf, res, AST_LAW(p));
06677                      }
06678 
06679                      if (res < 0) {
06680                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06681                         break;
06682                      } else if (res)
06683                         break;
06684                      else if (samples > (8000 * 10))
06685                         break;
06686                   }
06687                }
06688                if (res == 1) {
06689                   callerid_get(cs, &name, &number, &flags);
06690                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06691                }
06692 
06693                if (p->cid_signalling == CID_SIG_V23_JP) {
06694                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06695                   usleep(1);
06696                   res = 4000;
06697                } else {
06698 
06699                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
06700                   res = 2000;
06701                }
06702 
06703                for (;;) {
06704                   struct ast_frame *f;
06705                   res = ast_waitfor(chan, res);
06706                   if (res <= 0) {
06707                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06708                         "Exiting simple switch\n");
06709                      ast_hangup(chan);
06710                      goto quit;
06711                   } 
06712                   if (!(f = ast_read(chan))) {
06713                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06714                      ast_hangup(chan);
06715                      goto quit;
06716                   }
06717                   ast_frfree(f);
06718                   if (chan->_state == AST_STATE_RING ||
06719                       chan->_state == AST_STATE_RINGING) 
06720                      break; /* Got ring */
06721                }
06722    
06723                /* We must have a ring by now, so, if configured, lets try to listen for
06724                 * distinctive ringing */ 
06725                if (p->usedistinctiveringdetection) {
06726                   len = 0;
06727                   distMatches = 0;
06728                   /* Clear the current ring data array so we dont have old data in it. */
06729                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06730                      curRingData[receivedRingT] = 0;
06731                   receivedRingT = 0;
06732                   counter = 0;
06733                   counter1 = 0;
06734                   /* Check to see if context is what it should be, if not set to be. */
06735                   if (strcmp(p->context,p->defcontext) != 0) {
06736                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06737                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06738                   }
06739       
06740                   for (;;) {  
06741                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06742                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06743                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06744                         callerid_free(cs);
06745                         ast_hangup(chan);
06746                         goto quit;
06747                      }
06748                      if (i & DAHDI_IOMUX_SIGEVENT) {
06749                         res = dahdi_get_event(p->subs[index].dfd);
06750                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06751                         res = 0;
06752                         /* Let us detect distinctive ring */
06753       
06754                         curRingData[receivedRingT] = p->ringt;
06755       
06756                         if (p->ringt < p->ringt_base/2)
06757                            break;
06758                         /* Increment the ringT counter so we can match it against
06759                            values in chan_dahdi.conf for distinctive ring */
06760                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06761                            break;
06762                      } else if (i & DAHDI_IOMUX_READ) {
06763                         res = read(p->subs[index].dfd, buf, sizeof(buf));
06764                         if (res < 0) {
06765                            if (errno != ELAST) {
06766                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06767                               callerid_free(cs);
06768                               ast_hangup(chan);
06769                               goto quit;
06770                            }
06771                            break;
06772                         }
06773                         if (p->ringt) 
06774                            p->ringt--;
06775                         if (p->ringt == 1) {
06776                            res = -1;
06777                            break;
06778                         }
06779                      }
06780                   }
06781                   if (option_verbose > 2)
06782                      /* this only shows up if you have n of the dring patterns filled in */
06783                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06784    
06785                   for (counter = 0; counter < 3; counter++) {
06786                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06787                      channel */
06788                      distMatches = 0;
06789                      for (counter1 = 0; counter1 < 3; counter1++) {
06790                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06791                         (p->drings.ringnum[counter].ring[counter1]-10)) {
06792                            distMatches++;
06793                         }
06794                      }
06795                      if (distMatches == 3) {
06796                         /* The ring matches, set the context to whatever is for distinctive ring.. */
06797                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06798                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06799                         if (option_verbose > 2)
06800                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06801                         break;
06802                      }
06803                   }
06804                }
06805                /* Restore linear mode (if appropriate) for Caller*ID processing */
06806                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06807 #if 1
06808                restore_gains(p);
06809 #endif            
06810             } else
06811                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
06812          } else {
06813             ast_log(LOG_WARNING, "Channel %s in prering "
06814                "state, but I have nothing to do. "
06815                "Terminating simple switch, should be "
06816                "restarted by the actual ring.\n", 
06817                chan->name);
06818             ast_hangup(chan);
06819             goto quit;
06820          }
06821       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06822          /* FSK Bell202 callerID */
06823          cs = callerid_new(p->cid_signalling);
06824          if (cs) {
06825 #if 1
06826             bump_gains(p);
06827 #endif            
06828             samples = 0;
06829             len = 0;
06830             distMatches = 0;
06831             /* Clear the current ring data array so we dont have old data in it. */
06832             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06833                curRingData[receivedRingT] = 0;
06834             receivedRingT = 0;
06835             counter = 0;
06836             counter1 = 0;
06837             /* Check to see if context is what it should be, if not set to be. */
06838             if (strcmp(p->context,p->defcontext) != 0) {
06839                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06840                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06841             }
06842 
06843             /* Take out of linear mode for Caller*ID processing */
06844             dahdi_setlinear(p->subs[index].dfd, 0);
06845             for (;;) {  
06846                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06847                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06848                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06849                   callerid_free(cs);
06850                   ast_hangup(chan);
06851                   goto quit;
06852                }
06853                if (i & DAHDI_IOMUX_SIGEVENT) {
06854                   res = dahdi_get_event(p->subs[index].dfd);
06855                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06856                   /* If we get a PR event, they hung up while processing calerid */
06857                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06858                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06859                      p->polarity = POLARITY_IDLE;
06860                      callerid_free(cs);
06861                      ast_hangup(chan);
06862                      goto quit;
06863                   }
06864                   res = 0;
06865                   /* Let us detect callerid when the telco uses distinctive ring */
06866 
06867                   curRingData[receivedRingT] = p->ringt;
06868 
06869                   if (p->ringt < p->ringt_base/2)
06870                      break;
06871                   /* Increment the ringT counter so we can match it against
06872                      values in chan_dahdi.conf for distinctive ring */
06873                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06874                      break;
06875                } else if (i & DAHDI_IOMUX_READ) {
06876                   res = read(p->subs[index].dfd, buf, sizeof(buf));
06877                   if (res < 0) {
06878                      if (errno != ELAST) {
06879                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06880                         callerid_free(cs);
06881                         ast_hangup(chan);
06882                         goto quit;
06883                      }
06884                      break;
06885                   }
06886                   if (p->ringt) 
06887                      p->ringt--;
06888                   if (p->ringt == 1) {
06889                      res = -1;
06890                      break;
06891                   }
06892                   samples += res;
06893                   res = callerid_feed(cs, buf, res, AST_LAW(p));
06894                   if (res < 0) {
06895                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06896                      break;
06897                   } else if (res)
06898                      break;
06899                   else if (samples > (8000 * 10))
06900                      break;
06901                }
06902             }
06903             if (res == 1) {
06904                callerid_get(cs, &name, &number, &flags);
06905                if (option_debug)
06906                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06907             }
06908             if (distinctiveringaftercid == 1) {
06909                /* Clear the current ring data array so we dont have old data in it. */
06910                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06911                   curRingData[receivedRingT] = 0;
06912                }
06913                receivedRingT = 0;
06914                if (option_verbose > 2)
06915                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06916                for (;;) {
06917                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06918                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
06919                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06920                      callerid_free(cs);
06921                      ast_hangup(chan);
06922                      goto quit;
06923                   }
06924                   if (i & DAHDI_IOMUX_SIGEVENT) {
06925                      res = dahdi_get_event(p->subs[index].dfd);
06926                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06927                      res = 0;
06928                      /* Let us detect callerid when the telco uses distinctive ring */
06929 
06930                      curRingData[receivedRingT] = p->ringt;
06931 
06932                      if (p->ringt < p->ringt_base/2)
06933                         break;
06934                      /* Increment the ringT counter so we can match it against
06935                         values in chan_dahdi.conf for distinctive ring */
06936                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06937                         break;
06938                   } else if (i & DAHDI_IOMUX_READ) {
06939                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06940                      if (res < 0) {
06941                         if (errno != ELAST) {
06942                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06943                            callerid_free(cs);
06944                            ast_hangup(chan);
06945                            goto quit;
06946                         }
06947                         break;
06948                      }
06949                   if (p->ringt)
06950                      p->ringt--;
06951                      if (p->ringt == 1) {
06952                         res = -1;
06953                         break;
06954                      }
06955                   }
06956                }
06957             }
06958             if (p->usedistinctiveringdetection) {
06959                if (option_verbose > 2)
06960                   /* this only shows up if you have n of the dring patterns filled in */
06961                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06962 
06963                for (counter = 0; counter < 3; counter++) {
06964                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06965                   channel */
06966                   if (option_verbose > 2)
06967                      /* this only shows up if you have n of the dring patterns filled in */
06968                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06969                         p->drings.ringnum[counter].ring[0],
06970                         p->drings.ringnum[counter].ring[1],
06971                         p->drings.ringnum[counter].ring[2]);
06972                   distMatches = 0;
06973                   for (counter1 = 0; counter1 < 3; counter1++) {
06974                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06975                      (p->drings.ringnum[counter].ring[counter1]-10)) {
06976                         distMatches++;
06977                      }
06978                   }
06979                   if (distMatches == 3) {
06980                      /* The ring matches, set the context to whatever is for distinctive ring.. */
06981                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06982                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06983                      if (option_verbose > 2)
06984                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06985                      break;
06986                   }
06987                }
06988             }
06989             /* Restore linear mode (if appropriate) for Caller*ID processing */
06990             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06991 #if 1
06992             restore_gains(p);
06993 #endif            
06994             if (res < 0) {
06995                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06996             }
06997          } else
06998             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06999       }
07000       else
07001          cs = NULL;
07002 
07003       if (number)
07004          ast_shrink_phone_number(number);
07005       ast_set_callerid(chan, number, name, number);
07006 
07007       if (smdi_msg)
07008          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07009 
07010       if (cs)
07011          callerid_free(cs);
07012 
07013       ast_setstate(chan, AST_STATE_RING);
07014       chan->rings = 1;
07015       p->ringt = p->ringt_base;
07016       res = ast_pbx_run(chan);
07017       if (res) {
07018          ast_hangup(chan);
07019          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07020       }
07021       goto quit;
07022    default:
07023       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07024       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07025       if (res < 0)
07026             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07027    }
07028    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07029    if (res < 0)
07030          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07031    ast_hangup(chan);
07032 quit:
07033    ast_mutex_lock(&ss_thread_lock);
07034    ss_thread_count--;
07035    ast_cond_signal(&ss_thread_complete);
07036    ast_mutex_unlock(&ss_thread_lock);
07037    return NULL;
07038 }
07039 
07040 /* destroy a DAHDI channel, identified by its number */
07041 static int dahdi_destroy_channel_bynum(int channel)
07042 {
07043    struct dahdi_pvt *tmp = NULL;
07044    struct dahdi_pvt *prev = NULL;
07045 
07046    tmp = iflist;
07047    while (tmp) {
07048       if (tmp->channel == channel) {
07049          int x = DAHDI_FLASH;
07050          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 */
07051          destroy_channel(prev, tmp, 1);
07052          ast_module_unref(ast_module_info->self);
07053          return RESULT_SUCCESS;
07054       }
07055       prev = tmp;
07056       tmp = tmp->next;
07057    }
07058    return RESULT_FAILURE;
07059 }
07060 
07061 static int handle_init_event(struct dahdi_pvt *i, int event)
07062 {
07063    int res;
07064    pthread_t threadid;
07065    pthread_attr_t attr;
07066    struct ast_channel *chan;
07067    pthread_attr_init(&attr);
07068    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07069    /* Handle an event on a given channel for the monitor thread. */
07070    switch (event) {
07071    case DAHDI_EVENT_NONE:
07072    case DAHDI_EVENT_BITSCHANGED:
07073       break;
07074    case DAHDI_EVENT_WINKFLASH:
07075    case DAHDI_EVENT_RINGOFFHOOK:
07076       if (i->inalarm) break;
07077       if (i->radio) break;
07078       /* Got a ring/answer.  What kind of channel are we? */
07079       switch (i->sig) {
07080       case SIG_FXOLS:
07081       case SIG_FXOGS:
07082       case SIG_FXOKS:
07083          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07084          if (res && (errno == EBUSY))
07085             break;
07086          if (i->cidspill) {
07087             /* Cancel VMWI spill */
07088             free(i->cidspill);
07089             i->cidspill = NULL;
07090          }
07091          if (i->immediate) {
07092             dahdi_enable_ec(i);
07093             /* The channel is immediately up.  Start right away */
07094             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07095             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07096             if (!chan) {
07097                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07098                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07099                if (res < 0)
07100                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07101             }
07102          } else {
07103             /* Check for callerid, digits, etc */
07104             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07105             if (chan) {
07106                if (has_voicemail(i))
07107                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07108                else
07109                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07110                if (res < 0) 
07111                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07112                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07113                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07114                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07115                   if (res < 0)
07116                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07117                   ast_hangup(chan);
07118                }
07119             } else
07120                ast_log(LOG_WARNING, "Unable to create channel\n");
07121          }
07122          break;
07123       case SIG_FXSLS:
07124       case SIG_FXSGS:
07125       case SIG_FXSKS:
07126             i->ringt = i->ringt_base;
07127             /* Fall through */
07128       case SIG_EMWINK:
07129       case SIG_FEATD:
07130       case SIG_FEATDMF:
07131       case SIG_FEATDMF_TA:
07132       case SIG_E911:
07133       case SIG_FGC_CAMA:
07134       case SIG_FGC_CAMAMF:
07135       case SIG_FEATB:
07136       case SIG_EM:
07137       case SIG_EM_E1:
07138       case SIG_SFWINK:
07139       case SIG_SF_FEATD:
07140       case SIG_SF_FEATDMF:
07141       case SIG_SF_FEATB:
07142       case SIG_SF:
07143             /* Check for callerid, digits, etc */
07144             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
07145             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07146                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07147                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07148                if (res < 0)
07149                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07150                ast_hangup(chan);
07151             } else if (!chan) {
07152                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
07153             }
07154             break;
07155       default:
07156          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07157          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07158          if (res < 0)
07159                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07160          return -1;
07161       }
07162       break;
07163    case DAHDI_EVENT_NOALARM:
07164       i->inalarm = 0;
07165       if (!i->unknown_alarm) {
07166          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
07167          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07168                   "Channel: %d\r\n", i->channel);
07169       } else {
07170          i->unknown_alarm = 0;
07171       }
07172       break;
07173    case DAHDI_EVENT_ALARM:
07174       i->inalarm = 1;
07175       res = get_alarms(i);
07176       handle_alarms(i, res);
07177       /* fall thru intentionally */
07178    case DAHDI_EVENT_ONHOOK:
07179       if (i->radio)
07180          break;
07181       /* Back on hook.  Hang up. */
07182       switch (i->sig) {
07183       case SIG_FXOLS:
07184       case SIG_FXOGS:
07185       case SIG_FEATD:
07186       case SIG_FEATDMF:
07187       case SIG_FEATDMF_TA:
07188       case SIG_E911:
07189       case SIG_FGC_CAMA:
07190       case SIG_FGC_CAMAMF:
07191       case SIG_FEATB:
07192       case SIG_EM:
07193       case SIG_EM_E1:
07194       case SIG_EMWINK:
07195       case SIG_SF_FEATD:
07196       case SIG_SF_FEATDMF:
07197       case SIG_SF_FEATB:
07198       case SIG_SF:
07199       case SIG_SFWINK:
07200       case SIG_FXSLS:
07201       case SIG_FXSGS:
07202       case SIG_FXSKS:
07203       case SIG_GR303FXSKS:
07204          dahdi_disable_ec(i);
07205          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07206          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07207          break;
07208       case SIG_GR303FXOKS:
07209       case SIG_FXOKS:
07210          dahdi_disable_ec(i);
07211          /* Diddle the battery for the zhone */
07212 #ifdef ZHONE_HACK
07213          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07214          usleep(1);
07215 #endif         
07216          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07217          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07218          break;
07219       case SIG_PRI:
07220          dahdi_disable_ec(i);
07221          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07222          break;
07223       default:
07224          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07225          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07226          return -1;
07227       }
07228       break;
07229    case DAHDI_EVENT_POLARITY:
07230       switch (i->sig) {
07231       case SIG_FXSLS:
07232       case SIG_FXSKS:
07233       case SIG_FXSGS:
07234          /* We have already got a PR before the channel was 
07235             created, but it wasn't handled. We need polarity 
07236             to be REV for remote hangup detection to work. 
07237             At least in Spain */
07238          if (i->hanguponpolarityswitch)
07239             i->polarity = POLARITY_REV;
07240 
07241          if (i->cid_start == CID_START_POLARITY) {
07242             i->polarity = POLARITY_REV;
07243             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
07244                    "CID detection on channel %d\n",
07245                    i->channel);
07246             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
07247             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07248                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07249             }
07250          }
07251          break;
07252       default:
07253          ast_log(LOG_WARNING, "handle_init_event detected "
07254             "polarity reversal on non-FXO (SIG_FXS) "
07255             "interface %d\n", i->channel);
07256       }
07257       break;
07258    case DAHDI_EVENT_REMOVED: /* destroy channel */
07259       ast_log(LOG_NOTICE, 
07260             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
07261             i->channel);
07262       dahdi_destroy_channel_bynum(i->channel);
07263       break;
07264    }
07265    pthread_attr_destroy(&attr);
07266    return 0;
07267 }
07268 
07269 static void *do_monitor(void *data)
07270 {
07271    int count, res, res2, spoint, pollres=0;
07272    struct dahdi_pvt *i;
07273    struct dahdi_pvt *last = NULL;
07274    time_t thispass = 0, lastpass = 0;
07275    int found;
07276    char buf[1024];
07277    struct pollfd *pfds=NULL;
07278    int lastalloc = -1;
07279    /* This thread monitors all the frame relay interfaces which are not yet in use
07280       (and thus do not have a separate thread) indefinitely */
07281    /* From here on out, we die whenever asked */
07282 #if 0
07283    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
07284       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
07285       return NULL;
07286    }
07287    ast_log(LOG_DEBUG, "Monitor starting...\n");
07288 #endif
07289    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07290 
07291    for (;;) {
07292       /* Lock the interface list */
07293       ast_mutex_lock(&iflock);
07294       if (!pfds || (lastalloc != ifcount)) {
07295          if (pfds) {
07296             free(pfds);
07297             pfds = NULL;
07298          }
07299          if (ifcount) {
07300             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
07301                ast_mutex_unlock(&iflock);
07302                return NULL;
07303             }
07304          }
07305          lastalloc = ifcount;
07306       }
07307       /* Build the stuff we're going to poll on, that is the socket of every
07308          dahdi_pvt that does not have an associated owner channel */
07309       count = 0;
07310       i = iflist;
07311       while (i) {
07312          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
07313             if (!i->owner && !i->subs[SUB_REAL].owner) {
07314                /* This needs to be watched, as it lacks an owner */
07315                pfds[count].fd = i->subs[SUB_REAL].dfd;
07316                pfds[count].events = POLLPRI;
07317                pfds[count].revents = 0;
07318                /* Message waiting or r2 channels also get watched for reading */
07319                if (i->cidspill)
07320                   pfds[count].events |= POLLIN;
07321                count++;
07322             }
07323          }
07324          i = i->next;
07325       }
07326       /* Okay, now that we know what to do, release the interface lock */
07327       ast_mutex_unlock(&iflock);
07328       
07329       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07330       pthread_testcancel();
07331       /* Wait at least a second for something to happen */
07332       res = poll(pfds, count, 1000);
07333       pthread_testcancel();
07334       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07335 
07336       /* Okay, poll has finished.  Let's see what happened.  */
07337       if (res < 0) {
07338          if ((errno != EAGAIN) && (errno != EINTR))
07339             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07340          continue;
07341       }
07342       /* Alright, lock the interface list again, and let's look and see what has
07343          happened */
07344       ast_mutex_lock(&iflock);
07345       found = 0;
07346       spoint = 0;
07347       lastpass = thispass;
07348       thispass = time(NULL);
07349       i = iflist;
07350       while (i) {
07351          if (thispass != lastpass) {
07352             if (!found && ((i == last) || ((i == iflist) && !last))) {
07353                last = i;
07354                if (last) {
07355                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07356                      (last->sig & __DAHDI_SIG_FXO)) {
07357                      res = ast_app_has_voicemail(last->mailbox, NULL);
07358                      if (last->msgstate != res) {
07359                         int x;
07360                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07361                         x = DAHDI_FLUSH_BOTH;
07362                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07363                         if (res2)
07364                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07365                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07366                            /* Turn on on hook transfer for 4 seconds */
07367                            x = 4000;
07368                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07369                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07370                            last->cidpos = 0;
07371                            last->msgstate = res;
07372                            last->onhooktime = thispass;
07373                         }
07374                         found ++;
07375                      }
07376                   }
07377                   last = last->next;
07378                }
07379             }
07380          }
07381          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07382             if (i->radio && !i->owner)
07383             {
07384                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07385                if (res)
07386                {
07387                   if (option_debug)
07388                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07389                   /* Don't hold iflock while handling init events */
07390                   ast_mutex_unlock(&iflock);
07391                   handle_init_event(i, res);
07392                   ast_mutex_lock(&iflock);   
07393                }
07394                i = i->next;
07395                continue;
07396             }              
07397             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07398             if (pollres & POLLIN) {
07399                if (i->owner || i->subs[SUB_REAL].owner) {
07400 #ifdef HAVE_PRI
07401                   if (!i->pri)
07402 #endif                  
07403                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07404                   i = i->next;
07405                   continue;
07406                }
07407                if (!i->cidspill) {
07408                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07409                   i = i->next;
07410                   continue;
07411                }
07412                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07413                if (res > 0) {
07414                   /* We read some number of bytes.  Write an equal amount of data */
07415                   if (res > i->cidlen - i->cidpos) 
07416                      res = i->cidlen - i->cidpos;
07417                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07418                   if (res2 > 0) {
07419                      i->cidpos += res2;
07420                      if (i->cidpos >= i->cidlen) {
07421                         free(i->cidspill);
07422                         i->cidspill = 0;
07423                         i->cidpos = 0;
07424                         i->cidlen = 0;
07425                      }
07426                   } else {
07427                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07428                      i->msgstate = -1;
07429                   }
07430                } else {
07431                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07432                }
07433             }
07434             if (pollres & POLLPRI) {
07435                if (i->owner || i->subs[SUB_REAL].owner) {
07436 #ifdef HAVE_PRI
07437                   if (!i->pri)
07438 #endif                  
07439                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07440                   i = i->next;
07441                   continue;
07442                }
07443                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07444                if (option_debug)
07445                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07446                /* Don't hold iflock while handling init events */
07447                ast_mutex_unlock(&iflock);
07448                handle_init_event(i, res);
07449                ast_mutex_lock(&iflock);   
07450             }
07451          }
07452          i=i->next;
07453       }
07454       ast_mutex_unlock(&iflock);
07455    }
07456    /* Never reached */
07457    return NULL;
07458    
07459 }
07460 
07461 static int restart_monitor(void)
07462 {
07463    pthread_attr_t attr;
07464    pthread_attr_init(&attr);
07465    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07466    /* If we're supposed to be stopped -- stay stopped */
07467    if (monitor_thread == AST_PTHREADT_STOP)
07468       return 0;
07469    ast_mutex_lock(&monlock);
07470    if (monitor_thread == pthread_self()) {
07471       ast_mutex_unlock(&monlock);
07472       ast_log(LOG_WARNING, "Cannot kill myself\n");
07473       return -1;
07474    }
07475    if (monitor_thread != AST_PTHREADT_NULL) {
07476       /* Wake up the thread */
07477       pthread_kill(monitor_thread, SIGURG);
07478    } else {
07479       /* Start a new monitor */
07480       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07481          ast_mutex_unlock(&monlock);
07482          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07483          pthread_attr_destroy(&attr);
07484          return -1;
07485       }
07486    }
07487    ast_mutex_unlock(&monlock);
07488    pthread_attr_destroy(&attr);
07489    return 0;
07490 }
07491 
07492 #ifdef HAVE_PRI
07493 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
07494 {
07495    int x;
07496    int trunkgroup;
07497    /* Get appropriate trunk group if there is one */
07498    trunkgroup = pris[*span].mastertrunkgroup;
07499    if (trunkgroup) {
07500       /* Select a specific trunk group */
07501       for (x = 0; x < NUM_SPANS; x++) {
07502          if (pris[x].trunkgroup == trunkgroup) {
07503             *span = x;
07504             return 0;
07505          }
07506       }
07507       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07508       *span = -1;
07509    } else {
07510       if (pris[*span].trunkgroup) {
07511          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07512          *span = -1;
07513       } else if (pris[*span].mastertrunkgroup) {
07514          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07515          *span = -1;
07516       } else {
07517          if (si->totalchans == 31) {
07518             /* E1 */
07519             pris[*span].dchannels[0] = 16 + offset;
07520          } else if (si->totalchans == 24) {
07521             /* T1 or J1 */
07522             pris[*span].dchannels[0] = 24 + offset;
07523          } else if (si->totalchans == 3) {
07524             /* BRI */
07525             pris[*span].dchannels[0] = 3 + offset;
07526          } else {
07527             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);
07528             *span = -1;
07529             return 0;
07530          }
07531          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07532          pris[*span].offset = offset;
07533          pris[*span].span = *span + 1;
07534       }
07535    }
07536    return 0;
07537 }
07538 
07539 static int pri_create_trunkgroup(int trunkgroup, int *channels)
07540 {
07541    struct dahdi_spaninfo si;
07542    struct dahdi_params p;
07543    int fd;
07544    int span;
07545    int ospan=0;
07546    int x,y;
07547    for (x = 0; x < NUM_SPANS; x++) {
07548       if (pris[x].trunkgroup == trunkgroup) {
07549          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07550          return -1;
07551       }
07552    }
07553    for (y = 0; y < NUM_DCHANS; y++) {
07554       if (!channels[y]) 
07555          break;
07556       memset(&si, 0, sizeof(si));
07557       memset(&p, 0, sizeof(p));
07558       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
07559       if (fd < 0) {
07560          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07561          return -1;
07562       }
07563       x = channels[y];
07564       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07565          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07566          close(fd);
07567          return -1;
07568       }
07569       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07570          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07571          return -1;
07572       }
07573       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07574          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07575          close(fd);
07576          return -1;
07577       }
07578       span = p.spanno - 1;
07579       if (pris[span].trunkgroup) {
07580          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07581          close(fd);
07582          return -1;
07583       }
07584       if (pris[span].pvts[0]) {
07585          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07586          close(fd);
07587          return -1;
07588       }
07589       if (!y) {
07590          pris[span].trunkgroup = trunkgroup;
07591          pris[span].offset = channels[y] - p.chanpos;
07592          ospan = span;
07593       }
07594       pris[ospan].dchannels[y] = channels[y];
07595       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07596       pris[span].span = span + 1;
07597       close(fd);
07598    }
07599    return 0;   
07600 }
07601 
07602 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
07603 {
07604    if (pris[span].mastertrunkgroup) {
07605       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);
07606       return -1;
07607    }
07608    pris[span].mastertrunkgroup = trunkgroup;
07609    pris[span].prilogicalspan = logicalspan;
07610    return 0;
07611 }
07612 
07613 #endif
07614 
07615 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
07616 {
07617    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
07618    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
07619    char fn[80];
07620 #if 1
07621    struct dahdi_bufferinfo bi;
07622 #endif
07623    int res;
07624    int span=0;
07625    int here = 0;
07626    int x;
07627    struct dahdi_pvt **wlist;
07628    struct dahdi_pvt **wend;
07629    struct dahdi_params p;
07630 
07631    wlist = &iflist;
07632    wend = &ifend;
07633 
07634 #ifdef HAVE_PRI
07635    if (pri) {
07636       wlist = &pri->crvs;
07637       wend = &pri->crvend;
07638    }
07639 #endif
07640 
07641    tmp2 = *wlist;
07642    prev = NULL;
07643 
07644    while (tmp2) {
07645       if (!tmp2->destroy) {
07646          if (tmp2->channel == channel) {
07647             tmp = tmp2;
07648             here = 1;
07649             break;
07650          }
07651          if (tmp2->channel > channel) {
07652             break;
07653          }
07654       }
07655       prev = tmp2;
07656       tmp2 = tmp2->next;
07657    }
07658 
07659    if (!here && reloading != 1) {
07660       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07661          if (tmp)
07662             free(tmp);
07663          return NULL;
07664       }
07665       ast_mutex_init(&tmp->lock);
07666       ifcount++;
07667       for (x = 0; x < 3; x++)
07668          tmp->subs[x].dfd = -1;
07669       tmp->channel = channel;
07670    }
07671 
07672    if (tmp) {
07673       int chan_sig = conf->chan.sig;
07674       if (!here) {
07675          if ((channel != CHAN_PSEUDO) && !pri) {
07676             int count = 0;
07677             snprintf(fn, sizeof(fn), "%d", channel);
07678             /* Open non-blocking */
07679             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07680             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 */
07681                usleep(1);
07682                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07683                count++;
07684             }
07685             /* Allocate a DAHDI structure */
07686             if (tmp->subs[SUB_REAL].dfd < 0) {
07687                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);
07688                destroy_dahdi_pvt(&tmp);
07689                return NULL;
07690             }
07691             memset(&p, 0, sizeof(p));
07692             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07693             if (res < 0) {
07694                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07695                destroy_dahdi_pvt(&tmp);
07696                return NULL;
07697             }
07698             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07699                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));
07700                destroy_dahdi_pvt(&tmp);
07701                return NULL;
07702             }
07703             tmp->law = p.curlaw;
07704             tmp->span = p.spanno;
07705             span = p.spanno - 1;
07706          } else {
07707             if (channel == CHAN_PSEUDO)
07708                chan_sig = 0;
07709             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07710                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07711                return NULL;
07712             }
07713          }
07714 #ifdef HAVE_PRI
07715          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07716             int offset;
07717             int myswitchtype;
07718             int matchesdchan;
07719             int x,y;
07720             offset = 0;
07721             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07722                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07723                destroy_dahdi_pvt(&tmp);
07724                return NULL;
07725             }
07726             if (span >= NUM_SPANS) {
07727                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07728                destroy_dahdi_pvt(&tmp);
07729                return NULL;
07730             } else {
07731                struct dahdi_spaninfo si;
07732                si.spanno = 0;
07733                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07734                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07735                   destroy_dahdi_pvt(&tmp);
07736                   return NULL;
07737                }
07738                /* Store the logical span first based upon the real span */
07739                tmp->logicalspan = pris[span].prilogicalspan;
07740                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07741                if (span < 0) {
07742                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07743                   destroy_dahdi_pvt(&tmp);
07744                   return NULL;
07745                }
07746                if (chan_sig == SIG_PRI)
07747                   myswitchtype = conf->pri.switchtype;
07748                else
07749                   myswitchtype = PRI_SWITCH_GR303_TMC;
07750                /* Make sure this isn't a d-channel */
07751                matchesdchan=0;
07752                for (x = 0; x < NUM_SPANS; x++) {
07753                   for (y = 0; y < NUM_DCHANS; y++) {
07754                      if (pris[x].dchannels[y] == tmp->channel) {
07755                         matchesdchan = 1;
07756                         break;
07757                      }
07758                   }
07759                }
07760                offset = p.chanpos;
07761                if (!matchesdchan) {
07762                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07763                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07764                      destroy_dahdi_pvt(&tmp);
07765                      return NULL;
07766                   }
07767                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07768                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07769                      destroy_dahdi_pvt(&tmp);
07770                      return NULL;
07771                   }
07772                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07773                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07774                      destroy_dahdi_pvt(&tmp);
07775                      return NULL;
07776                   }
07777                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07778                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07779                      destroy_dahdi_pvt(&tmp);
07780                      return NULL;
07781                   }
07782                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07783                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07784                      destroy_dahdi_pvt(&tmp);
07785                      return NULL;
07786                   }
07787                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07788                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07789                      destroy_dahdi_pvt(&tmp);
07790                      return NULL;
07791                   }
07792                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07793                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07794                      destroy_dahdi_pvt(&tmp);
07795                      return NULL;
07796                   }
07797                   if (pris[span].numchans >= MAX_CHANNELS) {
07798                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07799                         pris[span].trunkgroup);
07800                      destroy_dahdi_pvt(&tmp);
07801                      return NULL;
07802                   }
07803                   pris[span].nodetype = conf->pri.nodetype;
07804                   pris[span].switchtype = myswitchtype;
07805                   pris[span].nsf = conf->pri.nsf;
07806                   pris[span].dialplan = conf->pri.dialplan;
07807                   pris[span].localdialplan = conf->pri.localdialplan;
07808                   pris[span].pvts[pris[span].numchans++] = tmp;
07809                   pris[span].minunused = conf->pri.minunused;
07810                   pris[span].minidle = conf->pri.minidle;
07811                   pris[span].overlapdial = conf->pri.overlapdial;
07812 #ifdef HAVE_PRI_INBANDDISCONNECT
07813                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07814 #endif
07815                   pris[span].facilityenable = conf->pri.facilityenable;
07816                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07817                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07818                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07819                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07820                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07821                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07822                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07823                   pris[span].resetinterval = conf->pri.resetinterval;
07824                   
07825                   tmp->pri = &pris[span];
07826                   tmp->prioffset = offset;
07827                   tmp->call = NULL;
07828                } else {
07829                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07830                   destroy_dahdi_pvt(&tmp);
07831                   return NULL;
07832                }
07833             }
07834          } else {
07835             tmp->prioffset = 0;
07836          }
07837 #endif
07838       } else {
07839          chan_sig = tmp->sig;
07840          memset(&p, 0, sizeof(p));
07841          if (tmp->subs[SUB_REAL].dfd > -1)
07842             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07843       }
07844       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
07845       switch (chan_sig) {
07846       case SIG_FXSKS:
07847       case SIG_FXSLS:
07848       case SIG_EM:
07849       case SIG_EM_E1:
07850       case SIG_EMWINK:
07851       case SIG_FEATD:
07852       case SIG_FEATDMF:
07853       case SIG_FEATDMF_TA:
07854       case SIG_FEATB:
07855       case SIG_E911:
07856       case SIG_SF:
07857       case SIG_SFWINK:
07858       case SIG_FGC_CAMA:
07859       case SIG_FGC_CAMAMF:
07860       case SIG_SF_FEATD:
07861       case SIG_SF_FEATDMF:
07862       case SIG_SF_FEATB:
07863          p.starttime = 250;
07864          break;
07865       }
07866 
07867       if (tmp->radio) {
07868          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
07869          p.channo = channel;
07870          p.rxwinktime = 1;
07871          p.rxflashtime = 1;
07872          p.starttime = 1;
07873          p.debouncetime = 5;
07874       }
07875       if (!tmp->radio) {
07876          p.channo = channel;
07877          /* Override timing settings based on config file */
07878          if (conf->timing.prewinktime >= 0)
07879             p.prewinktime = conf->timing.prewinktime;
07880          if (conf->timing.preflashtime >= 0)
07881             p.preflashtime = conf->timing.preflashtime;
07882          if (conf->timing.winktime >= 0)
07883             p.winktime = conf->timing.winktime;
07884          if (conf->timing.flashtime >= 0)
07885             p.flashtime = conf->timing.flashtime;
07886          if (conf->timing.starttime >= 0)
07887             p.starttime = conf->timing.starttime;
07888          if (conf->timing.rxwinktime >= 0)
07889             p.rxwinktime = conf->timing.rxwinktime;
07890          if (conf->timing.rxflashtime >= 0)
07891             p.rxflashtime = conf->timing.rxflashtime;
07892          if (conf->timing.debouncetime >= 0)
07893             p.debouncetime = conf->timing.debouncetime;
07894       }
07895       
07896       /* dont set parms on a pseudo-channel (or CRV) */
07897       if (tmp->subs[SUB_REAL].dfd >= 0)
07898       {
07899          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07900          if (res < 0) {
07901             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07902             destroy_dahdi_pvt(&tmp);
07903             return NULL;
07904          }
07905       }
07906 #if 1
07907       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07908          memset(&bi, 0, sizeof(bi));
07909          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07910          if (!res) {
07911             bi.txbufpolicy = conf->chan.buf_policy;
07912             bi.rxbufpolicy = conf->chan.buf_policy;
07913             bi.numbufs = conf->chan.buf_no;
07914             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07915             if (res < 0) {
07916                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07917             }
07918          } else
07919             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07920       }
07921 #endif
07922       tmp->immediate = conf->chan.immediate;
07923       tmp->transfertobusy = conf->chan.transfertobusy;
07924       tmp->sig = chan_sig;
07925       tmp->outsigmod = conf->chan.outsigmod;
07926       tmp->ringt_base = ringt_base;
07927       tmp->firstradio = 0;
07928       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07929          tmp->permcallwaiting = conf->chan.callwaiting;
07930       else
07931          tmp->permcallwaiting = 0;
07932       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
07933       tmp->destroy = 0;
07934       tmp->drings = drings;
07935       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07936       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07937       tmp->threewaycalling = conf->chan.threewaycalling;
07938       tmp->adsi = conf->chan.adsi;
07939       tmp->use_smdi = conf->chan.use_smdi;
07940       tmp->permhidecallerid = conf->chan.hidecallerid;
07941       tmp->callreturn = conf->chan.callreturn;
07942       tmp->echocancel = conf->chan.echocancel;
07943       tmp->echotraining = conf->chan.echotraining;
07944       tmp->pulse = conf->chan.pulse;
07945       if (tmp->echocancel)
07946          tmp->echocanbridged = conf->chan.echocanbridged;
07947       else {
07948          if (conf->chan.echocanbridged)
07949             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07950          tmp->echocanbridged = 0;
07951       }
07952       tmp->busydetect = conf->chan.busydetect;
07953       tmp->busycount = conf->chan.busycount;
07954       tmp->busycompare = conf->chan.busycompare;
07955       tmp->busytonelength = conf->chan.busytonelength;
07956       tmp->busyquietlength = conf->chan.busyquietlength;
07957       tmp->busyfuzziness = conf->chan.busyfuzziness;
07958       tmp->silencethreshold = conf->chan.silencethreshold;
07959       tmp->callprogress = conf->chan.callprogress;
07960       tmp->cancallforward = conf->chan.cancallforward;
07961       tmp->dtmfrelax = conf->chan.dtmfrelax;
07962       tmp->callwaiting = tmp->permcallwaiting;
07963       tmp->hidecallerid = tmp->permhidecallerid;
07964       tmp->channel = channel;
07965       tmp->stripmsd = conf->chan.stripmsd;
07966       tmp->use_callerid = conf->chan.use_callerid;
07967       tmp->cid_signalling = conf->chan.cid_signalling;
07968       tmp->cid_start = conf->chan.cid_start;
07969       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07970       tmp->restrictcid = conf->chan.restrictcid;
07971       tmp->use_callingpres = conf->chan.use_callingpres;
07972       tmp->priindication_oob = conf->chan.priindication_oob;
07973       tmp->priexclusive = conf->chan.priexclusive;
07974       if (tmp->usedistinctiveringdetection) {
07975          if (!tmp->use_callerid) {
07976             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07977             tmp->use_callerid = 1;
07978          }
07979       }
07980 
07981       if (tmp->cid_signalling == CID_SIG_SMDI) {
07982          if (!tmp->use_smdi) {
07983             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07984             tmp->use_smdi = 1;
07985          }
07986       }
07987       if (tmp->use_smdi) {
07988          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07989          if (!(tmp->smdi_iface)) {
07990             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07991             tmp->use_smdi = 0;
07992          }
07993       }
07994 
07995       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07996       tmp->amaflags = conf->chan.amaflags;
07997       if (!here) {
07998          tmp->confno = -1;
07999          tmp->propconfno = -1;
08000       }
08001       tmp->canpark = conf->chan.canpark;
08002       tmp->transfer = conf->chan.transfer;
08003       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08004       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08005       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08006       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08007       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08008       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08009       tmp->cid_ton = 0;
08010       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08011       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08012       tmp->msgstate = -1;
08013       tmp->group = conf->chan.group;
08014       tmp->callgroup = conf->chan.callgroup;
08015       tmp->pickupgroup= conf->chan.pickupgroup;
08016       tmp->rxgain = conf->chan.rxgain;
08017       tmp->txgain = conf->chan.txgain;
08018       tmp->tonezone = conf->chan.tonezone;
08019       tmp->onhooktime = time(NULL);
08020       if (tmp->subs[SUB_REAL].dfd > -1) {
08021          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
08022          if (tmp->dsp)
08023             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
08024          update_conf(tmp);
08025          if (!here) {
08026             if (chan_sig != SIG_PRI)
08027                /* Hang it up to be sure it's good */
08028                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08029          }
08030          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
08031 #ifdef HAVE_PRI
08032          /* the dchannel is down so put the channel in alarm */
08033          if (tmp->pri && !pri_is_up(tmp->pri)) {
08034             tmp->inalarm = 1;
08035          }
08036 #endif            
08037          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
08038             tmp->inalarm = 1;
08039             handle_alarms(tmp, res);
08040          } else {
08041             /* yes, this looks strange... the unknown_alarm flag is only used to
08042                control whether an 'alarm cleared' message gets generated when we
08043                get an indication that the channel is no longer in alarm status.
08044                however, the channel *could* be in an alarm status that we aren't
08045                aware of (since get_alarms() only reports span alarms, not channel
08046                alarms). setting this flag will cause any potential 'alarm cleared'
08047                message to be suppressed, but if a real alarm occurs before that
08048                happens, this flag will get cleared by it and the situation will
08049                be normal.
08050             */
08051             tmp->unknown_alarm = 1;
08052          }
08053       }
08054 
08055       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
08056       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
08057       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
08058       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
08059 
08060    }
08061    if (tmp && !here) {
08062       /* nothing on the iflist */
08063       if (!*wlist) {
08064          *wlist = tmp;
08065          tmp->prev = NULL;
08066          tmp->next = NULL;
08067          *wend = tmp;
08068       } else {
08069          /* at least one member on the iflist */
08070          struct dahdi_pvt *working = *wlist;
08071 
08072          /* check if we maybe have to put it on the begining */
08073          if (working->channel > tmp->channel) {
08074             tmp->next = *wlist;
08075             tmp->prev = NULL;
08076             (*wlist)->prev = tmp;
08077             *wlist = tmp;
08078          } else {
08079          /* go through all the members and put the member in the right place */
08080             while (working) {
08081                /* in the middle */
08082                if (working->next) {
08083                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
08084                      tmp->next = working->next;
08085                      tmp->prev = working;
08086                      working->next->prev = tmp;
08087                      working->next = tmp;
08088                      break;
08089                   }
08090                } else {
08091                /* the last */
08092                   if (working->channel < tmp->channel) {
08093                      working->next = tmp;
08094                      tmp->next = NULL;
08095                      tmp->prev = working;
08096                      *wend = tmp;
08097                      break;
08098                   }
08099                }
08100                working = working->next;
08101             }
08102          }
08103       }
08104    }
08105    return tmp;
08106 }
08107 
08108 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
08109 {
08110    int res;
08111    struct dahdi_params par;
08112 
08113    /* First, check group matching */
08114    if (groupmatch) {
08115       if ((p->group & groupmatch) != groupmatch)
08116          return 0;
08117       *groupmatched = 1;
08118    }
08119    /* Check to see if we have a channel match */
08120    if (channelmatch != -1) {
08121       if (p->channel != channelmatch)
08122          return 0;
08123       *channelmatched = 1;
08124    }
08125    /* We're at least busy at this point */
08126    if (busy) {
08127       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
08128          *busy = 1;
08129    }
08130    /* If do not disturb, definitely not */
08131    if (p->dnd)
08132       return 0;
08133    /* If guard time, definitely not */
08134    if (p->guardtime && (time(NULL) < p->guardtime)) 
08135       return 0;
08136       
08137    /* If no owner definitely available */
08138    if (!p->owner) {
08139 #ifdef HAVE_PRI
08140       /* Trust PRI */
08141       if (p->pri) {
08142          if (p->resetting || p->call)
08143             return 0;
08144          else
08145             return 1;
08146       }
08147 #endif
08148       if (!(p->radio || (p->oprmode < 0)))
08149       {
08150          if (!p->sig || (p->sig == SIG_FXSLS))
08151             return 1;
08152          /* Check hook state */
08153          if (p->subs[SUB_REAL].dfd > -1)
08154             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
08155          else {
08156             /* Assume not off hook on CVRS */
08157             res = 0;
08158             par.rxisoffhook = 0;
08159          }
08160          if (res) {
08161             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
08162          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
08163             /* When "onhook" that means no battery on the line, and thus
08164               it is out of service..., if it's on a TDM card... If it's a channel
08165               bank, there is no telling... */
08166             if (par.rxbits > -1)
08167                return 1;
08168             if (par.rxisoffhook)
08169                return 1;
08170             else
08171 #ifdef DAHDI_CHECK_HOOKSTATE
08172                return 0;
08173 #else
08174                return 1;
08175 #endif
08176          } else if (par.rxisoffhook) {
08177             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
08178             /* Not available when the other end is off hook */
08179             return 0;
08180          }
08181       }
08182       return 1;
08183    }
08184 
08185    /* If it's not an FXO, forget about call wait */
08186    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
08187       return 0;
08188 
08189    if (!p->callwaiting) {
08190       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
08191       return 0;
08192    }
08193 
08194    if (p->subs[SUB_CALLWAIT].dfd > -1) {
08195       /* If there is already a call waiting call, then we can't take a second one */
08196       return 0;
08197    }
08198    
08199    if ((p->owner->_state != AST_STATE_UP) &&
08200        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
08201       /* If the current call is not up, then don't allow the call */
08202       return 0;
08203    }
08204    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
08205       /* Can't take a call wait when the three way calling hasn't been merged yet. */
08206       return 0;
08207    }
08208    /* We're cool */
08209    return 1;
08210 }
08211 
08212 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
08213 {
08214    struct dahdi_pvt *p;
08215    struct dahdi_bufferinfo bi;
08216    int res;
08217    
08218    if ((p = ast_malloc(sizeof(*p)))) {
08219       memcpy(p, src, sizeof(struct dahdi_pvt));
08220       ast_mutex_init(&p->lock);
08221       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
08222       /* Allocate a DAHDI structure */
08223       if (p->subs[SUB_REAL].dfd < 0) {
08224          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
08225          destroy_dahdi_pvt(&p);
08226          return NULL;
08227       }
08228       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08229       if (!res) {
08230          bi.txbufpolicy = p->buf_policy;
08231          bi.rxbufpolicy = p->buf_policy;
08232          bi.numbufs = p->buf_no;
08233          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08234          if (res < 0) {
08235             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
08236          }
08237       } else
08238          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
08239    }
08240    p->destroy = 1;
08241    p->next = iflist;
08242    p->prev = NULL;
08243    iflist = p;
08244    if (iflist->next)
08245       iflist->next->prev = p;
08246    return p;
08247 }
08248    
08249 
08250 #ifdef HAVE_PRI
08251 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
08252 {
08253    int x;
08254    if (backwards)
08255       x = pri->numchans;
08256    else
08257       x = 0;
08258    for (;;) {
08259       if (backwards && (x < 0))
08260          break;
08261       if (!backwards && (x >= pri->numchans))
08262          break;
08263       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
08264          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
08265             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
08266          return x;
08267       }
08268       if (backwards)
08269          x--;
08270       else
08271          x++;
08272    }
08273    return -1;
08274 }
08275 #endif
08276 
08277 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
08278 {
08279    ast_group_t groupmatch = 0;
08280    int channelmatch = -1;
08281    int roundrobin = 0;
08282    int callwait = 0;
08283    int busy = 0;
08284    struct dahdi_pvt *p;
08285    struct ast_channel *tmp = NULL;
08286    char *dest=NULL;
08287    int x;
08288    char *s;
08289    char opt=0;
08290    int res=0, y=0;
08291    int backwards = 0;
08292 #ifdef HAVE_PRI
08293    int crv;
08294    int bearer = -1;
08295    int trunkgroup;
08296    struct dahdi_pri *pri=NULL;
08297 #endif   
08298    struct dahdi_pvt *exit, *start, *end;
08299    ast_mutex_t *lock;
08300    int channelmatched = 0;
08301    int groupmatched = 0;
08302    
08303    /*
08304     * data is ---v
08305     * Dial(DAHDI/pseudo[/extension])
08306     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
08307     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
08308     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
08309     *
08310     * g - channel group allocation search forward
08311     * G - channel group allocation search backward
08312     * r - channel group allocation round robin search forward
08313     * R - channel group allocation round robin search backward
08314     *
08315     * c - Wait for DTMF digit to confirm answer
08316     * r<cadance#> - Set distintive ring cadance number
08317     * d - Force bearer capability for ISDN call to digital.
08318     */
08319 
08320    /* Assume we're locking the iflock */
08321    lock = &iflock;
08322    start = iflist;
08323    end = ifend;
08324    if (data) {
08325       dest = ast_strdupa((char *)data);
08326    } else {
08327       ast_log(LOG_WARNING, "Channel requested with no data\n");
08328       return NULL;
08329    }
08330    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08331       /* Retrieve the group number */
08332       char *stringp;
08333 
08334       stringp = dest + 1;
08335       s = strsep(&stringp, "/");
08336       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08337          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08338          return NULL;
08339       }
08340       groupmatch = ((ast_group_t) 1 << x);
08341       if (toupper(dest[0]) == 'G') {
08342          if (dest[0] == 'G') {
08343             backwards = 1;
08344             p = ifend;
08345          } else
08346             p = iflist;
08347       } else {
08348          if (dest[0] == 'R') {
08349             backwards = 1;
08350             p = round_robin[x]?round_robin[x]->prev:ifend;
08351             if (!p)
08352                p = ifend;
08353          } else {
08354             p = round_robin[x]?round_robin[x]->next:iflist;
08355             if (!p)
08356                p = iflist;
08357          }
08358          roundrobin = 1;
08359       }
08360    } else {
08361       char *stringp;
08362 
08363       stringp = dest;
08364       s = strsep(&stringp, "/");
08365       p = iflist;
08366       if (!strcasecmp(s, "pseudo")) {
08367          /* Special case for pseudo */
08368          x = CHAN_PSEUDO;
08369          channelmatch = x;
08370       } 
08371 #ifdef HAVE_PRI
08372       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08373          if ((trunkgroup < 1) || (crv < 1)) {
08374             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08375             return NULL;
08376          }
08377          res--;
08378          for (x = 0; x < NUM_SPANS; x++) {
08379             if (pris[x].trunkgroup == trunkgroup) {
08380                pri = pris + x;
08381                lock = &pri->lock;
08382                start = pri->crvs;
08383                end = pri->crvend;
08384                break;
08385             }
08386          }
08387          if (!pri) {
08388             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08389             return NULL;
08390          }
08391          channelmatch = crv;
08392          p = pris[x].crvs;
08393       }
08394 #endif   
08395       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08396          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08397          return NULL;
08398       } else {
08399          channelmatch = x;
08400       }
08401    }
08402    /* Search for an unowned channel */
08403    ast_mutex_lock(lock);
08404    exit = p;
08405    while (p && !tmp) {
08406       if (roundrobin)
08407          round_robin[x] = p;
08408 #if 0
08409       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08410 #endif
08411 
08412       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08413          if (option_debug)
08414             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08415             if (p->inalarm) 
08416                goto next;
08417 
08418          callwait = (p->owner != NULL);
08419 #ifdef HAVE_PRI
08420          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08421             if (p->sig != SIG_FXSKS) {
08422                /* Gotta find an actual channel to use for this
08423                   CRV if this isn't a callwait */
08424                bearer = pri_find_empty_chan(pri, 0);
08425                if (bearer < 0) {
08426                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08427                   p = NULL;
08428                   break;
08429                }
08430                pri_assign_bearer(p, pri, pri->pvts[bearer]);
08431             } else {
08432                if (alloc_sub(p, 0)) {
08433                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08434                   p = NULL;
08435                   break;
08436                } else
08437                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08438                p->pri = pri;
08439             }
08440          }
08441 #endif         
08442          if (p->channel == CHAN_PSEUDO) {
08443             p = chandup(p);
08444             if (!p) {
08445                break;
08446             }
08447          }
08448          if (p->owner) {
08449             if (alloc_sub(p, SUB_CALLWAIT)) {
08450                p = NULL;
08451                break;
08452             }
08453          }
08454          p->outgoing = 1;
08455          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08456 #ifdef HAVE_PRI
08457          if (p->bearer) {
08458             /* Log owner to bearer channel, too */
08459             p->bearer->owner = tmp;
08460          }
08461 #endif         
08462          /* Make special notes */
08463          if (res > 1) {
08464             if (opt == 'c') {
08465                /* Confirm answer */
08466                p->confirmanswer = 1;
08467             } else if (opt == 'r') {
08468                /* Distinctive ring */
08469                if (res < 3)
08470                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08471                else
08472                   p->distinctivering = y;
08473             } else if (opt == 'd') {
08474                /* If this is an ISDN call, make it digital */
08475                p->digital = 1;
08476                if (tmp)
08477                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08478             } else {
08479                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08480             }
08481          }
08482          /* Note if the call is a call waiting call */
08483          if (tmp && callwait)
08484             tmp->cdrflags |= AST_CDR_CALLWAIT;
08485          break;
08486       }
08487 next:
08488       if (backwards) {
08489          p = p->prev;
08490          if (!p)
08491             p = end;
08492       } else {
08493          p = p->next;
08494          if (!p)
08495             p = start;
08496       }
08497       /* stop when you roll to the one that we started from */
08498       if (p == exit)
08499          break;
08500    }
08501    ast_mutex_unlock(lock);
08502    restart_monitor();
08503    if (callwait)
08504       *cause = AST_CAUSE_BUSY;
08505    else if (!tmp) {
08506       if (channelmatched) {
08507          if (busy)
08508             *cause = AST_CAUSE_BUSY;
08509       } else if (groupmatched) {
08510          *cause = AST_CAUSE_CONGESTION;
08511       }
08512    }
08513       
08514    return tmp;
08515 }
08516 
08517 
08518 #ifdef HAVE_PRI
08519 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
08520 {
08521    struct dahdi_pvt *p;
08522    p = pri->crvs;
08523    while (p) {
08524       if (p->channel == crv)
08525          return p;
08526       p = p->next;
08527    }
08528    return NULL;
08529 }
08530 
08531 
08532 static int pri_find_principle(struct dahdi_pri *pri, int channel)
08533 {
08534    int x;
08535    int span = PRI_SPAN(channel);
08536    int spanfd;
08537    struct dahdi_params param;
08538    int principle = -1;
08539    int explicit = PRI_EXPLICIT(channel);
08540    channel = PRI_CHANNEL(channel);
08541 
08542    if (!explicit) {
08543       spanfd = pri_active_dchan_fd(pri);
08544       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
08545          return -1;
08546       span = pris[param.spanno - 1].prilogicalspan;
08547    }
08548 
08549    for (x = 0; x < pri->numchans; x++) {
08550       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08551          principle = x;
08552          break;
08553       }
08554    }
08555    
08556    return principle;
08557 }
08558 
08559 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
08560 {
08561    int x;
08562    struct dahdi_pvt *crv;
08563    if (!c) {
08564       if (principle < 0)
08565          return -1;
08566       return principle;
08567    }
08568    if ((principle > -1) && 
08569       (principle < pri->numchans) && 
08570       (pri->pvts[principle]) && 
08571       (pri->pvts[principle]->call == c))
08572       return principle;
08573    /* First, check for other bearers */
08574    for (x = 0; x < pri->numchans; x++) {
08575       if (!pri->pvts[x])
08576          continue;
08577       if (pri->pvts[x]->call == c) {
08578          /* Found our call */
08579          if (principle != x) {
08580             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08581 
08582             if (option_verbose > 2)
08583                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08584                   old->channel, new->channel);
08585             if (new->owner) {
08586                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08587                   old->channel, new->channel, new->channel);
08588                return -1;
08589             }
08590             /* Fix it all up now */
08591             new->owner = old->owner;
08592             old->owner = NULL;
08593             if (new->owner) {
08594                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08595                new->owner->tech_pvt = new;
08596                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08597                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08598                old->subs[SUB_REAL].owner = NULL;
08599             } else
08600                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);
08601             new->call = old->call;
08602             old->call = NULL;
08603 
08604             /* Copy any DSP that may be present */
08605             new->dsp = old->dsp;
08606             new->dsp_features = old->dsp_features;
08607             old->dsp = NULL;
08608             old->dsp_features = 0;
08609          }
08610          return principle;
08611       }
08612    }
08613    /* Now check for a CRV with no bearer */
08614    crv = pri->crvs;
08615    while (crv) {
08616       if (crv->call == c) {
08617          /* This is our match...  Perform some basic checks */
08618          if (crv->bearer)
08619             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08620          else if (pri->pvts[principle]->owner) 
08621             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08622          else {
08623             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
08624                wakeup the potential sleeper */
08625             dahdi_close_sub(crv, SUB_REAL);
08626             pri->pvts[principle]->call = crv->call;
08627             pri_assign_bearer(crv, pri, pri->pvts[principle]);
08628             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08629                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08630                            pri->trunkgroup, crv->channel);
08631             wakeup_sub(crv, SUB_REAL, pri);
08632          }
08633          return principle;
08634       }
08635       crv = crv->next;
08636    }
08637    ast_log(LOG_WARNING, "Call specified, but not found?\n");
08638    return -1;
08639 }
08640 
08641 static void *do_idle_thread(void *vchan)
08642 {
08643    struct ast_channel *chan = vchan;
08644    struct dahdi_pvt *pvt = chan->tech_pvt;
08645    struct ast_frame *f;
08646    char ex[80];
08647    /* Wait up to 30 seconds for an answer */
08648    int newms, ms = 30000;
08649    if (option_verbose > 2) 
08650       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08651    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08652    if (ast_call(chan, ex, 0)) {
08653       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08654       ast_hangup(chan);
08655       return NULL;
08656    }
08657    while ((newms = ast_waitfor(chan, ms)) > 0) {
08658       f = ast_read(chan);
08659       if (!f) {
08660          /* Got hangup */
08661          break;
08662       }
08663       if (f->frametype == AST_FRAME_CONTROL) {
08664          switch (f->subclass) {
08665          case AST_CONTROL_ANSWER:
08666             /* Launch the PBX */
08667             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08668             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08669             chan->priority = 1;
08670             if (option_verbose > 3) 
08671                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08672             ast_pbx_run(chan);
08673             /* It's already hungup, return immediately */
08674             return NULL;
08675          case AST_CONTROL_BUSY:
08676             if (option_verbose > 3) 
08677                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08678             break;
08679          case AST_CONTROL_CONGESTION:
08680             if (option_verbose > 3) 
08681                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08682             break;
08683          };
08684       }
08685       ast_frfree(f);
08686       ms = newms;
08687    }
08688    /* Hangup the channel since nothing happend */
08689    ast_hangup(chan);
08690    return NULL;
08691 }
08692 
08693 #ifndef PRI_RESTART
08694 #error "Upgrade your libpri"
08695 #endif
08696 static void dahdi_pri_message(struct pri *pri, char *s)
08697 {
08698    int x, y;
08699    int dchan = -1, span = -1;
08700    int dchancount = 0;
08701 
08702    if (pri) {
08703       for (x = 0; x < NUM_SPANS; x++) {
08704          for (y = 0; y < NUM_DCHANS; y++) {
08705             if (pris[x].dchans[y])
08706                dchancount++;
08707 
08708             if (pris[x].dchans[y] == pri)
08709                dchan = y;
08710          }
08711          if (dchan >= 0) {
08712             span = x;
08713             break;
08714          }
08715          dchancount = 0;
08716       }
08717       if ((dchan >= 0) && (span >= 0)) {
08718          if (dchancount > 1)
08719             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08720          else
08721             ast_verbose("%s", s);
08722       } else
08723          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08724    } else
08725       ast_verbose("%s", s);
08726 
08727    ast_mutex_lock(&pridebugfdlock);
08728 
08729    if (pridebugfd >= 0) {
08730       if (write(pridebugfd, s, strlen(s)) < 0) {
08731          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08732       }
08733    }
08734 
08735    ast_mutex_unlock(&pridebugfdlock);
08736 }
08737 
08738 static void dahdi_pri_error(struct pri *pri, char *s)
08739 {
08740    int x, y;
08741    int dchan = -1, span = -1;
08742    int dchancount = 0;
08743 
08744    if (pri) {
08745       for (x = 0; x < NUM_SPANS; x++) {
08746          for (y = 0; y < NUM_DCHANS; y++) {
08747             if (pris[x].dchans[y])
08748                dchancount++;
08749 
08750             if (pris[x].dchans[y] == pri)
08751                dchan = y;
08752          }
08753          if (dchan >= 0) {
08754             span = x;
08755             break;
08756          }
08757          dchancount = 0;
08758       }
08759       if ((dchan >= 0) && (span >= 0)) {
08760          if (dchancount > 1)
08761             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08762          else
08763             ast_log(LOG_ERROR, "%s", s);
08764       } else
08765          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08766    } else
08767       ast_log(LOG_ERROR, "%s", s);
08768 
08769    ast_mutex_lock(&pridebugfdlock);
08770 
08771    if (pridebugfd >= 0) {
08772       if (write(pridebugfd, s, strlen(s)) < 0) {
08773          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08774       }
08775    }
08776 
08777    ast_mutex_unlock(&pridebugfdlock);
08778 }
08779 
08780 static int pri_check_restart(struct dahdi_pri *pri)
08781 {
08782    do {
08783       pri->resetpos++;
08784    } while ((pri->resetpos < pri->numchans) &&
08785        (!pri->pvts[pri->resetpos] ||
08786         pri->pvts[pri->resetpos]->call ||
08787         pri->pvts[pri->resetpos]->resetting));
08788    if (pri->resetpos < pri->numchans) {
08789       /* Mark the channel as resetting and restart it */
08790       pri->pvts[pri->resetpos]->resetting = 1;
08791       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08792    } else {
08793       pri->resetting = 0;
08794       time(&pri->lastreset);
08795    }
08796    return 0;
08797 }
08798 
08799 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
08800 {
08801    int x;
08802    int redo;
08803    ast_mutex_unlock(&pri->lock);
08804    ast_mutex_lock(&p->lock);
08805    do {
08806       redo = 0;
08807       for (x = 0; x < 3; x++) {
08808          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08809             redo++;
08810             DEADLOCK_AVOIDANCE(&p->lock);
08811          }
08812          if (p->subs[x].owner) {
08813             ast_queue_hangup(p->subs[x].owner);
08814             ast_mutex_unlock(&p->subs[x].owner->lock);
08815          }
08816       }
08817    } while (redo);
08818    ast_mutex_unlock(&p->lock);
08819    ast_mutex_lock(&pri->lock);
08820    return 0;
08821 }
08822 
08823 static char * redirectingreason2str(int redirectingreason)
08824 {
08825    switch (redirectingreason) {
08826    case 0:
08827       return "UNKNOWN";
08828    case 1:
08829       return "BUSY";
08830    case 2:
08831       return "NO_REPLY";
08832    case 0xF:
08833       return "UNCONDITIONAL";
08834    default:
08835       return "NOREDIRECT";
08836    }
08837 }
08838 
08839 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
08840 {
08841    switch (plan) {
08842    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
08843       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08844       break;
08845    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
08846       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08847       break;
08848    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
08849       snprintf(buf, size, "%s%s", pri->localprefix, number);
08850       break;
08851    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
08852       snprintf(buf, size, "%s%s", pri->privateprefix, number);
08853       break;
08854    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
08855       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08856       break;
08857    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
08858       snprintf(buf, size, "%s", number);
08859       break;
08860    }
08861 }
08862 
08863 static int dahdi_setlaw(int dfd, int law)
08864 {
08865    int res;
08866    res = ioctl(dfd, DAHDI_SETLAW, &law);
08867    if (res)
08868       return res;
08869    return 0;
08870 }
08871 
08872 static void *pri_dchannel(void *vpri)
08873 {
08874    struct dahdi_pri *pri = vpri;
08875    pri_event *e;
08876    struct pollfd fds[NUM_DCHANS];
08877    int res;
08878    int chanpos = 0;
08879    int x;
08880    int haveidles;
08881    int activeidles;
08882    int nextidle = -1;
08883    struct ast_channel *c;
08884    struct timeval tv, lowest, *next;
08885    struct timeval lastidle = { 0, 0 };
08886    int doidling=0;
08887    char *cc;
08888    char idlen[80];
08889    struct ast_channel *idle;
08890    pthread_t p;
08891    time_t t;
08892    int i, which=-1;
08893    int numdchans;
08894    int cause=0;
08895    struct dahdi_pvt *crv;
08896    pthread_t threadid;
08897    pthread_attr_t attr;
08898    char ani2str[6];
08899    char plancallingnum[256];
08900    char plancallingani[256];
08901    char calledtonstr[10];
08902    
08903    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08904 
08905    gettimeofday(&lastidle, NULL);
08906    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08907       /* Need to do idle dialing, check to be sure though */
08908       cc = strchr(pri->idleext, '@');
08909       if (cc) {
08910          *cc = '\0';
08911          cc++;
08912          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08913 #if 0
08914          /* Extensions may not be loaded yet */
08915          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08916             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08917          else
08918 #endif
08919             doidling = 1;
08920       } else
08921          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08922    }
08923    for (;;) {
08924       for (i = 0; i < NUM_DCHANS; i++) {
08925          if (!pri->dchannels[i])
08926             break;
08927          fds[i].fd = pri->fds[i];
08928          fds[i].events = POLLIN | POLLPRI;
08929          fds[i].revents = 0;
08930       }
08931       numdchans = i;
08932       time(&t);
08933       ast_mutex_lock(&pri->lock);
08934       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08935          if (pri->resetting && pri_is_up(pri)) {
08936             if (pri->resetpos < 0)
08937                pri_check_restart(pri);
08938          } else {
08939             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
08940                pri->resetting = 1;
08941                pri->resetpos = -1;
08942             }
08943          }
08944       }
08945       /* Look for any idle channels if appropriate */
08946       if (doidling && pri_is_up(pri)) {
08947          nextidle = -1;
08948          haveidles = 0;
08949          activeidles = 0;
08950          for (x = pri->numchans; x >= 0; x--) {
08951             if (pri->pvts[x] && !pri->pvts[x]->owner && 
08952                 !pri->pvts[x]->call) {
08953                if (haveidles < pri->minunused) {
08954                   haveidles++;
08955                } else if (!pri->pvts[x]->resetting) {
08956                   nextidle = x;
08957                   break;
08958                }
08959             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08960                activeidles++;
08961          }
08962          if (nextidle > -1) {
08963             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08964                /* Don't create a new idle call more than once per second */
08965                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08966                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08967                if (idle) {
08968                   pri->pvts[nextidle]->isidlecall = 1;
08969                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08970                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08971                      dahdi_hangup(idle);
08972                   }
08973                } else
08974                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08975                gettimeofday(&lastidle, NULL);
08976             }
08977          } else if ((haveidles < pri->minunused) &&
08978                (activeidles > pri->minidle)) {
08979             /* Mark something for hangup if there is something 
08980                that can be hungup */
08981             for (x = pri->numchans; x >= 0; x--) {
08982                /* find a candidate channel */
08983                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08984                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08985                   haveidles++;
08986                   /* Stop if we have enough idle channels or
08987                     can't spare any more active idle ones */
08988                   if ((haveidles >= pri->minunused) ||
08989                       (activeidles <= pri->minidle))
08990                      break;
08991                } 
08992             }
08993          }
08994       }
08995       /* Start with reasonable max */
08996       lowest = ast_tv(60, 0);
08997       for (i = 0; i < NUM_DCHANS; i++) {
08998          /* Find lowest available d-channel */
08999          if (!pri->dchannels[i])
09000             break;
09001          if ((next = pri_schedule_next(pri->dchans[i]))) {
09002             /* We need relative time here */
09003             tv = ast_tvsub(*next, ast_tvnow());
09004             if (tv.tv_sec < 0) {
09005                tv = ast_tv(0,0);
09006             }
09007             if (doidling || pri->resetting) {
09008                if (tv.tv_sec > 1) {
09009                   tv = ast_tv(1, 0);
09010                }
09011             } else {
09012                if (tv.tv_sec > 60) {
09013                   tv = ast_tv(60, 0);
09014                }
09015             }
09016          } else if (doidling || pri->resetting) {
09017             /* Make sure we stop at least once per second if we're
09018                monitoring idle channels */
09019             tv = ast_tv(1,0);
09020          } else {
09021             /* Don't poll for more than 60 seconds */
09022             tv = ast_tv(60, 0);
09023          }
09024          if (!i || ast_tvcmp(tv, lowest) < 0) {
09025             lowest = tv;
09026          }
09027       }
09028       ast_mutex_unlock(&pri->lock);
09029 
09030       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09031       pthread_testcancel();
09032       e = NULL;
09033       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
09034       pthread_testcancel();
09035       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09036 
09037       ast_mutex_lock(&pri->lock);
09038       if (!res) {
09039          for (which = 0; which < NUM_DCHANS; which++) {
09040             if (!pri->dchans[which])
09041                break;
09042             /* Just a timeout, run the scheduler */
09043             e = pri_schedule_run(pri->dchans[which]);
09044             if (e)
09045                break;
09046          }
09047       } else if (res > -1) {
09048          for (which = 0; which < NUM_DCHANS; which++) {
09049             if (!pri->dchans[which])
09050                break;
09051             if (fds[which].revents & POLLPRI) {
09052                /* Check for an event */
09053                x = 0;
09054                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
09055                if (x) 
09056                   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);
09057                /* Keep track of alarm state */  
09058                if (x == DAHDI_EVENT_ALARM) {
09059                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
09060                   pri_find_dchan(pri);
09061                } else if (x == DAHDI_EVENT_NOALARM) {
09062                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
09063                   pri_restart(pri->dchans[which]);
09064                }
09065             
09066                if (option_debug)
09067                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
09068             } else if (fds[which].revents & POLLIN) {
09069                e = pri_check_event(pri->dchans[which]);
09070             }
09071             if (e)
09072                break;
09073          }
09074       } else if (errno != EINTR)
09075          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
09076 
09077       if (e) {
09078          if (pri->debug)
09079             pri_dump_event(pri->dchans[which], e);
09080 
09081          if (e->e != PRI_EVENT_DCHAN_DOWN) {
09082             if (!(pri->dchanavail[which] & DCHAN_UP)) {
09083                if (option_verbose > 1) 
09084                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
09085             }
09086             pri->dchanavail[which] |= DCHAN_UP;
09087          } else {
09088             if (pri->dchanavail[which] & DCHAN_UP) {
09089                if (option_verbose > 1) 
09090                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
09091             }
09092             pri->dchanavail[which] &= ~DCHAN_UP;
09093          }
09094 
09095          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
09096             /* Must be an NFAS group that has the secondary dchan active */
09097             pri->pri = pri->dchans[which];
09098 
09099          switch (e->e) {
09100          case PRI_EVENT_DCHAN_UP:
09101             if (!pri->pri) pri_find_dchan(pri);
09102 
09103             /* Note presense of D-channel */
09104             time(&pri->lastreset);
09105 
09106             /* Restart in 5 seconds */
09107             if (pri->resetinterval > -1) {
09108                pri->lastreset -= pri->resetinterval;
09109                pri->lastreset += 5;
09110             }
09111             pri->resetting = 0;
09112             /* Take the channels from inalarm condition */
09113             for (i = 0; i < pri->numchans; i++)
09114                if (pri->pvts[i]) {
09115                   pri->pvts[i]->inalarm = 0;
09116                }
09117             break;
09118          case PRI_EVENT_DCHAN_DOWN:
09119             pri_find_dchan(pri);
09120             if (!pri_is_up(pri)) {
09121                pri->resetting = 0;
09122                /* Hangup active channels and put them in alarm mode */
09123                for (i = 0; i < pri->numchans; i++) {
09124                   struct dahdi_pvt *p = pri->pvts[i];
09125                   if (p) {
09126                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
09127                         /* T309 is not enabled : hangup calls when alarm occurs */
09128                         if (p->call) {
09129                            if (p->pri && p->pri->pri) {
09130                               pri_hangup(p->pri->pri, p->call, -1);
09131                               pri_destroycall(p->pri->pri, p->call);
09132                               p->call = NULL;
09133                            } else
09134                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
09135                         }
09136                         if (p->realcall) {
09137                            pri_hangup_all(p->realcall, pri);
09138                         } else if (p->owner)
09139                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09140                      }
09141                      p->inalarm = 1;
09142                   }
09143                }
09144             }
09145             break;
09146          case PRI_EVENT_RESTART:
09147             if (e->restart.channel > -1) {
09148                chanpos = pri_find_principle(pri, e->restart.channel);
09149                if (chanpos < 0)
09150                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
09151                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09152                else {
09153                   if (option_verbose > 2)
09154                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
09155                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09156                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09157                   if (pri->pvts[chanpos]->call) {
09158                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
09159                      pri->pvts[chanpos]->call = NULL;
09160                   }
09161                   /* Force soft hangup if appropriate */
09162                   if (pri->pvts[chanpos]->realcall) 
09163                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09164                   else if (pri->pvts[chanpos]->owner)
09165                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09166                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09167                }
09168             } else {
09169                if (option_verbose > 2)
09170                   ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
09171                for (x = 0; x < pri->numchans; x++)
09172                   if (pri->pvts[x]) {
09173                      ast_mutex_lock(&pri->pvts[x]->lock);
09174                      if (pri->pvts[x]->call) {
09175                         pri_destroycall(pri->pri, pri->pvts[x]->call);
09176                         pri->pvts[x]->call = NULL;
09177                      }
09178                      if (pri->pvts[chanpos]->realcall) 
09179                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09180                      else if (pri->pvts[x]->owner)
09181                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09182                      ast_mutex_unlock(&pri->pvts[x]->lock);
09183                   }
09184             }
09185             break;
09186          case PRI_EVENT_KEYPAD_DIGIT:
09187             chanpos = pri_find_principle(pri, e->digit.channel);
09188             if (chanpos < 0) {
09189                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
09190                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
09191             } else {
09192                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
09193                if (chanpos > -1) {
09194                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09195                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
09196                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
09197                      /* how to do that */
09198                      int digitlen = strlen(e->digit.digits);
09199                      char digit;
09200                      int i;               
09201                      for (i = 0; i < digitlen; i++) { 
09202                         digit = e->digit.digits[i];
09203                         {
09204                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
09205                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09206                         }
09207                      }
09208                   }
09209                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09210                }
09211             }
09212             break;
09213             
09214          case PRI_EVENT_INFO_RECEIVED:
09215             chanpos = pri_find_principle(pri, e->ring.channel);
09216             if (chanpos < 0) {
09217                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
09218                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09219             } else {
09220                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
09221                if (chanpos > -1) {
09222                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09223                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
09224                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
09225                      /* how to do that */
09226                      int digitlen = strlen(e->ring.callednum);
09227                      char digit;
09228                      int i;               
09229                      for (i = 0; i < digitlen; i++) { 
09230                         digit = e->ring.callednum[i];
09231                         {
09232                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
09233                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09234                         }
09235                      }
09236                   }
09237                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09238                }
09239             }
09240             break;
09241          case PRI_EVENT_RING:
09242             crv = NULL;
09243             if (e->ring.channel == -1)
09244                chanpos = pri_find_empty_chan(pri, 1);
09245             else
09246                chanpos = pri_find_principle(pri, e->ring.channel);
09247             /* if no channel specified find one empty */
09248             if (chanpos < 0) {
09249                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
09250                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09251             } else {
09252                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09253                if (pri->pvts[chanpos]->owner) {
09254                   if (pri->pvts[chanpos]->call == e->ring.call) {
09255                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
09256                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09257                      break;
09258                   } else {
09259                      /* This is where we handle initial glare */
09260                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
09261                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09262                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09263                      chanpos = -1;
09264                   }
09265                }
09266                if (chanpos > -1)
09267                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09268             }
09269             if ((chanpos < 0) && (e->ring.flexible))
09270                chanpos = pri_find_empty_chan(pri, 1);
09271             if (chanpos > -1) {
09272                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09273                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
09274                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
09275                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
09276                   if (crv)
09277                      ast_mutex_lock(&crv->lock);
09278                   if (!crv || crv->owner) {
09279                      pri->pvts[chanpos]->call = NULL;
09280                      if (crv) {
09281                         if (crv->owner)
09282                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09283                         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);
09284                      } else
09285                         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);
09286                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
09287                      if (crv)
09288                         ast_mutex_unlock(&crv->lock);
09289                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09290                      break;
09291                   }
09292                }
09293                pri->pvts[chanpos]->call = e->ring.call;
09294                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
09295                if (pri->pvts[chanpos]->use_callerid) {
09296                   ast_shrink_phone_number(plancallingnum);
09297                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
09298 #ifdef PRI_ANI
09299                   if (!ast_strlen_zero(e->ring.callingani)) {
09300                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
09301                      ast_shrink_phone_number(plancallingani);
09302                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
09303                   } else {
09304                      pri->pvts[chanpos]->cid_ani[0] = '\0';
09305                   }
09306 #endif
09307                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
09308                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
09309                } else {
09310                   pri->pvts[chanpos]->cid_num[0] = '\0';
09311                   pri->pvts[chanpos]->cid_ani[0] = '\0';
09312                   pri->pvts[chanpos]->cid_name[0] = '\0';
09313                   pri->pvts[chanpos]->cid_ton = 0;
09314                }
09315                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
09316                           e->ring.redirectingnum, e->ring.callingplanrdnis);
09317                /* If immediate=yes go to s|1 */
09318                if (pri->pvts[chanpos]->immediate) {
09319                   if (option_verbose > 2)
09320                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
09321                   pri->pvts[chanpos]->exten[0] = 's';
09322                   pri->pvts[chanpos]->exten[1] = '\0';
09323                }
09324                /* Get called number */
09325                else if (!ast_strlen_zero(e->ring.callednum)) {
09326                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
09327                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09328                } else if (pri->overlapdial)
09329                   pri->pvts[chanpos]->exten[0] = '\0';
09330                else {
09331                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
09332                   pri->pvts[chanpos]->exten[0] = 's';
09333                   pri->pvts[chanpos]->exten[1] = '\0';
09334                }
09335                /* Set DNID on all incoming calls -- even immediate */
09336                if (!ast_strlen_zero(e->ring.callednum))
09337                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09338                /* No number yet, but received "sending complete"? */
09339                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09340                   if (option_verbose > 2)
09341                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09342                   pri->pvts[chanpos]->exten[0] = 's';
09343                   pri->pvts[chanpos]->exten[1] = '\0';
09344                }
09345                /* Make sure extension exists (or in overlap dial mode, can exist) */
09346                if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09347                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09348                   /* Setup law */
09349                   int law;
09350                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09351                      /* Set to audio mode at this point */
09352                      law = 1;
09353                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09354                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09355                   }
09356                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09357                      law = DAHDI_LAW_ALAW;
09358                   else
09359                      law = DAHDI_LAW_MULAW;
09360                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09361                   if (res < 0) 
09362                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09363                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09364                   if (res < 0)
09365                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09366                   if (e->ring.complete || !pri->overlapdial) {
09367                      /* Just announce proceeding */
09368                      pri->pvts[chanpos]->proceeding = 1;
09369                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09370                   } else {
09371                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
09372                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09373                      else
09374                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09375                   }
09376                   /* Get the use_callingpres state */
09377                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09378                
09379                   /* Start PBX */
09380                   if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09381                      /* Release the PRI lock while we create the channel */
09382                      ast_mutex_unlock(&pri->lock);
09383                      if (crv) {
09384                         /* Set bearer and such */
09385                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09386                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09387                         pri->pvts[chanpos]->owner = &inuse;
09388                         ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09389                      } else {
09390                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09391                      }
09392 
09393                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09394 
09395                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09396                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09397                      }
09398                      if (e->ring.ani2 >= 0) {
09399                         snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09400                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09401                      }
09402 
09403 #ifdef SUPPORT_USERUSER
09404                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
09405                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09406                      }
09407 #endif
09408 
09409                      snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09410                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09411                      if (e->ring.redirectingreason >= 0)
09412                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09413                   
09414                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09415                      ast_mutex_lock(&pri->lock);
09416 
09417                      pthread_attr_init(&attr);
09418                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09419                      if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09420                         if (option_verbose > 2)
09421                            ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09422                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09423                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09424                      } else {
09425                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09426                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09427                         if (c)
09428                            ast_hangup(c);
09429                         else {
09430                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09431                            pri->pvts[chanpos]->call = NULL;
09432                         }
09433                      }
09434                      pthread_attr_destroy(&attr);
09435                   } else  {
09436                      ast_mutex_unlock(&pri->lock);
09437                      /* Release PRI lock while we create the channel */
09438                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09439                      if (c) {
09440                         char calledtonstr[10];
09441 
09442                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09443 
09444                         if (e->ring.ani2 >= 0) {
09445                            snprintf(ani2str, 5, "%d", e->ring.ani2);
09446                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09447                         }
09448 
09449 #ifdef SUPPORT_USERUSER
09450                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
09451                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09452                         }
09453 #endif
09454 
09455                         if (e->ring.redirectingreason >= 0)
09456                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09457                      
09458                         snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09459                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09460 
09461                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
09462                         ast_mutex_lock(&pri->lock);
09463 
09464                         if (option_verbose > 2)
09465                            ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09466                               plancallingnum, pri->pvts[chanpos]->exten, 
09467                                  pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09468                         dahdi_enable_ec(pri->pvts[chanpos]);
09469                      } else {
09470 
09471                         ast_mutex_lock(&pri->lock);
09472 
09473                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09474                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09475                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09476                         pri->pvts[chanpos]->call = NULL;
09477                      }
09478                   }
09479                } else {
09480                   if (option_verbose > 2)
09481                      ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
09482                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
09483                            pri->pvts[chanpos]->prioffset, pri->span);
09484                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09485                   pri->pvts[chanpos]->call = NULL;
09486                   pri->pvts[chanpos]->exten[0] = '\0';
09487                }
09488                if (crv)
09489                   ast_mutex_unlock(&crv->lock);
09490                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09491             } else {
09492                if (e->ring.flexible)
09493                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09494                else
09495                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09496             }
09497             break;
09498          case PRI_EVENT_RINGING:
09499             chanpos = pri_find_principle(pri, e->ringing.channel);
09500             if (chanpos < 0) {
09501                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
09502                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09503             } else {
09504                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09505                if (chanpos < 0) {
09506                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
09507                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09508                } else {
09509                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09510                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09511                      dahdi_enable_ec(pri->pvts[chanpos]);
09512                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09513                      pri->pvts[chanpos]->alerting = 1;
09514                   } else
09515                      ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09516 #ifdef PRI_PROGRESS_MASK
09517                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09518 #else
09519                   if (e->ringing.progress == 8) {
09520 #endif
09521                      /* Now we can do call progress detection */
09522                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09523                         /* RINGING detection isn't required because we got ALERTING signal */
09524                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09525                         pri->pvts[chanpos]->dsp_features = 0;
09526                      }
09527                   }
09528 
09529 #ifdef SUPPORT_USERUSER
09530                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09531                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09532                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09533                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09534                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09535                   }
09536 #endif
09537 
09538                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09539                }
09540             }
09541             break;
09542          case PRI_EVENT_PROGRESS:
09543             /* Get chan value if e->e is not PRI_EVNT_RINGING */
09544             chanpos = pri_find_principle(pri, e->proceeding.channel);
09545             if (chanpos > -1) {
09546 #ifdef PRI_PROGRESS_MASK
09547                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09548 #else
09549                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09550 #endif
09551                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09552 
09553                   if (e->proceeding.cause > -1) {
09554                      if (option_verbose > 2)
09555                         ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09556 
09557                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
09558                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09559                         if (pri->pvts[chanpos]->owner) {
09560                            if (option_verbose > 2)
09561                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09562 
09563                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09564                            f.subclass = AST_CONTROL_BUSY;
09565                         }
09566                      }
09567                   }
09568                   
09569                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09570                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09571                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09572                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09573 #ifdef PRI_PROGRESS_MASK
09574                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09575 #else
09576                   if (e->proceeding.progress == 8) {
09577 #endif
09578                      /* Now we can do call progress detection */
09579                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09580                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09581                         pri->pvts[chanpos]->dsp_features = 0;
09582                      }
09583                   }
09584                   pri->pvts[chanpos]->progress = 1;
09585                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09586                }
09587             }
09588             break;
09589          case PRI_EVENT_PROCEEDING:
09590             chanpos = pri_find_principle(pri, e->proceeding.channel);
09591             if (chanpos > -1) {
09592                if (!pri->pvts[chanpos]->proceeding) {
09593                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09594                   
09595                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09596                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09597                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09598                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09599 #ifdef PRI_PROGRESS_MASK
09600                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09601 #else
09602                   if (e->proceeding.progress == 8) {
09603 #endif
09604                      /* Now we can do call progress detection */
09605                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09606                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09607                         pri->pvts[chanpos]->dsp_features = 0;
09608                      }
09609                      /* Bring voice path up */
09610                      f.subclass = AST_CONTROL_PROGRESS;
09611                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09612                   }
09613                   pri->pvts[chanpos]->proceeding = 1;
09614                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09615                }
09616             }
09617             break;
09618          case PRI_EVENT_FACNAME:
09619             chanpos = pri_find_principle(pri, e->facname.channel);
09620             if (chanpos < 0) {
09621                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
09622                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09623             } else {
09624                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09625                if (chanpos < 0) {
09626                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
09627                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09628                } else {
09629                   /* Re-use *69 field for PRI */
09630                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09631                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09632                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09633                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09634                   dahdi_enable_ec(pri->pvts[chanpos]);
09635                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09636                }
09637             }
09638             break;            
09639          case PRI_EVENT_ANSWER:
09640             chanpos = pri_find_principle(pri, e->answer.channel);
09641             if (chanpos < 0) {
09642                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
09643                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09644             } else {
09645                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09646                if (chanpos < 0) {
09647                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
09648                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09649                } else {
09650                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09651                   /* Now we can do call progress detection */
09652 
09653                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
09654                    * By this time, we need DTMF detection and other features that were previously disabled
09655                    * -- Matt F */
09656                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09657                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09658                      pri->pvts[chanpos]->dsp_features = 0;
09659                   }
09660                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09661                      ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09662                      x = DAHDI_START;
09663                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09664                      if (res < 0) {
09665                         if (errno != EINPROGRESS) {
09666                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09667                         }
09668                      }
09669                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09670                      pri->pvts[chanpos]->dialing = 1;
09671                      /* Send any "w" waited stuff */
09672                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09673                      if (res < 0) {
09674                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09675                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09676                      } else 
09677                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09678                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09679                   } else if (pri->pvts[chanpos]->confirmanswer) {
09680                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09681                   } else {
09682                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09683                      /* Enable echo cancellation if it's not on already */
09684                      dahdi_enable_ec(pri->pvts[chanpos]);
09685                   }
09686 
09687 #ifdef SUPPORT_USERUSER
09688                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
09689                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09690                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09691                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09692                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09693                   }
09694 #endif
09695 
09696                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09697                }
09698             }
09699             break;            
09700          case PRI_EVENT_HANGUP:
09701             chanpos = pri_find_principle(pri, e->hangup.channel);
09702             if (chanpos < 0) {
09703                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
09704                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09705             } else {
09706                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09707                if (chanpos > -1) {
09708                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09709                   if (!pri->pvts[chanpos]->alreadyhungup) {
09710                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
09711                      pri->pvts[chanpos]->alreadyhungup = 1;
09712                      if (pri->pvts[chanpos]->realcall) 
09713                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09714                      else if (pri->pvts[chanpos]->owner) {
09715                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
09716                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09717                         if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09718                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09719                         else {
09720                            switch (e->hangup.cause) {
09721                               case PRI_CAUSE_USER_BUSY:
09722                                  pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09723                                  break;
09724                               case PRI_CAUSE_CALL_REJECTED:
09725                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09726                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09727                               case PRI_CAUSE_SWITCH_CONGESTION:
09728                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09729                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09730                                  pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09731                                  break;
09732                               default:
09733                                  pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09734                            }
09735                         }
09736                      }
09737                      if (option_verbose > 2) 
09738                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
09739                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09740                   } else {
09741                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09742                      pri->pvts[chanpos]->call = NULL;
09743                   }
09744                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09745                      if (option_verbose > 2)
09746                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
09747                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09748                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09749                      pri->pvts[chanpos]->resetting = 1;
09750                   }
09751                   if (e->hangup.aoc_units > -1)
09752                      if (option_verbose > 2)
09753                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09754                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09755 
09756 #ifdef SUPPORT_USERUSER
09757                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09758                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09759                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09760                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09761                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09762                   }
09763 #endif
09764 
09765                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09766                } else {
09767                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
09768                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09769                }
09770             } 
09771             break;
09772 #ifndef PRI_EVENT_HANGUP_REQ
09773 #error please update libpri
09774 #endif
09775          case PRI_EVENT_HANGUP_REQ:
09776             chanpos = pri_find_principle(pri, e->hangup.channel);
09777             if (chanpos < 0) {
09778                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
09779                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09780             } else {
09781                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09782                if (chanpos > -1) {
09783                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09784                   if (pri->pvts[chanpos]->realcall) 
09785                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09786                   else if (pri->pvts[chanpos]->owner) {
09787                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09788                      if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09789                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09790                      else {
09791                         switch (e->hangup.cause) {
09792                            case PRI_CAUSE_USER_BUSY:
09793                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09794                               break;
09795                            case PRI_CAUSE_CALL_REJECTED:
09796                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09797                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09798                            case PRI_CAUSE_SWITCH_CONGESTION:
09799                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09800                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09801                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09802                               break;
09803                            default:
09804                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09805                         }
09806                      }
09807                      if (option_verbose > 2) 
09808                         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);
09809                      if (e->hangup.aoc_units > -1)
09810                         if (option_verbose > 2)
09811                            ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09812                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09813                   } else {
09814                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09815                      pri->pvts[chanpos]->call = NULL;
09816                   }
09817                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09818                      if (option_verbose > 2)
09819                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
09820                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09821                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09822                      pri->pvts[chanpos]->resetting = 1;
09823                   }
09824 
09825 #ifdef SUPPORT_USERUSER
09826                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09827                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09828                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09829                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09830                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09831                   }
09832 #endif
09833 
09834                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09835                } else {
09836                   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);
09837                }
09838             } 
09839             break;
09840          case PRI_EVENT_HANGUP_ACK:
09841             chanpos = pri_find_principle(pri, e->hangup.channel);
09842             if (chanpos < 0) {
09843                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
09844                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09845             } else {
09846                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09847                if (chanpos > -1) {
09848                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09849                   pri->pvts[chanpos]->call = NULL;
09850                   pri->pvts[chanpos]->resetting = 0;
09851                   if (pri->pvts[chanpos]->owner) {
09852                      if (option_verbose > 2) 
09853                         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);
09854                   }
09855 
09856 #ifdef SUPPORT_USERUSER
09857                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09858                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09859                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09860                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09861                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09862                   }
09863 #endif
09864 
09865                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09866                }
09867             }
09868             break;
09869          case PRI_EVENT_CONFIG_ERR:
09870             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09871             break;
09872          case PRI_EVENT_RESTART_ACK:
09873             chanpos = pri_find_principle(pri, e->restartack.channel);
09874             if (chanpos < 0) {
09875                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
09876                   channel number, so we have to figure it out...  This must be why
09877                   everybody resets exactly a channel at a time. */
09878                for (x = 0; x < pri->numchans; x++) {
09879                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
09880                      chanpos = x;
09881                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09882                      ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
09883                            pri->pvts[chanpos]->prioffset, pri->span);
09884                      if (pri->pvts[chanpos]->realcall) 
09885                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09886                      else if (pri->pvts[chanpos]->owner) {
09887                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
09888                            pri->pvts[chanpos]->prioffset, pri->span);
09889                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09890                      }
09891                      pri->pvts[chanpos]->resetting = 0;
09892                      if (option_verbose > 2)
09893                         ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09894                            pri->pvts[chanpos]->prioffset, pri->span);
09895                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09896                      if (pri->resetting)
09897                         pri_check_restart(pri);
09898                      break;
09899                   }
09900                }
09901                if (chanpos < 0) {
09902                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
09903                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09904                }
09905             } else {
09906                if (pri->pvts[chanpos]) {
09907                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09908                   if (pri->pvts[chanpos]->realcall) 
09909                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09910                   else if (pri->pvts[chanpos]->owner) {
09911                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09912                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09913                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09914                   }
09915                   pri->pvts[chanpos]->resetting = 0;
09916                   if (option_verbose > 2)
09917                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09918                            pri->pvts[chanpos]->prioffset, pri->span);
09919                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09920                   if (pri->resetting)
09921                      pri_check_restart(pri);
09922                }
09923             }
09924             break;
09925          case PRI_EVENT_SETUP_ACK:
09926             chanpos = pri_find_principle(pri, e->setup_ack.channel);
09927             if (chanpos < 0) {
09928                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
09929                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09930             } else {
09931                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09932                if (chanpos > -1) {
09933                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09934                   pri->pvts[chanpos]->setup_ack = 1;
09935                   /* Send any queued digits */
09936                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09937                      ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09938                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
09939                         pri->pvts[chanpos]->dialdest[x]);
09940                   }
09941                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09942                } else
09943                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09944             }
09945             break;
09946          case PRI_EVENT_NOTIFY:
09947             chanpos = pri_find_principle(pri, e->notify.channel);
09948             if (chanpos < 0) {
09949                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09950                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09951             } else {
09952                struct ast_frame f = { AST_FRAME_CONTROL, };
09953                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09954                switch (e->notify.info) {
09955                case PRI_NOTIFY_REMOTE_HOLD:
09956                   f.subclass = AST_CONTROL_HOLD;
09957                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09958                   break;
09959                case PRI_NOTIFY_REMOTE_RETRIEVAL:
09960                   f.subclass = AST_CONTROL_UNHOLD;
09961                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09962                   break;
09963                }
09964                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09965             }
09966             break;
09967          default:
09968             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09969          }
09970       }  
09971       ast_mutex_unlock(&pri->lock);
09972    }
09973    /* Never reached */
09974    return NULL;
09975 }
09976 
09977 static int start_pri(struct dahdi_pri *pri)
09978 {
09979    int res, x;
09980    struct dahdi_params p;
09981    struct dahdi_bufferinfo bi;
09982    struct dahdi_spaninfo si;
09983    int i;
09984    
09985    for (i = 0; i < NUM_DCHANS; i++) {
09986       if (!pri->dchannels[i])
09987          break;
09988       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
09989       x = pri->dchannels[i];
09990       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
09991          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
09992          return -1;
09993       }
09994       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
09995       if (res) {
09996          dahdi_close_pri_fd(pri, i);
09997          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
09998          return -1;
09999       }
10000       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
10001          dahdi_close_pri_fd(pri, i);
10002          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
10003          return -1;
10004       }
10005       memset(&si, 0, sizeof(si));
10006       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
10007       if (res) {
10008          dahdi_close_pri_fd(pri, i);
10009          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
10010       }
10011       if (!si.alarms)
10012          pri->dchanavail[i] |= DCHAN_NOTINALARM;
10013       else
10014          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
10015       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
10016       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
10017       bi.numbufs = 32;
10018       bi.bufsize = 1024;
10019       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
10020          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
10021          dahdi_close_pri_fd(pri, i);
10022          return -1;
10023       }
10024       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
10025       /* Force overlap dial if we're doing GR-303! */
10026       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
10027          pri->overlapdial = 1;
10028       pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
10029 #ifdef HAVE_PRI_INBANDDISCONNECT
10030       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
10031 #endif
10032       /* Enslave to master if appropriate */
10033       if (i)
10034          pri_enslave(pri->dchans[0], pri->dchans[i]);
10035       if (!pri->dchans[i]) {
10036          dahdi_close_pri_fd(pri, i);
10037          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
10038          return -1;
10039       }
10040       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
10041       pri_set_nsf(pri->dchans[i], pri->nsf);
10042 #ifdef PRI_GETSET_TIMERS
10043       for (x = 0; x < PRI_MAX_TIMERS; x++) {
10044          if (pritimers[x] != 0)
10045             pri_set_timer(pri->dchans[i], x, pritimers[x]);
10046       }
10047 #endif
10048    }
10049    /* Assume primary is the one we use */
10050    pri->pri = pri->dchans[0];
10051    pri->resetpos = -1;
10052    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
10053       for (i = 0; i < NUM_DCHANS; i++) {
10054          if (!pri->dchannels[i])
10055             break;
10056          dahdi_close_pri_fd(pri, i);
10057       }
10058       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
10059       return -1;
10060    }
10061    return 0;
10062 }
10063 
10064 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
10065 {
10066    int which, span;
10067    char *ret = NULL;
10068 
10069    if (pos != rpos)
10070       return ret;
10071 
10072    for (which = span = 0; span < NUM_SPANS; span++) {
10073       if (pris[span].pri && ++which > state) {
10074          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
10075             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
10076          }
10077          break;
10078       }
10079    }
10080    return ret;
10081 }
10082 
10083 static char *complete_span_4(const char *line, const char *word, int pos, int state)
10084 {
10085    return complete_span_helper(line,word,pos,state,3);
10086 }
10087 
10088 static char *complete_span_5(const char *line, const char *word, int pos, int state)
10089 {
10090    return complete_span_helper(line,word,pos,state,4);
10091 }
10092 
10093 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
10094 {
10095    int myfd;
10096 
10097    if (!strncasecmp(argv[1], "set", 3)) {
10098       if (argc < 5) 
10099          return RESULT_SHOWUSAGE;
10100 
10101       if (ast_strlen_zero(argv[4]))
10102          return RESULT_SHOWUSAGE;
10103 
10104       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
10105       if (myfd < 0) {
10106          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
10107          return RESULT_SUCCESS;
10108       }
10109 
10110       ast_mutex_lock(&pridebugfdlock);
10111 
10112       if (pridebugfd >= 0)
10113          close(pridebugfd);
10114 
10115       pridebugfd = myfd;
10116       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
10117       
10118       ast_mutex_unlock(&pridebugfdlock);
10119 
10120       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
10121    } else {
10122       /* Assume it is unset */
10123       ast_mutex_lock(&pridebugfdlock);
10124       close(pridebugfd);
10125       pridebugfd = -1;
10126       ast_cli(fd, "PRI debug output to file disabled\n");
10127       ast_mutex_unlock(&pridebugfdlock);
10128    }
10129 
10130    return RESULT_SUCCESS;
10131 }
10132 
10133 #ifdef HAVE_PRI_VERSION
10134 static int handle_pri_version(int fd, int agc, char *argv[]) {
10135    ast_cli(fd, "libpri version: %s\n", pri_get_version());
10136    return RESULT_SUCCESS;
10137 }
10138 #endif
10139 
10140 static int handle_pri_debug(int fd, int argc, char *argv[])
10141 {
10142    int span;
10143    int x;
10144    if (argc < 4) {
10145       return RESULT_SHOWUSAGE;
10146    }
10147    span = atoi(argv[3]);
10148    if ((span < 1) || (span > NUM_SPANS)) {
10149       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
10150       return RESULT_SUCCESS;
10151    }
10152    if (!pris[span-1].pri) {
10153       ast_cli(fd, "No PRI running on span %d\n", span);
10154       return RESULT_SUCCESS;
10155    }
10156    for (x = 0; x < NUM_DCHANS; x++) {
10157       if (pris[span-1].dchans[x])
10158          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10159                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10160                                                PRI_DEBUG_Q921_STATE);
10161    }
10162    ast_cli(fd, "Enabled debugging on span %d\n", span);
10163    return RESULT_SUCCESS;
10164 }
10165 
10166 
10167 
10168 static int handle_pri_no_debug(int fd, int argc, char *argv[])
10169 {
10170    int span;
10171    int x;
10172    if (argc < 5)
10173       return RESULT_SHOWUSAGE;
10174    span = atoi(argv[4]);
10175    if ((span < 1) || (span > NUM_SPANS)) {
10176       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10177       return RESULT_SUCCESS;
10178    }
10179    if (!pris[span-1].pri) {
10180       ast_cli(fd, "No PRI running on span %d\n", span);
10181       return RESULT_SUCCESS;
10182    }
10183    for (x = 0; x < NUM_DCHANS; x++) {
10184       if (pris[span-1].dchans[x])
10185          pri_set_debug(pris[span-1].dchans[x], 0);
10186    }
10187    ast_cli(fd, "Disabled debugging on span %d\n", span);
10188    return RESULT_SUCCESS;
10189 }
10190 
10191 static int handle_pri_really_debug(int fd, int argc, char *argv[])
10192 {
10193    int span;
10194    int x;
10195    if (argc < 5)
10196       return RESULT_SHOWUSAGE;
10197    span = atoi(argv[4]);
10198    if ((span < 1) || (span > NUM_SPANS)) {
10199       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10200       return RESULT_SUCCESS;
10201    }
10202    if (!pris[span-1].pri) {
10203       ast_cli(fd, "No PRI running on span %d\n", span);
10204       return RESULT_SUCCESS;
10205    }
10206    for (x = 0; x < NUM_DCHANS; x++) {
10207       if (pris[span-1].dchans[x])
10208          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10209                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10210                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
10211    }
10212    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
10213    return RESULT_SUCCESS;
10214 }
10215 
10216 static void build_status(char *s, size_t len, int status, int active)
10217 {
10218    if (!s || len < 1) {
10219       return;
10220    }
10221    s[0] = '\0';
10222    if (status & DCHAN_PROVISIONED)
10223       strncat(s, "Provisioned, ", len - strlen(s) - 1);
10224    if (!(status & DCHAN_NOTINALARM))
10225       strncat(s, "In Alarm, ", len - strlen(s) - 1);
10226    if (status & DCHAN_UP)
10227       strncat(s, "Up", len - strlen(s) - 1);
10228    else
10229       strncat(s, "Down", len - strlen(s) - 1);
10230    if (active)
10231       strncat(s, ", Active", len - strlen(s) - 1);
10232    else
10233       strncat(s, ", Standby", len - strlen(s) - 1);
10234    s[len - 1] = '\0';
10235 }
10236 
10237 static int handle_pri_show_spans(int fd, int argc, char *argv[])
10238 {
10239    int span;
10240    int x;
10241    char status[256];
10242    if (argc != 3)
10243       return RESULT_SHOWUSAGE;
10244 
10245    for (span = 0; span < NUM_SPANS; span++) {
10246       if (pris[span].pri) {
10247          for (x = 0; x < NUM_DCHANS; x++) {
10248             if (pris[span].dchannels[x]) {
10249                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
10250                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
10251             }
10252          }
10253       }
10254    }
10255    return RESULT_SUCCESS;
10256 }
10257 
10258 static int handle_pri_show_span(int fd, int argc, char *argv[])
10259 {
10260    int span;
10261    int x;
10262    char status[256];
10263    if (argc < 4)
10264       return RESULT_SHOWUSAGE;
10265    span = atoi(argv[3]);
10266    if ((span < 1) || (span > NUM_SPANS)) {
10267       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
10268       return RESULT_SUCCESS;
10269    }
10270    if (!pris[span-1].pri) {
10271       ast_cli(fd, "No PRI running on span %d\n", span);
10272       return RESULT_SUCCESS;
10273    }
10274    for (x = 0; x < NUM_DCHANS; x++) {
10275       if (pris[span-1].dchannels[x]) {
10276 #ifdef PRI_DUMP_INFO_STR
10277          char *info_str = NULL;
10278 #endif
10279          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
10280          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
10281          ast_cli(fd, "Status: %s\n", status);
10282 #ifdef PRI_DUMP_INFO_STR
10283          info_str = pri_dump_info_str(pris[span-1].pri);
10284          if (info_str) {
10285             ast_cli(fd, "%s", info_str);
10286             free(info_str);
10287          }
10288 #else
10289          pri_dump_info(pris[span-1].pri);
10290 #endif
10291          ast_cli(fd, "\n");
10292       }
10293    }
10294    return RESULT_SUCCESS;
10295 }
10296 
10297 static int handle_pri_show_debug(int fd, int argc, char *argv[])
10298 {
10299    int x;
10300    int span;
10301    int count=0;
10302    int debug=0;
10303 
10304    for (span = 0; span < NUM_SPANS; span++) {
10305            if (pris[span].pri) {
10306          for (x = 0; x < NUM_DCHANS; x++) {
10307             debug = 0;
10308                if (pris[span].dchans[x]) {
10309                   debug = pri_get_debug(pris[span].dchans[x]);
10310                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" );
10311                count++;
10312             }
10313          }
10314       }
10315 
10316    }
10317    ast_mutex_lock(&pridebugfdlock);
10318    if (pridebugfd >= 0) 
10319       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
10320    ast_mutex_unlock(&pridebugfdlock);
10321        
10322    if (!count) 
10323       ast_cli(fd, "No debug set or no PRI running\n");
10324    return RESULT_SUCCESS;
10325 }
10326 
10327 static const char pri_debug_help[] = 
10328    "Usage: pri debug span <span>\n"
10329    "       Enables debugging on a given PRI span\n";
10330    
10331 static const char pri_no_debug_help[] = 
10332    "Usage: pri no debug span <span>\n"
10333    "       Disables debugging on a given PRI span\n";
10334 
10335 static const char pri_really_debug_help[] = 
10336    "Usage: pri intensive debug span <span>\n"
10337    "       Enables debugging down to the Q.921 level\n";
10338 
10339 static const char pri_show_span_help[] = 
10340    "Usage: pri show span <span>\n"
10341    "       Displays PRI Information on a given PRI span\n";
10342 
10343 static const char pri_show_spans_help[] = 
10344    "Usage: pri show spans\n"
10345    "       Displays PRI Information\n";
10346 
10347 static struct ast_cli_entry dahdi_pri_cli[] = {
10348    { { "pri", "debug", "span", NULL },
10349    handle_pri_debug, "Enables PRI debugging on a span",
10350    pri_debug_help, complete_span_4 },
10351 
10352    { { "pri", "no", "debug", "span", NULL },
10353    handle_pri_no_debug, "Disables PRI debugging on a span",
10354    pri_no_debug_help, complete_span_5 },
10355 
10356    { { "pri", "intense", "debug", "span", NULL },
10357    handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10358    pri_really_debug_help, complete_span_5 },
10359 
10360    { { "pri", "show", "spans", NULL },
10361    handle_pri_show_spans, "Displays PRI Information",
10362    pri_show_spans_help },
10363 
10364    { { "pri", "show", "span", NULL },
10365    handle_pri_show_span, "Displays PRI Information",
10366    pri_show_span_help, complete_span_4 },
10367 
10368    { { "pri", "show", "debug", NULL },
10369    handle_pri_show_debug, "Displays current PRI debug settings" },
10370 
10371    { { "pri", "set", "debug", "file", NULL },
10372    handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10373 
10374    { { "pri", "unset", "debug", "file", NULL },
10375    handle_pri_set_debug_file, "Ends PRI debug output to file" },
10376 
10377 #ifdef HAVE_PRI_VERSION
10378    { { "pri", "show", "version", NULL },
10379    handle_pri_version, "Displays version of libpri" },
10380 #endif
10381 };
10382 
10383 #endif /* HAVE_PRI */
10384 
10385 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10386 {
10387    int channel;
10388    
10389    if (argc != 4)
10390       return RESULT_SHOWUSAGE;
10391    
10392    channel = atoi(argv[3]);
10393 
10394    return dahdi_destroy_channel_bynum(channel);
10395 }
10396 
10397 static void dahdi_softhangup_all(void)
10398 {
10399    struct dahdi_pvt *p;
10400 retry:
10401    ast_mutex_lock(&iflock);
10402     for (p = iflist; p; p = p->next) {
10403       ast_mutex_lock(&p->lock);
10404         if (p->owner && !p->restartpending) {
10405          if (ast_channel_trylock(p->owner)) {
10406             if (option_debug > 2)
10407                ast_verbose("Avoiding deadlock\n");
10408             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10409             ast_mutex_unlock(&p->lock);
10410             ast_mutex_unlock(&iflock);
10411             goto retry;
10412          }
10413          if (option_debug > 2)
10414             ast_verbose("Softhanging up on %s\n", p->owner->name);
10415          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10416          p->restartpending = 1;
10417          num_restart_pending++;
10418          ast_channel_unlock(p->owner);
10419       }
10420       ast_mutex_unlock(&p->lock);
10421     }
10422    ast_mutex_unlock(&iflock);
10423 }
10424 
10425 static int setup_dahdi(int reload);
10426 static int dahdi_restart(void)
10427 {
10428 #if defined(HAVE_PRI)
10429    int i, j;
10430 #endif
10431    int cancel_code;
10432    struct dahdi_pvt *p;
10433 
10434    ast_mutex_lock(&restart_lock);
10435  
10436    if (option_verbose)
10437       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10438    dahdi_softhangup_all();
10439    if (option_verbose > 3)
10440       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10441 
10442    #if defined(HAVE_PRI)
10443    for (i = 0; i < NUM_SPANS; i++) {
10444       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10445          cancel_code = pthread_cancel(pris[i].master);
10446          pthread_kill(pris[i].master, SIGURG);
10447          if (option_debug > 3)
10448             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10449             pthread_join(pris[i].master, NULL);
10450          if (option_debug > 3)
10451             ast_verbose("Joined thread of span %d\n", i);
10452       }
10453     }
10454    #endif
10455 
10456     ast_mutex_lock(&monlock);
10457     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10458       cancel_code = pthread_cancel(monitor_thread);
10459       pthread_kill(monitor_thread, SIGURG);
10460       if (option_debug > 3)
10461          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10462         pthread_join(monitor_thread, NULL);
10463       if (option_debug > 3)
10464          ast_verbose("Joined monitor thread\n");
10465     }
10466    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10467 
10468    ast_mutex_lock(&ss_thread_lock);
10469    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10470       int x = DAHDI_FLASH;
10471       if (option_debug > 2)
10472          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10473 
10474       for (p = iflist; p; p = p->next) {
10475          if (p->owner)
10476             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 */    
10477       }
10478       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10479    }
10480 
10481    /* ensure any created channels before monitor threads were stopped are hungup */
10482    dahdi_softhangup_all();
10483    if (option_verbose > 3)
10484       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10485    destroy_all_channels();
10486    if (option_debug)
10487       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10488 
10489     ast_mutex_unlock(&monlock);
10490 
10491    #ifdef HAVE_PRI
10492    for (i = 0; i < NUM_SPANS; i++) {
10493       for (j = 0; j < NUM_DCHANS; j++)
10494             dahdi_close_pri_fd(&(pris[i]), j);
10495    }
10496 
10497    memset(pris, 0, sizeof(pris));
10498    for (i = 0; i < NUM_SPANS; i++) {
10499       ast_mutex_init(&pris[i].lock);
10500       pris[i].offset = -1;
10501       pris[i].master = AST_PTHREADT_NULL;
10502       for (j = 0; j < NUM_DCHANS; j++)
10503          pris[i].fds[j] = -1;
10504    }
10505    pri_set_error(dahdi_pri_error);
10506    pri_set_message(dahdi_pri_message);
10507    #endif
10508 
10509    if (setup_dahdi(2) != 0) {
10510       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10511       ast_mutex_unlock(&ss_thread_lock);
10512       return 1;
10513    }
10514    ast_mutex_unlock(&ss_thread_lock);
10515    ast_mutex_unlock(&restart_lock);
10516    return 0;
10517 }
10518 
10519 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10520 {
10521    if (argc != 2) {
10522       return RESULT_SHOWUSAGE;
10523    }
10524 
10525    if (dahdi_restart() != 0)
10526       return RESULT_FAILURE;
10527    return RESULT_SUCCESS;
10528 }
10529 
10530 static int dahdi_show_channels(int fd, int argc, char **argv)
10531 {
10532 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10533 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10534    struct dahdi_pvt *tmp = NULL;
10535    char tmps[20] = "";
10536    ast_mutex_t *lock;
10537    struct dahdi_pvt *start;
10538 #ifdef HAVE_PRI
10539    int trunkgroup;
10540    struct dahdi_pri *pri = NULL;
10541    int x;
10542 #endif
10543 
10544    lock = &iflock;
10545    start = iflist;
10546 
10547 #ifdef HAVE_PRI
10548    if (argc == 4) {
10549       if ((trunkgroup = atoi(argv[3])) < 1)
10550          return RESULT_SHOWUSAGE;
10551       for (x = 0; x < NUM_SPANS; x++) {
10552          if (pris[x].trunkgroup == trunkgroup) {
10553             pri = pris + x;
10554             break;
10555          }
10556       }
10557       if (pri) {
10558          start = pri->crvs;
10559          lock = &pri->lock;
10560       } else {
10561          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10562          return RESULT_FAILURE;
10563       }
10564    } else
10565 #endif
10566    if (argc != 3)
10567       return RESULT_SHOWUSAGE;
10568 
10569    ast_mutex_lock(lock);
10570 #ifdef HAVE_PRI
10571    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10572 #else
10573    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10574 #endif   
10575    
10576    tmp = start;
10577    while (tmp) {
10578       if (tmp->channel > 0) {
10579          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10580       } else
10581          ast_copy_string(tmps, "pseudo", sizeof(tmps));
10582       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10583       tmp = tmp->next;
10584    }
10585    ast_mutex_unlock(lock);
10586    return RESULT_SUCCESS;
10587 #undef FORMAT
10588 #undef FORMAT2
10589 }
10590 
10591 static int dahdi_show_channel(int fd, int argc, char **argv)
10592 {
10593    int channel;
10594    struct dahdi_pvt *tmp = NULL;
10595    struct dahdi_confinfo ci;
10596    struct dahdi_params ps;
10597    int x;
10598    ast_mutex_t *lock;
10599    struct dahdi_pvt *start;
10600 #ifdef HAVE_PRI
10601    char *c;
10602    int trunkgroup;
10603    struct dahdi_pri *pri=NULL;
10604 #endif
10605 
10606    lock = &iflock;
10607    start = iflist;
10608 
10609    if (argc != 4)
10610       return RESULT_SHOWUSAGE;
10611 #ifdef HAVE_PRI
10612    if ((c = strchr(argv[3], ':'))) {
10613       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10614          return RESULT_SHOWUSAGE;
10615       if ((trunkgroup < 1) || (channel < 1))
10616          return RESULT_SHOWUSAGE;
10617       for (x = 0; x < NUM_SPANS; x++) {
10618          if (pris[x].trunkgroup == trunkgroup) {
10619             pri = pris + x;
10620             break;
10621          }
10622       }
10623       if (pri) {
10624          start = pri->crvs;
10625          lock = &pri->lock;
10626       } else {
10627          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10628          return RESULT_FAILURE;
10629       }
10630    } else
10631 #endif
10632       channel = atoi(argv[3]);
10633 
10634    ast_mutex_lock(lock);
10635    tmp = start;
10636    while (tmp) {
10637       if (tmp->channel == channel) {
10638 #ifdef HAVE_PRI
10639          if (pri) 
10640             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10641          else
10642 #endif         
10643          ast_cli(fd, "Channel: %d\n", tmp->channel);
10644          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10645          ast_cli(fd, "Span: %d\n", tmp->span);
10646          ast_cli(fd, "Extension: %s\n", tmp->exten);
10647          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10648          ast_cli(fd, "Context: %s\n", tmp->context);
10649          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10650          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10651          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10652          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10653          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10654          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10655          ast_cli(fd, "Radio: %d\n", tmp->radio);
10656          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10657          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)" : "");
10658          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)" : "");
10659          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)" : "");
10660          ast_cli(fd, "Confno: %d\n", tmp->confno);
10661          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10662          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10663          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10664          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10665          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10666          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10667          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10668          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10669          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10670          if (tmp->master)
10671             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10672          for (x = 0; x < MAX_SLAVES; x++) {
10673             if (tmp->slaves[x])
10674                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10675          }
10676 #ifdef HAVE_PRI
10677          if (tmp->pri) {
10678             ast_cli(fd, "PRI Flags: ");
10679             if (tmp->resetting)
10680                ast_cli(fd, "Resetting ");
10681             if (tmp->call)
10682                ast_cli(fd, "Call ");
10683             if (tmp->bearer)
10684                ast_cli(fd, "Bearer ");
10685             ast_cli(fd, "\n");
10686             if (tmp->logicalspan) 
10687                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10688             else
10689                ast_cli(fd, "PRI Logical Span: Implicit\n");
10690          }
10691             
10692 #endif
10693          memset(&ci, 0, sizeof(ci));
10694          ps.channo = tmp->channel;
10695          if (tmp->subs[SUB_REAL].dfd > -1) {
10696             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10697                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10698             }
10699 #ifdef DAHDI_GETCONFMUTE
10700             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10701                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10702             }
10703 #endif
10704             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10705                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10706             } else {
10707                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10708             }
10709          }
10710          if (ISTRUNK(tmp)) {
10711             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
10712             if (!ast_strlen_zero(progzone))
10713                ast_cli(fd, "Progress Zone: %s\n", progzone);
10714             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
10715             if(tmp->busydetect) {
10716                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10717                if(tmp->busytonelength > 0) {
10718                   ast_cli(fd, "Busy Pattern:\n");
10719                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10720                   if (tmp->busyquietlength > 0) 
10721                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10722                   else 
10723                      ast_cli(fd, " -- Detect Tone Only\n");
10724                   if(tmp->busyfuzziness > 0)
10725                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10726                }
10727             }
10728          }
10729          ast_mutex_unlock(lock);
10730          return RESULT_SUCCESS;
10731       }
10732       tmp = tmp->next;
10733    }
10734    
10735    ast_cli(fd, "Unable to find given channel %d\n", channel);
10736    ast_mutex_unlock(lock);
10737    return RESULT_FAILURE;
10738 }
10739 
10740 static char dahdi_show_cadences_usage[] =
10741 "Usage: dahdi show cadences\n"
10742 "       Shows all cadences currently defined\n";
10743 
10744 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10745 {
10746    int i, j;
10747    for (i = 0; i < num_cadence; i++) {
10748       char output[1024];
10749       char tmp[16], tmp2[64];
10750       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10751       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10752 
10753       for (j = 0; j < 16; j++) {
10754          if (cadences[i].ringcadence[j] == 0)
10755             break;
10756          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10757          if (cidrings[i] * 2 - 1 == j)
10758             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10759          else
10760             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10761          if (j != 0)
10762             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10763          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10764       }
10765       ast_cli(fd,"%s\n",output);
10766    }
10767    return 0;
10768 }
10769 
10770 /* Based on irqmiss.c */
10771 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10772    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10773    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10774 
10775    int span;
10776    int res;
10777    char alarms[50];
10778 
10779    int ctl;
10780    struct dahdi_spaninfo s;
10781 
10782    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
10783       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
10784       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
10785       return RESULT_FAILURE;
10786    }
10787    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10788 
10789    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10790       s.spanno = span;
10791       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10792       if (res) {
10793          continue;
10794       }
10795       alarms[0] = '\0';
10796       if (s.alarms > 0) {
10797          if (s.alarms & DAHDI_ALARM_BLUE)
10798             strcat(alarms, "BLU/");
10799          if (s.alarms & DAHDI_ALARM_YELLOW)
10800             strcat(alarms, "YEL/");
10801          if (s.alarms & DAHDI_ALARM_RED)
10802             strcat(alarms, "RED/");
10803          if (s.alarms & DAHDI_ALARM_LOOPBACK)
10804             strcat(alarms, "LB/");
10805          if (s.alarms & DAHDI_ALARM_RECOVER)
10806             strcat(alarms, "REC/");
10807          if (s.alarms & DAHDI_ALARM_NOTOPEN)
10808             strcat(alarms, "NOP/");
10809          if (!strlen(alarms))
10810             strcat(alarms, "UUU/");
10811          if (strlen(alarms)) {
10812             /* Strip trailing / */
10813             alarms[strlen(alarms) - 1] = '\0';
10814          }
10815       } else {
10816          if (s.numchans)
10817             strcpy(alarms, "OK");
10818          else
10819             strcpy(alarms, "UNCONFIGURED");
10820       }
10821 
10822       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10823    }
10824    close(ctl);
10825 
10826    return RESULT_SUCCESS;
10827 #undef FORMAT
10828 #undef FORMAT2
10829 }
10830 
10831 static char show_channels_usage[] =
10832    "Usage: dahdi show channels\n"
10833    "  Shows a list of available channels\n";
10834 
10835 static char show_channel_usage[] =
10836    "Usage: dahdi show channel <chan num>\n"
10837    "  Detailed information about a given channel\n";
10838 
10839 static char dahdi_show_status_usage[] =
10840    "Usage: dahdi show status\n"
10841    "       Shows a list of DAHDI cards with status\n";
10842 
10843 static char destroy_channel_usage[] =
10844    "Usage: dahdi destroy channel <chan num>\n"
10845    "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
10846 
10847 static char dahdi_restart_usage[] =
10848    "Usage: dahdi restart\n"
10849    "  Restarts the DAHDI channels: destroys them all and then\n"
10850    "  re-reads them from chan_dahdi.conf.\n"
10851    "  Note that this will STOP any running CALL on DAHDI channels.\n"
10852    "";
10853 
10854 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10855    { "zap", "show", "cadences", NULL },
10856    handle_dahdi_show_cadences, NULL,
10857    NULL };
10858 
10859 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10860    { "zap", "show", "channels", NULL },
10861    dahdi_show_channels, NULL,
10862    NULL };
10863 
10864 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10865    { "zap", "show", "channel", NULL },
10866    dahdi_show_channel, NULL,
10867    NULL };
10868 
10869 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10870    { "zap", "destroy", "channel", NULL },
10871    dahdi_destroy_channel, NULL,
10872    NULL };
10873 
10874 static struct ast_cli_entry cli_zap_restart_deprecated = {
10875    { "zap", "restart", NULL },
10876    dahdi_restart_cmd, NULL,
10877    NULL };
10878 
10879 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10880    { "zap", "show", "status", NULL },
10881    dahdi_show_status, NULL,
10882    NULL };
10883 
10884 static struct ast_cli_entry dahdi_cli[] = {
10885    { { "dahdi", "show", "cadences", NULL },
10886    handle_dahdi_show_cadences, "List cadences",
10887    dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10888 
10889    { { "dahdi", "show", "channels", NULL},
10890    dahdi_show_channels, "Show active DAHDI channels",
10891    show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10892 
10893    { { "dahdi", "show", "channel", NULL},
10894    dahdi_show_channel, "Show information on a channel",
10895    show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10896 
10897    { { "dahdi", "destroy", "channel", NULL},
10898    dahdi_destroy_channel, "Destroy a channel",
10899    destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10900 
10901    { { "dahdi", "restart", NULL},
10902    dahdi_restart_cmd, "Fully restart DAHDI channels",
10903    dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10904 
10905    { { "dahdi", "show", "status", NULL},
10906    dahdi_show_status, "Show all DAHDI cards status",
10907    dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10908 };
10909 
10910 #define TRANSFER  0
10911 #define HANGUP    1
10912 
10913 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10914 {
10915    if (p) {
10916       switch (mode) {
10917          case TRANSFER:
10918             p->fake_event = DAHDI_EVENT_WINKFLASH;
10919             break;
10920          case HANGUP:
10921             p->fake_event = DAHDI_EVENT_ONHOOK;
10922             break;
10923          default:
10924             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10925       }
10926    }
10927    return 0;
10928 }
10929 static struct dahdi_pvt *find_channel(int channel)
10930 {
10931    struct dahdi_pvt *p = iflist;
10932    while (p) {
10933       if (p->channel == channel) {
10934          break;
10935       }
10936       p = p->next;
10937    }
10938    return p;
10939 }
10940 
10941 #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)
10942 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10943 
10944 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10945 {
10946    struct dahdi_pvt *p = NULL;
10947    const char *channel = local_astman_header(m, "Channel", zap_mode);
10948 
10949    if (ast_strlen_zero(channel)) {
10950       astman_send_error(s, m, "No channel specified");
10951       return 0;
10952    }
10953    if (!(p = find_channel(atoi(channel)))) {
10954       astman_send_error(s, m, "No such channel");
10955       return 0;
10956    }
10957    p->dnd = dnd;
10958    local_astman_ack(s, m, "DND", zap_mode);
10959 
10960    return 0;
10961 }
10962 
10963 static int zap_action_dndon(struct mansession *s, const struct message *m)
10964 {
10965    return __action_dnd(s, m, 1, 1);
10966 }
10967 
10968 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10969 {
10970    return __action_dnd(s, m, 0, 1);
10971 }
10972 
10973 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10974 {
10975    return __action_dnd(s, m, 1, 0);
10976 }
10977 
10978 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10979 {
10980    return __action_dnd(s, m, 0, 0);
10981 }
10982 
10983 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10984 {
10985    struct dahdi_pvt *p = NULL;
10986    const char *channel = local_astman_header(m, "Channel", zap_mode);
10987 
10988    if (ast_strlen_zero(channel)) {
10989       astman_send_error(s, m, "No channel specified");
10990       return 0;
10991    }
10992    if (!(p = find_channel(atoi(channel)))) {
10993       astman_send_error(s, m, "No such channel");
10994       return 0;
10995    }
10996    dahdi_fake_event(p,TRANSFER);
10997    local_astman_ack(s, m, "Transfer", zap_mode);
10998 
10999    return 0;
11000 }
11001 
11002 static int zap_action_transfer(struct mansession *s, const struct message *m)
11003 {
11004    return __action_transfer(s, m, 1);
11005 }
11006 
11007 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
11008 {
11009    return __action_transfer(s, m, 0);
11010 }
11011 
11012 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
11013 {
11014    struct dahdi_pvt *p = NULL;
11015    const char *channel = local_astman_header(m, "Channel", zap_mode);
11016 
11017    if (ast_strlen_zero(channel)) {
11018       astman_send_error(s, m, "No channel specified");
11019       return 0;
11020    }
11021    if (!(p = find_channel(atoi(channel)))) {
11022       astman_send_error(s, m, "No such channel");
11023       return 0;
11024    }
11025    dahdi_fake_event(p, HANGUP);
11026    local_astman_ack(s, m, "Hangup", zap_mode);
11027    return 0;
11028 }
11029 
11030 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
11031 {
11032    return __action_transferhangup(s, m, 1);
11033 }
11034 
11035 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
11036 {
11037    return __action_transferhangup(s, m, 0);
11038 }
11039 
11040 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
11041 {
11042    struct dahdi_pvt *p = NULL;
11043    const char *channel = local_astman_header(m, "Channel", zap_mode);
11044    const char *number = astman_get_header(m, "Number");
11045    int i;
11046 
11047    if (ast_strlen_zero(channel)) {
11048       astman_send_error(s, m, "No channel specified");
11049       return 0;
11050    }
11051    if (ast_strlen_zero(number)) {
11052       astman_send_error(s, m, "No number specified");
11053       return 0;
11054    }
11055    if (!(p = find_channel(atoi(channel)))) {
11056       astman_send_error(s, m, "No such channel");
11057       return 0;
11058    }
11059    if (!p->owner) {
11060       astman_send_error(s, m, "Channel does not have an owner");
11061       return 0;
11062    }
11063    for (i = 0; i < strlen(number); i++) {
11064       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
11065 
11066       dahdi_queue_frame(p, &f, NULL); 
11067    }
11068    local_astman_ack(s, m, "DialOffHook", zap_mode);
11069 
11070    return 0;
11071 }
11072 
11073 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
11074 {
11075    return __action_dialoffhook(s, m, 1);
11076 }
11077 
11078 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
11079 {
11080    return __action_dialoffhook(s, m, 0);
11081 }
11082 
11083 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
11084 {
11085    struct dahdi_pvt *tmp = NULL;
11086    const char *id = astman_get_header(m, "ActionID");
11087    char idText[256] = "";
11088 
11089    local_astman_ack(s, m, " channel status will follow", zap_mode);
11090    if (!ast_strlen_zero(id))
11091       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
11092 
11093    ast_mutex_lock(&iflock);
11094    
11095    tmp = iflist;
11096    while (tmp) {
11097       if (tmp->channel > 0) {
11098          int alarm = get_alarms(tmp);
11099          astman_append(s,
11100                   "Event: %sShowChannels\r\n"
11101                   "Channel: %d\r\n"
11102                   "Signalling: %s\r\n"
11103                   "Context: %s\r\n"
11104                   "DND: %s\r\n"
11105                   "Alarm: %s\r\n"
11106                   "%s"
11107                   "\r\n",
11108                   dahdi_chan_name,
11109                   tmp->channel, sig2str(tmp->sig), tmp->context, 
11110                   tmp->dnd ? "Enabled" : "Disabled",
11111                   alarm2str(alarm), idText);
11112       } 
11113 
11114       tmp = tmp->next;
11115    }
11116 
11117    ast_mutex_unlock(&iflock);
11118    
11119    astman_append(s, 
11120             "Event: %sShowChannelsComplete\r\n"
11121             "%s"
11122             "\r\n",
11123             dahdi_chan_name,
11124             idText);
11125    return 0;
11126 }
11127 
11128 static int zap_action_showchannels(struct mansession *s, const struct message *m)
11129 {
11130    return __action_showchannels(s, m, 1);
11131 }
11132 
11133 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
11134 {
11135    return __action_showchannels(s, m, 0);
11136 }
11137 
11138 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
11139 {
11140    if (dahdi_restart() != 0) {
11141       if (zap_mode) {
11142          astman_send_error(s, m, "Failed to restart Zap");
11143       } else {
11144          astman_send_error(s, m, "Failed to restart DAHDI");
11145       }
11146       return 1;
11147    }
11148    local_astman_ack(s, m, "Restart: Success", zap_mode);
11149    return 0;
11150 }
11151 
11152 static int zap_action_restart(struct mansession *s, const struct message *m)
11153 {
11154    return __action_restart(s, m, 1);
11155 }
11156 
11157 static int dahdi_action_restart(struct mansession *s, const struct message *m)
11158 {
11159    return __action_restart(s, m, 0);
11160 }
11161 
11162 #define local_astman_unregister(a) do { \
11163                if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11164                   ast_manager_unregister("DAHDI" a); \
11165                } \
11166                ast_manager_unregister("Zap" a); \
11167                } while (0)
11168 
11169 static int __unload_module(void)
11170 {
11171    struct dahdi_pvt *p;
11172 
11173 #ifdef HAVE_PRI
11174    int i, j;
11175    for (i = 0; i < NUM_SPANS; i++) {
11176       if (pris[i].master != AST_PTHREADT_NULL) 
11177          pthread_cancel(pris[i].master);
11178    }
11179    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11180 
11181    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11182       ast_unregister_application(dahdi_send_keypad_facility_app);
11183    }
11184    ast_unregister_application(zap_send_keypad_facility_app);
11185 #endif
11186    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11187    local_astman_unregister("DialOffHook");
11188    local_astman_unregister("Hangup");
11189    local_astman_unregister("Transfer");
11190    local_astman_unregister("DNDoff");
11191    local_astman_unregister("DNDon");
11192    local_astman_unregister("ShowChannels");
11193    local_astman_unregister("Restart");
11194    ast_channel_unregister(chan_tech);
11195    ast_mutex_lock(&iflock);
11196    /* Hangup all interfaces if they have an owner */
11197    p = iflist;
11198    while (p) {
11199       if (p->owner)
11200          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
11201       p = p->next;
11202    }
11203    ast_mutex_unlock(&iflock);
11204    ast_mutex_lock(&monlock);
11205    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11206       pthread_cancel(monitor_thread);
11207       pthread_kill(monitor_thread, SIGURG);
11208       pthread_join(monitor_thread, NULL);
11209    }
11210    monitor_thread = AST_PTHREADT_STOP;
11211    ast_mutex_unlock(&monlock);
11212 
11213    destroy_all_channels();
11214 #ifdef HAVE_PRI      
11215    for (i = 0; i < NUM_SPANS; i++) {
11216       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
11217          pthread_join(pris[i].master, NULL);
11218       for (j = 0; j < NUM_DCHANS; j++) {
11219          dahdi_close_pri_fd(&(pris[i]), j);
11220       }
11221    }
11222 #endif
11223    ast_cond_destroy(&ss_thread_complete);
11224    return 0;
11225 }
11226 
11227 static int unload_module(void)
11228 {
11229 #ifdef HAVE_PRI      
11230    int y;
11231    for (y = 0; y < NUM_SPANS; y++)
11232       ast_mutex_destroy(&pris[y].lock);
11233 #endif
11234    return __unload_module();
11235 }
11236 
11237 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
11238 {
11239    char *c, *chan;
11240    int x, start, finish;
11241    struct dahdi_pvt *tmp;
11242 #ifdef HAVE_PRI
11243    struct dahdi_pri *pri;
11244    int trunkgroup, y;
11245 #endif
11246    
11247    if ((reload == 0) && (conf->chan.sig < 0)) {
11248       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
11249       return -1;
11250    }
11251 
11252    c = ast_strdupa(value);
11253 
11254 #ifdef HAVE_PRI
11255    pri = NULL;
11256    if (iscrv) {
11257       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
11258          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
11259          return -1;
11260       }
11261       if (trunkgroup < 1) {
11262          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
11263          return -1;
11264       }
11265       c += y;
11266       for (y = 0; y < NUM_SPANS; y++) {
11267          if (pris[y].trunkgroup == trunkgroup) {
11268             pri = pris + y;
11269             break;
11270          }
11271       }
11272       if (!pri) {
11273          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
11274          return -1;
11275       }
11276    }
11277 #endif         
11278 
11279    while ((chan = strsep(&c, ","))) {
11280       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
11281          /* Range */
11282       } else if (sscanf(chan, "%d", &start)) {
11283          /* Just one */
11284          finish = start;
11285       } else if (!strcasecmp(chan, "pseudo")) {
11286          finish = start = CHAN_PSEUDO;
11287          if (found_pseudo)
11288             *found_pseudo = 1;
11289       } else {
11290          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
11291          return -1;
11292       }
11293       if (finish < start) {
11294          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
11295          x = finish;
11296          finish = start;
11297          start = x;
11298       }
11299 
11300       for (x = start; x <= finish; x++) {
11301 #ifdef HAVE_PRI
11302          tmp = mkintf(x, conf, pri, reload);
11303 #else       
11304          tmp = mkintf(x, conf, NULL, reload);
11305 #endif         
11306 
11307          if (tmp) {
11308             if (option_verbose > 2) {
11309 #ifdef HAVE_PRI
11310                if (pri)
11311                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
11312                else
11313 #endif
11314                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
11315             }
11316          } else {
11317             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
11318                (reload == 1) ? "reconfigure" : "register", value);
11319             return -1;
11320          }
11321       }
11322    }
11323 
11324    return 0;
11325 }
11326 
11327 /** The length of the parameters list of 'dahdichan'. 
11328  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
11329 #define MAX_CHANLIST_LEN 80
11330 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
11331 {
11332    struct dahdi_pvt *tmp;
11333    int y;
11334    int found_pseudo = 0;
11335         char dahdichan[MAX_CHANLIST_LEN] = {};
11336 
11337    for (; v; v = v->next) {
11338       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11339          continue;
11340 
11341       /* Create the interface list */
11342       if (!strcasecmp(v->name, "channel")
11343 #ifdef HAVE_PRI
11344           || !strcasecmp(v->name, "crv")
11345 #endif         
11346          ) {
11347          int iscrv;
11348          if (skipchannels)
11349             continue;
11350          iscrv = !strcasecmp(v->name, "crv");
11351          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11352                return -1;
11353       } else if (!strcasecmp(v->name, "buffers")) {
11354          int res;
11355          char policy[21] = "";
11356 
11357          res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
11358          if (res != 2) {
11359             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11360             confp->chan.buf_no = numbufs;
11361             continue;
11362          }
11363          if (confp->chan.buf_no < 0)
11364             confp->chan.buf_no = numbufs;
11365          if (!strcasecmp(policy, "full")) {
11366             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11367          } else if (!strcasecmp(policy, "immediate")) {
11368             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11369          } else {
11370             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11371          }
11372       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11373          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11374          if (v->name[0] == 'z' || v->name[0] == 'Z') {
11375             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11376          }
11377       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11378          if (ast_true(v->value))
11379             confp->chan.usedistinctiveringdetection = 1;
11380       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11381          if (ast_true(v->value))
11382             distinctiveringaftercid = 1;
11383       } else if (!strcasecmp(v->name, "dring1context")) {
11384          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11385       } else if (!strcasecmp(v->name, "dring2context")) {
11386          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11387       } else if (!strcasecmp(v->name, "dring3context")) {
11388          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11389       } else if (!strcasecmp(v->name, "dring1")) {
11390          sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11391       } else if (!strcasecmp(v->name, "dring2")) {
11392          sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11393       } else if (!strcasecmp(v->name, "dring3")) {
11394          sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11395       } else if (!strcasecmp(v->name, "usecallerid")) {
11396          confp->chan.use_callerid = ast_true(v->value);
11397       } else if (!strcasecmp(v->name, "cidsignalling")) {
11398          if (!strcasecmp(v->value, "bell"))
11399             confp->chan.cid_signalling = CID_SIG_BELL;
11400          else if (!strcasecmp(v->value, "v23"))
11401             confp->chan.cid_signalling = CID_SIG_V23;
11402          else if (!strcasecmp(v->value, "dtmf"))
11403             confp->chan.cid_signalling = CID_SIG_DTMF;
11404          else if (!strcasecmp(v->value, "smdi"))
11405             confp->chan.cid_signalling = CID_SIG_SMDI;
11406          else if (!strcasecmp(v->value, "v23_jp"))
11407             confp->chan.cid_signalling = CID_SIG_V23_JP;
11408          else if (ast_true(v->value))
11409             confp->chan.cid_signalling = CID_SIG_BELL;
11410       } else if (!strcasecmp(v->name, "cidstart")) {
11411          if (!strcasecmp(v->value, "ring"))
11412             confp->chan.cid_start = CID_START_RING;
11413          else if (!strcasecmp(v->value, "polarity"))
11414             confp->chan.cid_start = CID_START_POLARITY;
11415          else if (ast_true(v->value))
11416             confp->chan.cid_start = CID_START_RING;
11417       } else if (!strcasecmp(v->name, "threewaycalling")) {
11418          confp->chan.threewaycalling = ast_true(v->value);
11419       } else if (!strcasecmp(v->name, "cancallforward")) {
11420          confp->chan.cancallforward = ast_true(v->value);
11421       } else if (!strcasecmp(v->name, "relaxdtmf")) {
11422          if (ast_true(v->value)) 
11423             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11424          else
11425             confp->chan.dtmfrelax = 0;
11426       } else if (!strcasecmp(v->name, "mailbox")) {
11427          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11428       } else if (!strcasecmp(v->name, "hasvoicemail")) {
11429          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11430             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11431          }
11432       } else if (!strcasecmp(v->name, "adsi")) {
11433          confp->chan.adsi = ast_true(v->value);
11434       } else if (!strcasecmp(v->name, "usesmdi")) {
11435          confp->chan.use_smdi = ast_true(v->value);
11436       } else if (!strcasecmp(v->name, "smdiport")) {
11437          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11438       } else if (!strcasecmp(v->name, "transfer")) {
11439          confp->chan.transfer = ast_true(v->value);
11440       } else if (!strcasecmp(v->name, "canpark")) {
11441          confp->chan.canpark = ast_true(v->value);
11442       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11443          confp->chan.echocanbridged = ast_true(v->value);
11444       } else if (!strcasecmp(v->name, "busydetect")) {
11445          confp->chan.busydetect = ast_true(v->value);
11446       } else if (!strcasecmp(v->name, "busycount")) {
11447          confp->chan.busycount = atoi(v->value);
11448       } else if (!strcasecmp(v->name, "silencethreshold")) {
11449          confp->chan.silencethreshold = atoi(v->value);
11450       } else if (!strcasecmp(v->name, "busycompare")) {
11451          confp->chan.busycompare = ast_true(v->value);
11452       } else if (!strcasecmp(v->name, "busypattern")) {
11453          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11454          if (count == 1)
11455             confp->chan.busyquietlength = 0;
11456          else if (count < 1)
11457             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11458       } else if (!strcasecmp(v->name, "busyfuzziness")) {
11459          confp->chan.busyfuzziness = atoi(v->value);
11460       } else if (!strcasecmp(v->name, "callprogress")) {
11461          if (ast_true(v->value))
11462             confp->chan.callprogress |= 1;
11463          else
11464             confp->chan.callprogress &= ~1;
11465       } else if (!strcasecmp(v->name, "faxdetect")) {
11466          if (!strcasecmp(v->value, "incoming")) {
11467             confp->chan.callprogress |= 4;
11468             confp->chan.callprogress &= ~2;
11469          } else if (!strcasecmp(v->value, "outgoing")) {
11470             confp->chan.callprogress &= ~4;
11471             confp->chan.callprogress |= 2;
11472          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11473             confp->chan.callprogress |= 6;
11474          else
11475             confp->chan.callprogress &= ~6;
11476       } else if (!strcasecmp(v->name, "echocancel")) {
11477          if (!ast_strlen_zero(v->value)) {
11478             y = atoi(v->value);
11479          } else
11480             y = 0;
11481          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11482             confp->chan.echocancel = y;
11483          else {
11484             confp->chan.echocancel = ast_true(v->value);
11485             if (confp->chan.echocancel)
11486                confp->chan.echocancel=128;
11487          }
11488       } else if (!strcasecmp(v->name, "echotraining")) {
11489          if (sscanf(v->value, "%d", &y) == 1) {
11490             if ((y < 10) || (y > 4000)) {
11491                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
11492             } else {
11493                confp->chan.echotraining = y;
11494             }
11495          } else if (ast_true(v->value)) {
11496             confp->chan.echotraining = 400;
11497          } else
11498             confp->chan.echotraining = 0;
11499       } else if (!strcasecmp(v->name, "hidecallerid")) {
11500          confp->chan.hidecallerid = ast_true(v->value);
11501       } else if (!strcasecmp(v->name, "hidecalleridname")) {
11502          confp->chan.hidecalleridname = ast_true(v->value);
11503       } else if (!strcasecmp(v->name, "pulsedial")) {
11504          confp->chan.pulse = ast_true(v->value);
11505       } else if (!strcasecmp(v->name, "callreturn")) {
11506          confp->chan.callreturn = ast_true(v->value);
11507       } else if (!strcasecmp(v->name, "callwaiting")) {
11508          confp->chan.callwaiting = ast_true(v->value);
11509       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11510          confp->chan.callwaitingcallerid = ast_true(v->value);
11511       } else if (!strcasecmp(v->name, "context")) {
11512          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11513       } else if (!strcasecmp(v->name, "language")) {
11514          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11515       } else if (!strcasecmp(v->name, "progzone")) {
11516          ast_copy_string(progzone, v->value, sizeof(progzone));
11517       } else if (!strcasecmp(v->name, "mohinterpret") 
11518          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11519          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11520       } else if (!strcasecmp(v->name, "mohsuggest")) {
11521          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11522       } else if (!strcasecmp(v->name, "stripmsd")) {
11523          confp->chan.stripmsd = atoi(v->value);
11524       } else if (!strcasecmp(v->name, "jitterbuffers")) {
11525          numbufs = atoi(v->value);
11526       } else if (!strcasecmp(v->name, "group")) {
11527          confp->chan.group = ast_get_group(v->value);
11528       } else if (!strcasecmp(v->name, "callgroup")) {
11529          confp->chan.callgroup = ast_get_group(v->value);
11530       } else if (!strcasecmp(v->name, "pickupgroup")) {
11531          confp->chan.pickupgroup = ast_get_group(v->value);
11532       } else if (!strcasecmp(v->name, "immediate")) {
11533          confp->chan.immediate = ast_true(v->value);
11534       } else if (!strcasecmp(v->name, "transfertobusy")) {
11535          confp->chan.transfertobusy = ast_true(v->value);
11536       } else if (!strcasecmp(v->name, "rxgain")) {
11537          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11538             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11539          }
11540       } else if (!strcasecmp(v->name, "txgain")) {
11541          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11542             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11543          }
11544       } else if (!strcasecmp(v->name, "tonezone")) {
11545          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11546             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11547          }
11548       } else if (!strcasecmp(v->name, "callerid")) {
11549          if (!strcasecmp(v->value, "asreceived")) {
11550             confp->chan.cid_num[0] = '\0';
11551             confp->chan.cid_name[0] = '\0';
11552          } else {
11553             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11554          } 
11555       } else if (!strcasecmp(v->name, "fullname")) {
11556          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11557       } else if (!strcasecmp(v->name, "cid_number")) {
11558          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11559       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11560          confp->chan.dahditrcallerid = ast_true(v->value);
11561          if (strstr(v->name, "zap")) {
11562             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11563          }
11564       } else if (!strcasecmp(v->name, "restrictcid")) {
11565          confp->chan.restrictcid = ast_true(v->value);
11566       } else if (!strcasecmp(v->name, "usecallingpres")) {
11567          confp->chan.use_callingpres = ast_true(v->value);
11568       } else if (!strcasecmp(v->name, "accountcode")) {
11569          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11570       } else if (!strcasecmp(v->name, "amaflags")) {
11571          y = ast_cdr_amaflags2int(v->value);
11572          if (y < 0) 
11573             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11574          else
11575             confp->chan.amaflags = y;
11576       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11577          confp->chan.polarityonanswerdelay = atoi(v->value);
11578       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11579          confp->chan.answeronpolarityswitch = ast_true(v->value);
11580       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11581          confp->chan.hanguponpolarityswitch = ast_true(v->value);
11582       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11583          confp->chan.sendcalleridafter = atoi(v->value);
11584       } else if (reload != 1){ 
11585           if (!strcasecmp(v->name, "signalling")) {
11586             confp->chan.outsigmod = -1;
11587             if (!strcasecmp(v->value, "em")) {
11588                confp->chan.sig = SIG_EM;
11589             } else if (!strcasecmp(v->value, "em_e1")) {
11590                confp->chan.sig = SIG_EM_E1;
11591             } else if (!strcasecmp(v->value, "em_w")) {
11592                confp->chan.sig = SIG_EMWINK;
11593                confp->chan.radio = 0;
11594             } else if (!strcasecmp(v->value, "fxs_ls")) {
11595                confp->chan.sig = SIG_FXSLS;
11596                confp->chan.radio = 0;
11597             } else if (!strcasecmp(v->value, "fxs_gs")) {
11598                confp->chan.sig = SIG_FXSGS;
11599                confp->chan.radio = 0;
11600             } else if (!strcasecmp(v->value, "fxs_ks")) {
11601                confp->chan.sig = SIG_FXSKS;
11602                confp->chan.radio = 0;
11603             } else if (!strcasecmp(v->value, "fxo_ls")) {
11604                confp->chan.sig = SIG_FXOLS;
11605                confp->chan.radio = 0;
11606             } else if (!strcasecmp(v->value, "fxo_gs")) {
11607                confp->chan.sig = SIG_FXOGS;
11608                confp->chan.radio = 0;
11609             } else if (!strcasecmp(v->value, "fxo_ks")) {
11610                confp->chan.sig = SIG_FXOKS;
11611                confp->chan.radio = 0;
11612             } else if (!strcasecmp(v->value, "fxs_rx")) {
11613                confp->chan.sig = SIG_FXSKS;
11614                confp->chan.radio = 1;
11615             } else if (!strcasecmp(v->value, "fxo_rx")) {
11616                confp->chan.sig = SIG_FXOLS;
11617                confp->chan.radio = 1;
11618             } else if (!strcasecmp(v->value, "fxs_tx")) {
11619                confp->chan.sig = SIG_FXSLS;
11620                confp->chan.radio = 1;
11621             } else if (!strcasecmp(v->value, "fxo_tx")) {
11622                confp->chan.sig = SIG_FXOGS;
11623                confp->chan.radio = 1;
11624             } else if (!strcasecmp(v->value, "em_rx")) {
11625                confp->chan.sig = SIG_EM;
11626                confp->chan.radio = 1;
11627             } else if (!strcasecmp(v->value, "em_tx")) {
11628                confp->chan.sig = SIG_EM;
11629                confp->chan.radio = 1;
11630             } else if (!strcasecmp(v->value, "em_rxtx")) {
11631                confp->chan.sig = SIG_EM;
11632                confp->chan.radio = 2;
11633             } else if (!strcasecmp(v->value, "em_txrx")) {
11634                confp->chan.sig = SIG_EM;
11635                confp->chan.radio = 2;
11636             } else if (!strcasecmp(v->value, "sf")) {
11637                confp->chan.sig = SIG_SF;
11638                confp->chan.radio = 0;
11639             } else if (!strcasecmp(v->value, "sf_w")) {
11640                confp->chan.sig = SIG_SFWINK;
11641                confp->chan.radio = 0;
11642             } else if (!strcasecmp(v->value, "sf_featd")) {
11643                confp->chan.sig = SIG_FEATD;
11644                confp->chan.radio = 0;
11645             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11646                confp->chan.sig = SIG_FEATDMF;
11647                confp->chan.radio = 0;
11648             } else if (!strcasecmp(v->value, "sf_featb")) {
11649                confp->chan.sig = SIG_SF_FEATB;
11650                confp->chan.radio = 0;
11651             } else if (!strcasecmp(v->value, "sf")) {
11652                confp->chan.sig = SIG_SF;
11653                confp->chan.radio = 0;
11654             } else if (!strcasecmp(v->value, "sf_rx")) {
11655                confp->chan.sig = SIG_SF;
11656                confp->chan.radio = 1;
11657             } else if (!strcasecmp(v->value, "sf_tx")) {
11658                confp->chan.sig = SIG_SF;
11659                confp->chan.radio = 1;
11660             } else if (!strcasecmp(v->value, "sf_rxtx")) {
11661                confp->chan.sig = SIG_SF;
11662                confp->chan.radio = 2;
11663             } else if (!strcasecmp(v->value, "sf_txrx")) {
11664                confp->chan.sig = SIG_SF;
11665                confp->chan.radio = 2;
11666             } else if (!strcasecmp(v->value, "featd")) {
11667                confp->chan.sig = SIG_FEATD;
11668                confp->chan.radio = 0;
11669             } else if (!strcasecmp(v->value, "featdmf")) {
11670                confp->chan.sig = SIG_FEATDMF;
11671                confp->chan.radio = 0;
11672             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11673                confp->chan.sig = SIG_FEATDMF_TA;
11674                confp->chan.radio = 0;
11675             } else if (!strcasecmp(v->value, "e911")) {
11676                confp->chan.sig = SIG_E911;
11677                confp->chan.radio = 0;
11678             } else if (!strcasecmp(v->value, "fgccama")) {
11679                confp->chan.sig = SIG_FGC_CAMA;
11680                confp->chan.radio = 0;
11681             } else if (!strcasecmp(v->value, "fgccamamf")) {
11682                confp->chan.sig = SIG_FGC_CAMAMF;
11683                confp->chan.radio = 0;
11684             } else if (!strcasecmp(v->value, "featb")) {
11685                confp->chan.sig = SIG_FEATB;
11686                confp->chan.radio = 0;
11687 #ifdef HAVE_PRI
11688             } else if (!strcasecmp(v->value, "pri_net")) {
11689                confp->chan.radio = 0;
11690                confp->chan.sig = SIG_PRI;
11691                confp->pri.nodetype = PRI_NETWORK;
11692             } else if (!strcasecmp(v->value, "pri_cpe")) {
11693                confp->chan.sig = SIG_PRI;
11694                confp->chan.radio = 0;
11695                confp->pri.nodetype = PRI_CPE;
11696             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11697                confp->chan.sig = SIG_GR303FXOKS;
11698                confp->chan.radio = 0;
11699                confp->pri.nodetype = PRI_NETWORK;
11700             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11701                confp->chan.sig = SIG_GR303FXSKS;
11702                confp->chan.radio = 0;
11703                confp->pri.nodetype = PRI_CPE;
11704 #endif
11705             } else {
11706                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11707             }
11708           } else if (!strcasecmp(v->name, "outsignalling")) {
11709             if (!strcasecmp(v->value, "em")) {
11710                confp->chan.outsigmod = SIG_EM;
11711             } else if (!strcasecmp(v->value, "em_e1")) {
11712                confp->chan.outsigmod = SIG_EM_E1;
11713             } else if (!strcasecmp(v->value, "em_w")) {
11714                confp->chan.outsigmod = SIG_EMWINK;
11715             } else if (!strcasecmp(v->value, "sf")) {
11716                confp->chan.outsigmod = SIG_SF;
11717             } else if (!strcasecmp(v->value, "sf_w")) {
11718                confp->chan.outsigmod = SIG_SFWINK;
11719             } else if (!strcasecmp(v->value, "sf_featd")) {
11720                confp->chan.outsigmod = SIG_FEATD;
11721             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11722                confp->chan.outsigmod = SIG_FEATDMF;
11723             } else if (!strcasecmp(v->value, "sf_featb")) {
11724                confp->chan.outsigmod = SIG_SF_FEATB;
11725             } else if (!strcasecmp(v->value, "sf")) {
11726                confp->chan.outsigmod = SIG_SF;
11727             } else if (!strcasecmp(v->value, "featd")) {
11728                confp->chan.outsigmod = SIG_FEATD;
11729             } else if (!strcasecmp(v->value, "featdmf")) {
11730                confp->chan.outsigmod = SIG_FEATDMF;
11731             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11732                confp->chan.outsigmod = SIG_FEATDMF_TA;
11733             } else if (!strcasecmp(v->value, "e911")) {
11734                confp->chan.outsigmod = SIG_E911;
11735             } else if (!strcasecmp(v->value, "fgccama")) {
11736                confp->chan.outsigmod = SIG_FGC_CAMA;
11737             } else if (!strcasecmp(v->value, "fgccamamf")) {
11738                confp->chan.outsigmod = SIG_FGC_CAMAMF;
11739             } else if (!strcasecmp(v->value, "featb")) {
11740                confp->chan.outsigmod = SIG_FEATB;
11741             } else {
11742                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11743             }
11744 #ifdef HAVE_PRI
11745          } else if (!strcasecmp(v->name, "pridialplan")) {
11746             if (!strcasecmp(v->value, "national")) {
11747                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11748             } else if (!strcasecmp(v->value, "unknown")) {
11749                confp->pri.dialplan = PRI_UNKNOWN + 1;
11750             } else if (!strcasecmp(v->value, "private")) {
11751                confp->pri.dialplan = PRI_PRIVATE + 1;
11752             } else if (!strcasecmp(v->value, "international")) {
11753                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11754             } else if (!strcasecmp(v->value, "local")) {
11755                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11756             } else if (!strcasecmp(v->value, "dynamic")) {
11757                confp->pri.dialplan = -1;
11758             } else {
11759                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11760             }
11761          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11762             if (!strcasecmp(v->value, "national")) {
11763                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11764             } else if (!strcasecmp(v->value, "unknown")) {
11765                confp->pri.localdialplan = PRI_UNKNOWN + 1;
11766             } else if (!strcasecmp(v->value, "private")) {
11767                confp->pri.localdialplan = PRI_PRIVATE + 1;
11768             } else if (!strcasecmp(v->value, "international")) {
11769                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11770             } else if (!strcasecmp(v->value, "local")) {
11771                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11772             } else if (!strcasecmp(v->value, "dynamic")) {
11773                confp->pri.localdialplan = -1;
11774             } else {
11775                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11776             }
11777          } else if (!strcasecmp(v->name, "switchtype")) {
11778             if (!strcasecmp(v->value, "national")) 
11779                confp->pri.switchtype = PRI_SWITCH_NI2;
11780             else if (!strcasecmp(v->value, "ni1"))
11781                confp->pri.switchtype = PRI_SWITCH_NI1;
11782             else if (!strcasecmp(v->value, "dms100"))
11783                confp->pri.switchtype = PRI_SWITCH_DMS100;
11784             else if (!strcasecmp(v->value, "4ess"))
11785                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11786             else if (!strcasecmp(v->value, "5ess"))
11787                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11788             else if (!strcasecmp(v->value, "euroisdn"))
11789                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11790             else if (!strcasecmp(v->value, "qsig"))
11791                confp->pri.switchtype = PRI_SWITCH_QSIG;
11792             else {
11793                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11794                return -1;
11795             }
11796          } else if (!strcasecmp(v->name, "nsf")) {
11797             if (!strcasecmp(v->value, "sdn"))
11798                confp->pri.nsf = PRI_NSF_SDN;
11799             else if (!strcasecmp(v->value, "megacom"))
11800                confp->pri.nsf = PRI_NSF_MEGACOM;
11801             else if (!strcasecmp(v->value, "tollfreemegacom"))
11802                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
11803             else if (!strcasecmp(v->value, "accunet"))
11804                confp->pri.nsf = PRI_NSF_ACCUNET;
11805             else if (!strcasecmp(v->value, "none"))
11806                confp->pri.nsf = PRI_NSF_NONE;
11807             else {
11808                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11809                confp->pri.nsf = PRI_NSF_NONE;
11810             }
11811          } else if (!strcasecmp(v->name, "priindication")) {
11812             if (!strcasecmp(v->value, "outofband"))
11813                confp->chan.priindication_oob = 1;
11814             else if (!strcasecmp(v->value, "inband"))
11815                confp->chan.priindication_oob = 0;
11816             else
11817                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11818                   v->value, v->lineno);
11819          } else if (!strcasecmp(v->name, "priexclusive")) {
11820             confp->chan.priexclusive = ast_true(v->value);
11821          } else if (!strcasecmp(v->name, "internationalprefix")) {
11822             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11823          } else if (!strcasecmp(v->name, "nationalprefix")) {
11824             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11825          } else if (!strcasecmp(v->name, "localprefix")) {
11826             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11827          } else if (!strcasecmp(v->name, "privateprefix")) {
11828             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11829          } else if (!strcasecmp(v->name, "unknownprefix")) {
11830             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11831          } else if (!strcasecmp(v->name, "resetinterval")) {
11832             if (!strcasecmp(v->value, "never"))
11833                confp->pri.resetinterval = -1;
11834             else if (atoi(v->value) >= 60)
11835                confp->pri.resetinterval = atoi(v->value);
11836             else
11837                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11838                   v->value, v->lineno);
11839          } else if (!strcasecmp(v->name, "minunused")) {
11840             confp->pri.minunused = atoi(v->value);
11841          } else if (!strcasecmp(v->name, "minidle")) {
11842             confp->pri.minidle = atoi(v->value); 
11843          } else if (!strcasecmp(v->name, "idleext")) {
11844             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11845          } else if (!strcasecmp(v->name, "idledial")) {
11846             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11847          } else if (!strcasecmp(v->name, "overlapdial")) {
11848             confp->pri.overlapdial = ast_true(v->value);
11849 #ifdef HAVE_PRI_INBANDDISCONNECT
11850          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11851             confp->pri.inbanddisconnect = ast_true(v->value);
11852 #endif
11853          } else if (!strcasecmp(v->name, "pritimer")) {
11854 #ifdef PRI_GETSET_TIMERS
11855             char *timerc, *c;
11856             int timer, timeridx;
11857             c = v->value;
11858             timerc = strsep(&c, ",");
11859             if (timerc) {
11860                timer = atoi(c);
11861                if (!timer)
11862                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11863                else {
11864                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
11865                      pritimers[timeridx] = timer;
11866                   else
11867                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11868                }
11869             } else
11870                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11871 
11872          } else if (!strcasecmp(v->name, "facilityenable")) {
11873             confp->pri.facilityenable = ast_true(v->value);
11874 #endif /* PRI_GETSET_TIMERS */
11875 #endif /* HAVE_PRI */
11876          } else if (!strcasecmp(v->name, "cadence")) {
11877             /* setup to scan our argument */
11878             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11879             int i;
11880             struct dahdi_ring_cadence new_cadence;
11881             int cid_location = -1;
11882             int firstcadencepos = 0;
11883             char original_args[80];
11884             int cadence_is_ok = 1;
11885 
11886             ast_copy_string(original_args, v->value, sizeof(original_args));
11887             /* 16 cadences allowed (8 pairs) */
11888             element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &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]);
11889    
11890             /* Cadence must be even (on/off) */
11891             if (element_count % 2 == 1) {
11892                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11893                cadence_is_ok = 0;
11894             }
11895    
11896             /* Ring cadences cannot be negative */
11897             for (i = 0; i < element_count; i++) {
11898                if (c[i] == 0) {
11899                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11900                   cadence_is_ok = 0;
11901                   break;
11902                } else if (c[i] < 0) {
11903                   if (i % 2 == 1) {
11904                      /* Silence duration, negative possibly okay */
11905                      if (cid_location == -1) {
11906                         cid_location = i;
11907                         c[i] *= -1;
11908                      } else {
11909                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11910                         cadence_is_ok = 0;
11911                         break;
11912                      }
11913                   } else {
11914                      if (firstcadencepos == 0) {
11915                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
11916                                  /* duration will be passed negative to the DAHDI driver */
11917                      } else {
11918                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11919                         cadence_is_ok = 0;
11920                         break;
11921                      }
11922                   }
11923                }
11924             }
11925    
11926             /* Substitute our scanned cadence */
11927             for (i = 0; i < 16; i++) {
11928                new_cadence.ringcadence[i] = c[i];
11929             }
11930    
11931             if (cadence_is_ok) {
11932                /* ---we scanned it without getting annoyed; now some sanity checks--- */
11933                if (element_count < 2) {
11934                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11935                } else {
11936                   if (cid_location == -1) {
11937                      /* user didn't say; default to first pause */
11938                      cid_location = 1;
11939                   } else {
11940                      /* convert element_index to cidrings value */
11941                      cid_location = (cid_location + 1) / 2;
11942                   }
11943                   /* ---we like their cadence; try to install it--- */
11944                   if (!user_has_defined_cadences++)
11945                      /* this is the first user-defined cadence; clear the default user cadences */
11946                      num_cadence = 0;
11947                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
11948                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11949                   else {
11950                      cadences[num_cadence] = new_cadence;
11951                      cidrings[num_cadence++] = cid_location;
11952                      if (option_verbose > 2)
11953                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11954                   }
11955                }
11956             }
11957          } else if (!strcasecmp(v->name, "ringtimeout")) {
11958             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11959          } else if (!strcasecmp(v->name, "prewink")) {
11960             confp->timing.prewinktime = atoi(v->value);
11961          } else if (!strcasecmp(v->name, "preflash")) {
11962             confp->timing.preflashtime = atoi(v->value);
11963          } else if (!strcasecmp(v->name, "wink")) {
11964             confp->timing.winktime = atoi(v->value);
11965          } else if (!strcasecmp(v->name, "flash")) {
11966             confp->timing.flashtime = atoi(v->value);
11967          } else if (!strcasecmp(v->name, "start")) {
11968             confp->timing.starttime = atoi(v->value);
11969          } else if (!strcasecmp(v->name, "rxwink")) {
11970             confp->timing.rxwinktime = atoi(v->value);
11971          } else if (!strcasecmp(v->name, "rxflash")) {
11972             confp->timing.rxflashtime = atoi(v->value);
11973          } else if (!strcasecmp(v->name, "debounce")) {
11974             confp->timing.debouncetime = atoi(v->value);
11975          } else if (!strcasecmp(v->name, "toneduration")) {
11976             int toneduration;
11977             int ctlfd;
11978             int res;
11979             struct dahdi_dialparams dps;
11980 
11981             ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
11982 
11983             if (ctlfd == -1) {
11984                ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
11985                return -1;
11986             }
11987 
11988             toneduration = atoi(v->value);
11989             if (toneduration > -1) {
11990                memset(&dps, 0, sizeof(dps));
11991 
11992                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11993                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11994                if (res < 0) {
11995                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11996                   return -1;
11997                }
11998             }
11999             close(ctlfd);
12000          } else if (!strcasecmp(v->name, "defaultcic")) {
12001             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
12002          } else if (!strcasecmp(v->name, "defaultozz")) {
12003             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
12004          } 
12005       } else if (!skipchannels)
12006          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
12007    }
12008    if (dahdichan[0]) { 
12009       /* The user has set 'dahdichan' */
12010       /*< \todo pass proper line number instead of 0 */
12011       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
12012          return -1;
12013       }
12014    }
12015    /*< \todo why check for the pseudo in the per-channel section.
12016     * Any actual use for manual setup of the pseudo channel? */
12017    if (!found_pseudo && reload == 0) {
12018       /* use the default configuration for a channel, so
12019          that any settings from real configured channels
12020          don't "leak" into the pseudo channel config
12021       */
12022       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12023 
12024       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
12025 
12026       if (tmp) {
12027          if (option_verbose > 2)
12028             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
12029       } else {
12030          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
12031       }
12032    }
12033    return 0;
12034 }
12035       
12036 static int setup_dahdi(int reload)
12037 {
12038    struct ast_config *cfg;
12039    struct ast_variable *v;
12040    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12041    int res;
12042 
12043 #ifdef HAVE_PRI
12044    char *c;
12045    int spanno;
12046    int i, x;
12047    int logicalspan;
12048    int trunkgroup;
12049    int dchannels[NUM_DCHANS];
12050 #endif
12051 
12052 #ifdef HAVE_ZAPTEL
12053    int load_from_zapata_conf = 1;
12054 #else
12055    int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
12056 #endif
12057 
12058    if (load_from_zapata_conf) {
12059       if (!(cfg = ast_config_load("zapata.conf"))) {
12060          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
12061          return 0;
12062       }
12063    } else {
12064       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
12065          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
12066          return 0;
12067       }
12068    }
12069 
12070    /* It's a little silly to lock it, but we mind as well just to be sure */
12071    ast_mutex_lock(&iflock);
12072 #ifdef HAVE_PRI
12073    if (reload != 1) {
12074       /* Process trunkgroups first */
12075       v = ast_variable_browse(cfg, "trunkgroups");
12076       while (v) {
12077          if (!strcasecmp(v->name, "trunkgroup")) {
12078             trunkgroup = atoi(v->value);
12079             if (trunkgroup > 0) {
12080                if ((c = strchr(v->value, ','))) {
12081                   i = 0;
12082                   memset(dchannels, 0, sizeof(dchannels));
12083                   while (c && (i < NUM_DCHANS)) {
12084                      dchannels[i] = atoi(c + 1);
12085                      if (dchannels[i] < 0) {
12086                         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);
12087                      } else
12088                         i++;
12089                      c = strchr(c + 1, ',');
12090                   }
12091                   if (i) {
12092                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
12093                         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);
12094                      } else if (option_verbose > 1)
12095                         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");
12096                   } else
12097                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12098                } else
12099                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12100             } else
12101                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
12102          } else if (!strcasecmp(v->name, "spanmap")) {
12103             spanno = atoi(v->value);
12104             if (spanno > 0) {
12105                if ((c = strchr(v->value, ','))) {
12106                   trunkgroup = atoi(c + 1);
12107                   if (trunkgroup > 0) {
12108                      if ((c = strchr(c + 1, ','))) 
12109                         logicalspan = atoi(c + 1);
12110                      else
12111                         logicalspan = 0;
12112                      if (logicalspan >= 0) {
12113                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
12114                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12115                         } else if (option_verbose > 1) 
12116                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12117                      } else
12118                         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);
12119                   } else
12120                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
12121                } else
12122                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
12123             } else
12124                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
12125          } else {
12126             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
12127          }
12128          v = v->next;
12129       }
12130    }
12131 #endif
12132    
12133    /* Copy the default jb config over global_jbconf */
12134    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
12135 
12136    v = ast_variable_browse(cfg, "channels");
12137    res = process_dahdi(&conf, "", v, reload, 0);
12138    ast_mutex_unlock(&iflock);
12139    ast_config_destroy(cfg);
12140    if (res)
12141       return res;
12142    cfg = ast_config_load("users.conf");
12143    if (cfg) {
12144       char *cat;
12145       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
12146       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
12147          if (!strcasecmp(cat, "general"))
12148             continue;
12149          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
12150             struct dahdi_chan_conf sect_conf;
12151             memcpy(&sect_conf, &conf, sizeof(sect_conf));
12152 
12153             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
12154          }
12155       }
12156       ast_config_destroy(cfg);
12157    }
12158 #ifdef HAVE_PRI
12159    if (reload != 1) {
12160       for (x = 0; x < NUM_SPANS; x++) {
12161          if (pris[x].pvts[0]) {
12162             if (start_pri(pris + x)) {
12163                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
12164                return -1;
12165             } else if (option_verbose > 1)
12166                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
12167          }
12168       }
12169    }
12170 #endif
12171    /* And start the monitor for the first time */
12172    restart_monitor();
12173    return 0;
12174 }
12175 
12176 #define local_astman_register(a, b, c, d) do { \
12177                   if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12178                      ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
12179                   } \
12180                   ast_manager_register("Zap" a, b, zap_ ## c, d); \
12181                  } while (0)
12182 
12183 static int load_module(void)
12184 {
12185    int res;
12186 
12187 #ifdef HAVE_PRI
12188    int y,i;
12189    memset(pris, 0, sizeof(pris));
12190    for (y = 0; y < NUM_SPANS; y++) {
12191       ast_mutex_init(&pris[y].lock);
12192       pris[y].offset = -1;
12193       pris[y].master = AST_PTHREADT_NULL;
12194       for (i = 0; i < NUM_DCHANS; i++)
12195          pris[y].fds[i] = -1;
12196    }
12197    pri_set_error(dahdi_pri_error);
12198    pri_set_message(dahdi_pri_message);
12199    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12200       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
12201          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
12202    }
12203    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
12204       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
12205 #endif
12206    if ((res = setup_dahdi(0))) {
12207       return AST_MODULE_LOAD_DECLINE;
12208    }
12209    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12210       chan_tech = &dahdi_tech;
12211    } else {
12212       chan_tech = &zap_tech;
12213    }
12214    if (ast_channel_register(chan_tech)) {
12215       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
12216       __unload_module();
12217       return -1;
12218    }
12219 #ifdef HAVE_PRI
12220    ast_string_field_init(&inuse, 16);
12221    ast_string_field_set(&inuse, name, "GR-303InUse");
12222    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12223 #endif   
12224    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12225    
12226    memset(round_robin, 0, sizeof(round_robin));
12227    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
12228    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
12229    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
12230    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
12231    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
12232    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
12233    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
12234 
12235    ast_cond_init(&ss_thread_complete, NULL);
12236 
12237    return res;
12238 }
12239 
12240 static int dahdi_sendtext(struct ast_channel *c, const char *text)
12241 {
12242 #define  END_SILENCE_LEN 400
12243 #define  HEADER_MS 50
12244 #define  TRAILER_MS 5
12245 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
12246 #define  ASCII_BYTES_PER_CHAR 80
12247 
12248    unsigned char *buf,*mybuf;
12249    struct dahdi_pvt *p = c->tech_pvt;
12250    struct pollfd fds[1];
12251    int size,res,fd,len,x;
12252    int bytes=0;
12253    /* Initial carrier (imaginary) */
12254    float cr = 1.0;
12255    float ci = 0.0;
12256    float scont = 0.0;
12257    int index;
12258 
12259    index = dahdi_get_index(c, p, 0);
12260    if (index < 0) {
12261       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
12262       return -1;
12263    }
12264    if (!text[0]) return(0); /* if nothing to send, dont */
12265    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
12266    if (p->mate) 
12267       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
12268    else
12269       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
12270    if (!buf)
12271       return -1;
12272    mybuf = buf;
12273    if (p->mate) {
12274       int codec = AST_LAW(p);
12275       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
12276          PUT_CLID_MARKMS;
12277       }
12278       /* Put actual message */
12279       for (x = 0; text[x]; x++) {
12280          PUT_CLID(text[x]);
12281       }
12282       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
12283          PUT_CLID_MARKMS;
12284       }
12285       len = bytes;
12286       buf = mybuf;
12287    } else {
12288       len = tdd_generate(p->tdd, buf, text);
12289       if (len < 1) {
12290          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
12291          free(mybuf);
12292          return -1;
12293       }
12294    }
12295    memset(buf + len, 0x7f, END_SILENCE_LEN);
12296    len += END_SILENCE_LEN;
12297    fd = p->subs[index].dfd;
12298    while (len) {
12299       if (ast_check_hangup(c)) {
12300          free(mybuf);
12301          return -1;
12302       }
12303       size = len;
12304       if (size > READ_SIZE)
12305          size = READ_SIZE;
12306       fds[0].fd = fd;
12307       fds[0].events = POLLOUT | POLLPRI;
12308       fds[0].revents = 0;
12309       res = poll(fds, 1, -1);
12310       if (!res) {
12311          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
12312          continue;
12313       }
12314         /* if got exception */
12315       if (fds[0].revents & POLLPRI) {
12316          ast_free(mybuf);
12317          return -1;
12318       }
12319       if (!(fds[0].revents & POLLOUT)) {
12320          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12321          continue;
12322       }
12323       res = write(fd, buf, size);
12324       if (res != size) {
12325          if (res == -1) {
12326             free(mybuf);
12327             return -1;
12328          }
12329          if (option_debug)
12330             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12331          break;
12332       }
12333       len -= size;
12334       buf += size;
12335    }
12336    free(mybuf);
12337    return(0);
12338 }
12339 
12340 
12341 static int reload(void)
12342 {
12343    int res = 0;
12344 
12345    res = setup_dahdi(1);
12346    if (res) {
12347       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12348       return -1;
12349    }
12350    return 0;
12351 }
12352 
12353 /* This is a workaround so that menuselect displays a proper description
12354  * AST_MODULE_INFO(, , "DAHDI Telephony"
12355  */
12356 
12357 #ifdef HAVE_PRI
12358 #define tdesc "DAHDI Telephony w/PRI"
12359 #else
12360 #define tdesc "DAHDI Telephony"
12361 #endif
12362 
12363 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12364       .load = load_module,
12365       .unload = unload_module,
12366       .reload = reload,
12367           );
12368 
12369 

Generated on Thu May 14 14:48:53 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7