Tue Apr 6 15:45:27 2010

Asterisk developer's documentation


chan_dahdi.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief DAHDI Pseudo TDM interface 
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  * 
00025  * Connects to the DAHDI telephony library as well as 
00026  * libpri. Libpri is optional and needed only if you are
00027  * going to use ISDN connections.
00028  *
00029  * You need to install libraries before you attempt to compile
00030  * and install the DAHDI channel.
00031  *
00032  * \par See also
00033  * \arg \ref Config_dahdi
00034  *
00035  * \ingroup channel_drivers
00036  *
00037  * \todo Deprecate the "musiconhold" configuration option post 1.4
00038  */
00039 
00040 /*** MODULEINFO
00041    <depend>res_smdi</depend>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <depend>res_features</depend>
00045    <use>pri</use>
00046    <use>openr2</use>
00047  ***/
00048 
00049 #include "asterisk.h"
00050 
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 232090 $")
00052 
00053 #include <stdio.h>
00054 #include <string.h>
00055 #ifdef __NetBSD__
00056 #include <pthread.h>
00057 #include <signal.h>
00058 #else
00059 #include <sys/signal.h>
00060 #endif
00061 #include <errno.h>
00062 #include <stdlib.h>
00063 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00064 #include <stdint.h>
00065 #endif
00066 #include <unistd.h>
00067 #include <sys/ioctl.h>
00068 #include <math.h>
00069 #include <ctype.h>
00070 
00071 #ifdef HAVE_PRI
00072 #include <libpri.h>
00073 #endif
00074 
00075 #ifdef HAVE_OPENR2
00076 #include <openr2.h>
00077 #endif
00078 
00079 #include "asterisk/lock.h"
00080 #include "asterisk/channel.h"
00081 #include "asterisk/config.h"
00082 #include "asterisk/logger.h"
00083 #include "asterisk/module.h"
00084 #include "asterisk/pbx.h"
00085 #include "asterisk/options.h"
00086 #include "asterisk/file.h"
00087 #include "asterisk/ulaw.h"
00088 #include "asterisk/alaw.h"
00089 #include "asterisk/callerid.h"
00090 #include "asterisk/adsi.h"
00091 #include "asterisk/cli.h"
00092 #include "asterisk/cdr.h"
00093 #include "asterisk/features.h"
00094 #include "asterisk/musiconhold.h"
00095 #include "asterisk/say.h"
00096 #include "asterisk/tdd.h"
00097 #include "asterisk/app.h"
00098 #include "asterisk/dsp.h"
00099 #include "asterisk/astdb.h"
00100 #include "asterisk/manager.h"
00101 #include "asterisk/causes.h"
00102 #include "asterisk/term.h"
00103 #include "asterisk/utils.h"
00104 #include "asterisk/transcap.h"
00105 #include "asterisk/stringfields.h"
00106 #include "asterisk/abstract_jb.h"
00107 #include "asterisk/smdi.h"
00108 #include "asterisk/astobj.h"
00109 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00110 
00111 #include "asterisk/dahdi_compat.h"
00112 #include "asterisk/tonezone_compat.h"
00113 
00114 /*! Global jitterbuffer configuration - by default, jb is disabled */
00115 static struct ast_jb_conf default_jbconf =
00116 {
00117    .flags = 0,
00118    .max_size = -1,
00119    .resync_threshold = -1,
00120    .impl = ""
00121 };
00122 static struct ast_jb_conf global_jbconf;
00123 
00124 #ifndef DAHDI_TONEDETECT
00125 /* Work around older code with no tone detect */
00126 #define DAHDI_EVENT_DTMFDOWN 0
00127 #define DAHDI_EVENT_DTMFUP 0
00128 #endif
00129 
00130 /* define this to send PRI user-user information elements */
00131 #undef SUPPORT_USERUSER
00132 
00133 /*! 
00134  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00135  * the user hangs up to reset the state machine so ring works properly.
00136  * This is used to be able to support kewlstart by putting the zhone in
00137  * groundstart mode since their forward disconnect supervision is entirely
00138  * broken even though their documentation says it isn't and their support
00139  * is entirely unwilling to provide any assistance with their channel banks
00140  * even though their web site says they support their products for life.
00141  */
00142 /* #define ZHONE_HACK */
00143 
00144 /*! \note
00145  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00146  * before dialing on it.  Certain FXO interfaces always think they're out of
00147  * service with this method however.
00148  */
00149 /* #define DAHDI_CHECK_HOOKSTATE */
00150 
00151 /*! \brief Typically, how many rings before we should send Caller*ID */
00152 #define DEFAULT_CIDRINGS 1
00153 
00154 #define CHANNEL_PSEUDO -12
00155 
00156 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00157 
00158 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00159 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) 
00160 
00161 static const char tdesc[] = "DAHDI Telephony Driver"
00162 #ifdef HAVE_PRI
00163                " w/PRI"
00164 #endif
00165 #ifdef HAVE_OPENR2
00166           " w/OPENR2"
00167 #endif
00168 ;
00169 
00170 #define SIG_EM    DAHDI_SIG_EM
00171 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00175 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00178 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI      DAHDI_SIG_CLEAR
00186 #define SIG_MFCR2 DAHDI_SIG_CAS
00187 #define  SIG_SF      DAHDI_SIG_SF
00188 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00189 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00190 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00191 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00192 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00193 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00194 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00195 
00196 #define NUM_SPANS       32
00197 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00198 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00199 
00200 #define CHAN_PSEUDO  -2
00201 
00202 #define DCHAN_PROVISIONED (1 << 0)
00203 #define DCHAN_NOTINALARM  (1 << 1)
00204 #define DCHAN_UP          (1 << 2)
00205 
00206 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00207 
00208 /* Overlap dialing option types */
00209 #define DAHDI_OVERLAPDIAL_NONE 0
00210 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00211 #define DAHDI_OVERLAPDIAL_INCOMING 2
00212 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00213 
00214 static char defaultcic[64] = "";
00215 static char defaultozz[64] = "";
00216 
00217 static char progzone[10] = "";
00218 
00219 static int distinctiveringaftercid = 0;
00220 
00221 static int numbufs = 4;
00222 static int dtmfcid_level = 256;
00223 
00224 #ifdef HAVE_PRI
00225 static struct ast_channel inuse;
00226 #ifdef PRI_GETSET_TIMERS
00227 static int pritimers[PRI_MAX_TIMERS];
00228 #endif
00229 static int pridebugfd = -1;
00230 static char pridebugfilename[1024] = "";
00231 #endif
00232 
00233 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00234 static int firstdigittimeout = 16000;
00235 
00236 /*! \brief How long to wait for following digits (FXO logic) */
00237 static int gendigittimeout = 8000;
00238 
00239 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00240 static int matchdigittimeout = 3000;
00241 
00242 /*! \brief Protect the interface list (of dahdi_pvt's) */
00243 AST_MUTEX_DEFINE_STATIC(iflock);
00244 
00245 
00246 static int ifcount = 0;
00247 
00248 #ifdef HAVE_PRI
00249 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00250 #endif
00251 
00252 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00253    when it's doing something critical. */
00254 AST_MUTEX_DEFINE_STATIC(monlock);
00255 
00256 /*! \brief This is the thread for the monitor which checks for input on the channels
00257    which are not currently in use. */
00258 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00259 static ast_cond_t ss_thread_complete;
00260 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00261 AST_MUTEX_DEFINE_STATIC(restart_lock);
00262 static int ss_thread_count = 0;
00263 static int num_restart_pending = 0;
00264 
00265 static int restart_monitor(void);
00266 
00267 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);
00268 
00269 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00270 
00271 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00272 static inline int dahdi_get_event(int fd)
00273 {
00274    int j;
00275    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00276       return -1;
00277    return j;
00278 }
00279 
00280 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00281 static inline int dahdi_wait_event(int fd)
00282 {
00283    int i, j = 0;
00284    i = DAHDI_IOMUX_SIGEVENT;
00285    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00286       return -1;
00287    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00288       return -1;
00289    return j;
00290 }
00291 
00292 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00293 #define READ_SIZE 160
00294 
00295 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00296 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00297 
00298 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00299 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00300 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00301 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00302 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00303 
00304 struct dahdi_pvt;
00305 
00306 /*!
00307  * \brief Configured ring timeout base.
00308  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00309  */
00310 static int ringt_base = DEFAULT_RINGT;
00311 
00312 #ifdef HAVE_OPENR2
00313 
00314 struct dahdi_mfcr2 {
00315    pthread_t master;           /*!< Thread of master */
00316    openr2_context_t *protocol_context;    /*!< OpenR2 context handle */ 
00317    struct dahdi_pvt *pvts[MAX_CHANNELS];     /*!< Member channel pvt structs */
00318    int numchans;                          /*!< Number of channels in this R2 block */
00319 };
00320 
00321 static struct dahdi_mfcr2 r2links[NUM_SPANS];
00322 static openr2_variant_t mfcr2_cur_variant = OR2_VAR_UNKNOWN;
00323 static int mfcr2_cur_mfback_timeout = -1;
00324 static int mfcr2_cur_metering_pulse_timeout = -1;
00325 static int mfcr2_cur_max_ani = 10;
00326 static int mfcr2_cur_max_dnis = 4;
00327 static int mfcr2_cur_get_ani_first = -1;
00328 static int mfcr2_cur_skip_category = -1;
00329 static int mfcr2_cur_context_index = 0;
00330 static int mfcr2_cur_call_files = 0;
00331 static int mfcr2_cur_allow_collect_calls = 0;
00332 static int mfcr2_cur_accept_on_offer = 1;
00333 static int mfcr2_cur_charge_calls = 1;
00334 static int mfcr2_cur_forced_release = 0;
00335 static int mfcr2_cur_double_answer = 0;
00336 static int mfcr2_cur_immediate_accept = -1;
00337 /* starting with openr2 interface 3 we have DTMF support */
00338 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00339 static int mfcr2_cur_dtmf_dialing = -1;
00340 static int mfcr2_cur_dtmf_detection = -1;
00341 static int mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
00342 static int mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
00343 #endif
00344 static char mfcr2_cur_logdir[OR2_MAX_PATH];
00345 static char mfcr2_cur_r2proto_file[OR2_MAX_PATH];
00346 static openr2_log_level_t mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
00347 static openr2_calling_party_category_t mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
00348 
00349 #endif /* HAVE_OPENR2 */
00350 
00351 #ifdef HAVE_PRI
00352 
00353 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00354 #define PRI_CHANNEL(p) ((p) & 0xff)
00355 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00356 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00357 
00358 struct dahdi_pri {
00359    pthread_t master;                /*!< Thread of master */
00360    ast_mutex_t lock;                /*!< Mutex */
00361    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00362    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00363    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00364    int minunused;                   /*!< Min # of channels to keep empty */
00365    int minidle;                     /*!< Min # of "idling" calls to keep active */
00366    int nodetype;                    /*!< Node type */
00367    int switchtype;                     /*!< Type of switch to emulate */
00368    int nsf;                   /*!< Network-Specific Facilities */
00369    int dialplan;                    /*!< Dialing plan */
00370    int localdialplan;                  /*!< Local dialing plan */
00371    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00372    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00373    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00374    char privateprefix[20];                /*!< for private dialplans */
00375    char unknownprefix[20];                /*!< for unknown dialplans */
00376    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00377    int trunkgroup;                     /*!< What our trunkgroup is */
00378    int mastertrunkgroup;                  /*!< What trunk group is our master */
00379    int prilogicalspan;                 /*!< Logical span number within trunk group */
00380    int numchans;                    /*!< Num of channels we represent */
00381    int overlapdial;                 /*!< In overlap dialing mode */
00382    int facilityenable;                 /*!< Enable facility IEs */
00383    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00384    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00385    struct pri *pri;                 /*!< Currently active D-channel */
00386    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00387    int debug;
00388    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00389    /*! \brief Value set but not used */
00390    int offset;
00391    /*! \brief Span number put into user output messages */
00392    int span;
00393    /*! \brief TRUE if span is being reset/restarted */
00394    int resetting;
00395    /*! \brief Current position during a reset (-1 if not started) */
00396    int resetpos;
00397 #ifdef HAVE_PRI_INBANDDISCONNECT
00398    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00399 #endif
00400    time_t lastreset;                /*!< time when unused channels were last reset */
00401    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00402    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00403    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00404    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00405 };
00406 
00407 
00408 static struct dahdi_pri pris[NUM_SPANS];
00409 
00410 #if 0
00411 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00412 #else
00413 #define DEFAULT_PRI_DEBUG 0
00414 #endif
00415 
00416 static inline void pri_rel(struct dahdi_pri *pri)
00417 {
00418    ast_mutex_unlock(&pri->lock);
00419 }
00420 
00421 #else
00422 /*! Shut up the compiler */
00423 struct dahdi_pri;
00424 #endif
00425 
00426 #define SUB_REAL  0        /*!< Active call */
00427 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00428 #define SUB_THREEWAY 2        /*!< Three-way call */
00429 
00430 /* Polarity states */
00431 #define POLARITY_IDLE   0
00432 #define POLARITY_REV    1
00433 
00434 
00435 static struct dahdi_distRings drings;
00436 
00437 struct distRingData {
00438    int ring[3];
00439 };
00440 struct ringContextData {
00441    char contextData[AST_MAX_CONTEXT];
00442 };
00443 struct dahdi_distRings {
00444    struct distRingData ringnum[3];
00445    struct ringContextData ringContext[3];
00446 };
00447 
00448 static char *subnames[] = {
00449    "Real",
00450    "Callwait",
00451    "Threeway"
00452 };
00453 
00454 struct dahdi_subchannel {
00455    int dfd;
00456    struct ast_channel *owner;
00457    int chan;
00458    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00459    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00460    unsigned int needringing:1;
00461    unsigned int needbusy:1;
00462    unsigned int needcongestion:1;
00463    unsigned int needcallerid:1;
00464    unsigned int needanswer:1;
00465    unsigned int needflash:1;
00466    unsigned int needhold:1;
00467    unsigned int needunhold:1;
00468    unsigned int linear:1;
00469    unsigned int inthreeway:1;
00470    struct dahdi_confinfo curconf;
00471 };
00472 
00473 #define CONF_USER_REAL     (1 << 0)
00474 #define CONF_USER_THIRDCALL   (1 << 1)
00475 
00476 #define MAX_SLAVES   4
00477 
00478 static struct dahdi_pvt {
00479    ast_mutex_t lock;
00480    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00481                      /*!< Up to three channels can be associated with this call */
00482       
00483    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00484    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00485    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00486 
00487    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00488    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00489    int inconference;          /*!< If our real should be in the conference */
00490    
00491    int buf_no;             /*!< Number of buffers */
00492    int buf_policy;            /*!< Buffer policy */
00493    int sig;             /*!< Signalling style */
00494    /*!
00495     * \brief Nonzero if the signaling type is sent over a radio.
00496     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00497     */
00498    int radio;
00499    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00500    int oprmode;               /*!< "Operator Services" mode */
00501    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00502    /*! \brief Rx gain set by chan_dahdi.conf */
00503    float rxgain;
00504    /*! \brief Tx gain set by chan_dahdi.conf */
00505    float txgain;
00506    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00507    struct dahdi_pvt *next;          /*!< Next channel in list */
00508    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00509 
00510    /* flags */
00511 
00512    /*!
00513     * \brief TRUE if ADSI (Analog Display Services Interface) available
00514     * \note Set from the "adsi" value read in from chan_dahdi.conf
00515     */
00516    unsigned int adsi:1;
00517    /*!
00518     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00519     * call is answered by the remote party.
00520     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00521     */
00522    unsigned int answeronpolarityswitch:1;
00523    /*!
00524     * \brief TRUE if busy detection is enabled.
00525     * (Listens for the beep-beep busy pattern.)
00526     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00527     */
00528    unsigned int busydetect:1;
00529    /*!
00530     * \brief TRUE if call return is enabled.
00531     * (*69, if your dialplan doesn't catch this first)
00532     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00533     */
00534    unsigned int callreturn:1;
00535    /*!
00536     * \brief TRUE if busy extensions will hear the call-waiting tone
00537     * and can use hook-flash to switch between callers.
00538     * \note Can be disabled by dialing *70.
00539     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00540     */
00541    unsigned int callwaiting:1;
00542    /*!
00543     * \brief TRUE if send caller ID for Call Waiting
00544     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00545     */
00546    unsigned int callwaitingcallerid:1;
00547    /*!
00548     * \brief TRUE if support for call forwarding enabled.
00549     * Dial *72 to enable call forwarding.
00550     * Dial *73 to disable call forwarding.
00551     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00552     */
00553    unsigned int cancallforward:1;
00554    /*!
00555     * \brief TRUE if support for call parking is enabled.
00556     * \note Set from the "canpark" value read in from chan_dahdi.conf
00557     */
00558    unsigned int canpark:1;
00559    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00560    unsigned int confirmanswer:1;
00561    /*!
00562     * \brief TRUE if the channel is to be destroyed on hangup.
00563     * (Used by pseudo channels.)
00564     */
00565    unsigned int destroy:1;
00566    unsigned int didtdd:1;           /*!< flag to say its done it once */
00567    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00568    unsigned int dialednone:1;
00569    /*! \brief TRUE if in the process of dialing digits or sending something. */
00570    unsigned int dialing:1;
00571    /*! \brief TRUE if the transfer capability of the call is digital. */
00572    unsigned int digital:1;
00573    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00574    unsigned int dnd:1;
00575    /*! \brief XXX BOOLEAN Purpose??? */
00576    unsigned int echobreak:1;
00577    /*!
00578     * \brief TRUE if echo cancellation enabled when bridged.
00579     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00580     * \note Disabled if the echo canceller is not setup.
00581     */
00582    unsigned int echocanbridged:1;
00583    /*! \brief TRUE if echo cancellation is turned on. */
00584    unsigned int echocanon:1;
00585    /*! \brief TRUE if a fax tone has already been handled. */
00586    unsigned int faxhandled:1;
00587    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00588    unsigned int firstradio:1;
00589    /*!
00590     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00591     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00592     */
00593    unsigned int hanguponpolarityswitch:1;
00594    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00595    unsigned int hardwaredtmf:1;
00596    /*!
00597     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00598     * \note Caller ID can be disabled by dialing *67.
00599     * \note Caller ID can be enabled by dialing *82.
00600     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00601     */
00602    unsigned int hidecallerid:1;
00603    /*!
00604     * \brief TRUE if hide just the name not the number for legacy PBX use.
00605     * \note Only applies to PRI channels.
00606     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00607     */
00608    unsigned int hidecalleridname:1;
00609    /*! \brief TRUE if DTMF detection is disabled. */
00610    unsigned int ignoredtmf:1;
00611    /*!
00612     * \brief TRUE if the channel should be answered immediately
00613     * without attempting to gather any digits.
00614     * \note Set from the "immediate" value read in from chan_dahdi.conf
00615     */
00616    unsigned int immediate:1;
00617    /*! \brief TRUE if in an alarm condition. */
00618    unsigned int inalarm:1;
00619    unsigned int unknown_alarm:1;
00620    /*! \brief TRUE if TDD in MATE mode */
00621    unsigned int mate:1;
00622    /*! \brief TRUE if we originated the call leg. */
00623    unsigned int outgoing:1;
00624    /* unsigned int overlapdial:1;         unused and potentially confusing */
00625    /*!
00626     * \brief TRUE if busy extensions will hear the call-waiting tone
00627     * and can use hook-flash to switch between callers.
00628     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00629     */
00630    unsigned int permcallwaiting:1;
00631    /*!
00632     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00633     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00634     */
00635    unsigned int permhidecallerid:1;
00636    /*!
00637     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00638     * \note Set from the "priindication" value read in from chan_dahdi.conf
00639     */
00640    unsigned int priindication_oob:1;
00641    /*!
00642     * \brief TRUE if PRI B channels are always exclusively selected.
00643     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00644     */
00645    unsigned int priexclusive:1;
00646    /*!
00647     * \brief TRUE if we will pulse dial.
00648     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00649     */
00650    unsigned int pulse:1;
00651    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00652    unsigned int pulsedial:1;
00653    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00654    /*!
00655     * \brief TRUE if caller ID is restricted.
00656     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00657     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00658     */
00659    unsigned int restrictcid:1;
00660    /*!
00661     * \brief TRUE if three way calling is enabled
00662     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00663     */
00664    unsigned int threewaycalling:1;
00665    /*!
00666     * \brief TRUE if call transfer is enabled
00667     * \note For FXS ports (either direct analog or over T1/E1):
00668     *   Support flash-hook call transfer
00669     * \note For digital ports using ISDN PRI protocols:
00670     *   Support switch-side transfer (called 2BCT, RLT or other names)
00671     * \note Set from the "transfer" value read in from chan_dahdi.conf
00672     */
00673    unsigned int transfer:1;
00674    /*!
00675     * \brief TRUE if caller ID is used on this channel.
00676     * \note PRI spans will save caller ID from the networking peer.
00677     * \note FXS ports will generate the caller ID spill.
00678     * \note FXO ports will listen for the caller ID spill.
00679     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00680     */
00681    unsigned int use_callerid:1;
00682    /*!
00683     * \brief TRUE if we will use the calling presentation setting
00684     * from the Asterisk channel for outgoing calls.
00685     * \note Only applies to PRI channels.
00686     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00687     */
00688    unsigned int use_callingpres:1;
00689    /*!
00690     * \brief TRUE if distinctive rings are to be detected.
00691     * \note For FXO lines
00692     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00693     */
00694    unsigned int usedistinctiveringdetection:1;
00695    /*!
00696     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00697     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00698     */
00699    unsigned int dahditrcallerid:1;
00700    /*!
00701     * \brief TRUE if allowed to flash-transfer to busy channels.
00702     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00703     */
00704    unsigned int transfertobusy:1;
00705 #if defined(HAVE_PRI)
00706    /*! \brief TRUE if channel is alerting/ringing */
00707    unsigned int alerting:1;
00708    /*! \brief TRUE if the call has already gone/hungup */
00709    unsigned int alreadyhungup:1;
00710    /*!
00711     * \brief TRUE if this is an idle call
00712     * \note Applies to PRI channels.
00713     */
00714    unsigned int isidlecall:1;
00715    /*!
00716     * \brief TRUE if call is in a proceeding state.
00717     * The call has started working its way through the network.
00718     */
00719    unsigned int proceeding:1;
00720    /*! \brief TRUE if the call has seen progress through the network. */
00721    unsigned int progress:1;
00722    /*!
00723     * \brief TRUE if this channel is being reset/restarted
00724     * \note Applies to PRI channels.
00725     */
00726    unsigned int resetting:1;
00727    /*!
00728     * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
00729     * \note Applies to PRI channels.
00730     */
00731    unsigned int setup_ack:1;
00732 #endif
00733    /*!
00734     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00735     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00736     */
00737    unsigned int use_smdi:1;
00738    /*! \brief The serial port to listen for SMDI data on */
00739    struct ast_smdi_interface *smdi_iface;
00740 
00741    /*! \brief Distinctive Ring data */
00742    struct dahdi_distRings drings;
00743 
00744    /*!
00745     * \brief The configured context for incoming calls.
00746     * \note The "context" string read in from chan_dahdi.conf
00747     */
00748    char context[AST_MAX_CONTEXT];
00749    /*!
00750     * \brief Saved context string.
00751     */
00752    char defcontext[AST_MAX_CONTEXT];
00753    /*! \brief Extension to use in the dialplan. */
00754    char exten[AST_MAX_EXTENSION];
00755    /*!
00756     * \brief Language configured for calls.
00757     * \note The "language" string read in from chan_dahdi.conf
00758     */
00759    char language[MAX_LANGUAGE];
00760    /*!
00761     * \brief The configured music-on-hold class to use for calls.
00762     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00763     */
00764    char mohinterpret[MAX_MUSICCLASS];
00765    /*!
00766     * \brief Sugggested music-on-hold class for peer channel to use for calls.
00767     * \note The "mohsuggest" string read in from chan_dahdi.conf
00768     */
00769    char mohsuggest[MAX_MUSICCLASS];
00770 #ifdef PRI_ANI
00771    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
00772    char cid_ani[AST_MAX_EXTENSION];
00773 #endif
00774    /*! \brief Caller ID number from an incoming call. */
00775    char cid_num[AST_MAX_EXTENSION];
00776    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
00777    int cid_ton;
00778    /*! \brief Caller ID name from an incoming call. */
00779    char cid_name[AST_MAX_EXTENSION];
00780    /*! \brief Last Caller ID number from an incoming call. */
00781    char lastcid_num[AST_MAX_EXTENSION];
00782    /*! \brief Last Caller ID name from an incoming call. */
00783    char lastcid_name[AST_MAX_EXTENSION];
00784    char *origcid_num;            /*!< malloced original callerid */
00785    char *origcid_name;           /*!< malloced original callerid */
00786    /*! \brief Call waiting number. */
00787    char callwait_num[AST_MAX_EXTENSION];
00788    /*! \brief Call waiting name. */
00789    char callwait_name[AST_MAX_EXTENSION];
00790    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
00791    char rdnis[AST_MAX_EXTENSION];
00792    /*! \brief Dialed Number Identifier */
00793    char dnid[AST_MAX_EXTENSION];
00794    /*!
00795     * \brief Bitmapped groups this belongs to.
00796     * \note The "group" bitmapped group string read in from chan_dahdi.conf
00797     */
00798    ast_group_t group;
00799    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
00800    int law;
00801    int confno;             /*!< Our conference */
00802    int confusers;             /*!< Who is using our conference */
00803    int propconfno;               /*!< Propagated conference number */
00804    /*!
00805     * \brief Bitmapped call groups this belongs to.
00806     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
00807     */
00808    ast_group_t callgroup;
00809    /*!
00810     * \brief Bitmapped pickup groups this belongs to.
00811     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
00812     */
00813    ast_group_t pickupgroup;
00814    int channel;               /*!< Channel Number or CRV */
00815    int span;               /*!< Span number */
00816    time_t guardtime;          /*!< Must wait this much time before using for new call */
00817    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
00818    int cid_start;             /*!< CID start indicator, polarity or ring or DTMF without warning event */
00819    int dtmfcid_holdoff_state;    /*!< State indicator that allows for line to settle before checking for dtmf energy */
00820    struct timeval dtmfcid_delay;  /*!< Time value used for allow line to settle */
00821    int callingpres;           /*!< The value of callling presentation that we're going to use when placing a PRI call */
00822    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
00823    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
00824    /*! \brief Analog caller ID waveform sample buffer */
00825    unsigned char *cidspill;
00826    /*! \brief Position in the cidspill buffer to send out next. */
00827    int cidpos;
00828    /*! \brief Length of the cidspill buffer containing samples. */
00829    int cidlen;
00830    /*! \brief Ring timeout timer?? */
00831    int ringt;
00832    /*!
00833     * \brief Ring timeout base.
00834     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
00835     */
00836    int ringt_base;
00837    /*!
00838     * \brief Number of most significant digits/characters to strip from the dialed number.
00839     * \note Feature is deprecated.  Use dialplan logic.
00840     * \note The characters are stripped before the PRI TON/NPI prefix
00841     * characters are processed.
00842     */
00843    int stripmsd;
00844    /*! \brief BOOLEAN. XXX Meaning what?? */
00845    int callwaitcas;
00846    /*! \brief Number of call waiting rings. */
00847    int callwaitrings;
00848    /*! \brief Number of echo cancel taps.  0 if echo canceller not requested. */
00849    int echocancel;
00850    /*!
00851     * \brief Echo training time. 0 = disabled
00852     * \note Set from the "echotraining" value read in from chan_dahdi.conf
00853     */
00854    int echotraining;
00855    /*! \brief Filled with 'w'.  XXX Purpose?? */
00856    char echorest[20];
00857    /*!
00858     * \brief Number of times to see "busy" tone before hanging up.
00859     * \note Set from the "busycount" value read in from chan_dahdi.conf
00860     */
00861    int busycount;
00862    /*!
00863     * \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
00864     * \note Set from the "busycompare" value read in from chan_dahdi.conf
00865     */
00866    int busycompare;
00867    /*!
00868     * \brief Lenght of "tone" in ms.
00869     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00870     */
00871    int busytonelength;
00872    /*!
00873     * \brief Lenght of "silence" in ms.
00874     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00875     */
00876    int busyquietlength;
00877    /*!
00878     * \brief  Maximun percentage difference allowed between measured and actual pattern
00879     * \note Set from the "busyfuzziness" value read in from chan_dahdi.conf
00880     */
00881    int busyfuzziness;
00882    /*!
00883     * \brief Maximun signal average level considered as silence in this channel
00884     * \note Set from the "silencethreshold" value read in from chan_dahdi.conf
00885     */
00886    int silencethreshold;
00887    /*!
00888     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
00889     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
00890     */
00891    int callprogress;
00892    struct timeval flashtime;        /*!< Last flash-hook time */
00893    /*! \brief Opaque DSP configuration structure. */
00894    struct ast_dsp *dsp;
00895    //int cref;             /*!< Call reference number (Not used) */
00896    /*! \brief DAHDI dial operation command struct for ioctl() call. */
00897    struct dahdi_dialoperation dop;
00898    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
00899    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
00900    char finaldial[64];
00901    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
00902    int amaflags;              /*!< AMA Flags */
00903    struct tdd_state *tdd;           /*!< TDD flag */
00904    /*! \brief Accumulated call forwarding number. */
00905    char call_forward[AST_MAX_EXTENSION];
00906    /*!
00907     * \brief Voice mailbox location.
00908     * \note Set from the "mailbox" string read in from chan_dahdi.conf
00909     */
00910    char mailbox[AST_MAX_EXTENSION];
00911    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
00912    char dialdest[256];
00913    /*! \brief Time the interface went on-hook. */
00914    int onhooktime;
00915    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
00916    int msgstate;
00917    int distinctivering;          /*!< Which distinctivering to use */
00918    int cidrings;              /*!< Which ring to deliver CID on */
00919    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
00920    /*! \brief Holding place for event injected from outside normal operation. */
00921    int fake_event;
00922    /*!
00923     * \brief Minimal time period (ms) between the answer polarity
00924     * switch and hangup polarity switch.
00925     */
00926    int polarityonanswerdelay;
00927    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
00928    struct timeval polaritydelaytv;
00929    /*!
00930     * \brief Send caller ID after this many rings.
00931     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
00932     */
00933    int sendcalleridafter;
00934 #ifdef HAVE_PRI
00935    /*! \brief DAHDI PRI control parameters */
00936    struct dahdi_pri *pri;
00937    /*! \brief XXX Purpose??? */
00938    struct dahdi_pvt *bearer;
00939    /*! \brief XXX Purpose??? */
00940    struct dahdi_pvt *realcall;
00941    /*! \brief Opaque libpri call control structure */
00942    q931_call *call;
00943    /*! \brief Channel number in span. */
00944    int prioffset;
00945    /*! \brief Logical span number within trunk group */
00946    int logicalspan;
00947 #endif   
00948 #ifdef HAVE_OPENR2
00949    int mfcr2call;
00950    int mfcr2block;
00951    struct dahdi_mfcr2 *mfcr2;
00952    openr2_chan_t *r2chan;
00953    openr2_calling_party_category_t mfcr2_recvd_category;
00954    openr2_calling_party_category_t mfcr2_category;
00955    int mfcr2_accept_on_offer;
00956    int mfcr2_charge_calls;
00957    int mfcr2_allow_collect_calls;
00958    int mfcr2_forced_release;
00959    int mfcr2_dnis_index;
00960    int mfcr2_ani_index;
00961    int mfcr2_dnis_matched;
00962    int mfcr2_call_accepted;
00963 #endif
00964    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
00965    int polarity;
00966    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
00967    int dsp_features;
00968    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
00969    char begindigit;
00970 } *iflist = NULL, *ifend = NULL;
00971 
00972 /*! \brief Channel configuration from chan_dahdi.conf .
00973  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
00974  * Generally there is a field here for every possible configuration item.
00975  *
00976  * The state of fields is saved along the parsing and whenever a 'channel'
00977  * statement is reached, the current dahdi_chan_conf is used to configure the 
00978  * channel (struct dahdi_pvt)
00979  *
00980  * @seealso dahdi_chan_init for the default values.
00981  */
00982 struct dahdi_chan_conf {
00983    struct dahdi_pvt chan;
00984 #ifdef HAVE_PRI
00985    struct dahdi_pri pri;
00986 #endif
00987    struct dahdi_params timing;
00988 
00989    /*!
00990     * \brief The serial port to listen for SMDI data on
00991     * \note Set from the "smdiport" string read in from chan_dahdi.conf
00992     */
00993    char smdi_port[SMDI_MAX_FILENAME_LEN];
00994 };
00995 
00996 /** returns a new dahdi_chan_conf with default values (by-value) */
00997 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00998    /* recall that if a field is not included here it is initialized
00999     * to 0 or equivalent
01000     */
01001    struct dahdi_chan_conf conf = {
01002 #ifdef HAVE_PRI
01003       .pri = {
01004          .nsf = PRI_NSF_NONE,
01005          .switchtype = PRI_SWITCH_NI2,
01006          .dialplan = PRI_NATIONAL_ISDN + 1,
01007          .localdialplan = PRI_NATIONAL_ISDN + 1,
01008          .nodetype = PRI_CPE,
01009 
01010          .minunused = 2,
01011          .idleext = "",
01012          .idledial = "",
01013          .internationalprefix = "",
01014          .nationalprefix = "",
01015          .localprefix = "",
01016          .privateprefix = "",
01017          .unknownprefix = "",
01018 
01019          .resetinterval = 3600
01020       },
01021 #endif
01022       .chan = {
01023          .context = "default",
01024          .cid_num = "",
01025          .cid_name = "",
01026          .mohinterpret = "default",
01027          .mohsuggest = "",
01028          .transfertobusy = 1,
01029 
01030          .cid_signalling = CID_SIG_BELL,
01031          .cid_start = CID_START_RING,
01032          .dahditrcallerid = 0,
01033          .use_callerid = 1,
01034          .sig = -1,
01035          .outsigmod = -1,
01036 
01037          .tonezone = -1,
01038 
01039          .echocancel = 1,
01040 
01041          .busycount = 3,
01042          .busycompare = 0,
01043          .busytonelength = 0,
01044          .busyquietlength = 0,
01045          .busyfuzziness = 0,
01046          .silencethreshold = 0,
01047 
01048          .accountcode = "",
01049 
01050          .mailbox = "",
01051 
01052 
01053          .polarityonanswerdelay = 600,
01054 
01055          .sendcalleridafter = DEFAULT_CIDRINGS,
01056 
01057          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01058          .buf_no = numbufs
01059       },
01060       .timing = {
01061          .prewinktime = -1,
01062          .preflashtime = -1,
01063          .winktime = -1,
01064          .flashtime = -1,
01065          .starttime = -1,
01066          .rxwinktime = -1,
01067          .rxflashtime = -1,
01068          .debouncetime = -1
01069       },
01070       .smdi_port = "/dev/ttyS0",
01071    };
01072 
01073    return conf;
01074 }
01075 
01076 
01077 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01078 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01079 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01080 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01081 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01082 static int dahdi_hangup(struct ast_channel *ast);
01083 static int dahdi_answer(struct ast_channel *ast);
01084 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01085 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01086 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01087 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01088 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01089 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01090 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
01091 
01092 static const struct ast_channel_tech dahdi_tech = {
01093    .type = "DAHDI",
01094    .description = tdesc,
01095    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01096    .requester = dahdi_request,
01097    .send_digit_begin = dahdi_digit_begin,
01098    .send_digit_end = dahdi_digit_end,
01099    .send_text = dahdi_sendtext,
01100    .call = dahdi_call,
01101    .hangup = dahdi_hangup,
01102    .answer = dahdi_answer,
01103    .read = dahdi_read,
01104    .write = dahdi_write,
01105    .bridge = dahdi_bridge,
01106    .exception = dahdi_exception,
01107    .indicate = dahdi_indicate,
01108    .fixup = dahdi_fixup,
01109    .setoption = dahdi_setoption,
01110    .func_channel_read = dahdi_func_read,
01111 };
01112 
01113 static const struct ast_channel_tech zap_tech = {
01114    .type = "Zap",
01115    .description = tdesc,
01116    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01117    .requester = dahdi_request,
01118    .send_digit_begin = dahdi_digit_begin,
01119    .send_digit_end = dahdi_digit_end,
01120    .send_text = dahdi_sendtext,
01121    .call = dahdi_call,
01122    .hangup = dahdi_hangup,
01123    .answer = dahdi_answer,
01124    .read = dahdi_read,
01125    .write = dahdi_write,
01126    .bridge = dahdi_bridge,
01127    .exception = dahdi_exception,
01128    .indicate = dahdi_indicate,
01129    .fixup = dahdi_fixup,
01130    .setoption = dahdi_setoption,
01131    .func_channel_read = dahdi_func_read,
01132 };
01133 
01134 static const struct ast_channel_tech *chan_tech;
01135 
01136 #ifdef HAVE_PRI
01137 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01138 #else
01139 #define GET_CHANNEL(p) ((p)->channel)
01140 #endif
01141 
01142 struct dahdi_pvt *round_robin[32];
01143 
01144 #ifdef HAVE_PRI
01145 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01146 {
01147    int res;
01148    /* Grab the lock first */
01149    do {
01150       res = ast_mutex_trylock(&pri->lock);
01151       if (res) {
01152          DEADLOCK_AVOIDANCE(&pvt->lock);
01153       }
01154    } while (res);
01155    /* Then break the poll */
01156    if (pri->master != AST_PTHREADT_NULL)
01157       pthread_kill(pri->master, SIGURG);
01158    return 0;
01159 }
01160 #endif
01161 
01162 #define NUM_CADENCE_MAX 25
01163 static int num_cadence = 4;
01164 static int user_has_defined_cadences = 0;
01165 
01166 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01167    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01168    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01169    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01170    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01171 };
01172 
01173 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01174  * is 1, the second pause is 2 and so on.
01175  */
01176 
01177 static int cidrings[NUM_CADENCE_MAX] = {
01178    2,                            /*!< Right after first long ring */
01179    4,                            /*!< Right after long part */
01180    3,                            /*!< After third chirp */
01181    2,                            /*!< Second spell */
01182 };
01183 
01184 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01185          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01186 
01187 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01188 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01189 
01190 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01191 {
01192    int res;
01193    if (p->subs[SUB_REAL].owner == ast)
01194       res = 0;
01195    else if (p->subs[SUB_CALLWAIT].owner == ast)
01196       res = 1;
01197    else if (p->subs[SUB_THREEWAY].owner == ast)
01198       res = 2;
01199    else {
01200       res = -1;
01201       if (!nullok)
01202          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01203    }
01204    return res;
01205 }
01206 
01207 #ifdef HAVE_PRI
01208 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01209 #else
01210 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01211 #endif
01212 {
01213 #ifdef HAVE_PRI
01214    if (pri)
01215       ast_mutex_unlock(&pri->lock);
01216 #endif         
01217    for (;;) {
01218       if (p->subs[a].owner) {
01219          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01220             DEADLOCK_AVOIDANCE(&p->lock);
01221          } else {
01222             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01223             ast_mutex_unlock(&p->subs[a].owner->lock);
01224             break;
01225          }
01226       } else
01227          break;
01228    }
01229 #ifdef HAVE_PRI
01230    if (pri)
01231       ast_mutex_lock(&pri->lock);
01232 #endif         
01233 }
01234 
01235 #ifdef HAVE_PRI
01236 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
01237 #else
01238 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
01239 #endif
01240 {
01241    /* We must unlock the PRI to avoid the possibility of a deadlock */
01242 #ifdef HAVE_PRI
01243    if (pri)
01244       ast_mutex_unlock(&pri->lock);
01245 #endif      
01246    for (;;) {
01247       if (p->owner) {
01248          if (ast_mutex_trylock(&p->owner->lock)) {
01249             DEADLOCK_AVOIDANCE(&p->lock);
01250          } else {
01251             ast_queue_frame(p->owner, f);
01252             ast_mutex_unlock(&p->owner->lock);
01253             break;
01254          }
01255       } else
01256          break;
01257    }
01258 #ifdef HAVE_PRI
01259    if (pri)
01260       ast_mutex_lock(&pri->lock);
01261 #endif      
01262 }
01263 
01264 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability);
01265 #ifdef HAVE_OPENR2
01266 static void init_mfcr2_globals(void)
01267 {
01268    int r;
01269    mfcr2_cur_context_index = 0;
01270    mfcr2_cur_variant = OR2_VAR_UNKNOWN;
01271    mfcr2_cur_mfback_timeout = -1;
01272    mfcr2_cur_metering_pulse_timeout = -1;
01273    mfcr2_cur_max_ani = 10;
01274    mfcr2_cur_max_dnis = 4;
01275    mfcr2_cur_get_ani_first = -1;
01276 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01277    mfcr2_cur_dtmf_dialing = -1;
01278    mfcr2_cur_dtmf_detection = -1;
01279    mfcr2_cur_dtmf_time_on = OR2_DEFAULT_DTMF_ON;
01280    mfcr2_cur_dtmf_time_off = OR2_DEFAULT_DTMF_OFF;
01281 #endif
01282    mfcr2_cur_skip_category = -1;
01283    mfcr2_cur_call_files = 0;
01284    mfcr2_cur_allow_collect_calls = 0;
01285    mfcr2_cur_forced_release = 0;
01286    mfcr2_cur_double_answer = 0;
01287    mfcr2_cur_immediate_accept = -1;
01288    mfcr2_cur_loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING;
01289    mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
01290    memset(mfcr2_cur_logdir, 0, sizeof(mfcr2_cur_logdir));
01291    memset(mfcr2_cur_r2proto_file, 0, sizeof(mfcr2_cur_r2proto_file));
01292    memset(r2links, 0, sizeof(r2links));
01293    for (r = 0; r < NUM_SPANS; r++) {
01294       r2links[r].master = AST_PTHREADT_NULL;
01295    }
01296 }
01297 
01298 static int dahdi_r2_answer(struct dahdi_pvt *p)
01299 {
01300    int res = 0;
01301    /* openr2 1.1.0 and older does not even define OR2_LIB_INTERFACE
01302     * and does not has support for openr2_chan_answer_call_with_mode
01303     *  */
01304 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01305    const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
01306    int wants_double_answer = ast_true(double_answer) ? 1 : 0;
01307    if (!double_answer) {
01308       /* this still can result in double answer if the channel context 
01309        * was configured that way */
01310       res = openr2_chan_answer_call(p->r2chan);
01311    } else if (wants_double_answer) {
01312       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
01313    } else {
01314       res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
01315    } 
01316 #else
01317    res = openr2_chan_answer_call(p->r2chan);
01318 #endif
01319    return res;
01320 }
01321 
01322 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
01323 {
01324    openr2_calling_party_category_t cat;
01325    const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
01326    struct dahdi_pvt *p = c->tech_pvt;
01327    if (ast_strlen_zero(catstr)) {
01328       ast_log(LOG_DEBUG, "no MFC/R2 category specified for chan %s, using default %s\n", 
01329             c->name, openr2_proto_get_category_string(p->mfcr2_category));
01330       return p->mfcr2_category;
01331    }
01332    if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
01333       ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
01334             catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
01335       return p->mfcr2_category;
01336    }
01337    ast_log(LOG_DEBUG, "Using category %s\n", catstr);
01338    return cat;
01339 }
01340 
01341 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
01342 {
01343    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01344    ast_mutex_lock(&p->lock);
01345    if (p->mfcr2call) {
01346       ast_mutex_unlock(&p->lock);
01347       /* TODO: This can happen when some other thread just finished zt_request requesting this very same
01348       interface but has not yet seized the line (zt_call), and the far end wins and seize the line,
01349       can we avoid this somehow?, at this point when zt_call send the seize, it is likely that since
01350       the other end will see our seize as a forced release and drop the call, we will see an invalid
01351       pattern that will be seen and treated as protocol error. */
01352       ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
01353       return;
01354    }
01355    p->mfcr2call = 1;
01356    /* better safe than sorry ... */
01357    p->cid_name[0] = 0;
01358    p->cid_num[0] = 0;
01359    p->rdnis[0] = 0;
01360    p->exten[0] = 0;
01361    p->mfcr2_ani_index = 0;
01362    p->mfcr2_dnis_index = 0;
01363    p->mfcr2_dnis_matched = 0;
01364    p->mfcr2_call_accepted = 0;
01365    ast_mutex_unlock(&p->lock);
01366    ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
01367 }
01368 
01369 static void handle_alarms(struct dahdi_pvt *p, int alarms);
01370 static int get_alarms(struct dahdi_pvt *p);
01371 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
01372 {
01373    int res;
01374    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01375    ast_mutex_lock(&p->lock);
01376    p->inalarm = alarm ? 1 : 0;
01377    if (p->inalarm) {
01378       res = get_alarms(p);
01379       /* unknown_alarm may be set here */
01380       handle_alarms(p, res);
01381    } else {
01382       if (!p->unknown_alarm) {
01383          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
01384          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
01385       } else {
01386          p->unknown_alarm = 0;
01387       }
01388    }
01389    ast_mutex_unlock(&p->lock);
01390    ast_log(LOG_WARNING, "Zap alarm on chan %d.\n", openr2_chan_get_number(r2chan));
01391 }
01392 
01393 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
01394 {
01395    ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
01396 }
01397 
01398 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
01399 {
01400    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01401    ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
01402    if (p->owner) {
01403       p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
01404       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01405    } 
01406    ast_mutex_lock(&p->lock);
01407    p->mfcr2call = 0;
01408    ast_mutex_unlock(&p->lock);
01409 }
01410 
01411 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
01412 {
01413    if (openr2_chan_disconnect_call(p->r2chan, cause)) {
01414       ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n", 
01415             p->channel, openr2_proto_get_disconnect_string(cause));
01416       /* force the chan to idle and release the call flag now since we will not see a clean on_call_end */
01417       openr2_chan_set_idle(p->r2chan);
01418       ast_mutex_lock(&p->lock);
01419       p->mfcr2call = 0;
01420       ast_mutex_unlock(&p->lock);
01421    }
01422 }
01423 
01424 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
01425 {
01426    struct dahdi_pvt *p;
01427    struct ast_channel *c;
01428    ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n", 
01429          openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis, openr2_proto_get_category_string(category));
01430    p = openr2_chan_get_client_data(r2chan);
01431    if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
01432       ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call on chan %d\n", p->channel);
01433       dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
01434       return;
01435    }
01436    ast_mutex_lock(&p->lock);
01437    p->mfcr2_recvd_category = category;
01438    /* if we're not supposed to use CID, clear whatever we have */
01439    if (!p->use_callerid) {
01440       ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
01441       p->cid_num[0] = 0;
01442       p->cid_name[0] = 0;
01443    }
01444    /* if we're supposed to answer immediately, clear DNIS and set 's' exten */
01445    if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
01446       ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
01447       p->exten[0] = 's';
01448       p->exten[1] = 0;
01449    }
01450    ast_mutex_unlock(&p->lock);
01451    if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01452       ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
01453             p->channel, p->exten, p->context);
01454       dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
01455    } else {
01456       /* if the user does not want to accept on offer, then we should launch the PBX thread now */
01457       if (!p->mfcr2_accept_on_offer) {
01458          c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01459          if (!c) {
01460             ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01461             dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01462          }
01463          /* Don't disable reading since we still need to generate MF tone to accept
01464             the call or reject it and detect the tone off condition of the other end */
01465       } else if (p->mfcr2_charge_calls) {
01466          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with charge on chan %d\n", p->channel);
01467          openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
01468       } else {
01469          ast_log(LOG_DEBUG, "Accepting MFC/R2 call on offer with no charge on chan %d\n", p->channel);
01470          openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
01471       }  
01472    }  
01473 }
01474 
01475 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
01476 {
01477    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01478    ast_verbose("MFC/R2 call end on chan %d\n", p->channel);
01479    ast_mutex_lock(&p->lock);
01480    p->mfcr2call = 0;
01481    ast_mutex_unlock(&p->lock);
01482 }
01483 
01484 static void dahdi_enable_ec(struct dahdi_pvt *p);
01485 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
01486 {
01487    struct dahdi_pvt *p = NULL;
01488    struct ast_channel *c = NULL;
01489    p = openr2_chan_get_client_data(r2chan);
01490    dahdi_enable_ec(p);
01491    p->mfcr2_call_accepted = 1;
01492    if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
01493       ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
01494       /* if accept on offer is not set, it means at this point the PBX thread is already
01495          launched and therefore this callback is being executed in the PBX thread rather than
01496          the monitor thread, don't launch any other thread, just disable the R2 reading and
01497          answer the call */
01498       if (!p->mfcr2_accept_on_offer) {
01499          openr2_chan_disable_read(r2chan);
01500          ast_verbose("Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
01501          dahdi_r2_answer(p);
01502          return;
01503       }
01504       c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, 0);
01505       if (c) {
01506          /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01507          openr2_chan_disable_read(r2chan);
01508       } else {
01509          ast_log(LOG_ERROR, "Unable to create PBX channel on chan %d\n", p->channel);
01510          dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
01511          return;
01512       }
01513    } else {
01514       ast_verbose("Call accepted on forward channel %d\n", p->channel);
01515       p->subs[SUB_REAL].needringing = 1;
01516       p->dialing = 0;
01517       /* chan_dahdi will take care of reading from now on, tell the library to forget about it */
01518       openr2_chan_disable_read(r2chan);
01519    }  
01520 }
01521 
01522 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
01523 {
01524    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01525    ast_verbose("MFC/R2 call has been answered on chan %d\n", openr2_chan_get_number(r2chan));
01526    p->subs[SUB_REAL].needanswer = 1;
01527 }
01528 
01529 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
01530 {
01531    /*ast_log(LOG_DEBUG, "Read data from dahdi channel %d\n", openr2_chan_get_number(r2chan));*/
01532 }
01533 
01534 /*static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
01535 {
01536    switch (cause) {
01537    case OR2_CAUSE_BUSY_NUMBER:
01538       return AST_CAUSE_BUSY;
01539    case OR2_CAUSE_NETWORK_CONGESTION:
01540       return AST_CAUSE_CONGESTION;
01541    case OR2_CAUSE_OUT_OF_ORDER:
01542       return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01543    case OR2_CAUSE_UNALLOCATED_NUMBER:
01544       return AST_CAUSE_UNREGISTERED;
01545    case OR2_CAUSE_NO_ANSWER:
01546       return AST_CAUSE_NO_ANSWER;
01547    case OR2_CAUSE_NORMAL_CLEARING:
01548       return AST_CAUSE_NORMAL_CLEARING;
01549    case OR2_CAUSE_UNSPECIFIED:
01550    default:
01551       return AST_CAUSE_NOTDEFINED;
01552    }  
01553 }*/
01554 
01555 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
01556 {
01557    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01558    ast_verbose("MFC/R2 call disconnected on chan %d\n", openr2_chan_get_number(r2chan));
01559    ast_mutex_lock(&p->lock);
01560    if (p->owner) {
01561       /* when we have an owner we don't call openr2_chan_disconnect_call here, that will
01562          be done in zt_hangup */
01563       if (p->owner->_state == AST_STATE_UP) {
01564          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01565          ast_mutex_unlock(&p->lock);
01566       } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
01567          /* being the forward side we must report what happened to the call to whoever requested it */
01568          switch (cause) {
01569          case OR2_CAUSE_BUSY_NUMBER:
01570             p->owner->hangupcause = AST_CAUSE_BUSY;
01571             p->subs[SUB_REAL].needbusy = 1;
01572             break;
01573          case OR2_CAUSE_NUMBER_CHANGED:
01574             p->owner->hangupcause = AST_CAUSE_NUMBER_CHANGED;
01575             p->subs[SUB_REAL].needcongestion = 1;
01576             break;
01577          case OR2_CAUSE_NETWORK_CONGESTION:
01578             p->owner->hangupcause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
01579             p->subs[SUB_REAL].needcongestion = 1;
01580             break;
01581          case OR2_CAUSE_OUT_OF_ORDER:
01582             p->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01583             p->subs[SUB_REAL].needcongestion = 1;
01584             break;
01585          case OR2_CAUSE_UNALLOCATED_NUMBER:
01586             p->owner->hangupcause = AST_CAUSE_UNALLOCATED;
01587             p->subs[SUB_REAL].needcongestion = 1;
01588             break;
01589          case OR2_CAUSE_NO_ANSWER:
01590             p->owner->hangupcause = AST_CAUSE_NO_ANSWER;
01591             p->subs[SUB_REAL].needcongestion = 1;
01592             break;
01593          case OR2_CAUSE_UNSPECIFIED:
01594             p->owner->hangupcause = AST_CAUSE_NOTDEFINED;
01595             p->subs[SUB_REAL].needcongestion = 1;
01596             break;
01597          case OR2_CAUSE_NORMAL_CLEARING:
01598             p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING;
01599             p->subs[SUB_REAL].needcongestion = 1;
01600             break;
01601          default:
01602             ast_log(LOG_WARNING, "Unhandled cause %d\n", cause);
01603          }
01604          p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
01605          ast_mutex_unlock(&p->lock);
01606       } else {
01607          ast_mutex_unlock(&p->lock);
01608          /* being the backward side and not UP yet, we only need to request hangup */
01609          /* TODO: what about doing this same thing when were AST_STATE_UP? */
01610          ast_queue_hangup(p->owner);
01611       }  
01612    } else {
01613       ast_mutex_unlock(&p->lock);
01614       /* no owner, therefore we can't use zt_hangup to disconnect, do it right now */
01615       dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
01616    }
01617 }
01618 
01619 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
01620 {
01621    switch (level) {
01622    case OR2_LOG_NOTICE:
01623       ast_verbose("%s", logmessage);
01624       break;
01625    case OR2_LOG_WARNING:
01626       ast_log(LOG_WARNING, "%s", logmessage);
01627       break;
01628    case OR2_LOG_ERROR:
01629       ast_log(LOG_ERROR, "%s", logmessage);
01630       break;
01631    case OR2_LOG_STACK_TRACE:
01632    case OR2_LOG_MF_TRACE:
01633    case OR2_LOG_CAS_TRACE:
01634    case OR2_LOG_DEBUG:
01635    case OR2_LOG_EX_DEBUG:
01636       ast_log(LOG_DEBUG, "%s", logmessage);
01637       break;
01638    default:
01639       ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
01640       ast_log(LOG_NOTICE, "%s", logmessage);
01641       break;
01642    }
01643 }
01644 
01645 #define DAHDI_R2_REMOTE_BLOCK (1 << 0)
01646 #define DAHDI_R2_LOCAL_BLOCK (1 << 1)
01647 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
01648 {
01649    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01650    ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", p->channel);
01651    ast_mutex_lock(&p->lock);
01652    p->mfcr2block |= DAHDI_R2_REMOTE_BLOCK;
01653    ast_mutex_unlock(&p->lock);
01654 }
01655 
01656 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
01657 {
01658    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01659    ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
01660    ast_mutex_lock(&p->lock);
01661    p->mfcr2block &= ~DAHDI_R2_REMOTE_BLOCK;
01662    ast_mutex_unlock(&p->lock);
01663 }
01664 
01665 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01666    __attribute__((format (printf, 3, 0)));
01667 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
01668 {
01669    char logmsg[256];
01670    char completemsg[sizeof(logmsg)+50];
01671    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01672    snprintf(completemsg, sizeof(completemsg), "Context - %s", logmsg);
01673    dahdi_r2_write_log(level, completemsg);
01674 }
01675 
01676 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01677    __attribute__((format (printf, 3, 0)));
01678 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
01679 {
01680    char logmsg[256];
01681    char completemsg[sizeof(logmsg)+50];
01682    vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
01683    snprintf(completemsg, sizeof(completemsg), "Chan %d - %s", openr2_chan_get_number(r2chan), logmsg);
01684    dahdi_r2_write_log(level, completemsg);
01685 }
01686 
01687 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
01688 {
01689    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01690    /* if 'immediate' is set, let's stop requesting DNIS */
01691    if (p->immediate) {
01692       return 0;
01693    }
01694    p->exten[p->mfcr2_dnis_index] = digit;
01695    p->rdnis[p->mfcr2_dnis_index] = digit;
01696    p->mfcr2_dnis_index++;
01697    p->exten[p->mfcr2_dnis_index] = 0;
01698    p->rdnis[p->mfcr2_dnis_index] = 0;
01699    /*
01700    ast_log(LOG_DEBUG, "Got digit %c in dahdi, dnis so far: %s\n", digit, p->exten);
01701    int ret;
01702    ret = ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num);
01703    ast_log(LOG_DEBUG, "ast_exists_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01704    ret = ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num);
01705    ast_log(LOG_DEBUG, "ast_matchmore_extension(%s, %s, 1, %s) = %d\n", p->context, p->exten, p->cid_num, ret);
01706    */
01707    /* if the DNIS is a match and cannot match more, stop requesting DNIS */
01708    if ((p->mfcr2_dnis_matched || 
01709        (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
01710        !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
01711       return 0;
01712    }
01713    /* otherwise keep going */
01714    return 1;
01715 }
01716 
01717 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
01718 {
01719    struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
01720    p->cid_num[p->mfcr2_ani_index] = digit;
01721    p->cid_name[p->mfcr2_ani_index] = digit;
01722    p->mfcr2_ani_index++;
01723    p->cid_num[p->mfcr2_ani_index] = 0;
01724    p->cid_name[p->mfcr2_ani_index] = 0;
01725 }
01726 
01727 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
01728 {
01729    ast_log(LOG_NOTICE, "MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
01730 }
01731 
01732 static openr2_event_interface_t dahdi_r2_event_iface = {
01733    .on_call_init = dahdi_r2_on_call_init,
01734    .on_call_offered = dahdi_r2_on_call_offered,
01735    .on_call_accepted = dahdi_r2_on_call_accepted,
01736    .on_call_answered = dahdi_r2_on_call_answered,
01737    .on_call_disconnect = dahdi_r2_on_call_disconnect,
01738    .on_call_end = dahdi_r2_on_call_end,
01739    .on_call_read = dahdi_r2_on_call_read,
01740    .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
01741    .on_os_error = dahdi_r2_on_os_error,
01742    .on_protocol_error = dahdi_r2_on_protocol_error,
01743    .on_line_blocked = dahdi_r2_on_line_blocked,
01744    .on_line_idle = dahdi_r2_on_line_idle,
01745    /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
01746    .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
01747    .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
01748    .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
01749    /* so far we do nothing with billing pulses, just log it */
01750    .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received 
01751 };
01752 
01753 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
01754 {
01755    return AST_ALAW(sample);
01756 }
01757 
01758 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
01759 {
01760    return AST_LIN2A(sample);
01761 }
01762 
01763 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
01764    dahdi_r2_alaw_to_linear,
01765    dahdi_r2_linear_to_alaw
01766 };
01767 
01768 #endif /* HAVE_OPENR2 */
01769 
01770 static int restore_gains(struct dahdi_pvt *p);
01771 
01772 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01773 {
01774    int tchan;
01775    int tinthreeway;
01776    struct ast_channel *towner;
01777 
01778    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01779 
01780    tchan = p->subs[a].chan;
01781    towner = p->subs[a].owner;
01782    tinthreeway = p->subs[a].inthreeway;
01783 
01784    p->subs[a].chan = p->subs[b].chan;
01785    p->subs[a].owner = p->subs[b].owner;
01786    p->subs[a].inthreeway = p->subs[b].inthreeway;
01787 
01788    p->subs[b].chan = tchan;
01789    p->subs[b].owner = towner;
01790    p->subs[b].inthreeway = tinthreeway;
01791 
01792    if (p->subs[a].owner) 
01793       p->subs[a].owner->fds[0] = p->subs[a].dfd;
01794    if (p->subs[b].owner) 
01795       p->subs[b].owner->fds[0] = p->subs[b].dfd;
01796    wakeup_sub(p, a, NULL);
01797    wakeup_sub(p, b, NULL);
01798 }
01799 
01800 static int dahdi_open(char *fn)
01801 {
01802    int fd;
01803    int isnum;
01804    int chan = 0;
01805    int bs;
01806    int x;
01807    isnum = 1;
01808    for (x = 0; x < strlen(fn); x++) {
01809       if (!isdigit(fn[x])) {
01810          isnum = 0;
01811          break;
01812       }
01813    }
01814    if (isnum) {
01815       chan = atoi(fn);
01816       if (chan < 1) {
01817          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01818          return -1;
01819       }
01820       fn = DAHDI_FILE_CHANNEL;
01821    }
01822    fd = open(fn, O_RDWR | O_NONBLOCK);
01823    if (fd < 0) {
01824       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01825       return -1;
01826    }
01827    if (chan) {
01828       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01829          x = errno;
01830          close(fd);
01831          errno = x;
01832          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01833          return -1;
01834       }
01835    }
01836    bs = READ_SIZE;
01837    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01838       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01839       x = errno;
01840       close(fd);
01841       errno = x;
01842       return -1;
01843    }
01844    return fd;
01845 }
01846 
01847 static void dahdi_close(int fd)
01848 {
01849    if (fd > 0)
01850       close(fd);
01851 }
01852 
01853 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01854 {
01855    dahdi_close(chan_pvt->subs[sub_num].dfd);
01856    chan_pvt->subs[sub_num].dfd = -1;
01857 }
01858  
01859 #ifdef HAVE_PRI
01860 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01861 {
01862    dahdi_close(pri->fds[fd_num]);
01863    pri->fds[fd_num] = -1;
01864 }
01865 #endif
01866 
01867 static int dahdi_setlinear(int dfd, int linear)
01868 {
01869    int res;
01870    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01871    if (res)
01872       return res;
01873    return 0;
01874 }
01875 
01876 
01877 static int alloc_sub(struct dahdi_pvt *p, int x)
01878 {
01879    struct dahdi_bufferinfo bi;
01880    int res;
01881    if (p->subs[x].dfd < 0) {
01882       p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01883       if (p->subs[x].dfd > -1) {
01884          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01885          if (!res) {
01886             bi.txbufpolicy = p->buf_policy;
01887             bi.rxbufpolicy = p->buf_policy;
01888             bi.numbufs = p->buf_no;
01889             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01890             if (res < 0) {
01891                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01892             }
01893          } else 
01894             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01895          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01896             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01897             dahdi_close_sub(p, x);
01898             return -1;
01899          }
01900          if (option_debug)
01901             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01902          return 0;
01903       } else
01904          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01905       return -1;
01906    }
01907    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01908    return -1;
01909 }
01910 
01911 static int unalloc_sub(struct dahdi_pvt *p, int x)
01912 {
01913    if (!x) {
01914       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01915       return -1;
01916    }
01917    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01918    dahdi_close_sub(p, x);
01919    p->subs[x].linear = 0;
01920    p->subs[x].chan = 0;
01921    p->subs[x].owner = NULL;
01922    p->subs[x].inthreeway = 0;
01923    p->polarity = POLARITY_IDLE;
01924    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01925    return 0;
01926 }
01927 
01928 static int digit_to_dtmfindex(char digit)
01929 {
01930    if (isdigit(digit))
01931       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01932    else if (digit >= 'A' && digit <= 'D')
01933       return DAHDI_TONE_DTMF_A + (digit - 'A');
01934    else if (digit >= 'a' && digit <= 'd')
01935       return DAHDI_TONE_DTMF_A + (digit - 'a');
01936    else if (digit == '*')
01937       return DAHDI_TONE_DTMF_s;
01938    else if (digit == '#')
01939       return DAHDI_TONE_DTMF_p;
01940    else
01941       return -1;
01942 }
01943 
01944 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01945 {
01946    struct dahdi_pvt *pvt;
01947    int index;
01948    int dtmf = -1;
01949    
01950    pvt = chan->tech_pvt;
01951 
01952    ast_mutex_lock(&pvt->lock);
01953 
01954    index = dahdi_get_index(chan, pvt, 0);
01955 
01956    if ((index != SUB_REAL) || !pvt->owner)
01957       goto out;
01958 
01959 #ifdef HAVE_PRI
01960    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01961       if (pvt->setup_ack) {
01962          if (!pri_grab(pvt, pvt->pri)) {
01963             pri_information(pvt->pri->pri, pvt->call, digit);
01964             pri_rel(pvt->pri);
01965          } else
01966             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01967       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01968          int res;
01969          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01970          res = strlen(pvt->dialdest);
01971          pvt->dialdest[res++] = digit;
01972          pvt->dialdest[res] = '\0';
01973       }
01974       goto out;
01975    }
01976 #endif
01977    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01978       goto out;
01979 
01980    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01981       int res;
01982       struct dahdi_dialoperation zo = {
01983          .op = DAHDI_DIAL_OP_APPEND,
01984          .dialstr[0] = 'T',
01985          .dialstr[1] = digit,
01986          .dialstr[2] = 0,
01987       };
01988       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01989          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01990       else
01991          pvt->dialing = 1;
01992    } else {
01993       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01994       pvt->dialing = 1;
01995       pvt->begindigit = digit;
01996    }
01997 
01998 out:
01999    ast_mutex_unlock(&pvt->lock);
02000 
02001    return 0;
02002 }
02003 
02004 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
02005 {
02006    struct dahdi_pvt *pvt;
02007    int res = 0;
02008    int index;
02009    int x;
02010    
02011    pvt = chan->tech_pvt;
02012 
02013    ast_mutex_lock(&pvt->lock);
02014    
02015    index = dahdi_get_index(chan, pvt, 0);
02016 
02017    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
02018       goto out;
02019 
02020 #ifdef HAVE_PRI
02021    /* This means that the digit was already sent via PRI signalling */
02022    if (pvt->sig == SIG_PRI && !pvt->begindigit)
02023       goto out;
02024 #endif
02025 
02026    if (pvt->begindigit) {
02027       x = -1;
02028       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
02029       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02030       pvt->dialing = 0;
02031       pvt->begindigit = 0;
02032    }
02033 
02034 out:
02035    ast_mutex_unlock(&pvt->lock);
02036 
02037    return res;
02038 }
02039 
02040 static char *events[] = {
02041    "No event",
02042    "On hook",
02043    "Ring/Answered",
02044    "Wink/Flash",
02045    "Alarm",
02046    "No more alarm",
02047    "HDLC Abort",
02048    "HDLC Overrun",
02049    "HDLC Bad FCS",
02050    "Dial Complete",
02051    "Ringer On",
02052    "Ringer Off",
02053    "Hook Transition Complete",
02054    "Bits Changed",
02055    "Pulse Start",
02056    "Timer Expired",
02057    "Timer Ping",
02058    "Polarity Reversal",
02059    "Ring Begin",
02060 };
02061 
02062 static struct {
02063    int alarm;
02064    char *name;
02065 } alarms[] = {
02066    { DAHDI_ALARM_RED, "Red Alarm" },
02067    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
02068    { DAHDI_ALARM_BLUE, "Blue Alarm" },
02069    { DAHDI_ALARM_RECOVER, "Recovering" },
02070    { DAHDI_ALARM_LOOPBACK, "Loopback" },
02071    { DAHDI_ALARM_NOTOPEN, "Not Open" },
02072    { DAHDI_ALARM_NONE, "None" },
02073 };
02074 
02075 static char *alarm2str(int alarm)
02076 {
02077    int x;
02078    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
02079       if (alarms[x].alarm & alarm)
02080          return alarms[x].name;
02081    }
02082    return alarm ? "Unknown Alarm" : "No Alarm";
02083 }
02084 
02085 static char *event2str(int event)
02086 {
02087    static char buf[256];
02088    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
02089       return events[event];
02090    sprintf(buf, "Event %d", event); /* safe */
02091    return buf;
02092 }
02093 
02094 #ifdef HAVE_PRI
02095 static char *dialplan2str(int dialplan)
02096 {
02097    if (dialplan == -1) {
02098       return("Dynamically set dialplan in ISDN");
02099    }
02100    return (pri_plan2str(dialplan));
02101 }
02102 #endif
02103 
02104 static char *dahdi_sig2str(int sig)
02105 {
02106    static char buf[256];
02107    switch (sig) {
02108    case SIG_EM:
02109       return "E & M Immediate";
02110    case SIG_EMWINK:
02111       return "E & M Wink";
02112    case SIG_EM_E1:
02113       return "E & M E1";
02114    case SIG_FEATD:
02115       return "Feature Group D (DTMF)";
02116    case SIG_FEATDMF:
02117       return "Feature Group D (MF)";
02118    case SIG_FEATDMF_TA:
02119       return "Feature Groud D (MF) Tandem Access";
02120    case SIG_FEATB:
02121       return "Feature Group B (MF)";
02122    case SIG_E911:
02123       return "E911 (MF)";
02124    case SIG_FGC_CAMA:
02125       return "FGC/CAMA (Dialpulse)";
02126    case SIG_FGC_CAMAMF:
02127       return "FGC/CAMA (MF)";
02128    case SIG_FXSLS:
02129       return "FXS Loopstart";
02130    case SIG_FXSGS:
02131       return "FXS Groundstart";
02132    case SIG_FXSKS:
02133       return "FXS Kewlstart";
02134    case SIG_FXOLS:
02135       return "FXO Loopstart";
02136    case SIG_FXOGS:
02137       return "FXO Groundstart";
02138    case SIG_FXOKS:
02139       return "FXO Kewlstart";
02140    case SIG_PRI:
02141       return "ISDN PRI";
02142    case SIG_MFCR2:
02143       return "MFC/R2";
02144    case SIG_SF:
02145       return "SF (Tone) Immediate";
02146    case SIG_SFWINK:
02147       return "SF (Tone) Wink";
02148    case SIG_SF_FEATD:
02149       return "SF (Tone) with Feature Group D (DTMF)";
02150    case SIG_SF_FEATDMF:
02151       return "SF (Tone) with Feature Group D (MF)";
02152    case SIG_SF_FEATB:
02153       return "SF (Tone) with Feature Group B (MF)";
02154    case SIG_GR303FXOKS:
02155       return "GR-303 with FXOKS";
02156    case SIG_GR303FXSKS:
02157       return "GR-303 with FXSKS";
02158    case 0:
02159       return "Pseudo";
02160    default:
02161       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02162       return buf;
02163    }
02164 }
02165 
02166 #define sig2str dahdi_sig2str
02167 
02168 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
02169 {
02170    /* If the conference already exists, and we're already in it
02171       don't bother doing anything */
02172    struct dahdi_confinfo zi;
02173    
02174    memset(&zi, 0, sizeof(zi));
02175    zi.chan = 0;
02176 
02177    if (slavechannel > 0) {
02178       /* If we have only one slave, do a digital mon */
02179       zi.confmode = DAHDI_CONF_DIGITALMON;
02180       zi.confno = slavechannel;
02181    } else {
02182       if (!index) {
02183          /* Real-side and pseudo-side both participate in conference */
02184          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02185             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02186       } else
02187          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02188       zi.confno = p->confno;
02189    }
02190    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02191       return 0;
02192    if (c->dfd < 0)
02193       return 0;
02194    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02195       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02196       return -1;
02197    }
02198    if (slavechannel < 1) {
02199       p->confno = zi.confno;
02200    }
02201    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02202    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02203    return 0;
02204 }
02205 
02206 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
02207 {
02208    /* If they're listening to our channel, they're ours */  
02209    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02210       return 1;
02211    /* If they're a talker on our (allocated) conference, they're ours */
02212    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02213       return 1;
02214    return 0;
02215 }
02216 
02217 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
02218 {
02219    struct dahdi_confinfo zi;
02220    if (/* Can't delete if there's no dfd */
02221       (c->dfd < 0) ||
02222       /* Don't delete from the conference if it's not our conference */
02223       !isourconf(p, c)
02224       /* Don't delete if we don't think it's conferenced at all (implied) */
02225       ) return 0;
02226    memset(&zi, 0, sizeof(zi));
02227    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02228       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02229       return -1;
02230    }
02231    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02232    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02233    return 0;
02234 }
02235 
02236 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
02237 {
02238    int x;
02239    int useslavenative;
02240    struct dahdi_pvt *slave = NULL;
02241    /* Start out optimistic */
02242    useslavenative = 1;
02243    /* Update conference state in a stateless fashion */
02244    for (x = 0; x < 3; x++) {
02245       /* Any three-way calling makes slave native mode *definitely* out
02246          of the question */
02247       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02248          useslavenative = 0;
02249    }
02250    /* If we don't have any 3-way calls, check to see if we have
02251       precisely one slave */
02252    if (useslavenative) {
02253       for (x = 0; x < MAX_SLAVES; x++) {
02254          if (p->slaves[x]) {
02255             if (slave) {
02256                /* Whoops already have a slave!  No 
02257                   slave native and stop right away */
02258                slave = NULL;
02259                useslavenative = 0;
02260                break;
02261             } else {
02262                /* We have one slave so far */
02263                slave = p->slaves[x];
02264             }
02265          }
02266       }
02267    }
02268    /* If no slave, slave native definitely out */
02269    if (!slave)
02270       useslavenative = 0;
02271    else if (slave->law != p->law) {
02272       useslavenative = 0;
02273       slave = NULL;
02274    }
02275    if (out)
02276       *out = slave;
02277    return useslavenative;
02278 }
02279 
02280 static int reset_conf(struct dahdi_pvt *p)
02281 {
02282    p->confno = -1;
02283    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02284    if (p->subs[SUB_REAL].dfd > -1) {
02285       struct dahdi_confinfo zi;
02286 
02287       memset(&zi, 0, sizeof(zi));
02288       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02289          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02290    }
02291    return 0;
02292 }
02293 
02294 static int update_conf(struct dahdi_pvt *p)
02295 {
02296    int needconf = 0;
02297    int x;
02298    int useslavenative;
02299    struct dahdi_pvt *slave = NULL;
02300 
02301    useslavenative = isslavenative(p, &slave);
02302    /* Start with the obvious, general stuff */
02303    for (x = 0; x < 3; x++) {
02304       /* Look for three way calls */
02305       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02306          conf_add(p, &p->subs[x], x, 0);
02307          needconf++;
02308       } else {
02309          conf_del(p, &p->subs[x], x);
02310       }
02311    }
02312    /* If we have a slave, add him to our conference now. or DAX
02313       if this is slave native */
02314    for (x = 0; x < MAX_SLAVES; x++) {
02315       if (p->slaves[x]) {
02316          if (useslavenative)
02317             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02318          else {
02319             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02320             needconf++;
02321          }
02322       }
02323    }
02324    /* If we're supposed to be in there, do so now */
02325    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02326       if (useslavenative)
02327          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02328       else {
02329          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02330          needconf++;
02331       }
02332    }
02333    /* If we have a master, add ourselves to his conference */
02334    if (p->master) {
02335       if (isslavenative(p->master, NULL)) {
02336          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02337       } else {
02338          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02339       }
02340    }
02341    if (!needconf) {
02342       /* Nobody is left (or should be left) in our conference.
02343          Kill it. */
02344       p->confno = -1;
02345    }
02346    if (option_debug)
02347       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02348    return 0;
02349 }
02350 
02351 static void dahdi_enable_ec(struct dahdi_pvt *p)
02352 {
02353    int x;
02354    int res;
02355    if (!p)
02356       return;
02357    if (p->echocanon) {
02358       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
02359       return;
02360    }
02361    if (p->digital) {
02362       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
02363       return;
02364    }
02365    if (p->echocancel) {
02366       if (p->sig == SIG_PRI) {
02367          x = 1;
02368          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02369          if (res)
02370             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02371       }
02372       x = p->echocancel;
02373       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02374       if (res) 
02375          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02376       else {
02377          p->echocanon = 1;
02378          if (option_debug)
02379             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
02380       }
02381    } else if (option_debug)
02382       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
02383 }
02384 
02385 static void dahdi_train_ec(struct dahdi_pvt *p)
02386 {
02387    int x;
02388    int res;
02389    if (p && p->echocancel && p->echotraining) {
02390       x = p->echotraining;
02391       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02392       if (res)
02393          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02394       else {
02395          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
02396       }
02397    } else
02398       ast_log(LOG_DEBUG, "No echo training requested\n");
02399 }
02400 
02401 static void dahdi_disable_ec(struct dahdi_pvt *p)
02402 {
02403    int x;
02404    int res;
02405    if (p->echocancel) {
02406       x = 0;
02407       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
02408       if (res)
02409          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02410       else if (option_debug)
02411          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
02412    }
02413    p->echocanon = 0;
02414 }
02415 
02416 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02417 {
02418    int j;
02419    int k;
02420    float linear_gain = pow(10.0, gain / 20.0);
02421 
02422    switch (law) {
02423    case DAHDI_LAW_ALAW:
02424       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02425          if (gain) {
02426             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02427             if (k > 32767) k = 32767;
02428             if (k < -32767) k = -32767;
02429             g->txgain[j] = AST_LIN2A(k);
02430          } else {
02431             g->txgain[j] = j;
02432          }
02433       }
02434       break;
02435    case DAHDI_LAW_MULAW:
02436       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
02437          if (gain) {
02438             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02439             if (k > 32767) k = 32767;
02440             if (k < -32767) k = -32767;
02441             g->txgain[j] = AST_LIN2MU(k);
02442          } else {
02443             g->txgain[j] = j;
02444          }
02445       }
02446       break;
02447    }
02448 }
02449 
02450 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02451 {
02452    int j;
02453    int k;
02454    float linear_gain = pow(10.0, gain / 20.0);
02455 
02456    switch (law) {
02457    case DAHDI_LAW_ALAW:
02458       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02459          if (gain) {
02460             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02461             if (k > 32767) k = 32767;
02462             if (k < -32767) k = -32767;
02463             g->rxgain[j] = AST_LIN2A(k);
02464          } else {
02465             g->rxgain[j] = j;
02466          }
02467       }
02468       break;
02469    case DAHDI_LAW_MULAW:
02470       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
02471          if (gain) {
02472             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02473             if (k > 32767) k = 32767;
02474             if (k < -32767) k = -32767;
02475             g->rxgain[j] = AST_LIN2MU(k);
02476          } else {
02477             g->rxgain[j] = j;
02478          }
02479       }
02480       break;
02481    }
02482 }
02483 
02484 static int set_actual_txgain(int fd, int chan, float gain, int law)
02485 {
02486    struct dahdi_gains g;
02487    int res;
02488 
02489    memset(&g, 0, sizeof(g));
02490    g.chan = chan;
02491    res = ioctl(fd, DAHDI_GETGAINS, &g);
02492    if (res) {
02493       if (option_debug)
02494          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02495       return res;
02496    }
02497 
02498    fill_txgain(&g, gain, law);
02499 
02500    return ioctl(fd, DAHDI_SETGAINS, &g);
02501 }
02502 
02503 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02504 {
02505    struct dahdi_gains g;
02506    int res;
02507 
02508    memset(&g, 0, sizeof(g));
02509    g.chan = chan;
02510    res = ioctl(fd, DAHDI_GETGAINS, &g);
02511    if (res) {
02512       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
02513       return res;
02514    }
02515 
02516    fill_rxgain(&g, gain, law);
02517 
02518    return ioctl(fd, DAHDI_SETGAINS, &g);
02519 }
02520 
02521 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02522 {
02523    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02524 }
02525 
02526 static int bump_gains(struct dahdi_pvt *p)
02527 {
02528    int res;
02529 
02530    /* Bump receive gain by 5.0db */
02531    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
02532    if (res) {
02533       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02534       return -1;
02535    }
02536 
02537    return 0;
02538 }
02539 
02540 static int restore_gains(struct dahdi_pvt *p)
02541 {
02542    int res;
02543 
02544    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02545    if (res) {
02546       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02547       return -1;
02548    }
02549 
02550    return 0;
02551 }
02552 
02553 static inline int dahdi_set_hook(int fd, int hs)
02554 {
02555    int x, res;
02556 
02557    x = hs;
02558    res = ioctl(fd, DAHDI_HOOK, &x);
02559 
02560    if (res < 0) {
02561       if (errno == EINPROGRESS)
02562          return 0;
02563       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02564       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02565    }
02566 
02567    return res;
02568 }
02569 
02570 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02571 {
02572    int x, y, res;
02573    x = muted;
02574    if (p->sig == SIG_PRI) {
02575       y = 1;
02576       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02577       if (res)
02578          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02579    }
02580    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02581    if (res < 0)
02582       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02583    return res;
02584 }
02585 
02586 static int save_conference(struct dahdi_pvt *p)
02587 {
02588    struct dahdi_confinfo c;
02589    int res;
02590    if (p->saveconf.confmode) {
02591       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02592       return -1;
02593    }
02594    p->saveconf.chan = 0;
02595    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02596    if (res) {
02597       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02598       p->saveconf.confmode = 0;
02599       return -1;
02600    }
02601    memset(&c, 0, sizeof(c));
02602    c.confmode = DAHDI_CONF_NORMAL;
02603    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02604    if (res) {
02605       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02606       return -1;
02607    }
02608    if (option_debug)
02609       ast_log(LOG_DEBUG, "Disabled conferencing\n");
02610    return 0;
02611 }
02612 
02613 static int restore_conference(struct dahdi_pvt *p)
02614 {
02615    int res;
02616    if (p->saveconf.confmode) {
02617       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02618       p->saveconf.confmode = 0;
02619       if (res) {
02620          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02621          return -1;
02622       }
02623    }
02624    if (option_debug)
02625       ast_log(LOG_DEBUG, "Restored conferencing\n");
02626    return 0;
02627 }
02628 
02629 static int send_callerid(struct dahdi_pvt *p);
02630 
02631 static int send_cwcidspill(struct dahdi_pvt *p)
02632 {
02633    p->callwaitcas = 0;
02634    p->cidcwexpire = 0;
02635    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02636       return -1;
02637    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02638    /* Make sure we account for the end */
02639    p->cidlen += READ_SIZE * 4;
02640    p->cidpos = 0;
02641    send_callerid(p);
02642    if (option_verbose > 2)
02643       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02644    return 0;
02645 }
02646 
02647 static int has_voicemail(struct dahdi_pvt *p)
02648 {
02649 
02650    return ast_app_has_voicemail(p->mailbox, NULL);
02651 }
02652 
02653 static int send_callerid(struct dahdi_pvt *p)
02654 {
02655    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02656    int res;
02657    /* Take out of linear mode if necessary */
02658    if (p->subs[SUB_REAL].linear) {
02659       p->subs[SUB_REAL].linear = 0;
02660       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02661    }
02662    while (p->cidpos < p->cidlen) {
02663       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02664       if (res < 0) {
02665          if (errno == EAGAIN)
02666             return 0;
02667          else {
02668             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02669             return -1;
02670          }
02671       }
02672       if (!res)
02673          return 0;
02674       p->cidpos += res;
02675    }
02676    free(p->cidspill);
02677    p->cidspill = NULL;
02678    if (p->callwaitcas) {
02679       /* Wait for CID/CW to expire */
02680       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02681    } else
02682       restore_conference(p);
02683    return 0;
02684 }
02685 
02686 static int dahdi_callwait(struct ast_channel *ast)
02687 {
02688    struct dahdi_pvt *p = ast->tech_pvt;
02689    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02690    if (p->cidspill) {
02691       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02692       free(p->cidspill);
02693    }
02694    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02695       return -1;
02696    save_conference(p);
02697    /* Silence */
02698    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02699    if (!p->callwaitrings && p->callwaitingcallerid) {
02700       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02701       p->callwaitcas = 1;
02702       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02703    } else {
02704       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02705       p->callwaitcas = 0;
02706       p->cidlen = 2400 + READ_SIZE * 4;
02707    }
02708    p->cidpos = 0;
02709    send_callerid(p);
02710    
02711    return 0;
02712 }
02713 
02714 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02715 {
02716    struct dahdi_pvt *p = ast->tech_pvt;
02717    int x, res, index,mysig;
02718    char *c, *n, *l;
02719 #ifdef HAVE_PRI
02720    char *s = NULL;
02721 #endif
02722    char dest[256]; /* must be same length as p->dialdest */
02723    ast_mutex_lock(&p->lock);
02724    ast_copy_string(dest, rdest, sizeof(dest));
02725    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02726    if ((ast->_state == AST_STATE_BUSY)) {
02727       p->subs[SUB_REAL].needbusy = 1;
02728       ast_mutex_unlock(&p->lock);
02729       return 0;
02730    }
02731    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02732       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02733       ast_mutex_unlock(&p->lock);
02734       return -1;
02735    }
02736    p->dialednone = 0;
02737    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02738    {
02739       /* Special pseudo -- automatically up */
02740       ast_setstate(ast, AST_STATE_UP); 
02741       ast_mutex_unlock(&p->lock);
02742       return 0;
02743    }
02744    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02745    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02746    if (res)
02747       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02748    p->outgoing = 1;
02749 
02750    if (IS_DIGITAL(ast->transfercapability)) {
02751       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
02752    } else {
02753       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02754    }
02755 
02756    mysig = p->sig;
02757    if (p->outsigmod > -1)
02758       mysig = p->outsigmod;
02759 
02760    switch (mysig) {
02761    case SIG_FXOLS:
02762    case SIG_FXOGS:
02763    case SIG_FXOKS:
02764       if (p->owner == ast) {
02765          /* Normal ring, on hook */
02766          
02767          /* Don't send audio while on hook, until the call is answered */
02768          p->dialing = 1;
02769          if (p->use_callerid) {
02770             /* Generate the Caller-ID spill if desired */
02771             if (p->cidspill) {
02772                ast_log(LOG_WARNING, "cidspill already exists??\n");
02773                free(p->cidspill);
02774             }
02775             p->callwaitcas = 0;
02776             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02777                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02778                p->cidpos = 0;
02779                send_callerid(p);
02780             }
02781          }
02782          /* Choose proper cadence */
02783          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02784             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02785                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02786             p->cidrings = cidrings[p->distinctivering - 1];
02787          } else {
02788             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02789                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02790             p->cidrings = p->sendcalleridafter;
02791          }
02792 
02793          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02794          c = strchr(dest, '/');
02795          if (c)
02796             c++;
02797          if (c && (strlen(c) < p->stripmsd)) {
02798             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02799             c = NULL;
02800          }
02801          if (c) {
02802             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02803             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02804             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02805          } else {
02806             p->dop.dialstr[0] = '\0';
02807          }
02808          x = DAHDI_RING;
02809          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02810             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02811             ast_mutex_unlock(&p->lock);
02812             return -1;
02813          }
02814          p->dialing = 1;
02815       } else {
02816          /* Call waiting call */
02817          p->callwaitrings = 0;
02818          if (ast->cid.cid_num)
02819             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02820          else
02821             p->callwait_num[0] = '\0';
02822          if (ast->cid.cid_name)
02823             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02824          else
02825             p->callwait_name[0] = '\0';
02826          /* Call waiting tone instead */
02827          if (dahdi_callwait(ast)) {
02828             ast_mutex_unlock(&p->lock);
02829             return -1;
02830          }
02831          /* Make ring-back */
02832          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02833             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02834             
02835       }
02836       n = ast->cid.cid_name;
02837       l = ast->cid.cid_num;
02838       if (l)
02839          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02840       else
02841          p->lastcid_num[0] = '\0';
02842       if (n)
02843          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02844       else
02845          p->lastcid_name[0] = '\0';
02846       ast_setstate(ast, AST_STATE_RINGING);
02847       index = dahdi_get_index(ast, p, 0);
02848       if (index > -1) {
02849          p->subs[index].needringing = 1;
02850       }
02851       break;
02852    case SIG_FXSLS:
02853    case SIG_FXSGS:
02854    case SIG_FXSKS:
02855    case SIG_EMWINK:
02856    case SIG_EM:
02857    case SIG_EM_E1:
02858    case SIG_FEATD:
02859    case SIG_FEATDMF:
02860    case SIG_E911:
02861    case SIG_FGC_CAMA:
02862    case SIG_FGC_CAMAMF:
02863    case SIG_FEATB:
02864    case SIG_SFWINK:
02865    case SIG_SF:
02866    case SIG_SF_FEATD:
02867    case SIG_SF_FEATDMF:
02868    case SIG_FEATDMF_TA:
02869    case SIG_SF_FEATB:
02870       c = strchr(dest, '/');
02871       if (c)
02872          c++;
02873       else
02874          c = "";
02875       if (strlen(c) < p->stripmsd) {
02876          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02877          ast_mutex_unlock(&p->lock);
02878          return -1;
02879       }
02880 #ifdef HAVE_PRI
02881       /* Start the trunk, if not GR-303 */
02882       if (!p->pri) {
02883 #endif
02884          x = DAHDI_START;
02885          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02886          if (res < 0) {
02887             if (errno != EINPROGRESS) {
02888                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02889                ast_mutex_unlock(&p->lock);
02890                return -1;
02891             }
02892          }
02893 #ifdef HAVE_PRI
02894       }
02895 #endif
02896       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02897       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02898 
02899       c += p->stripmsd;
02900 
02901       switch (mysig) {
02902       case SIG_FEATD:
02903          l = ast->cid.cid_num;
02904          if (l) 
02905             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02906          else
02907             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02908          break;
02909       case SIG_FEATDMF:
02910          l = ast->cid.cid_num;
02911          if (l) 
02912             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02913          else
02914             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02915          break;
02916       case SIG_FEATDMF_TA:
02917       {
02918          const char *cic, *ozz;
02919 
02920          /* If you have to go through a Tandem Access point you need to use this */
02921          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02922          if (!ozz)
02923             ozz = defaultozz;
02924          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02925          if (!cic)
02926             cic = defaultcic;
02927          if (!ozz || !cic) {
02928             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02929             ast_mutex_unlock(&p->lock);
02930             return -1;
02931          }
02932          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02933          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02934          p->whichwink = 0;
02935       }
02936          break;
02937       case SIG_E911:
02938          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02939          break;
02940       case SIG_FGC_CAMA:
02941          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02942          break;
02943       case SIG_FGC_CAMAMF:
02944       case SIG_FEATB:
02945          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02946          break;
02947       default:
02948          if (p->pulse)
02949             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02950          else
02951             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02952          break;
02953       }
02954 
02955       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02956          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02957          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02958          p->echorest[sizeof(p->echorest) - 1] = '\0';
02959          p->echobreak = 1;
02960          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02961       } else
02962          p->echobreak = 0;
02963       if (!res) {
02964          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02965             int saveerr = errno;
02966 
02967             x = DAHDI_ONHOOK;
02968             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02969             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02970             ast_mutex_unlock(&p->lock);
02971             return -1;
02972          }
02973       } else
02974          ast_log(LOG_DEBUG, "Deferring dialing... (res %d)\n", res);
02975       p->dialing = 1;
02976       if (ast_strlen_zero(c))
02977          p->dialednone = 1;
02978       ast_setstate(ast, AST_STATE_DIALING);
02979       break;
02980    case 0:
02981       /* Special pseudo -- automatically up*/
02982       ast_setstate(ast, AST_STATE_UP);
02983       break;      
02984    case SIG_PRI:
02985    case SIG_MFCR2:
02986       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02987       p->dialdest[0] = '\0';
02988       p->dialing = 1;
02989       break;
02990    default:
02991       ast_log(LOG_DEBUG, "not yet implemented\n");
02992       ast_mutex_unlock(&p->lock);
02993       return -1;
02994    }
02995 #ifdef HAVE_OPENR2
02996    if (p->mfcr2) {
02997       int strip = p->stripmsd;
02998       int callres = 0;
02999       c = strchr(dest, '/');
03000       if (c) {
03001          c++;
03002       } else {
03003          c = dest;
03004       }
03005       if (!p->hidecallerid) {
03006          l = ast->cid.cid_num;
03007       } else {
03008          l = NULL;
03009       }
03010       if (strlen(c) < strip) {
03011          ast_log(LOG_WARNING, "Destiny number '%s' is shorter than stripmsd(%d)? hum, you should fix that. Assuming stripmsd = 0\n", c, strip);
03012          strip = 0;
03013       }
03014       p->dialing = 1;
03015       callres = openr2_chan_make_call(p->r2chan, l, (c + strip), dahdi_r2_get_channel_category(ast));
03016       if (-1 == callres) {
03017          ast_mutex_unlock(&p->lock);
03018          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03019          return -1;
03020       }
03021       ast_setstate(ast, AST_STATE_DIALING);
03022    }
03023 #endif /* HAVE_OPENR2 */
03024 #ifdef HAVE_PRI
03025    if (p->pri) {
03026       struct pri_sr *sr;
03027 #ifdef SUPPORT_USERUSER
03028       const char *useruser;
03029 #endif
03030       int pridialplan;
03031       int dp_strip;
03032       int prilocaldialplan;
03033       int ldp_strip;
03034       int exclusive;
03035       const char *rr_str;
03036       int redirect_reason;
03037 
03038       c = strchr(dest, '/');
03039       if (c) {
03040          c++;
03041       } else {
03042          c = "";
03043       }
03044 
03045       l = NULL;
03046       n = NULL;
03047       if (!p->hidecallerid) {
03048          l = ast->cid.cid_num;
03049          if (!p->hidecalleridname) {
03050             n = ast->cid.cid_name;
03051          }
03052       }
03053 
03054 
03055       if (strlen(c) < p->stripmsd) {
03056          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03057          ast_mutex_unlock(&p->lock);
03058          return -1;
03059       }
03060       if (mysig != SIG_FXSKS) {
03061          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03062          s = strchr(c + p->stripmsd, 'w');
03063          if (s) {
03064             if (strlen(s) > 1)
03065                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03066             else
03067                p->dop.dialstr[0] = '\0';
03068             *s = '\0';
03069          } else {
03070             p->dop.dialstr[0] = '\0';
03071          }
03072       }
03073       if (pri_grab(p, p->pri)) {
03074          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03075          ast_mutex_unlock(&p->lock);
03076          return -1;
03077       }
03078       if (!(p->call = pri_new_call(p->pri->pri))) {
03079          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03080          pri_rel(p->pri);
03081          ast_mutex_unlock(&p->lock);
03082          return -1;
03083       }
03084       if (!(sr = pri_sr_new())) {
03085          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03086          pri_destroycall(p->pri->pri, p->call);
03087          p->call = NULL;
03088          pri_rel(p->pri);
03089          ast_mutex_unlock(&p->lock);
03090          return -1;
03091       }
03092       if (p->bearer || (mysig == SIG_FXSKS)) {
03093          if (p->bearer) {
03094             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);
03095             p->bearer->call = p->call;
03096          } else
03097             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
03098          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03099       }
03100       p->digital = IS_DIGITAL(ast->transfercapability);
03101 
03102       /* Should the picked channel be used exclusively? */
03103       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03104          exclusive = 1;
03105       } else {
03106          exclusive = 0;
03107       }
03108       
03109       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03110       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
03111                (p->digital ? -1 : 
03112                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03113       if (p->pri->facilityenable)
03114          pri_facility_enable(p->pri->pri);
03115 
03116       if (option_verbose > 2)
03117          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03118       dp_strip = 0;
03119       pridialplan = p->pri->dialplan - 1;
03120       if (pridialplan == -2) { /* compute dynamically */
03121          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03122             dp_strip = strlen(p->pri->internationalprefix);
03123             pridialplan = PRI_INTERNATIONAL_ISDN;
03124          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03125             dp_strip = strlen(p->pri->nationalprefix);
03126             pridialplan = PRI_NATIONAL_ISDN;
03127          } else {
03128             pridialplan = PRI_LOCAL_ISDN;
03129          }
03130       }
03131       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03132 
03133       ldp_strip = 0;
03134       prilocaldialplan = p->pri->localdialplan - 1;
03135       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
03136          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03137             ldp_strip = strlen(p->pri->internationalprefix);
03138             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03139          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03140             ldp_strip = strlen(p->pri->nationalprefix);
03141             prilocaldialplan = PRI_NATIONAL_ISDN;
03142          } else {
03143             prilocaldialplan = PRI_LOCAL_ISDN;
03144          }
03145       }
03146       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03147          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03148       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03149          if (!strcasecmp(rr_str, "UNKNOWN"))
03150             redirect_reason = 0;
03151          else if (!strcasecmp(rr_str, "BUSY"))
03152             redirect_reason = 1;
03153          else if (!strcasecmp(rr_str, "NO_REPLY"))
03154             redirect_reason = 2;
03155          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03156             redirect_reason = 15;
03157          else
03158             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03159       } else
03160          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03161       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03162 
03163 #ifdef SUPPORT_USERUSER
03164       /* User-user info */
03165       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03166 
03167       if (useruser)
03168          pri_sr_set_useruser(sr, useruser);
03169 #endif
03170 
03171       if (pri_setup(p->pri->pri, p->call, sr)) {
03172          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
03173             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03174          pri_rel(p->pri);
03175          ast_mutex_unlock(&p->lock);
03176          pri_sr_free(sr);
03177          return -1;
03178       }
03179       pri_sr_free(sr);
03180       ast_setstate(ast, AST_STATE_DIALING);
03181       pri_rel(p->pri);
03182    }
03183 #endif      
03184    ast_mutex_unlock(&p->lock);
03185    return 0;
03186 }
03187 
03188 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03189 {
03190    struct dahdi_pvt *p = *pvt;
03191    /* Remove channel from the list */
03192    if (p->prev)
03193       p->prev->next = p->next;
03194    if (p->next)
03195       p->next->prev = p->prev;
03196    if (p->use_smdi)
03197       ast_smdi_interface_unref(p->smdi_iface);
03198    ast_mutex_destroy(&p->lock);
03199    dahdi_close_sub(p, SUB_REAL);
03200    if (p->owner)
03201       p->owner->tech_pvt = NULL;
03202    free(p);
03203    *pvt = NULL;
03204 }
03205 
03206 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03207 {
03208    int owned = 0;
03209    int i = 0;
03210 
03211    if (!now) {
03212       if (cur->owner) {
03213          owned = 1;
03214       }
03215 
03216       for (i = 0; i < 3; i++) {
03217          if (cur->subs[i].owner) {
03218             owned = 1;
03219          }
03220       }
03221       if (!owned) {
03222          if (prev) {
03223             prev->next = cur->next;
03224             if (prev->next)
03225                prev->next->prev = prev;
03226             else
03227                ifend = prev;
03228          } else {
03229             iflist = cur->next;
03230             if (iflist)
03231                iflist->prev = NULL;
03232             else
03233                ifend = NULL;
03234          }
03235          destroy_dahdi_pvt(&cur);
03236       }
03237    } else {
03238       if (prev) {
03239          prev->next = cur->next;
03240          if (prev->next)
03241             prev->next->prev = prev;
03242          else
03243             ifend = prev;
03244       } else {
03245          iflist = cur->next;
03246          if (iflist)
03247             iflist->prev = NULL;
03248          else
03249             ifend = NULL;
03250       }
03251       destroy_dahdi_pvt(&cur);
03252    }
03253    return 0;
03254 }
03255 
03256 static void destroy_all_channels(void)
03257 {
03258    int x;
03259    struct dahdi_pvt *p, *pl;
03260 
03261    while (num_restart_pending) {
03262       usleep(1);
03263    }
03264 
03265    ast_mutex_lock(&iflock);
03266    /* Destroy all the interfaces and free their memory */
03267    p = iflist;
03268    while (p) {
03269       /* Free any callerid */
03270       if (p->cidspill)
03271          ast_free(p->cidspill);
03272       pl = p;
03273       p = p->next;
03274       x = pl->channel;
03275       /* Free associated memory */
03276       if (pl)
03277          destroy_dahdi_pvt(&pl);
03278       if (option_verbose > 2) 
03279          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03280    }
03281    iflist = NULL;
03282    ifcount = 0;
03283    ast_mutex_unlock(&iflock);
03284 }
03285 
03286 #ifdef HAVE_PRI
03287 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03288 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
03289 
03290 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03291 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03292 
03293 static char *dahdi_send_keypad_facility_descrip = 
03294 "  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03295 "  IE over the current channel.\n";
03296 static char *zap_send_keypad_facility_descrip = 
03297 "  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03298 "  IE over the current channel.\n";
03299 
03300 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
03301 {
03302    /* Data will be our digit string */
03303    struct dahdi_pvt *p;
03304    char *digits = (char *) data;
03305 
03306    if (ast_strlen_zero(digits)) {
03307       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
03308       return -1;
03309    }
03310 
03311    p = (struct dahdi_pvt *)chan->tech_pvt;
03312 
03313    if (!p) {
03314       ast_log(LOG_DEBUG, "Unable to find technology private\n");
03315       return -1;
03316    }
03317 
03318    ast_mutex_lock(&p->lock);
03319 
03320    if (!p->pri || !p->call) {
03321       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
03322       ast_mutex_unlock(&p->lock);
03323       return -1;
03324    }
03325 
03326    if (!pri_grab(p, p->pri)) {
03327       pri_keypad_facility(p->pri->pri, p->call, digits);
03328       pri_rel(p->pri);
03329    } else {
03330       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
03331       ast_mutex_unlock(&p->lock);
03332       return -1;
03333    }
03334 
03335    ast_mutex_unlock(&p->lock);
03336 
03337    return 0;
03338 }
03339 
03340 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03341 {
03342    return send_keypad_facility_exec(chan, data);
03343 }
03344 
03345 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03346 {
03347    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);  
03348    return send_keypad_facility_exec(chan, data);
03349 }
03350 
03351 static int pri_is_up(struct dahdi_pri *pri)
03352 {
03353    int x;
03354    for (x = 0; x < NUM_DCHANS; x++) {
03355       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03356          return 1;
03357    }
03358    return 0;
03359 }
03360 
03361 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03362 {
03363    bearer->owner = &inuse;
03364    bearer->realcall = crv;
03365    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03366    if (crv->subs[SUB_REAL].owner)
03367       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
03368    crv->bearer = bearer;
03369    crv->call = bearer->call;
03370    crv->pri = pri;
03371    return 0;
03372 }
03373 
03374 static char *pri_order(int level)
03375 {
03376    switch (level) {
03377    case 0:
03378       return "Primary";
03379    case 1:
03380       return "Secondary";
03381    case 2:
03382       return "Tertiary";
03383    case 3:
03384       return "Quaternary";
03385    default:
03386       return "<Unknown>";
03387    }     
03388 }
03389 
03390 /* Returns fd of the active dchan */
03391 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03392 {
03393    int x = -1;
03394 
03395    for (x = 0; x < NUM_DCHANS; x++) {
03396       if ((pri->dchans[x] == pri->pri))
03397          break;
03398    }
03399 
03400    return pri->fds[x];
03401 }
03402 
03403 static int pri_find_dchan(struct dahdi_pri *pri)
03404 {
03405    int oldslot = -1;
03406    struct pri *old;
03407    int newslot = -1;
03408    int x;
03409    old = pri->pri;
03410    for (x = 0; x < NUM_DCHANS; x++) {
03411       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03412          newslot = x;
03413       if (pri->dchans[x] == old) {
03414          oldslot = x;
03415       }
03416    }
03417    if (newslot < 0) {
03418       newslot = 0;
03419       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03420          pri->dchannels[newslot]);
03421    }
03422    if (old && (oldslot != newslot))
03423       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03424          pri->dchannels[oldslot], pri->dchannels[newslot]);
03425    pri->pri = pri->dchans[newslot];
03426    return 0;
03427 }
03428 #endif
03429 
03430 #ifdef HAVE_OPENR2
03431 static char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
03432 static char *zap_accept_r2_call_app = "ZapAcceptR2Call";
03433 
03434 static char *dahdi_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03435 static char *zap_accept_r2_call_synopsis = "Accept an R2 call if its not already accepted (you still need to answer it)";
03436 
03437 static char *dahdi_accept_r2_call_descrip = 
03438 "  DAHDIAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03439 "  You can specify yes or no as argument to accept with or without charge.\n";
03440 
03441 static char *zap_accept_r2_call_descrip = 
03442 "  ZapAcceptR2Call(): This application will accept the current MFC/R2 call\n"
03443 "  You can specify yes or no as argument to accept with or without charge.\n";
03444 
03445 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
03446 {
03447    /* data is whether to accept with charge or no charge */
03448    openr2_call_mode_t accept_mode;
03449    int res, timeout, maxloops;
03450    struct ast_frame *f;
03451    struct dahdi_pvt *p;
03452    char *parse;
03453    AST_DECLARE_APP_ARGS(args,
03454          AST_APP_ARG(charge);
03455    );
03456 
03457    if (ast_strlen_zero(data)) {
03458       ast_log(LOG_DEBUG, "No data sent to application!\n");
03459       return -1;
03460    }
03461 
03462    if (chan->tech != &dahdi_tech) {
03463       ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
03464       return -1;
03465    }
03466 
03467    p = (struct dahdi_pvt *)chan->tech_pvt;
03468    if (!p) {
03469       ast_log(LOG_DEBUG, "Unable to find technology private!\n");
03470       return -1;
03471    }
03472 
03473    parse = ast_strdupa(data);
03474    AST_STANDARD_APP_ARGS(args, parse);
03475 
03476    if (ast_strlen_zero(args.charge)) {
03477       ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
03478       return -1;
03479    }
03480 
03481    ast_mutex_lock(&p->lock);
03482    if (!p->mfcr2 || !p->mfcr2call) {
03483       ast_mutex_unlock(&p->lock);
03484       ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
03485       return -1;
03486    }
03487 
03488    if (p->mfcr2_call_accepted) {
03489       ast_mutex_unlock(&p->lock);
03490       ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
03491       return 0;
03492    }
03493    accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
03494    if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
03495       ast_mutex_unlock(&p->lock);
03496       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03497       return -1;
03498    }
03499    ast_mutex_unlock(&p->lock);
03500 
03501    res = 0;
03502    timeout = 100;
03503    maxloops = 50; /* wait up to 5 seconds */
03504    /* we need to read() until the call is accepted */
03505    while (maxloops > 0) {
03506       maxloops--;
03507       if (ast_check_hangup(chan)) {
03508          break;
03509       }
03510       res = ast_waitfor(chan, timeout);
03511       if (res < 0) {
03512          ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
03513          res = -1;
03514          break;
03515       }
03516       if (res == 0) {
03517          continue;
03518       }
03519       f = ast_read(chan);
03520       if (!f) {
03521          ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
03522          res = -1;
03523          break;
03524       }
03525       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
03526          ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
03527          ast_frfree(f);
03528          res = -1;
03529          break;
03530       }
03531       ast_frfree(f);
03532       ast_mutex_lock(&p->lock);
03533       if (p->mfcr2_call_accepted) {
03534          ast_mutex_unlock(&p->lock);
03535          ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
03536          break;
03537       }
03538       ast_mutex_unlock(&p->lock);
03539    }
03540    if (res == -1) {
03541       ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
03542    }
03543    return res;
03544 }
03545 
03546 static int zap_accept_r2_call_exec(struct ast_channel *chan, void *data)
03547 {
03548    return dahdi_accept_r2_call_exec(chan, data);
03549 }
03550 
03551 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
03552 {
03553    openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
03554    switch (cause) {
03555    case AST_CAUSE_USER_BUSY:
03556    case AST_CAUSE_CALL_REJECTED:
03557    case AST_CAUSE_INTERWORKING: /* I don't know wtf is this but is used sometimes when ekiga rejects a call */
03558       r2cause = OR2_CAUSE_BUSY_NUMBER;
03559       break;
03560 
03561    case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
03562    case AST_CAUSE_SWITCH_CONGESTION:
03563       r2cause = OR2_CAUSE_NETWORK_CONGESTION;
03564       break;
03565 
03566    case AST_CAUSE_UNALLOCATED:
03567       r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
03568       break;
03569 
03570    case AST_CAUSE_NETWORK_OUT_OF_ORDER:
03571    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03572       r2cause = OR2_CAUSE_OUT_OF_ORDER;
03573       break;
03574 
03575    case AST_CAUSE_NO_ANSWER:
03576    case AST_CAUSE_NO_USER_RESPONSE:
03577       r2cause = OR2_CAUSE_NO_ANSWER;
03578       break;
03579 
03580    default:
03581       r2cause = OR2_CAUSE_NORMAL_CLEARING;
03582       break;
03583    }
03584    ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n", 
03585          r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
03586    return r2cause;
03587 }
03588 #endif
03589 
03590 static int dahdi_hangup(struct ast_channel *ast)
03591 {
03592    int res;
03593    int index,x, law;
03594    /*static int restore_gains(struct dahdi_pvt *p);*/
03595    struct dahdi_pvt *p = ast->tech_pvt;
03596    struct dahdi_pvt *tmp = NULL;
03597    struct dahdi_pvt *prev = NULL;
03598    struct dahdi_params par;
03599 
03600    if (option_debug)
03601       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
03602    if (!ast->tech_pvt) {
03603       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03604       return 0;
03605    }
03606    
03607    ast_mutex_lock(&p->lock);
03608    
03609    index = dahdi_get_index(ast, p, 1);
03610 
03611    if (p->sig == SIG_PRI) {
03612       x = 1;
03613       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03614       p->cid_num[0] = '\0';
03615       p->cid_name[0] = '\0';
03616    }
03617 
03618    x = 0;
03619    dahdi_confmute(p, 0);
03620    restore_gains(p);
03621    if (p->origcid_num) {
03622       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03623       free(p->origcid_num);
03624       p->origcid_num = NULL;
03625    }  
03626    if (p->origcid_name) {
03627       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03628       free(p->origcid_name);
03629       p->origcid_name = NULL;
03630    }  
03631    if (p->dsp)
03632       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
03633    p->exten[0] = '\0';
03634 
03635    if (option_debug)
03636       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03637       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03638    p->ignoredtmf = 0;
03639    
03640    if (index > -1) {
03641       /* Real channel, do some fixup */
03642       p->subs[index].owner = NULL;
03643       p->subs[index].needanswer = 0;
03644       p->subs[index].needflash = 0;
03645       p->subs[index].needringing = 0;
03646       p->subs[index].needbusy = 0;
03647       p->subs[index].needcongestion = 0;
03648       p->subs[index].linear = 0;
03649       p->subs[index].needcallerid = 0;
03650       p->polarity = POLARITY_IDLE;
03651       dahdi_setlinear(p->subs[index].dfd, 0);
03652       if (index == SUB_REAL) {
03653          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03654             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
03655             if (p->subs[SUB_CALLWAIT].inthreeway) {
03656                /* We had flipped over to answer a callwait and now it's gone */
03657                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
03658                /* Move to the call-wait, but un-own us until they flip back. */
03659                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03660                unalloc_sub(p, SUB_CALLWAIT);
03661                p->owner = NULL;
03662             } else {
03663                /* The three way hung up, but we still have a call wait */
03664                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
03665                swap_subs(p, SUB_THREEWAY, SUB_REAL);
03666                unalloc_sub(p, SUB_THREEWAY);
03667                if (p->subs[SUB_REAL].inthreeway) {
03668                   /* This was part of a three way call.  Immediately make way for
03669                      another call */
03670                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03671                   p->owner = p->subs[SUB_REAL].owner;
03672                } else {
03673                   /* This call hasn't been completed yet...  Set owner to NULL */
03674                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03675                   p->owner = NULL;
03676                }
03677                p->subs[SUB_REAL].inthreeway = 0;
03678             }
03679          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03680             /* Move to the call-wait and switch back to them. */
03681             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03682             unalloc_sub(p, SUB_CALLWAIT);
03683             p->owner = p->subs[SUB_REAL].owner;
03684             if (p->owner->_state != AST_STATE_UP)
03685                p->subs[SUB_REAL].needanswer = 1;
03686             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03687                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03688          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03689             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03690             unalloc_sub(p, SUB_THREEWAY);
03691             if (p->subs[SUB_REAL].inthreeway) {
03692                /* This was part of a three way call.  Immediately make way for
03693                   another call */
03694                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
03695                p->owner = p->subs[SUB_REAL].owner;
03696             } else {
03697                /* This call hasn't been completed yet...  Set owner to NULL */
03698                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
03699                p->owner = NULL;
03700             }
03701             p->subs[SUB_REAL].inthreeway = 0;
03702          }
03703       } else if (index == SUB_CALLWAIT) {
03704          /* Ditch the holding callwait call, and immediately make it availabe */
03705          if (p->subs[SUB_CALLWAIT].inthreeway) {
03706             /* This is actually part of a three way, placed on hold.  Place the third part
03707                on music on hold now */
03708             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03709                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
03710                   S_OR(p->mohsuggest, NULL),
03711                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03712             }
03713             p->subs[SUB_THREEWAY].inthreeway = 0;
03714             /* Make it the call wait now */
03715             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03716             unalloc_sub(p, SUB_THREEWAY);
03717          } else
03718             unalloc_sub(p, SUB_CALLWAIT);
03719       } else if (index == SUB_THREEWAY) {
03720          if (p->subs[SUB_CALLWAIT].inthreeway) {
03721             /* The other party of the three way call is currently in a call-wait state.
03722                Start music on hold for them, and take the main guy out of the third call */
03723             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03724                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
03725                   S_OR(p->mohsuggest, NULL),
03726                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03727             }
03728             p->subs[SUB_CALLWAIT].inthreeway = 0;
03729          }
03730          p->subs[SUB_REAL].inthreeway = 0;
03731          /* If this was part of a three way call index, let us make
03732             another three way call */
03733          unalloc_sub(p, SUB_THREEWAY);
03734       } else {
03735          /* This wasn't any sort of call, but how are we an index? */
03736          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03737       }
03738    }
03739 
03740    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03741       p->owner = NULL;
03742       p->ringt = 0;
03743       p->distinctivering = 0;
03744       p->confirmanswer = 0;
03745       p->cidrings = 1;
03746       p->outgoing = 0;
03747       p->digital = 0;
03748       p->faxhandled = 0;
03749       p->pulsedial = 0;
03750       p->onhooktime = time(NULL);
03751 #ifdef HAVE_PRI
03752       p->proceeding = 0;
03753       p->dialing = 0;
03754       p->progress = 0;
03755       p->alerting = 0;
03756       p->setup_ack = 0;
03757 #endif      
03758       if (p->dsp) {
03759          ast_dsp_free(p->dsp);
03760          p->dsp = NULL;
03761       }
03762 
03763       law = DAHDI_LAW_DEFAULT;
03764       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03765       if (res < 0) 
03766          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03767       /* Perform low level hangup if no owner left */
03768 #ifdef HAVE_OPENR2
03769       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
03770          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
03771          ast_log(LOG_DEBUG, "ast->hangupcause is %d\n", ast->hangupcause);
03772          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
03773             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
03774          } else {
03775             const char *r2causestr = pbx_builtin_getvar_helper(ast,"MFCR2_CAUSE");
03776             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
03777             openr2_call_disconnect_cause_t r2cause = r2cause_user
03778                                ? dahdi_ast_cause_to_r2_cause(r2cause_user)
03779                                : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
03780             dahdi_r2_disconnect_call(p, r2cause);
03781          }
03782       } else if (p->mfcr2call) {
03783          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
03784          p->mfcr2call = 0;
03785       }
03786 #endif
03787 #ifdef HAVE_PRI
03788       if (p->pri) {
03789 #ifdef SUPPORT_USERUSER
03790          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03791 #endif
03792 
03793          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03794          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03795             if (!pri_grab(p, p->pri)) {
03796                if (p->alreadyhungup) {
03797                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
03798 
03799 #ifdef SUPPORT_USERUSER
03800                   pri_call_set_useruser(p->call, useruser);
03801 #endif
03802 
03803                   pri_hangup(p->pri->pri, p->call, -1);
03804                   p->call = NULL;
03805                   if (p->bearer) 
03806                      p->bearer->call = NULL;
03807                } else {
03808                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03809                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03810                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03811 
03812 #ifdef SUPPORT_USERUSER
03813                   pri_call_set_useruser(p->call, useruser);
03814 #endif
03815 
03816                   p->alreadyhungup = 1;
03817                   if (p->bearer)
03818                      p->bearer->alreadyhungup = 1;
03819                   if (cause) {
03820                      if (atoi(cause))
03821                         icause = atoi(cause);
03822                   }
03823                   pri_hangup(p->pri->pri, p->call, icause);
03824                }
03825                if (res < 0) 
03826                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03827                pri_rel(p->pri);        
03828             } else {
03829                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03830                res = -1;
03831             }
03832          } else {
03833             if (p->bearer)
03834                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03835             p->call = NULL;
03836             res = 0;
03837          }
03838       }
03839 #endif
03840       if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_MFCR2))
03841          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03842       if (res < 0) {
03843          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03844       }
03845       switch (p->sig) {
03846       case SIG_FXOGS:
03847       case SIG_FXOLS:
03848       case SIG_FXOKS:
03849          memset(&par, 0, sizeof(par));
03850          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03851          if (!res) {
03852 #if 0
03853             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03854 #endif
03855             /* If they're off hook, try playing congestion */
03856             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03857                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03858             else
03859                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03860          }
03861          break;
03862       case SIG_FXSGS:
03863       case SIG_FXSLS:
03864       case SIG_FXSKS:
03865          /* Make sure we're not made available for at least two seconds assuming
03866             we were actually used for an inbound or outbound call. */
03867          if (ast->_state != AST_STATE_RESERVED) {
03868             time(&p->guardtime);
03869             p->guardtime += 2;
03870          }
03871          break;
03872       default:
03873          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03874       }
03875       if (p->cidspill)
03876          free(p->cidspill);
03877       if (p->sig)
03878          dahdi_disable_ec(p);
03879       x = 0;
03880       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03881       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03882       p->didtdd = 0;
03883       p->cidspill = NULL;
03884       p->callwaitcas = 0;
03885       p->callwaiting = p->permcallwaiting;
03886       p->hidecallerid = p->permhidecallerid;
03887       p->dialing = 0;
03888       p->rdnis[0] = '\0';
03889       update_conf(p);
03890       reset_conf(p);
03891       /* Restore data mode */
03892       if (p->sig == SIG_PRI) {
03893          x = 0;
03894          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03895       }
03896 #ifdef HAVE_PRI
03897       if (p->bearer) {
03898          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03899          /* Free up the bearer channel as well, and
03900             don't use its file descriptor anymore */
03901          update_conf(p->bearer);
03902          reset_conf(p->bearer);
03903          p->bearer->owner = NULL;
03904          p->bearer->realcall = NULL;
03905          p->bearer = NULL;
03906          p->subs[SUB_REAL].dfd = -1;
03907          p->pri = NULL;
03908       }
03909 #endif
03910       if (num_restart_pending == 0)
03911          restart_monitor();
03912    }
03913 
03914    p->callwaitingrepeat = 0;
03915    p->cidcwexpire = 0;
03916    p->oprmode = 0;
03917    ast->tech_pvt = NULL;
03918    ast_mutex_unlock(&p->lock);
03919    ast_module_unref(ast_module_info->self);
03920    if (option_verbose > 2) 
03921       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03922 
03923    ast_mutex_lock(&iflock);
03924 
03925    if (p->restartpending) {
03926       num_restart_pending--;
03927    }
03928 
03929    tmp = iflist;
03930    prev = NULL;
03931    if (p->destroy) {
03932       while (tmp) {
03933          if (tmp == p) {
03934             destroy_channel(prev, tmp, 0);
03935             break;
03936          } else {
03937             prev = tmp;
03938             tmp = tmp->next;
03939          }
03940       }
03941    }
03942    ast_mutex_unlock(&iflock);
03943    return 0;
03944 }
03945 
03946 static int dahdi_answer(struct ast_channel *ast)
03947 {
03948    struct dahdi_pvt *p = ast->tech_pvt;
03949    int res = 0;
03950    int index;
03951    int oldstate = ast->_state;
03952    ast_setstate(ast, AST_STATE_UP);
03953    ast_mutex_lock(&p->lock);
03954    index = dahdi_get_index(ast, p, 0);
03955    if (index < 0)
03956       index = SUB_REAL;
03957    /* nothing to do if a radio channel */
03958    if ((p->radio || (p->oprmode < 0))) {
03959       ast_mutex_unlock(&p->lock);
03960       return 0;
03961    }
03962    switch (p->sig) {
03963    case SIG_FXSLS:
03964    case SIG_FXSGS:
03965    case SIG_FXSKS:
03966       p->ringt = 0;
03967       /* Fall through */
03968    case SIG_EM:
03969    case SIG_EM_E1:
03970    case SIG_EMWINK:
03971    case SIG_FEATD:
03972    case SIG_FEATDMF:
03973    case SIG_FEATDMF_TA:
03974    case SIG_E911:
03975    case SIG_FGC_CAMA:
03976    case SIG_FGC_CAMAMF:
03977    case SIG_FEATB:
03978    case SIG_SF:
03979    case SIG_SFWINK:
03980    case SIG_SF_FEATD:
03981    case SIG_SF_FEATDMF:
03982    case SIG_SF_FEATB:
03983    case SIG_FXOLS:
03984    case SIG_FXOGS:
03985    case SIG_FXOKS:
03986       /* Pick up the line */
03987       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03988       if (p->hanguponpolarityswitch) {
03989          gettimeofday(&p->polaritydelaytv, NULL);
03990       }
03991       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03992       tone_zone_play_tone(p->subs[index].dfd, -1);
03993       p->dialing = 0;
03994       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03995          if (oldstate == AST_STATE_RINGING) {
03996             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03997             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03998             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03999             p->owner = p->subs[SUB_REAL].owner;
04000          }
04001       }
04002       if (p->sig & __DAHDI_SIG_FXS) {
04003          dahdi_enable_ec(p);
04004          dahdi_train_ec(p);
04005       }
04006       break;
04007 #ifdef HAVE_PRI
04008    case SIG_PRI:
04009       /* Send a pri acknowledge */
04010       if (!pri_grab(p, p->pri)) {
04011          p->proceeding = 1;
04012          p->dialing = 0;
04013          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04014          pri_rel(p->pri);
04015       } else {
04016          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04017          res = -1;
04018       }
04019       break;
04020 #endif
04021 #ifdef HAVE_OPENR2
04022    case SIG_MFCR2:
04023       if (!p->mfcr2_accept_on_offer) {
04024          /* the call was not accepted on offer, so it must be accepted now before answering,
04025             the answer will be executed when the callback on_call_accepted is executed */
04026          if (p->mfcr2_charge_calls) {
04027             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with charge on chan %d\n", p->channel);
04028             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04029          } else {
04030             ast_log(LOG_DEBUG, "Accepting MFC/R2 call before answering with no charge on chan %d\n", p->channel);
04031             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04032          }
04033       } else {
04034          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04035          res = dahdi_r2_answer(p);
04036       }
04037       break;
04038 #endif
04039    case 0:
04040       ast_mutex_unlock(&p->lock);
04041       return 0;
04042    default:
04043       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04044       res = -1;
04045    }
04046    ast_mutex_unlock(&p->lock);
04047    return res;
04048 }
04049 
04050 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
04051 {
04052    char *cp;
04053    signed char *scp;
04054    int x;
04055    int index;
04056    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04057    struct oprmode *oprmode;
04058    
04059 
04060    /* all supported options require data */
04061    if (!data || (datalen < 1)) {
04062       errno = EINVAL;
04063       return -1;
04064    }
04065 
04066    switch (option) {
04067    case AST_OPTION_TXGAIN:
04068       scp = (signed char *) data;
04069       index = dahdi_get_index(chan, p, 0);
04070       if (index < 0) {
04071          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04072          return -1;
04073       }
04074       if (option_debug)
04075          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04076       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
04077    case AST_OPTION_RXGAIN:
04078       scp = (signed char *) data;
04079       index = dahdi_get_index(chan, p, 0);
04080       if (index < 0) {
04081          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04082          return -1;
04083       }
04084       if (option_debug)
04085          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04086       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
04087    case AST_OPTION_TONE_VERIFY:
04088       if (!p->dsp)
04089          break;
04090       cp = (char *) data;
04091       switch (*cp) {
04092       case 1:
04093          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04094          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
04095          break;
04096       case 2:
04097          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04098          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
04099          break;
04100       default:
04101          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04102          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
04103          break;
04104       }
04105       break;
04106    case AST_OPTION_TDD:
04107       /* turn on or off TDD */
04108       cp = (char *) data;
04109       p->mate = 0;
04110       if (!*cp) { /* turn it off */
04111          if (option_debug)
04112             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04113          if (p->tdd)
04114             tdd_free(p->tdd);
04115          p->tdd = 0;
04116          break;
04117       }
04118       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
04119          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04120       dahdi_disable_ec(p);
04121       /* otherwise, turn it on */
04122       if (!p->didtdd) { /* if havent done it yet */
04123          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
04124          unsigned char *buf;
04125          int size, res, fd, len;
04126          struct pollfd fds[1];
04127 
04128          buf = mybuf;
04129          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
04130          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
04131          len = 40000;
04132          index = dahdi_get_index(chan, p, 0);
04133          if (index < 0) {
04134             ast_log(LOG_WARNING, "No index in TDD?\n");
04135             return -1;
04136          }
04137          fd = p->subs[index].dfd;
04138          while (len) {
04139             if (ast_check_hangup(chan))
04140                return -1;
04141             size = len;
04142             if (size > READ_SIZE)
04143                size = READ_SIZE;
04144             fds[0].fd = fd;
04145             fds[0].events = POLLPRI | POLLOUT;
04146             fds[0].revents = 0;
04147             res = poll(fds, 1, -1);
04148             if (!res) {
04149                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
04150                continue;
04151             }
04152             /* if got exception */
04153             if (fds[0].revents & POLLPRI)
04154                return -1;
04155             if (!(fds[0].revents & POLLOUT)) {
04156                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
04157                continue;
04158             }
04159             res = write(fd, buf, size);
04160             if (res != size) {
04161                if (res == -1) return -1;
04162                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04163                break;
04164             }
04165             len -= size;
04166             buf += size;
04167          }
04168          p->didtdd = 1; /* set to have done it now */    
04169       }
04170       if (*cp == 2) { /* Mate mode */
04171          if (p->tdd)
04172             tdd_free(p->tdd);
04173          p->tdd = 0;
04174          p->mate = 1;
04175          break;
04176       }     
04177       if (!p->tdd) { /* if we dont have one yet */
04178          p->tdd = tdd_new(); /* allocate one */
04179       }     
04180       break;
04181    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
04182       if (!p->dsp)
04183          break;
04184       cp = (char *) data;
04185       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04186          *cp ? "ON" : "OFF", (int) *cp, chan->name);
04187                 p->dtmfrelax = 0;
04188                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
04189                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04190       break;
04191    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
04192       cp = (char *) data;
04193       if (!*cp) {    
04194          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04195          x = 0;
04196          dahdi_disable_ec(p);
04197       } else {    
04198          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04199          x = 1;
04200       }
04201       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04202          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04203       break;
04204    case AST_OPTION_OPRMODE:  /* Operator services mode */
04205       oprmode = (struct oprmode *) data;
04206       pp = oprmode->peer->tech_pvt;
04207       p->oprmode = pp->oprmode = 0;
04208       /* setup peers */
04209       p->oprpeer = pp;
04210       pp->oprpeer = p;
04211       /* setup modes, if any */
04212       if (oprmode->mode) 
04213       {
04214          pp->oprmode = oprmode->mode;
04215          p->oprmode = -oprmode->mode;
04216       }
04217       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
04218          oprmode->mode, chan->name,oprmode->peer->name);;
04219       break;
04220    case AST_OPTION_ECHOCAN:
04221       cp = (char *) data;
04222       if (*cp) {
04223          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
04224          dahdi_enable_ec(p);
04225       } else {
04226          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
04227          dahdi_disable_ec(p);
04228       }
04229       break;
04230    }
04231    errno = 0;
04232 
04233    return 0;
04234 }
04235 
04236 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
04237 {
04238    struct dahdi_pvt *p = chan->tech_pvt;
04239    
04240    if (!strcasecmp(data, "rxgain")) {
04241       ast_mutex_lock(&p->lock);
04242       snprintf(buf, len, "%f", p->rxgain);
04243       ast_mutex_unlock(&p->lock);   
04244    } else if (!strcasecmp(data, "txgain")) {
04245       ast_mutex_lock(&p->lock);
04246       snprintf(buf, len, "%f", p->txgain);
04247       ast_mutex_unlock(&p->lock);   
04248    } else {
04249       ast_copy_string(buf, "", len);
04250    }
04251    return 0;
04252 }
04253 
04254 
04255 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04256 {
04257    /* Unlink a specific slave or all slaves/masters from a given master */
04258    int x;
04259    int hasslaves;
04260    if (!master)
04261       return;
04262    if (needlock) {
04263       ast_mutex_lock(&master->lock);
04264       if (slave) {
04265          while (ast_mutex_trylock(&slave->lock)) {
04266             DEADLOCK_AVOIDANCE(&master->lock);
04267          }
04268       }
04269    }
04270    hasslaves = 0;
04271    for (x = 0; x < MAX_SLAVES; x++) {
04272       if (master->slaves[x]) {
04273          if (!slave || (master->slaves[x] == slave)) {
04274             /* Take slave out of the conference */
04275             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04276             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04277             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04278             master->slaves[x]->master = NULL;
04279             master->slaves[x] = NULL;
04280          } else
04281             hasslaves = 1;
04282       }
04283       if (!hasslaves)
04284          master->inconference = 0;
04285    }
04286    if (!slave) {
04287       if (master->master) {
04288          /* Take master out of the conference */
04289          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04290          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04291          hasslaves = 0;
04292          for (x = 0; x < MAX_SLAVES; x++) {
04293             if (master->master->slaves[x] == master)
04294                master->master->slaves[x] = NULL;
04295             else if (master->master->slaves[x])
04296                hasslaves = 1;
04297          }
04298          if (!hasslaves)
04299             master->master->inconference = 0;
04300       }
04301       master->master = NULL;
04302    }
04303    update_conf(master);
04304    if (needlock) {
04305       if (slave)
04306          ast_mutex_unlock(&slave->lock);
04307       ast_mutex_unlock(&master->lock);
04308    }
04309 }
04310 
04311 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04312    int x;
04313    if (!slave || !master) {
04314       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04315       return;
04316    }
04317    for (x = 0; x < MAX_SLAVES; x++) {
04318       if (!master->slaves[x]) {
04319          master->slaves[x] = slave;
04320          break;
04321       }
04322    }
04323    if (x >= MAX_SLAVES) {
04324       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04325       master->slaves[MAX_SLAVES - 1] = slave;
04326    }
04327    if (slave->master) 
04328       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04329    slave->master = master;
04330    
04331    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04332 }
04333 
04334 static void disable_dtmf_detect(struct dahdi_pvt *p)
04335 {
04336 #ifdef DAHDI_TONEDETECT
04337    int val;
04338 #endif
04339 
04340    p->ignoredtmf = 1;
04341 
04342 #ifdef DAHDI_TONEDETECT
04343    val = 0;
04344    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04345 #endif      
04346    if (!p->hardwaredtmf && p->dsp) {
04347       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04348       ast_dsp_set_features(p->dsp, p->dsp_features);
04349    }
04350 }
04351 
04352 static void enable_dtmf_detect(struct dahdi_pvt *p)
04353 {
04354 #ifdef DAHDI_TONEDETECT
04355    int val;
04356 #endif
04357 
04358    if (p->channel == CHAN_PSEUDO)
04359       return;
04360 
04361    p->ignoredtmf = 0;
04362 
04363 #ifdef DAHDI_TONEDETECT
04364    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04365    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04366 #endif      
04367    if (!p->hardwaredtmf && p->dsp) {
04368       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04369       ast_dsp_set_features(p->dsp, p->dsp_features);
04370    }
04371 }
04372 
04373 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)
04374 {
04375    struct ast_channel *who;
04376    struct dahdi_pvt *p0, *p1, *op0, *op1;
04377    struct dahdi_pvt *master = NULL, *slave = NULL;
04378    struct ast_frame *f;
04379    int inconf = 0;
04380    int nothingok = 1;
04381    int ofd0, ofd1;
04382    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04383    int os0 = -1, os1 = -1;
04384    int priority = 0;
04385    struct ast_channel *oc0, *oc1;
04386    enum ast_bridge_result res;
04387 
04388 #ifdef PRI_2BCT
04389    int triedtopribridge = 0;
04390    q931_call *q931c0 = NULL, *q931c1 = NULL;
04391 #endif
04392 
04393    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
04394       There is code below to handle it properly until DTMF is actually seen,
04395       but due to currently unresolved issues it's ignored...
04396    */
04397 
04398    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04399       return AST_BRIDGE_FAILED_NOWARN;
04400 
04401    ast_mutex_lock(&c0->lock);
04402    while (ast_mutex_trylock(&c1->lock)) {
04403       DEADLOCK_AVOIDANCE(&c0->lock);
04404    }
04405 
04406    p0 = c0->tech_pvt;
04407    p1 = c1->tech_pvt;
04408    /* cant do pseudo-channels here */
04409    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04410       ast_mutex_unlock(&c0->lock);
04411       ast_mutex_unlock(&c1->lock);
04412       return AST_BRIDGE_FAILED_NOWARN;
04413    }
04414 
04415    oi0 = dahdi_get_index(c0, p0, 0);
04416    oi1 = dahdi_get_index(c1, p1, 0);
04417    if ((oi0 < 0) || (oi1 < 0)) {
04418       ast_mutex_unlock(&c0->lock);
04419       ast_mutex_unlock(&c1->lock);
04420       return AST_BRIDGE_FAILED;
04421    }
04422 
04423    op0 = p0 = c0->tech_pvt;
04424    op1 = p1 = c1->tech_pvt;
04425    ofd0 = c0->fds[0];
04426    ofd1 = c1->fds[0];
04427    oc0 = p0->owner;
04428    oc1 = p1->owner;
04429 
04430    if (ast_mutex_trylock(&p0->lock)) {
04431       /* Don't block, due to potential for deadlock */
04432       ast_mutex_unlock(&c0->lock);
04433       ast_mutex_unlock(&c1->lock);
04434       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04435       return AST_BRIDGE_RETRY;
04436    }
04437    if (ast_mutex_trylock(&p1->lock)) {
04438       /* Don't block, due to potential for deadlock */
04439       ast_mutex_unlock(&p0->lock);
04440       ast_mutex_unlock(&c0->lock);
04441       ast_mutex_unlock(&c1->lock);
04442       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04443       return AST_BRIDGE_RETRY;
04444    }
04445 
04446    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04447       if (p0->owner && p1->owner) {
04448          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
04449          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04450             master = p0;
04451             slave = p1;
04452             inconf = 1;
04453          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04454             master = p1;
04455             slave = p0;
04456             inconf = 1;
04457          } else {
04458             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
04459             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04460                p0->channel,
04461                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04462                p0->subs[SUB_REAL].inthreeway, p0->channel,
04463                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04464                p1->subs[SUB_REAL].inthreeway);
04465          }
04466          nothingok = 0;
04467       }
04468    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04469       if (p1->subs[SUB_THREEWAY].inthreeway) {
04470          master = p1;
04471          slave = p0;
04472          nothingok = 0;
04473       }
04474    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04475       if (p0->subs[SUB_THREEWAY].inthreeway) {
04476          master = p0;
04477          slave = p1;
04478          nothingok = 0;
04479       }
04480    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04481       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
04482          don't put us in anything */
04483       if (p1->subs[SUB_CALLWAIT].inthreeway) {
04484          master = p1;
04485          slave = p0;
04486          nothingok = 0;
04487       }
04488    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04489       /* Same as previous */
04490       if (p0->subs[SUB_CALLWAIT].inthreeway) {
04491          master = p0;
04492          slave = p1;
04493          nothingok = 0;
04494       }
04495    }
04496    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
04497       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04498    if (master && slave) {
04499       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
04500          in an active threeway call with a channel that is ringing, we should
04501          indicate ringing. */
04502       if ((oi1 == SUB_THREEWAY) && 
04503           p1->subs[SUB_THREEWAY].inthreeway && 
04504           p1->subs[SUB_REAL].owner && 
04505           p1->subs[SUB_REAL].inthreeway && 
04506           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04507          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04508          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04509          os1 = p1->subs[SUB_REAL].owner->_state;
04510       } else {
04511          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04512          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04513       }
04514       if ((oi0 == SUB_THREEWAY) && 
04515           p0->subs[SUB_THREEWAY].inthreeway && 
04516           p0->subs[SUB_REAL].owner && 
04517           p0->subs[SUB_REAL].inthreeway && 
04518           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04519          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04520          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04521          os0 = p0->subs[SUB_REAL].owner->_state;
04522       } else {
04523          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04524          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04525       }
04526       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04527          if (!p0->echocanbridged || !p1->echocanbridged) {
04528             /* Disable echo cancellation if appropriate */
04529             dahdi_disable_ec(p0);
04530             dahdi_disable_ec(p1);
04531          }
04532       }
04533       dahdi_link(slave, master);
04534       master->inconference = inconf;
04535    } else if (!nothingok)
04536       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04537 
04538    update_conf(p0);
04539    update_conf(p1);
04540    t0 = p0->subs[SUB_REAL].inthreeway;
04541    t1 = p1->subs[SUB_REAL].inthreeway;
04542 
04543    ast_mutex_unlock(&p0->lock);
04544    ast_mutex_unlock(&p1->lock);
04545 
04546    ast_mutex_unlock(&c0->lock);
04547    ast_mutex_unlock(&c1->lock);
04548 
04549    /* Native bridge failed */
04550    if ((!master || !slave) && !nothingok) {
04551       dahdi_enable_ec(p0);
04552       dahdi_enable_ec(p1);
04553       return AST_BRIDGE_FAILED;
04554    }
04555    
04556    if (option_verbose > 2) 
04557       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
04558 
04559    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04560       disable_dtmf_detect(op0);
04561 
04562    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04563       disable_dtmf_detect(op1);
04564 
04565    for (;;) {
04566       struct ast_channel *c0_priority[2] = {c0, c1};
04567       struct ast_channel *c1_priority[2] = {c1, c0};
04568 
04569       /* Here's our main loop...  Start by locking things, looking for private parts, 
04570          and then balking if anything is wrong */
04571       ast_mutex_lock(&c0->lock);
04572       while (ast_mutex_trylock(&c1->lock)) {
04573          DEADLOCK_AVOIDANCE(&c0->lock);
04574       }
04575 
04576       p0 = c0->tech_pvt;
04577       p1 = c1->tech_pvt;
04578 
04579       if (op0 == p0)
04580          i0 = dahdi_get_index(c0, p0, 1);
04581       if (op1 == p1)
04582          i1 = dahdi_get_index(c1, p1, 1);
04583       ast_mutex_unlock(&c0->lock);
04584       ast_mutex_unlock(&c1->lock);
04585 
04586       if (!timeoutms || 
04587           (op0 != p0) ||
04588           (op1 != p1) || 
04589           (ofd0 != c0->fds[0]) || 
04590           (ofd1 != c1->fds[0]) ||
04591           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
04592           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
04593           (oc0 != p0->owner) || 
04594           (oc1 != p1->owner) ||
04595           (t0 != p0->subs[SUB_REAL].inthreeway) ||
04596           (t1 != p1->subs[SUB_REAL].inthreeway) ||
04597           (oi0 != i0) ||
04598           (oi1 != i1)) {
04599          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04600             op0->channel, oi0, op1->channel, oi1);
04601          res = AST_BRIDGE_RETRY;
04602          goto return_from_bridge;
04603       }
04604 
04605 #ifdef PRI_2BCT
04606       q931c0 = p0->call;
04607       q931c1 = p1->call;
04608       if (p0->transfer && p1->transfer 
04609           && q931c0 && q931c1 
04610           && !triedtopribridge) {
04611          pri_channel_bridge(q931c0, q931c1);
04612          triedtopribridge = 1;
04613       }
04614 #endif
04615 
04616       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04617       if (!who) {
04618          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
04619          continue;
04620       }
04621       f = ast_read(who);
04622       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04623          *fo = f;
04624          *rc = who;
04625          res = AST_BRIDGE_COMPLETE;
04626          goto return_from_bridge;
04627       }
04628       if (f->frametype == AST_FRAME_DTMF) {
04629          if ((who == c0) && p0->pulsedial) {
04630             ast_write(c1, f);
04631          } else if ((who == c1) && p1->pulsedial) {
04632             ast_write(c0, f);
04633          } else {
04634             *fo = f;
04635             *rc = who;
04636             res = AST_BRIDGE_COMPLETE;
04637             goto return_from_bridge;
04638          }
04639       }
04640       ast_frfree(f);
04641       
04642       /* Swap who gets priority */
04643       priority = !priority;
04644    }
04645 
04646 return_from_bridge:
04647    if (op0 == p0)
04648       dahdi_enable_ec(p0);
04649 
04650    if (op1 == p1)
04651       dahdi_enable_ec(p1);
04652 
04653    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04654       enable_dtmf_detect(op0);
04655 
04656    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04657       enable_dtmf_detect(op1);
04658 
04659    dahdi_unlink(slave, master, 1);
04660 
04661    return res;
04662 }
04663 
04664 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04665 {
04666    struct dahdi_pvt *p = newchan->tech_pvt;
04667    int x;
04668    ast_mutex_lock(&p->lock);
04669    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
04670    if (p->owner == oldchan) {
04671       p->owner = newchan;
04672    }
04673    for (x = 0; x < 3; x++)
04674       if (p->subs[x].owner == oldchan) {
04675          if (!x)
04676             dahdi_unlink(NULL, p, 0);
04677          p->subs[x].owner = newchan;
04678       }
04679    if (newchan->_state == AST_STATE_RINGING) 
04680       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04681    update_conf(p);
04682    ast_mutex_unlock(&p->lock);
04683    return 0;
04684 }
04685 
04686 static int dahdi_ring_phone(struct dahdi_pvt *p)
04687 {
04688    int x;
04689    int res;
04690    /* Make sure our transmit state is on hook */
04691    x = 0;
04692    x = DAHDI_ONHOOK;
04693    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04694    do {
04695       x = DAHDI_RING;
04696       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04697       if (res) {
04698          switch (errno) {
04699          case EBUSY:
04700          case EINTR:
04701             /* Wait just in case */
04702             usleep(10000);
04703             continue;
04704          case EINPROGRESS:
04705             res = 0;
04706             break;
04707          default:
04708             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04709             res = 0;
04710          }
04711       }
04712    } while (res);
04713    return res;
04714 }
04715 
04716 static void *ss_thread(void *data);
04717 
04718 static int attempt_transfer(struct dahdi_pvt *p)
04719 {
04720    /* In order to transfer, we need at least one of the channels to
04721       actually be in a call bridge.  We can't conference two applications
04722       together (but then, why would we want to?) */
04723    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04724       /* The three-way person we're about to transfer to could still be in MOH, so
04725          stop if now if appropriate */
04726       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04727          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04728       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04729          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04730       }
04731       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04732          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04733       }
04734        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04735          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04736                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04737          return -1;
04738       }
04739       /* Orphan the channel after releasing the lock */
04740       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04741       unalloc_sub(p, SUB_THREEWAY);
04742    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04743       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04744       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04745          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04746       }
04747       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04748          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04749       }
04750       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04751          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04752                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04753          return -1;
04754       }
04755       /* Three-way is now the REAL */
04756       swap_subs(p, SUB_THREEWAY, SUB_REAL);
04757       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
04758       unalloc_sub(p, SUB_THREEWAY);
04759       /* Tell the caller not to hangup */
04760       return 1;
04761    } else {
04762       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04763                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04764       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04765       return -1;
04766    }
04767    return 0;
04768 }
04769 
04770 static int check_for_conference(struct dahdi_pvt *p)
04771 {
04772    struct dahdi_confinfo ci;
04773    /* Fine if we already have a master, etc */
04774    if (p->master || (p->confno > -1))
04775       return 0;
04776    memset(&ci, 0, sizeof(ci));
04777    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04778       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04779       return 0;
04780    }
04781    /* If we have no master and don't have a confno, then 
04782       if we're in a conference, it's probably a MeetMe room or
04783       some such, so don't let us 3-way out! */
04784    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04785       if (option_verbose > 2) 
04786          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
04787       return 1;
04788    }
04789    return 0;
04790 }
04791 
04792 static int get_alarms(struct dahdi_pvt *p)
04793 {
04794    int res;
04795    struct dahdi_spaninfo zi;
04796 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04797    /*
04798     * The conditional compilation is needed only in asterisk-1.4 for
04799     * backward compatibility with old zaptel drivers that don't have
04800     * a DAHDI_PARAMS.chan_alarms field.
04801     */
04802    struct dahdi_params params;
04803 #endif
04804 
04805    memset(&zi, 0, sizeof(zi));
04806    zi.spanno = p->span;
04807 
04808    /* First check for span alarms */
04809    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
04810       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04811       return 0;
04812    }
04813    if (zi.alarms != DAHDI_ALARM_NONE)
04814       return zi.alarms;
04815 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04816    /* No alarms on the span. Check for channel alarms. */
04817    memset(&params, 0, sizeof(params));
04818    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04819       return params.chan_alarms;
04820    /* ioctl failed */
04821    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04822 #endif
04823    return DAHDI_ALARM_NONE;
04824 }
04825 
04826 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
04827 {
04828    struct dahdi_pvt *p = ast->tech_pvt;
04829    struct ast_frame *f = *dest;
04830 
04831    if (option_debug)
04832       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04833 
04834    if (p->confirmanswer) {
04835       if (option_debug)
04836          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04837       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04838          of a DTMF digit */
04839       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04840       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04841       *dest = &p->subs[index].f;
04842       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04843       p->confirmanswer = 0;
04844    } else if (p->callwaitcas) {
04845       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04846          if (option_debug)
04847             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04848          if (p->cidspill)
04849             free(p->cidspill);
04850          send_cwcidspill(p);
04851       }
04852       if ((f->subclass != 'm') && (f->subclass != 'u')) 
04853          p->callwaitcas = 0;
04854       p->subs[index].f.frametype = AST_FRAME_NULL;
04855       p->subs[index].f.subclass = 0;
04856       *dest = &p->subs[index].f;
04857    } else if (f->subclass == 'f') {
04858       /* Fax tone -- Handle and return NULL */
04859       if ((p->callprogress & 0x6) && !p->faxhandled) {
04860          p->faxhandled = 1;
04861          if (strcmp(ast->exten, "fax")) {
04862             const char *target_context = S_OR(ast->macrocontext, ast->context);
04863 
04864             /* We need to unlock 'ast' here because ast_exists_extension has the
04865              * potential to start autoservice on the channel. Such action is prone
04866              * to deadlock.
04867              */
04868             ast_mutex_unlock(&p->lock);
04869             ast_channel_unlock(ast);
04870             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04871                ast_channel_lock(ast);
04872                ast_mutex_lock(&p->lock);
04873                if (option_verbose > 2)
04874                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04875                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04876                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04877                if (ast_async_goto(ast, target_context, "fax", 1))
04878                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04879             } else {
04880                ast_channel_lock(ast);
04881                ast_mutex_lock(&p->lock);
04882                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04883             }
04884          } else if (option_debug)
04885             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04886       } else if (option_debug)
04887             ast_log(LOG_DEBUG, "Fax already handled\n");
04888       dahdi_confmute(p, 0);
04889       p->subs[index].f.frametype = AST_FRAME_NULL;
04890       p->subs[index].f.subclass = 0;
04891       *dest = &p->subs[index].f;
04892    } else if (f->subclass == 'm') {
04893       /* Confmute request */
04894       dahdi_confmute(p, 1);
04895       p->subs[index].f.frametype = AST_FRAME_NULL;
04896       p->subs[index].f.subclass = 0;
04897       *dest = &p->subs[index].f;    
04898    } else if (f->subclass == 'u') {
04899       /* Unmute */
04900       dahdi_confmute(p, 0);
04901       p->subs[index].f.frametype = AST_FRAME_NULL;
04902       p->subs[index].f.subclass = 0;
04903       *dest = &p->subs[index].f;    
04904    } else
04905       dahdi_confmute(p, 0);
04906 }
04907          
04908 static void handle_alarms(struct dahdi_pvt *p, int alarms)
04909 {
04910    const char *alarm_str = alarm2str(alarms);
04911    
04912    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
04913     * doesn't know what to do with it.  Don't confuse users with log messages. */
04914    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04915       p->unknown_alarm = 1;
04916       return;
04917    } else {
04918       p->unknown_alarm = 0;
04919    }
04920    
04921    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04922    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04923             "Alarm: %s\r\n"
04924             "Channel: %d\r\n",
04925             alarm_str, p->channel);
04926 }
04927 
04928 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04929 {
04930    int res, x;
04931    int index, mysig;
04932    char *c;
04933    struct dahdi_pvt *p = ast->tech_pvt;
04934    pthread_t threadid;
04935    pthread_attr_t attr;
04936    struct ast_channel *chan;
04937    struct ast_frame *f;
04938 
04939    index = dahdi_get_index(ast, p, 0);
04940    mysig = p->sig;
04941    if (p->outsigmod > -1)
04942       mysig = p->outsigmod;
04943    p->subs[index].f.frametype = AST_FRAME_NULL;
04944    p->subs[index].f.subclass = 0;
04945    p->subs[index].f.datalen = 0;
04946    p->subs[index].f.samples = 0;
04947    p->subs[index].f.mallocd = 0;
04948    p->subs[index].f.offset = 0;
04949    p->subs[index].f.src = "dahdi_handle_event";
04950    p->subs[index].f.data = NULL;
04951    f = &p->subs[index].f;
04952 
04953    if (index < 0)
04954       return &p->subs[index].f;
04955    if (p->fake_event) {
04956       res = p->fake_event;
04957       p->fake_event = 0;
04958    } else
04959       res = dahdi_get_event(p->subs[index].dfd);
04960 
04961    if (option_debug)
04962       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04963 
04964    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04965       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04966 
04967       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04968 #ifdef HAVE_PRI
04969       if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04970          /* absorb event */
04971       } else {
04972 #endif
04973          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04974          p->subs[index].f.subclass = res & 0xff;
04975 #ifdef HAVE_PRI
04976       }
04977 #endif
04978       dahdi_handle_dtmfup(ast, index, &f);
04979       return f;
04980    }
04981 
04982    if (res & DAHDI_EVENT_DTMFDOWN) {
04983       if (option_debug)
04984          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04985       /* Mute conference */
04986       dahdi_confmute(p, 1);
04987       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04988       p->subs[index].f.subclass = res & 0xff;
04989       return &p->subs[index].f;
04990    }
04991 
04992    switch (res) {
04993 #ifdef DAHDI_EVENT_EC_DISABLED
04994       case DAHDI_EVENT_EC_DISABLED:
04995          if (option_verbose > 2) 
04996             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04997          p->echocanon = 0;
04998          break;
04999 #endif
05000       case DAHDI_EVENT_BITSCHANGED:
05001 #ifdef HAVE_OPENR2
05002          if (p->sig != SIG_MFCR2) {
05003             ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05004          } else {
05005             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05006             openr2_chan_handle_cas(p->r2chan);
05007          }
05008 #else
05009          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
05010 #endif
05011       case DAHDI_EVENT_PULSE_START:
05012          /* Stop tone if there's a pulse start and the PBX isn't started */
05013          if (!ast->pbx)
05014             tone_zone_play_tone(p->subs[index].dfd, -1);
05015          break;   
05016       case DAHDI_EVENT_DIALCOMPLETE:
05017 #ifdef HAVE_OPENR2
05018          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05019             /* we don't need to do anything for this event for R2 signaling 
05020                if the call is being setup */
05021             break;
05022          }
05023 #endif
05024          if (p->inalarm) break;
05025          if ((p->radio || (p->oprmode < 0))) break;
05026          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
05027             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05028             return NULL;
05029          }
05030          if (!x) { /* if not still dialing in driver */
05031             dahdi_enable_ec(p);
05032             if (p->echobreak) {
05033                dahdi_train_ec(p);
05034                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05035                p->dop.op = DAHDI_DIAL_OP_REPLACE;
05036                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05037                p->echobreak = 0;
05038             } else {
05039                p->dialing = 0;
05040                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05041                   /* if thru with dialing after offhook */
05042                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05043                      ast_setstate(ast, AST_STATE_UP);
05044                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05045                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05046                      break;
05047                   } else { /* if to state wait for offhook to dial rest */
05048                      /* we now wait for off hook */
05049                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05050                   }
05051                }
05052                if (ast->_state == AST_STATE_DIALING) {
05053                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05054                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
05055                   } 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)))) {
05056                      ast_setstate(ast, AST_STATE_RINGING);
05057                   } else if (!p->answeronpolarityswitch) {
05058                      ast_setstate(ast, AST_STATE_UP);
05059                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
05060                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05061                      /* If aops=0 and hops=1, this is necessary */
05062                      p->polarity = POLARITY_REV;
05063                   } else {
05064                      /* Start clean, so we can catch the change to REV polarity when party answers */
05065                      p->polarity = POLARITY_IDLE;
05066                   }
05067                }
05068             }
05069          }
05070          break;
05071       case DAHDI_EVENT_ALARM:
05072 #ifdef HAVE_PRI
05073          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05074             /* T309 is not enabled : hangup calls when alarm occurs */
05075             if (p->call) {
05076                if (p->pri && p->pri->pri) {
05077                   if (!pri_grab(p, p->pri)) {
05078                      pri_hangup(p->pri->pri, p->call, -1);
05079                      pri_destroycall(p->pri->pri, p->call);
05080                      p->call = NULL;
05081                      pri_rel(p->pri);
05082                   } else
05083                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05084                } else
05085                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05086             }
05087             if (p->owner)
05088                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05089          }
05090          if (p->bearer)
05091             p->bearer->inalarm = 1;
05092          else
05093 #endif
05094          p->inalarm = 1;
05095          res = get_alarms(p);
05096          handle_alarms(p, res);
05097 #ifdef HAVE_PRI
05098          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05099             /* fall through intentionally */
05100          } else {
05101             break;
05102          }
05103 #endif
05104 #ifdef HAVE_OPENR2
05105          if (p->sig == SIG_MFCR2)
05106             break;
05107 #endif
05108       case DAHDI_EVENT_ONHOOK:
05109          if (p->radio) {
05110             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05111             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05112             break;
05113          }
05114          if (p->oprmode < 0)
05115          {
05116             if (p->oprmode != -1) break;
05117             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05118             {
05119                /* Make sure it starts ringing */
05120                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05121                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05122                save_conference(p->oprpeer);
05123                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05124             }
05125             break;
05126          }
05127          switch (p->sig) {
05128          case SIG_FXOLS:
05129          case SIG_FXOGS:
05130          case SIG_FXOKS:
05131             p->onhooktime = time(NULL);
05132             p->msgstate = -1;
05133             /* Check for some special conditions regarding call waiting */
05134             if (index == SUB_REAL) {
05135                /* The normal line was hung up */
05136                if (p->subs[SUB_CALLWAIT].owner) {
05137                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
05138                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05139                   if (option_verbose > 2) 
05140                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05141                   unalloc_sub(p, SUB_CALLWAIT); 
05142 #if 0
05143                   p->subs[index].needanswer = 0;
05144                   p->subs[index].needringing = 0;
05145 #endif                  
05146                   p->callwaitingrepeat = 0;
05147                   p->cidcwexpire = 0;
05148                   p->owner = NULL;
05149                   /* Don't start streaming audio yet if the incoming call isn't up yet */
05150                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05151                      p->dialing = 1;
05152                   dahdi_ring_phone(p);
05153                } else if (p->subs[SUB_THREEWAY].owner) {
05154                   unsigned int mssinceflash;
05155                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
05156                      the private structure -- not especially easy or clean */
05157                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
05158                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
05159                      ast_mutex_unlock(&p->lock);
05160                      DEADLOCK_AVOIDANCE(&ast->lock);
05161                      /* We can grab ast and p in that order, without worry.  We should make sure
05162                         nothing seriously bad has happened though like some sort of bizarre double
05163                         masquerade! */
05164                      ast_mutex_lock(&p->lock);
05165                      if (p->owner != ast) {
05166                         ast_log(LOG_WARNING, "This isn't good...\n");
05167                         return NULL;
05168                      }
05169                   }
05170                   if (!p->subs[SUB_THREEWAY].owner) {
05171                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05172                      return NULL;
05173                   }
05174                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05175                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
05176                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
05177                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
05178                         hanging up.  Hangup both channels now */
05179                      if (p->subs[SUB_THREEWAY].owner)
05180                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
05181                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05182                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05183                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05184                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05185                      if (p->transfer) {
05186                         /* In any case this isn't a threeway call anymore */
05187                         p->subs[SUB_REAL].inthreeway = 0;
05188                         p->subs[SUB_THREEWAY].inthreeway = 0;
05189                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
05190                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05191                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05192                            /* Swap subs and dis-own channel */
05193                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
05194                            p->owner = NULL;
05195                            /* Ring the phone */
05196                            dahdi_ring_phone(p);
05197                         } else {
05198                            if ((res = attempt_transfer(p)) < 0) {
05199                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05200                               if (p->subs[SUB_THREEWAY].owner)
05201                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05202                            } else if (res) {
05203                               /* Don't actually hang up at this point */
05204                               if (p->subs[SUB_THREEWAY].owner)
05205                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05206                               break;
05207                            }
05208                         }
05209                      } else {
05210                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05211                         if (p->subs[SUB_THREEWAY].owner)
05212                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05213                      }
05214                   } else {
05215                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
05216                      /* Swap subs and dis-own channel */
05217                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05218                      p->owner = NULL;
05219                      /* Ring the phone */
05220                      dahdi_ring_phone(p);
05221                   }
05222                }
05223             } else {
05224                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
05225             }
05226             /* Fall through */
05227          default:
05228             dahdi_disable_ec(p);
05229             return NULL;
05230          }
05231          break;
05232       case DAHDI_EVENT_RINGOFFHOOK:
05233          if (p->inalarm) break;
05234          if (p->oprmode < 0)
05235          {
05236             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05237             {
05238                /* Make sure it stops ringing */
05239                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05240                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
05241                restore_conference(p->oprpeer);
05242             }
05243             break;
05244          }
05245          if (p->radio)
05246          {
05247             p->subs[index].f.frametype = AST_FRAME_CONTROL;
05248             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05249             break;
05250          }
05251          /* for E911, its supposed to wait for offhook then dial
05252             the second half of the dial string */
05253          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
05254             c = strchr(p->dialdest, '/');
05255             if (c)
05256                c++;
05257             else
05258                c = p->dialdest;
05259             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05260             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05261             if (strlen(p->dop.dialstr) > 4) {
05262                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05263                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05264                p->echorest[sizeof(p->echorest) - 1] = '\0';
05265                p->echobreak = 1;
05266                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05267             } else
05268                p->echobreak = 0;
05269             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05270                int saveerr = errno;
05271 
05272                x = DAHDI_ONHOOK;
05273                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05274                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05275                return NULL;
05276                }
05277             p->dialing = 1;
05278             return &p->subs[index].f;
05279          }
05280          switch (p->sig) {
05281          case SIG_FXOLS:
05282          case SIG_FXOGS:
05283          case SIG_FXOKS:
05284             switch (ast->_state) {
05285             case AST_STATE_RINGING:
05286                dahdi_enable_ec(p);
05287                dahdi_train_ec(p);
05288                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05289                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05290                /* Make sure it stops ringing */
05291                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05292                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
05293                if (p->cidspill) {
05294                   /* Cancel any running CallerID spill */
05295                   free(p->cidspill);
05296                   p->cidspill = NULL;
05297                }
05298                p->dialing = 0;
05299                p->callwaitcas = 0;
05300                if (p->confirmanswer) {
05301                   /* Ignore answer if "confirm answer" is enabled */
05302                   p->subs[index].f.frametype = AST_FRAME_NULL;
05303                   p->subs[index].f.subclass = 0;
05304                } else if (!ast_strlen_zero(p->dop.dialstr)) {
05305                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
05306                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05307                   if (res < 0) {
05308                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05309                      p->dop.dialstr[0] = '\0';
05310                      return NULL;
05311                   } else {
05312                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05313                      p->subs[index].f.frametype = AST_FRAME_NULL;
05314                      p->subs[index].f.subclass = 0;
05315                      p->dialing = 1;
05316                   }
05317                   p->dop.dialstr[0] = '\0';
05318                   ast_setstate(ast, AST_STATE_DIALING);
05319                } else
05320                   ast_setstate(ast, AST_STATE_UP);
05321                return &p->subs[index].f;
05322             case AST_STATE_DOWN:
05323                ast_setstate(ast, AST_STATE_RING);
05324                ast->rings = 1;
05325                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05326                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
05327                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
05328                return &p->subs[index].f;
05329             case AST_STATE_UP:
05330                /* Make sure it stops ringing */
05331                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05332                /* Okay -- probably call waiting*/
05333                if (ast_bridged_channel(p->owner))
05334                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05335                p->subs[index].needunhold = 1;
05336                break;
05337             case AST_STATE_RESERVED:
05338                /* Start up dialtone */
05339                if (has_voicemail(p))
05340                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05341                else
05342                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05343                break;
05344             default:
05345                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05346             }
05347             break;
05348          case SIG_FXSLS:
05349          case SIG_FXSGS:
05350          case SIG_FXSKS:
05351             if (ast->_state == AST_STATE_RING) {
05352                p->ringt = p->ringt_base;
05353             }
05354 
05355             /* Fall through */
05356          case SIG_EM:
05357          case SIG_EM_E1:
05358          case SIG_EMWINK:
05359          case SIG_FEATD:
05360          case SIG_FEATDMF:
05361          case SIG_FEATDMF_TA:
05362          case SIG_E911:
05363          case SIG_FGC_CAMA:
05364          case SIG_FGC_CAMAMF:
05365          case SIG_FEATB:
05366          case SIG_SF:
05367          case SIG_SFWINK:
05368          case SIG_SF_FEATD:
05369          case SIG_SF_FEATDMF:
05370          case SIG_SF_FEATB:
05371             if (ast->_state == AST_STATE_PRERING)
05372                ast_setstate(ast, AST_STATE_RING);
05373             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05374                if (option_debug)
05375                   ast_log(LOG_DEBUG, "Ring detected\n");
05376                p->subs[index].f.frametype = AST_FRAME_CONTROL;
05377                p->subs[index].f.subclass = AST_CONTROL_RING;
05378             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05379                if (option_debug)
05380                   ast_log(LOG_DEBUG, "Line answered\n");
05381                if (p->confirmanswer) {
05382                   p->subs[index].f.frametype = AST_FRAME_NULL;
05383                   p->subs[index].f.subclass = 0;
05384                } else {
05385                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
05386                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05387                   ast_setstate(ast, AST_STATE_UP);
05388                }
05389             } else if (ast->_state != AST_STATE_RING)
05390                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05391             break;
05392          default:
05393             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05394          }
05395          break;
05396 #ifdef DAHDI_EVENT_RINGBEGIN
05397       case DAHDI_EVENT_RINGBEGIN:
05398          switch (p->sig) {
05399          case SIG_FXSLS:
05400          case SIG_FXSGS:
05401          case SIG_FXSKS:
05402             if (ast->_state == AST_STATE_RING) {
05403                p->ringt = p->ringt_base;
05404             }
05405             break;
05406          }
05407          break;
05408 #endif         
05409       case DAHDI_EVENT_RINGEROFF:
05410          if (p->inalarm) break;
05411          if ((p->radio || (p->oprmode < 0))) break;
05412          ast->rings++;
05413          if ((ast->rings > p->cidrings) && (p->cidspill)) {
05414             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
05415             free(p->cidspill);
05416             p->cidspill = NULL;
05417             p->callwaitcas = 0;
05418          }
05419          p->subs[index].f.frametype = AST_FRAME_CONTROL;
05420          p->subs[index].f.subclass = AST_CONTROL_RINGING;
05421          break;
05422       case DAHDI_EVENT_RINGERON:
05423          break;
05424       case DAHDI_EVENT_NOALARM:
05425          p->inalarm = 0;
05426 #ifdef HAVE_PRI
05427          /* Extremely unlikely but just in case */
05428          if (p->bearer)
05429             p->bearer->inalarm = 0;
05430 #endif            
05431          if (!p->unknown_alarm) {
05432             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05433             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05434                "Channel: %d\r\n", p->channel);
05435          } else {
05436             p->unknown_alarm = 0;
05437          }
05438          break;
05439       case DAHDI_EVENT_WINKFLASH:
05440          if (p->inalarm) break;
05441          if (p->radio) break;
05442          if (p->oprmode < 0) break;
05443          if (p->oprmode > 1)
05444          {
05445             struct dahdi_params par;
05446 
05447             memset(&par, 0, sizeof(par));
05448             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05449             {
05450                if (!par.rxisoffhook)
05451                {
05452                   /* Make sure it stops ringing */
05453                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05454                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05455                   save_conference(p);
05456                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05457                }
05458             }
05459             break;
05460          }
05461          /* Remember last time we got a flash-hook */
05462          gettimeofday(&p->flashtime, NULL);
05463          switch (mysig) {
05464          case SIG_FXOLS:
05465          case SIG_FXOGS:
05466          case SIG_FXOKS:
05467             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05468                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05469             p->callwaitcas = 0;
05470 
05471             if (index != SUB_REAL) {
05472                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
05473                goto winkflashdone;
05474             }
05475             
05476             if (p->subs[SUB_CALLWAIT].owner) {
05477                /* Swap to call-wait */
05478                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05479                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05480                p->owner = p->subs[SUB_REAL].owner;
05481                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
05482                if (p->owner->_state == AST_STATE_RINGING) {
05483                   ast_setstate(p->owner, AST_STATE_UP);
05484                   p->subs[SUB_REAL].needanswer = 1;
05485                }
05486                p->callwaitingrepeat = 0;
05487                p->cidcwexpire = 0;
05488                /* Start music on hold if appropriate */
05489                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05490                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05491                      S_OR(p->mohsuggest, NULL),
05492                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05493                }
05494                p->subs[SUB_CALLWAIT].needhold = 1;
05495                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05496                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05497                      S_OR(p->mohsuggest, NULL),
05498                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05499                }
05500                p->subs[SUB_REAL].needunhold = 1;
05501             } else if (!p->subs[SUB_THREEWAY].owner) {
05502                if (!p->threewaycalling) {
05503                   /* Just send a flash if no 3-way calling */
05504                   p->subs[SUB_REAL].needflash = 1;
05505                   goto winkflashdone;
05506                } else if (!check_for_conference(p)) {
05507                   char cid_num[256];
05508                   char cid_name[256];
05509 
05510                   cid_num[0] = 0;
05511                   cid_name[0] = 0;
05512                   if (p->dahditrcallerid && p->owner) {
05513                      if (p->owner->cid.cid_num)
05514                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05515                      if (p->owner->cid.cid_name)
05516                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05517                   }
05518                   /* XXX This section needs much more error checking!!! XXX */
05519                   /* Start a 3-way call if feasible */
05520                   if (!((ast->pbx) ||
05521                         (ast->_state == AST_STATE_UP) ||
05522                         (ast->_state == AST_STATE_RING))) {
05523                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
05524                         goto winkflashdone;
05525                   }
05526                   if (alloc_sub(p, SUB_THREEWAY)) {
05527                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05528                      goto winkflashdone;
05529                   }
05530                   /* Make new channel */
05531                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05532                   if (p->dahditrcallerid) {
05533                      if (!p->origcid_num)
05534                         p->origcid_num = ast_strdup(p->cid_num);
05535                      if (!p->origcid_name)
05536                         p->origcid_name = ast_strdup(p->cid_name);
05537                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05538                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05539                   }
05540                   /* Swap things around between the three-way and real call */
05541                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
05542                   /* Disable echo canceller for better dialing */
05543                   dahdi_disable_ec(p);
05544                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05545                   if (res)
05546                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05547                   p->owner = chan;
05548                   pthread_attr_init(&attr);
05549                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
05550                   if (!chan) {
05551                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05552                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
05553                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05554                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05555                      dahdi_enable_ec(p);
05556                      ast_hangup(chan);
05557                   } else {
05558                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05559                      int way3bridge = 0, cdr3way = 0;
05560                      
05561                      if (!other) {
05562                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05563                      } else
05564                         way3bridge = 1;
05565                      
05566                      if (p->subs[SUB_THREEWAY].owner->cdr)
05567                         cdr3way = 1;
05568                      
05569                      if (option_verbose > 2) 
05570                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
05571                      /* Start music on hold if appropriate */
05572                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05573                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05574                            S_OR(p->mohsuggest, NULL),
05575                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05576                      }
05577                      p->subs[SUB_THREEWAY].needhold = 1;
05578                   }
05579                   pthread_attr_destroy(&attr);
05580                }
05581             } else {
05582                /* Already have a 3 way call */
05583                if (p->subs[SUB_THREEWAY].inthreeway) {
05584                   /* Call is already up, drop the last person */
05585                   if (option_debug)
05586                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05587                   /* If the primary call isn't answered yet, use it */
05588                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05589                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
05590                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05591                      p->owner = p->subs[SUB_REAL].owner;
05592                   }
05593                   /* Drop the last call and stop the conference */
05594                   if (option_verbose > 2)
05595                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05596                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05597                   p->subs[SUB_REAL].inthreeway = 0;
05598                   p->subs[SUB_THREEWAY].inthreeway = 0;
05599                } else {
05600                   /* Lets see what we're up to */
05601                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
05602                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05603                      int otherindex = SUB_THREEWAY;
05604                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05605                      int way3bridge = 0, cdr3way = 0;
05606                      
05607                      if (!other) {
05608                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05609                      } else
05610                         way3bridge = 1;
05611                      
05612                      if (p->subs[SUB_THREEWAY].owner->cdr)
05613                         cdr3way = 1;
05614 
05615                      if (option_verbose > 2)
05616                         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);
05617                      /* Put them in the threeway, and flip */
05618                      p->subs[SUB_THREEWAY].inthreeway = 1;
05619                      p->subs[SUB_REAL].inthreeway = 1;
05620                      if (ast->_state == AST_STATE_UP) {
05621                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
05622                         otherindex = SUB_REAL;
05623                      }
05624                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05625                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05626                      p->subs[otherindex].needunhold = 1;
05627                      p->owner = p->subs[SUB_REAL].owner;
05628                      if (ast->_state == AST_STATE_RINGING) {
05629                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
05630                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05631                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05632                      }
05633                   } else {
05634                      if (option_verbose > 2)
05635                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05636                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05637                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05638                      p->owner = p->subs[SUB_REAL].owner;
05639                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05640                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05641                      p->subs[SUB_REAL].needunhold = 1;
05642                      dahdi_enable_ec(p);
05643                   }
05644                      
05645                }
05646             }
05647          winkflashdone:              
05648             update_conf(p);
05649             break;
05650          case SIG_EM:
05651          case SIG_EM_E1:
05652          case SIG_FEATD:
05653          case SIG_SF:
05654          case SIG_SFWINK:
05655          case SIG_SF_FEATD:
05656          case SIG_FXSLS:
05657          case SIG_FXSGS:
05658             if (p->dialing)
05659                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
05660             else
05661                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05662             break;
05663          case SIG_FEATDMF_TA:
05664             switch (p->whichwink) {
05665             case 0:
05666                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05667                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05668                break;
05669             case 1:
05670                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05671                break;
05672             case 2:
05673                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05674                return NULL;
05675             }
05676             p->whichwink++;
05677             /* Fall through */
05678          case SIG_FEATDMF:
05679          case SIG_E911:
05680          case SIG_FGC_CAMAMF:
05681          case SIG_FGC_CAMA:
05682          case SIG_FEATB:
05683          case SIG_SF_FEATDMF:
05684          case SIG_SF_FEATB:
05685          case SIG_EMWINK:
05686             /* FGD MF and EMWINK *Must* wait for wink */
05687             if (!ast_strlen_zero(p->dop.dialstr)) {
05688                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05689                if (res < 0) {
05690                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05691                   p->dop.dialstr[0] = '\0';
05692                   return NULL;
05693                } else 
05694                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05695             }
05696             p->dop.dialstr[0] = '\0';
05697             break;
05698          default:
05699             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05700          }
05701          break;
05702       case DAHDI_EVENT_HOOKCOMPLETE:
05703          if (p->inalarm) break;
05704          if ((p->radio || (p->oprmode < 0))) break;
05705          switch (mysig) {
05706          case SIG_FXSLS:  /* only interesting for FXS */
05707          case SIG_FXSGS:
05708          case SIG_FXSKS:
05709          case SIG_EM:
05710          case SIG_EM_E1:
05711          case SIG_EMWINK:
05712          case SIG_FEATD:
05713          case SIG_SF:
05714          case SIG_SFWINK:
05715          case SIG_SF_FEATD:
05716             if (!ast_strlen_zero(p->dop.dialstr)) {
05717                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05718                if (res < 0) {
05719                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05720                   p->dop.dialstr[0] = '\0';
05721                   return NULL;
05722                } else 
05723                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
05724             }
05725             p->dop.dialstr[0] = '\0';
05726             p->dop.op = DAHDI_DIAL_OP_REPLACE;
05727             break;
05728          case SIG_FEATDMF:
05729          case SIG_FEATDMF_TA:
05730          case SIG_E911:
05731          case SIG_FGC_CAMA:
05732          case SIG_FGC_CAMAMF:
05733          case SIG_FEATB:
05734          case SIG_SF_FEATDMF:
05735          case SIG_SF_FEATB:
05736             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05737             break;
05738          default:
05739             break;
05740          }
05741          break;
05742       case DAHDI_EVENT_POLARITY:
05743          /*
05744           * If we get a Polarity Switch event, check to see
05745           * if we should change the polarity state and
05746           * mark the channel as UP or if this is an indication
05747           * of remote end disconnect.
05748           */
05749          if (p->polarity == POLARITY_IDLE) {
05750             p->polarity = POLARITY_REV;
05751             if (p->answeronpolarityswitch &&
05752                 ((ast->_state == AST_STATE_DIALING) ||
05753                 (ast->_state == AST_STATE_RINGING))) {
05754                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
05755                ast_setstate(p->owner, AST_STATE_UP);
05756                if (p->hanguponpolarityswitch) {
05757                   gettimeofday(&p->polaritydelaytv, NULL);
05758                }
05759             } else
05760                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05761          } 
05762          /* Removed else statement from here as it was preventing hangups from ever happening*/
05763          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
05764          if (p->hanguponpolarityswitch &&
05765             (p->polarityonanswerdelay > 0) &&
05766                 (p->polarity == POLARITY_REV) &&
05767             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05768                                 /* Added log_debug information below to provide a better indication of what is going on */
05769             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) );
05770          
05771             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05772                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05773                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05774                p->polarity = POLARITY_IDLE;
05775             } else {
05776                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);
05777             }
05778          } else {
05779             p->polarity = POLARITY_IDLE;
05780             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05781          }
05782                         /* Added more log_debug information below to provide a better indication of what is going on */
05783          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) );
05784          break;
05785       default:
05786          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05787    }
05788    return &p->subs[index].f;
05789 }
05790 
05791 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05792 {
05793    struct dahdi_pvt *p = ast->tech_pvt;
05794    int res;
05795    int usedindex=-1;
05796    int index;
05797    struct ast_frame *f;
05798 
05799 
05800    index = dahdi_get_index(ast, p, 1);
05801    
05802    p->subs[index].f.frametype = AST_FRAME_NULL;
05803    p->subs[index].f.datalen = 0;
05804    p->subs[index].f.samples = 0;
05805    p->subs[index].f.mallocd = 0;
05806    p->subs[index].f.offset = 0;
05807    p->subs[index].f.subclass = 0;
05808    p->subs[index].f.delivery = ast_tv(0,0);
05809    p->subs[index].f.src = "dahdi_exception";
05810    p->subs[index].f.data = NULL;
05811    
05812    
05813    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05814       /* If nobody owns us, absorb the event appropriately, otherwise
05815          we loop indefinitely.  This occurs when, during call waiting, the
05816          other end hangs up our channel so that it no longer exists, but we
05817          have neither FLASH'd nor ONHOOK'd to signify our desire to
05818          change to the other channel. */
05819       if (p->fake_event) {
05820          res = p->fake_event;
05821          p->fake_event = 0;
05822       } else
05823          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05824       /* Switch to real if there is one and this isn't something really silly... */
05825       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05826          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05827          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
05828          p->owner = p->subs[SUB_REAL].owner;
05829          if (p->owner && ast_bridged_channel(p->owner))
05830             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05831          p->subs[SUB_REAL].needunhold = 1;
05832       }
05833       switch (res) {
05834       case DAHDI_EVENT_ONHOOK:
05835          dahdi_disable_ec(p);
05836          if (p->owner) {
05837             if (option_verbose > 2) 
05838                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05839             dahdi_ring_phone(p);
05840             p->callwaitingrepeat = 0;
05841             p->cidcwexpire = 0;
05842          } else
05843             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05844          update_conf(p);
05845          break;
05846       case DAHDI_EVENT_RINGOFFHOOK:
05847          dahdi_enable_ec(p);
05848          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05849          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05850             p->subs[SUB_REAL].needanswer = 1;
05851             p->dialing = 0;
05852          }
05853          break;
05854       case DAHDI_EVENT_HOOKCOMPLETE:
05855       case DAHDI_EVENT_RINGERON:
05856       case DAHDI_EVENT_RINGEROFF:
05857          /* Do nothing */
05858          break;
05859       case DAHDI_EVENT_WINKFLASH:
05860          gettimeofday(&p->flashtime, NULL);
05861          if (p->owner) {
05862             if (option_verbose > 2) 
05863                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05864             if (p->owner->_state != AST_STATE_UP) {
05865                /* Answer if necessary */
05866                usedindex = dahdi_get_index(p->owner, p, 0);
05867                if (usedindex > -1) {
05868                   p->subs[usedindex].needanswer = 1;
05869                }
05870                ast_setstate(p->owner, AST_STATE_UP);
05871             }
05872             p->callwaitingrepeat = 0;
05873             p->cidcwexpire = 0;
05874             if (ast_bridged_channel(p->owner))
05875                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05876             p->subs[SUB_REAL].needunhold = 1;
05877          } else
05878             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05879          update_conf(p);
05880          break;
05881       default:
05882          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05883       }
05884       f = &p->subs[index].f;
05885       return f;
05886    }
05887    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
05888       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05889    /* If it's not us, return NULL immediately */
05890    if (ast != p->owner) {
05891       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05892       f = &p->subs[index].f;
05893       return f;
05894    }
05895    f = dahdi_handle_event(ast);
05896    return f;
05897 }
05898 
05899 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05900 {
05901    struct dahdi_pvt *p = ast->tech_pvt;
05902    struct ast_frame *f;
05903    ast_mutex_lock(&p->lock);
05904    f = __dahdi_exception(ast);
05905    ast_mutex_unlock(&p->lock);
05906    return f;
05907 }
05908 
05909 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
05910 {
05911    struct dahdi_pvt *p = ast->tech_pvt;
05912    int res;
05913    int index;
05914    void *readbuf;
05915    struct ast_frame *f;
05916 
05917    while (ast_mutex_trylock(&p->lock)) {
05918       DEADLOCK_AVOIDANCE(&ast->lock);
05919    }
05920 
05921    index = dahdi_get_index(ast, p, 0);
05922    
05923    /* Hang up if we don't really exist */
05924    if (index < 0) {
05925       ast_log(LOG_WARNING, "We dont exist?\n");
05926       ast_mutex_unlock(&p->lock);
05927       return NULL;
05928    }
05929    
05930    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
05931       ast_mutex_unlock(&p->lock);
05932       return NULL;
05933    }
05934 
05935    p->subs[index].f.frametype = AST_FRAME_NULL;
05936    p->subs[index].f.datalen = 0;
05937    p->subs[index].f.samples = 0;
05938    p->subs[index].f.mallocd = 0;
05939    p->subs[index].f.offset = 0;
05940    p->subs[index].f.subclass = 0;
05941    p->subs[index].f.delivery = ast_tv(0,0);
05942    p->subs[index].f.src = "dahdi_read";
05943    p->subs[index].f.data = NULL;
05944    
05945    /* make sure it sends initial key state as first frame */
05946    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05947    {
05948       struct dahdi_params ps;
05949 
05950       memset(&ps, 0, sizeof(ps));
05951       ps.channo = p->channel;
05952       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05953          ast_mutex_unlock(&p->lock);
05954          return NULL;
05955       }
05956       p->firstradio = 1;
05957       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05958       if (ps.rxisoffhook)
05959       {
05960          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05961       }
05962       else
05963       {
05964          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05965       }
05966       ast_mutex_unlock(&p->lock);
05967       return &p->subs[index].f;
05968    }
05969    if (p->ringt == 1) {
05970       ast_mutex_unlock(&p->lock);
05971       return NULL;
05972    }
05973    else if (p->ringt > 0) 
05974       p->ringt--;
05975 
05976 #ifdef HAVE_OPENR2
05977    if (p->mfcr2) {
05978       openr2_chan_process_event(p->r2chan);
05979    }  
05980 #endif
05981 
05982    if (p->subs[index].needringing) {
05983       /* Send ringing frame if requested */
05984       p->subs[index].needringing = 0;
05985       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05986       p->subs[index].f.subclass = AST_CONTROL_RINGING;
05987       ast_setstate(ast, AST_STATE_RINGING);
05988       ast_mutex_unlock(&p->lock);
05989       return &p->subs[index].f;
05990    }
05991 
05992    if (p->subs[index].needbusy) {
05993       /* Send busy frame if requested */
05994       p->subs[index].needbusy = 0;
05995       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05996       p->subs[index].f.subclass = AST_CONTROL_BUSY;
05997       ast_mutex_unlock(&p->lock);
05998       return &p->subs[index].f;
05999    }
06000 
06001    if (p->subs[index].needcongestion) {
06002       /* Send congestion frame if requested */
06003       p->subs[index].needcongestion = 0;
06004       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06005       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
06006       ast_mutex_unlock(&p->lock);
06007       return &p->subs[index].f;
06008    }
06009 
06010    if (p->subs[index].needcallerid) {
06011       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06012                      S_OR(p->lastcid_name, NULL),
06013                      S_OR(p->lastcid_num, NULL)
06014                      );
06015       p->subs[index].needcallerid = 0;
06016    }
06017    
06018    if (p->subs[index].needanswer) {
06019       /* Send answer frame if requested */
06020       p->subs[index].needanswer = 0;
06021       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06022       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
06023       ast_mutex_unlock(&p->lock);
06024       return &p->subs[index].f;
06025    }  
06026 
06027 #ifdef HAVE_OPENR2
06028    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06029       /* openr2 took care of reading and handling any event 
06030         (needanswer, needbusy etc), if we continue we will read()
06031         twice, lets just return a null frame. This should only
06032         happen when openr2 is dialing out */
06033       p->subs[index].f.frametype = AST_FRAME_NULL;
06034       p->subs[index].f.subclass = 0;
06035       p->subs[index].f.samples = 0;
06036       p->subs[index].f.mallocd = 0;
06037       p->subs[index].f.offset = 0;
06038       p->subs[index].f.data = NULL;
06039       p->subs[index].f.datalen= 0;
06040       ast_mutex_unlock(&p->lock);
06041       return &p->subs[index].f;
06042    }
06043 #endif
06044    
06045    if (p->subs[index].needflash) {
06046       /* Send answer frame if requested */
06047       p->subs[index].needflash = 0;
06048       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06049       p->subs[index].f.subclass = AST_CONTROL_FLASH;
06050       ast_mutex_unlock(&p->lock);
06051       return &p->subs[index].f;
06052    }  
06053    
06054    if (p->subs[index].needhold) {
06055       /* Send answer frame if requested */
06056       p->subs[index].needhold = 0;
06057       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06058       p->subs[index].f.subclass = AST_CONTROL_HOLD;
06059       ast_mutex_unlock(&p->lock);
06060       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
06061       return &p->subs[index].f;
06062    }  
06063    
06064    if (p->subs[index].needunhold) {
06065       /* Send answer frame if requested */
06066       p->subs[index].needunhold = 0;
06067       p->subs[index].f.frametype = AST_FRAME_CONTROL;
06068       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
06069       ast_mutex_unlock(&p->lock);
06070       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
06071       return &p->subs[index].f;
06072    }  
06073    
06074    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06075       if (!p->subs[index].linear) {
06076          p->subs[index].linear = 1;
06077          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06078          if (res) 
06079             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
06080       }
06081    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06082          (ast->rawreadformat == AST_FORMAT_ALAW)) {
06083       if (p->subs[index].linear) {
06084          p->subs[index].linear = 0;
06085          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06086          if (res) 
06087             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
06088       }
06089    } else {
06090       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06091       ast_mutex_unlock(&p->lock);
06092       return NULL;
06093    }
06094    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
06095    CHECK_BLOCKING(ast);
06096    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06097    ast_clear_flag(ast, AST_FLAG_BLOCKING);
06098    /* Check for hangup */
06099    if (res < 0) {
06100       f = NULL;
06101       if (res == -1)  {
06102          if (errno == EAGAIN) {
06103             /* Return "NULL" frame if there is nobody there */
06104             ast_mutex_unlock(&p->lock);
06105             return &p->subs[index].f;
06106          } else if (errno == ELAST) {
06107             f = __dahdi_exception(ast);
06108          } else
06109             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06110       }
06111       ast_mutex_unlock(&p->lock);
06112       return f;
06113    }
06114    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
06115       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
06116       f = __dahdi_exception(ast);
06117       ast_mutex_unlock(&p->lock);
06118       return f;
06119    }
06120    if (p->tdd) { /* if in TDD mode, see if we receive that */
06121       int c;
06122 
06123       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06124       if (c < 0) {
06125          ast_log(LOG_DEBUG,"tdd_feed failed\n");
06126          ast_mutex_unlock(&p->lock);
06127          return NULL;
06128       }
06129       if (c) { /* if a char to return */
06130          p->subs[index].f.subclass = 0;
06131          p->subs[index].f.frametype = AST_FRAME_TEXT;
06132          p->subs[index].f.mallocd = 0;
06133          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06134          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
06135          p->subs[index].f.datalen = 1;
06136          *((char *) p->subs[index].f.data) = c;
06137          ast_mutex_unlock(&p->lock);
06138          return &p->subs[index].f;
06139       }
06140    }
06141    /* Ensure the CW timer decrements only on a single subchannel */
06142    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06143       p->callwaitingrepeat--;
06144    }
06145    if (p->cidcwexpire)
06146       p->cidcwexpire--;
06147    /* Repeat callwaiting */
06148    if (p->callwaitingrepeat == 1) {
06149       p->callwaitrings++;
06150       dahdi_callwait(ast);
06151    }
06152    /* Expire CID/CW */
06153    if (p->cidcwexpire == 1) {
06154       if (option_verbose > 2)
06155          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
06156       restore_conference(p);
06157    }
06158    if (p->subs[index].linear) {
06159       p->subs[index].f.datalen = READ_SIZE * 2;
06160    } else 
06161       p->subs[index].f.datalen = READ_SIZE;
06162 
06163    /* Handle CallerID Transmission */
06164    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06165       send_callerid(p);
06166    }
06167 
06168    p->subs[index].f.frametype = AST_FRAME_VOICE;
06169    p->subs[index].f.subclass = ast->rawreadformat;
06170    p->subs[index].f.samples = READ_SIZE;
06171    p->subs[index].f.mallocd = 0;
06172    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
06173    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
06174 #if 0
06175    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
06176 #endif   
06177    if (p->dialing || /* Transmitting something */
06178       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
06179       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
06180       ) {
06181       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
06182          don't send anything */
06183       p->subs[index].f.frametype = AST_FRAME_NULL;
06184       p->subs[index].f.subclass = 0;
06185       p->subs[index].f.samples = 0;
06186       p->subs[index].f.mallocd = 0;
06187       p->subs[index].f.offset = 0;
06188       p->subs[index].f.data = NULL;
06189       p->subs[index].f.datalen= 0;
06190    }
06191    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
06192       /* Perform busy detection. etc on the dahdi line */
06193       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
06194       if (f) {
06195          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
06196             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
06197                /* Treat this as a "hangup" instead of a "busy" on the assumption that
06198                   a busy  */
06199                f = NULL;
06200             }
06201          } else if (f->frametype == AST_FRAME_DTMF) {
06202 #ifdef HAVE_PRI
06203             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial &&
06204                ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
06205                (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
06206                /* Don't accept in-band DTMF when in overlap dial mode */
06207                f->frametype = AST_FRAME_NULL;
06208                f->subclass = 0;
06209             }
06210 #endif            
06211             /* DSP clears us of being pulse */
06212             p->pulsedial = 0;
06213          }
06214       }
06215    } else 
06216       f = &p->subs[index].f; 
06217 
06218    if (f && (f->frametype == AST_FRAME_DTMF))
06219       dahdi_handle_dtmfup(ast, index, &f);
06220 
06221    /* If we have a fake_event, trigger exception to handle it */
06222    if (p->fake_event)
06223       ast_set_flag(ast, AST_FLAG_EXCEPTION);
06224 
06225    ast_mutex_unlock(&p->lock);
06226    return f;
06227 }
06228 
06229 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
06230 {
06231    int sent=0;
06232    int size;
06233    int res;
06234    int fd;
06235    fd = p->subs[index].dfd;
06236    while (len) {
06237       size = len;
06238       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
06239          size = (linear ? READ_SIZE * 2 : READ_SIZE);
06240       res = write(fd, buf, size);
06241       if (res != size) {
06242          if (option_debug)
06243             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06244          return sent;
06245       }
06246       len -= size;
06247       buf += size;
06248    }
06249    return sent;
06250 }
06251 
06252 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
06253 {
06254    struct dahdi_pvt *p = ast->tech_pvt;
06255    int res;
06256    int index;
06257    index = dahdi_get_index(ast, p, 0);
06258    if (index < 0) {
06259       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06260       return -1;
06261    }
06262 
06263 #if 0
06264 #ifdef HAVE_PRI
06265    ast_mutex_lock(&p->lock);
06266    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06267       if (p->pri->pri) {      
06268          if (!pri_grab(p, p->pri)) {
06269                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06270                pri_rel(p->pri);
06271          } else
06272                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06273       }
06274       p->proceeding=1;
06275    }
06276    ast_mutex_unlock(&p->lock);
06277 #endif
06278 #endif
06279    /* Write a frame of (presumably voice) data */
06280    if (frame->frametype != AST_FRAME_VOICE) {
06281       if (frame->frametype != AST_FRAME_IMAGE)
06282          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06283       return 0;
06284    }
06285    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06286        (frame->subclass != AST_FORMAT_ULAW) &&
06287        (frame->subclass != AST_FORMAT_ALAW)) {
06288       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06289       return -1;
06290    }
06291    if (p->dialing) {
06292       if (option_debug)
06293          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06294       return 0;
06295    }
06296    if (!p->owner) {
06297       if (option_debug)
06298          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
06299       return 0;
06300    }
06301    if (p->cidspill) {
06302       if (option_debug)
06303          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
06304       return 0;
06305    }
06306    /* Return if it's not valid data */
06307    if (!frame->data || !frame->datalen)
06308       return 0;
06309 
06310    if (frame->subclass == AST_FORMAT_SLINEAR) {
06311       if (!p->subs[index].linear) {
06312          p->subs[index].linear = 1;
06313          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06314          if (res)
06315             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06316       }
06317       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
06318    } else {
06319       /* x-law already */
06320       if (p->subs[index].linear) {
06321          p->subs[index].linear = 0;
06322          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06323          if (res)
06324             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06325       }
06326       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
06327    }
06328    if (res < 0) {
06329       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06330       return -1;
06331    } 
06332    return 0;
06333 }
06334 
06335 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06336 {
06337    struct dahdi_pvt *p = chan->tech_pvt;
06338    int res=-1;
06339    int index;
06340    int func = DAHDI_FLASH;
06341    ast_mutex_lock(&p->lock);
06342    index = dahdi_get_index(chan, p, 0);
06343    ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
06344 #ifdef HAVE_OPENR2
06345    if (p->mfcr2 && !p->mfcr2_call_accepted) {
06346       ast_mutex_unlock(&p->lock);
06347       /* if this an R2 call and the call is not yet accepted we don't want the 
06348          tone indications to mess up with the MF tones */
06349       return 0;
06350    }
06351 #endif
06352    if (index == SUB_REAL) {
06353       switch (condition) {
06354       case AST_CONTROL_BUSY:
06355 #ifdef HAVE_PRI
06356          if (p->priindication_oob && p->sig == SIG_PRI) {
06357             chan->hangupcause = AST_CAUSE_USER_BUSY;
06358             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06359             res = 0;
06360          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06361             if (p->pri->pri) {      
06362                if (!pri_grab(p, p->pri)) {
06363                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06364                   pri_rel(p->pri);
06365                }
06366                else
06367                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06368             }
06369             p->progress = 1;
06370             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06371          } else
06372 #endif
06373             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
06374          break;
06375       case AST_CONTROL_RINGING:
06376 #ifdef HAVE_PRI
06377          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06378             if (p->pri->pri) {      
06379                if (!pri_grab(p, p->pri)) {
06380                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06381                   pri_rel(p->pri);
06382                }
06383                else
06384                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06385             }
06386             p->alerting = 1;
06387          }
06388 #endif
06389          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
06390          if (chan->_state != AST_STATE_UP) {
06391             if ((chan->_state != AST_STATE_RING) ||
06392                ((p->sig != SIG_FXSKS) &&
06393                 (p->sig != SIG_FXSLS) &&
06394                 (p->sig != SIG_FXSGS)))
06395                ast_setstate(chan, AST_STATE_RINGING);
06396          }
06397          break;
06398       case AST_CONTROL_PROCEEDING:
06399          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06400 #ifdef HAVE_PRI
06401          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06402             if (p->pri->pri) {      
06403                if (!pri_grab(p, p->pri)) {
06404                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06405                   pri_rel(p->pri);
06406                }
06407                else
06408                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06409             }
06410             p->proceeding = 1;
06411             p->dialing = 0;
06412          }
06413 #endif
06414          /* don't continue in ast_indicate */
06415          res = 0;
06416          break;
06417       case AST_CONTROL_PROGRESS:
06418          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06419 #ifdef HAVE_PRI
06420          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
06421          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06422             if (p->pri->pri) {      
06423                if (!pri_grab(p, p->pri)) {
06424                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06425                   pri_rel(p->pri);
06426                }
06427                else
06428                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06429             }
06430             p->progress = 1;
06431          }
06432 #endif
06433          /* don't continue in ast_indicate */
06434          res = 0;
06435          break;
06436       case AST_CONTROL_CONGESTION:
06437          chan->hangupcause = AST_CAUSE_CONGESTION;
06438 #ifdef HAVE_PRI
06439          if (p->priindication_oob && p->sig == SIG_PRI) {
06440             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06441             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06442             res = 0;
06443          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06444             if (p->pri) {     
06445                if (!pri_grab(p, p->pri)) {
06446                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06447                   pri_rel(p->pri);
06448                } else
06449                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06450             }
06451             p->progress = 1;
06452             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06453          } else
06454 #endif
06455             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06456          break;
06457       case AST_CONTROL_HOLD:
06458 #ifdef HAVE_PRI
06459          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06460             if (!pri_grab(p, p->pri)) {
06461                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06462                pri_rel(p->pri);
06463             } else
06464                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06465          } else
06466 #endif
06467             ast_moh_start(chan, data, p->mohinterpret);
06468          break;
06469       case AST_CONTROL_UNHOLD:
06470 #ifdef HAVE_PRI
06471          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06472             if (!pri_grab(p, p->pri)) {
06473                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06474                pri_rel(p->pri);
06475             } else
06476                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06477          } else
06478 #endif
06479             ast_moh_stop(chan);
06480          break;
06481       case AST_CONTROL_RADIO_KEY:
06482          if (p->radio) 
06483              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
06484          res = 0;
06485          break;
06486       case AST_CONTROL_RADIO_UNKEY:
06487          if (p->radio)
06488              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
06489          res = 0;
06490          break;
06491       case AST_CONTROL_FLASH:
06492          /* flash hookswitch */
06493          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06494             /* Clear out the dial buffer */
06495             p->dop.dialstr[0] = '\0';
06496             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06497                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06498                   chan->name, strerror(errno));
06499             } else
06500                res = 0;
06501          } else
06502             res = 0;
06503          break;
06504       case AST_CONTROL_SRCUPDATE:
06505          res = 0;
06506          break;
06507       case -1:
06508          res = tone_zone_play_tone(p->subs[index].dfd, -1);
06509          break;
06510       }
06511    } else
06512       res = 0;
06513    ast_mutex_unlock(&p->lock);
06514    return res;
06515 }
06516 
06517 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
06518 {
06519    struct ast_channel *tmp;
06520    int deflaw;
06521    int res;
06522    int x,y;
06523    int features;
06524    char *b2 = NULL;
06525    struct dahdi_params ps;
06526    char chanprefix[*dahdi_chan_name_len + 4];
06527 
06528    if (i->subs[index].owner) {
06529       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
06530       return NULL;
06531    }
06532    y = 1;
06533    do {
06534       if (b2)
06535          free(b2);
06536 #ifdef HAVE_PRI
06537       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06538          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06539       else
06540 #endif
06541       if (i->channel == CHAN_PSEUDO)
06542          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
06543       else  
06544          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
06545       for (x = 0; x < 3; x++) {
06546          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
06547             break;
06548       }
06549       y++;
06550    } while (x < 3);
06551    strcpy(chanprefix, dahdi_chan_name);
06552    strcat(chanprefix, "/%s");
06553    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
06554    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
06555       free(b2);
06556    if (!tmp)
06557       return NULL;
06558    tmp->tech = chan_tech;
06559    memset(&ps, 0, sizeof(ps));
06560    ps.channo = i->channel;
06561    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06562    if (res) {
06563       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06564       ps.curlaw = DAHDI_LAW_MULAW;
06565    }
06566    if (ps.curlaw == DAHDI_LAW_ALAW)
06567       deflaw = AST_FORMAT_ALAW;
06568    else
06569       deflaw = AST_FORMAT_ULAW;
06570    if (law) {
06571       if (law == DAHDI_LAW_ALAW)
06572          deflaw = AST_FORMAT_ALAW;
06573       else
06574          deflaw = AST_FORMAT_ULAW;
06575    }
06576    tmp->fds[0] = i->subs[index].dfd;
06577    tmp->nativeformats = deflaw;
06578    /* Start out assuming ulaw since it's smaller :) */
06579    tmp->rawreadformat = deflaw;
06580    tmp->readformat = deflaw;
06581    tmp->rawwriteformat = deflaw;
06582    tmp->writeformat = deflaw;
06583    i->subs[index].linear = 0;
06584    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
06585    features = 0;
06586    if (index == SUB_REAL) {
06587       if (i->busydetect && CANBUSYDETECT(i))
06588          features |= DSP_FEATURE_BUSY_DETECT;
06589       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
06590          features |= DSP_FEATURE_CALL_PROGRESS;
06591       if ((!i->outgoing && (i->callprogress & 4)) || 
06592           (i->outgoing && (i->callprogress & 2))) {
06593          features |= DSP_FEATURE_FAX_DETECT;
06594       }
06595 #ifdef DAHDI_TONEDETECT
06596       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06597       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
06598 #endif      
06599          i->hardwaredtmf = 0;
06600          features |= DSP_FEATURE_DTMF_DETECT;
06601 #ifdef DAHDI_TONEDETECT
06602       } else if (NEED_MFDETECT(i)) {
06603          i->hardwaredtmf = 1;
06604          features |= DSP_FEATURE_DTMF_DETECT;
06605       }
06606 #endif
06607    }
06608    if (features) {
06609       if (i->dsp) {
06610          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
06611       } else {
06612          if (i->channel != CHAN_PSEUDO)
06613             i->dsp = ast_dsp_new();
06614          else
06615             i->dsp = NULL;
06616          if (i->dsp) {
06617             i->dsp_features = features;
06618 #ifdef HAVE_PRI
06619             /* We cannot do progress detection until receives PROGRESS message */
06620             if (i->outgoing && (i->sig == SIG_PRI)) {
06621                /* Remember requested DSP features, don't treat
06622                   talking as ANSWER */
06623                i->dsp_features = features & ~DSP_PROGRESS_TALK;
06624                features = 0;
06625             }
06626 #endif
06627             ast_dsp_set_features(i->dsp, features);
06628             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06629             if (!ast_strlen_zero(progzone))
06630                ast_dsp_set_call_progress_zone(i->dsp, progzone);
06631             if (i->busydetect && CANBUSYDETECT(i)) {
06632                if(i->silencethreshold > 0)
06633                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06634                ast_dsp_set_busy_count(i->dsp, i->busycount);
06635                if(i->busytonelength > 0)
06636                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06637                if((i->busytonelength == i->busyquietlength) && i->busycompare)
06638                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06639             }
06640          }
06641       }
06642    }
06643       
06644    if (state == AST_STATE_RING)
06645       tmp->rings = 1;
06646    tmp->tech_pvt = i;
06647    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06648       /* Only FXO signalled stuff can be picked up */
06649       tmp->callgroup = i->callgroup;
06650       tmp->pickupgroup = i->pickupgroup;
06651    }
06652    if (!ast_strlen_zero(i->language))
06653       ast_string_field_set(tmp, language, i->language);
06654    if (!i->owner)
06655       i->owner = tmp;
06656    if (!ast_strlen_zero(i->accountcode))
06657       ast_string_field_set(tmp, accountcode, i->accountcode);
06658    if (i->amaflags)
06659       tmp->amaflags = i->amaflags;
06660    i->subs[index].owner = tmp;
06661    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06662    ast_string_field_set(tmp, call_forward, i->call_forward);
06663    /* If we've been told "no ADSI" then enforce it */
06664    if (!i->adsi)
06665       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06666    if (!ast_strlen_zero(i->exten))
06667       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06668    if (!ast_strlen_zero(i->rdnis))
06669       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06670    if (!ast_strlen_zero(i->dnid))
06671       tmp->cid.cid_dnid = ast_strdup(i->dnid);
06672 
06673    /* Don't use ast_set_callerid() here because it will
06674     * generate a needless NewCallerID event */
06675 #ifdef PRI_ANI
06676    if (!ast_strlen_zero(i->cid_ani))
06677       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06678    else  
06679       tmp->cid.cid_ani = ast_strdup(i->cid_num);
06680 #else
06681    tmp->cid.cid_ani = ast_strdup(i->cid_num);
06682 #endif
06683    tmp->cid.cid_pres = i->callingpres;
06684    tmp->cid.cid_ton = i->cid_ton;
06685 #ifdef HAVE_PRI
06686    tmp->transfercapability = transfercapability;
06687    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06688    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
06689       i->digital = 1;
06690    /* Assume calls are not idle calls unless we're told differently */
06691    i->isidlecall = 0;
06692    i->alreadyhungup = 0;
06693 #endif
06694    /* clear the fake event in case we posted one before we had ast_channel */
06695    i->fake_event = 0;
06696    /* Assure there is no confmute on this channel */
06697    dahdi_confmute(i, 0);
06698    /* Configure the new channel jb */
06699    ast_jb_configure(tmp, &global_jbconf);
06700    if (startpbx) {
06701 #ifdef HAVE_OPENR2
06702       if (i->mfcr2call) {
06703          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
06704       }
06705 #endif
06706       if (ast_pbx_start(tmp)) {
06707          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06708          ast_hangup(tmp);
06709          i->owner = NULL;
06710          return NULL;
06711       }
06712    }
06713 
06714    ast_module_ref(ast_module_info->self);
06715    
06716    return tmp;
06717 }
06718 
06719 
06720 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06721 {
06722    char c;
06723 
06724    *str = 0; /* start with empty output buffer */
06725    for (;;)
06726    {
06727       /* Wait for the first digit (up to specified ms). */
06728       c = ast_waitfordigit(chan, ms);
06729       /* if timeout, hangup or error, return as such */
06730       if (c < 1)
06731          return c;
06732       *str++ = c;
06733       *str = 0;
06734       if (strchr(term, c))
06735          return 1;
06736    }
06737 }
06738 
06739 static int dahdi_wink(struct dahdi_pvt *p, int index)
06740 {
06741    int j;
06742    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06743    for (;;)
06744    {
06745          /* set bits of interest */
06746       j = DAHDI_IOMUX_SIGEVENT;
06747           /* wait for some happening */
06748       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06749          /* exit loop if we have it */
06750       if (j & DAHDI_IOMUX_SIGEVENT) break;
06751    }
06752      /* get the event info */
06753    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06754    return 0;
06755 }
06756 
06757 static void *ss_thread(void *data)
06758 {
06759    struct ast_channel *chan = data;
06760    struct dahdi_pvt *p = chan->tech_pvt;
06761    char exten[AST_MAX_EXTENSION] = "";
06762    char exten2[AST_MAX_EXTENSION] = "";
06763    unsigned char buf[256];
06764    char dtmfcid[300];
06765    char dtmfbuf[300];
06766    struct callerid_state *cs = NULL;
06767    char *name = NULL, *number = NULL;
06768    int distMatches;
06769    int curRingData[3];
06770    int receivedRingT;
06771    int counter1;
06772    int counter;
06773    int samples = 0;
06774    struct ast_smdi_md_message *smdi_msg = NULL;
06775    int flags = 0;
06776    int i;
06777    int timeout;
06778    int getforward = 0;
06779    char *s1, *s2;
06780    int len = 0;
06781    int res;
06782    int index;
06783 
06784    ast_mutex_lock(&ss_thread_lock);
06785    ss_thread_count++;
06786    ast_mutex_unlock(&ss_thread_lock);
06787    /* in the bizarre case where the channel has become a zombie before we
06788       even get started here, abort safely
06789    */
06790    if (!p) {
06791       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06792       ast_hangup(chan);
06793       goto quit;
06794    }
06795    if (option_verbose > 2) 
06796       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
06797    index = dahdi_get_index(chan, p, 1);
06798    if (index < 0) {
06799       ast_log(LOG_WARNING, "Huh?\n");
06800       ast_hangup(chan);
06801       goto quit;
06802    }
06803    if (p->dsp)
06804       ast_dsp_digitreset(p->dsp);
06805    switch (p->sig) {
06806 #ifdef HAVE_PRI
06807    case SIG_PRI:
06808       /* Now loop looking for an extension */
06809       ast_copy_string(exten, p->exten, sizeof(exten));
06810       len = strlen(exten);
06811       res = 0;
06812       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06813          if (len && !ast_ignore_pattern(chan->context, exten))
06814             tone_zone_play_tone(p->subs[index].dfd, -1);
06815          else
06816             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06817          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06818             timeout = matchdigittimeout;
06819          else
06820             timeout = gendigittimeout;
06821          res = ast_waitfordigit(chan, timeout);
06822          if (res < 0) {
06823             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06824             ast_hangup(chan);
06825             goto quit;
06826          } else if (res) {
06827             exten[len++] = res;
06828             exten[len] = '\0';
06829          } else
06830             break;
06831       }
06832       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
06833       if (ast_strlen_zero(exten)) {
06834          if (option_verbose > 2)
06835             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
06836          exten[0] = 's';
06837          exten[1] = '\0';
06838       }
06839       tone_zone_play_tone(p->subs[index].dfd, -1);
06840       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06841          /* Start the real PBX */
06842          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06843          if (p->dsp) ast_dsp_digitreset(p->dsp);
06844          dahdi_enable_ec(p);
06845          ast_setstate(chan, AST_STATE_RING);
06846          res = ast_pbx_run(chan);
06847          if (res) {
06848             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06849          }
06850       } else {
06851          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06852          chan->hangupcause = AST_CAUSE_UNALLOCATED;
06853          ast_hangup(chan);
06854          p->exten[0] = '\0';
06855          /* Since we send release complete here, we won't get one */
06856          p->call = NULL;
06857       }
06858       goto quit;
06859       break;
06860 #endif
06861    case SIG_FEATD:
06862    case SIG_FEATDMF:
06863    case SIG_FEATDMF_TA:
06864    case SIG_E911:
06865    case SIG_FGC_CAMAMF:
06866    case SIG_FEATB:
06867    case SIG_EMWINK:
06868    case SIG_SF_FEATD:
06869    case SIG_SF_FEATDMF:
06870    case SIG_SF_FEATB:
06871    case SIG_SFWINK:
06872       if (dahdi_wink(p, index))  
06873          goto quit;
06874       /* Fall through */
06875    case SIG_EM:
06876    case SIG_EM_E1:
06877    case SIG_SF:
06878    case SIG_FGC_CAMA:
06879       res = tone_zone_play_tone(p->subs[index].dfd, -1);
06880       if (p->dsp)
06881          ast_dsp_digitreset(p->dsp);
06882       /* set digit mode appropriately */
06883       if (p->dsp) {
06884          if (NEED_MFDETECT(p))
06885             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
06886          else 
06887             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06888       }
06889       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06890       /* Wait for the first digit only if immediate=no */
06891       if (!p->immediate)
06892          /* Wait for the first digit (up to 5 seconds). */
06893          res = ast_waitfordigit(chan, 5000);
06894       else
06895          res = 0;
06896       if (res > 0) {
06897          /* save first char */
06898          dtmfbuf[0] = res;
06899          switch (p->sig) {
06900          case SIG_FEATD:
06901          case SIG_SF_FEATD:
06902             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06903             if (res > 0)
06904                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06905             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06906             break;
06907          case SIG_FEATDMF_TA:
06908             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06909             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06910             if (dahdi_wink(p, index)) goto quit;
06911             dtmfbuf[0] = 0;
06912             /* Wait for the first digit (up to 5 seconds). */
06913             res = ast_waitfordigit(chan, 5000);
06914             if (res <= 0) break;
06915             dtmfbuf[0] = res;
06916             /* fall through intentionally */
06917          case SIG_FEATDMF:
06918          case SIG_E911:
06919          case SIG_FGC_CAMAMF:
06920          case SIG_SF_FEATDMF:
06921             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06922             /* if international caca, do it again to get real ANO */
06923             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06924             {
06925                if (dahdi_wink(p, index)) goto quit;
06926                dtmfbuf[0] = 0;
06927                /* Wait for the first digit (up to 5 seconds). */
06928                res = ast_waitfordigit(chan, 5000);
06929                if (res <= 0) break;
06930                dtmfbuf[0] = res;
06931                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06932             }
06933             if (res > 0) {
06934                /* if E911, take off hook */
06935                if (p->sig == SIG_E911)
06936                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06937                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06938             }
06939             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06940             break;
06941          case SIG_FEATB:
06942          case SIG_SF_FEATB:
06943             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06944             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06945             break;
06946          case SIG_EMWINK:
06947             /* if we received a '*', we are actually receiving Feature Group D
06948                dial syntax, so use that mode; otherwise, fall through to normal
06949                mode
06950             */
06951             if (res == '*') {
06952                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06953                if (res > 0)
06954                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06955                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06956                break;
06957             }
06958          default:
06959             /* If we got the first digit, get the rest */
06960             len = 1;
06961             dtmfbuf[len] = '\0';
06962             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06963                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06964                   timeout = matchdigittimeout;
06965                } else {
06966                   timeout = gendigittimeout;
06967                }
06968                res = ast_waitfordigit(chan, timeout);
06969                if (res < 0) {
06970                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06971                   ast_hangup(chan);
06972                   goto quit;
06973                } else if (res) {
06974                   dtmfbuf[len++] = res;
06975                   dtmfbuf[len] = '\0';
06976                } else {
06977                   break;
06978                }
06979             }
06980             break;
06981          }
06982       }
06983       if (res == -1) {
06984          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06985          ast_hangup(chan);
06986          goto quit;
06987       } else if (res < 0) {
06988          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06989          ast_hangup(chan);
06990          goto quit;
06991       }
06992 
06993       if (p->sig == SIG_FGC_CAMA) {
06994          char anibuf[100];
06995 
06996          if (ast_safe_sleep(chan,1000) == -1) {
06997                            ast_hangup(chan);
06998                            goto quit;
06999          }
07000                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07001                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
07002                         res = my_getsigstr(chan, anibuf, "#", 10000);
07003                         if ((res > 0) && (strlen(anibuf) > 2)) {
07004             if (anibuf[strlen(anibuf) - 1] == '#')
07005                anibuf[strlen(anibuf) - 1] = 0;
07006             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07007          }
07008                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
07009       }
07010 
07011       ast_copy_string(exten, dtmfbuf, sizeof(exten));
07012       if (ast_strlen_zero(exten))
07013          ast_copy_string(exten, "s", sizeof(exten));
07014       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07015          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
07016          if (exten[0] == '*') {
07017             char *stringp=NULL;
07018             ast_copy_string(exten2, exten, sizeof(exten2));
07019             /* Parse out extension and callerid */
07020             stringp=exten2 +1;
07021             s1 = strsep(&stringp, "*");
07022             s2 = strsep(&stringp, "*");
07023             if (s2) {
07024                if (!ast_strlen_zero(p->cid_num))
07025                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07026                else
07027                   ast_set_callerid(chan, s1, NULL, s1);
07028                ast_copy_string(exten, s2, sizeof(exten));
07029             } else
07030                ast_copy_string(exten, s1, sizeof(exten));
07031          } else if (p->sig == SIG_FEATD)
07032             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07033       }
07034       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07035          if (exten[0] == '*') {
07036             char *stringp=NULL;
07037             ast_copy_string(exten2, exten, sizeof(exten2));
07038             /* Parse out extension and callerid */
07039             stringp=exten2 +1;
07040             s1 = strsep(&stringp, "#");
07041             s2 = strsep(&stringp, "#");
07042             if (s2) {
07043                if (!ast_strlen_zero(p->cid_num))
07044                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07045                else
07046                   if (*(s1 + 2))
07047                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07048                ast_copy_string(exten, s2 + 1, sizeof(exten));
07049             } else
07050                ast_copy_string(exten, s1 + 2, sizeof(exten));
07051          } else
07052             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07053       }
07054       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07055          if (exten[0] == '*') {
07056             char *stringp=NULL;
07057             ast_copy_string(exten2, exten, sizeof(exten2));
07058             /* Parse out extension and callerid */
07059             stringp=exten2 +1;
07060             s1 = strsep(&stringp, "#");
07061             s2 = strsep(&stringp, "#");
07062             if (s2 && (*(s2 + 1) == '0')) {
07063                if (*(s2 + 2))
07064                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07065             }
07066             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
07067             else ast_copy_string(exten, "911", sizeof(exten));
07068          } else
07069             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07070       }
07071       if (p->sig == SIG_FEATB) {
07072          if (exten[0] == '*') {
07073             char *stringp=NULL;
07074             ast_copy_string(exten2, exten, sizeof(exten2));
07075             /* Parse out extension and callerid */
07076             stringp=exten2 +1;
07077             s1 = strsep(&stringp, "#");
07078             ast_copy_string(exten, exten2 + 1, sizeof(exten));
07079          } else
07080             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07081       }
07082       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07083          dahdi_wink(p, index);
07084                         /* some switches require a minimum guard time between
07085                            the last FGD wink and something that answers
07086                            immediately. This ensures it */
07087                         if (ast_safe_sleep(chan,100)) goto quit;
07088       }
07089       dahdi_enable_ec(p);
07090       if (NEED_MFDETECT(p)) {
07091          if (p->dsp) {
07092             if (!p->hardwaredtmf)
07093                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
07094             else {
07095                ast_dsp_free(p->dsp);
07096                p->dsp = NULL;
07097             }
07098          }
07099       }
07100 
07101       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
07102          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07103          if (p->dsp) ast_dsp_digitreset(p->dsp);
07104          res = ast_pbx_run(chan);
07105          if (res) {
07106             ast_log(LOG_WARNING, "PBX exited non-zero\n");
07107             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07108          }
07109          goto quit;
07110       } else {
07111          if (option_verbose > 2)
07112             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
07113          sleep(2);
07114          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
07115          if (res < 0)
07116             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
07117          else
07118             sleep(1);
07119          res = ast_streamfile(chan, "ss-noservice", chan->language);
07120          if (res >= 0)
07121             ast_waitstream(chan, "");
07122          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07123          ast_hangup(chan);
07124          goto quit;
07125       }
07126       break;
07127    case SIG_FXOLS:
07128    case SIG_FXOGS:
07129    case SIG_FXOKS:
07130       /* Read the first digit */
07131       timeout = firstdigittimeout;
07132       /* If starting a threeway call, never timeout on the first digit so someone
07133          can use flash-hook as a "hold" feature */
07134       if (p->subs[SUB_THREEWAY].owner) 
07135          timeout = 999999;
07136       while (len < AST_MAX_EXTENSION-1) {
07137          /* Read digit unless it's supposed to be immediate, in which case the
07138             only answer is 's' */
07139          if (p->immediate) 
07140             res = 's';
07141          else
07142             res = ast_waitfordigit(chan, timeout);
07143          timeout = 0;
07144          if (res < 0) {
07145             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
07146             res = tone_zone_play_tone(p->subs[index].dfd, -1);
07147             ast_hangup(chan);
07148             goto quit;
07149          } else if (res)  {
07150             exten[len++]=res;
07151             exten[len] = '\0';
07152          }
07153          if (!ast_ignore_pattern(chan->context, exten))
07154             tone_zone_play_tone(p->subs[index].dfd, -1);
07155          else
07156             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07157          if (!strcmp(exten,ast_pickup_ext())) {
07158             /* Scan all channels and see if there are any
07159              * ringing channels that have call groups
07160              * that equal this channels pickup group
07161              */
07162             if (index == SUB_REAL) {
07163                /* Switch us from Third call to Call Wait */
07164                if (p->subs[SUB_THREEWAY].owner) {
07165                   /* If you make a threeway call and the *8# a call, it should actually
07166                      look like a callwait */
07167                   alloc_sub(p, SUB_CALLWAIT);
07168                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07169                   unalloc_sub(p, SUB_THREEWAY);
07170                }
07171                dahdi_enable_ec(p);
07172                if (ast_pickup_call(chan)) {
07173                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
07174                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07175                   dahdi_wait_event(p->subs[index].dfd);
07176                }
07177                ast_hangup(chan);
07178                goto quit;
07179             } else {
07180                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
07181                ast_hangup(chan);
07182                goto quit;
07183             }
07184 
07185          } else if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
07186             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07187                if (getforward) {
07188                   /* Record this as the forwarding extension */
07189                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
07190                   if (option_verbose > 2)
07191                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
07192                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07193                   if (res)
07194                      break;
07195                   usleep(500000);
07196                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07197                   sleep(1);
07198                   memset(exten, 0, sizeof(exten));
07199                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
07200                   len = 0;
07201                   getforward = 0;
07202                } else  {
07203                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
07204                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07205                   if (!ast_strlen_zero(p->cid_num)) {
07206                      if (!p->hidecallerid)
07207                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
07208                      else
07209                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
07210                   }
07211                   if (!ast_strlen_zero(p->cid_name)) {
07212                      if (!p->hidecallerid)
07213                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
07214                   }
07215                   ast_setstate(chan, AST_STATE_RING);
07216                   dahdi_enable_ec(p);
07217                   res = ast_pbx_run(chan);
07218                   if (res) {
07219                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
07220                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07221                   }
07222                   goto quit;
07223                }
07224             } else {
07225                /* It's a match, but they just typed a digit, and there is an ambiguous match,
07226                   so just set the timeout to matchdigittimeout and wait some more */
07227                timeout = matchdigittimeout;
07228             }
07229          } else if (res == 0) {
07230             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
07231             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07232             dahdi_wait_event(p->subs[index].dfd);
07233             ast_hangup(chan);
07234             goto quit;
07235          } else if (p->callwaiting && !strcmp(exten, "*70")) {
07236             if (option_verbose > 2) 
07237                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
07238             /* Disable call waiting if enabled */
07239             p->callwaiting = 0;
07240             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07241             if (res) {
07242                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07243                   chan->name, strerror(errno));
07244             }
07245             len = 0;
07246             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
07247             memset(exten, 0, sizeof(exten));
07248             timeout = firstdigittimeout;
07249                
07250          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07251             if (option_verbose > 2) 
07252                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
07253             /* Disable Caller*ID if enabled */
07254             p->hidecallerid = 1;
07255             if (chan->cid.cid_num)
07256                free(chan->cid.cid_num);
07257             chan->cid.cid_num = NULL;
07258             if (chan->cid.cid_name)
07259                free(chan->cid.cid_name);
07260             chan->cid.cid_name = NULL;
07261             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07262             if (res) {
07263                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07264                   chan->name, strerror(errno));
07265             }
07266             len = 0;
07267             memset(exten, 0, sizeof(exten));
07268             timeout = firstdigittimeout;
07269          } else if (p->callreturn && !strcmp(exten, "*69")) {
07270             res = 0;
07271             if (!ast_strlen_zero(p->lastcid_num)) {
07272                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07273             }
07274             if (!res)
07275                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07276             break;
07277          } else if (!strcmp(exten, "*78")) {
07278             /* Do not disturb */
07279             if (option_verbose > 2)
07280                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
07281             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07282                      "Channel: %s/%d\r\n"
07283                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
07284             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07285             p->dnd = 1;
07286             getforward = 0;
07287             memset(exten, 0, sizeof(exten));
07288             len = 0;
07289          } else if (!strcmp(exten, "*79")) {
07290             /* Do not disturb */
07291             if (option_verbose > 2)
07292                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
07293             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07294                      "Channel: %s/%d\r\n"
07295                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
07296             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07297             p->dnd = 0;
07298             getforward = 0;
07299             memset(exten, 0, sizeof(exten));
07300             len = 0;
07301          } else if (p->cancallforward && !strcmp(exten, "*72")) {
07302             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07303             getforward = 1;
07304             memset(exten, 0, sizeof(exten));
07305             len = 0;
07306          } else if (p->cancallforward && !strcmp(exten, "*73")) {
07307             if (option_verbose > 2)
07308                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
07309             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07310             memset(p->call_forward, 0, sizeof(p->call_forward));
07311             getforward = 0;
07312             memset(exten, 0, sizeof(exten));
07313             len = 0;
07314          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
07315                   p->subs[SUB_THREEWAY].owner &&
07316                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07317             /* This is a three way call, the main call being a real channel, 
07318                and we're parking the first call. */
07319             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07320             if (option_verbose > 2)
07321                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
07322             break;
07323          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07324             if (option_verbose > 2)
07325                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
07326             res = ast_db_put("blacklist", p->lastcid_num, "1");
07327             if (!res) {
07328                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07329                memset(exten, 0, sizeof(exten));
07330                len = 0;
07331             }
07332          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07333             if (option_verbose > 2) 
07334                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
07335             /* Enable Caller*ID if enabled */
07336             p->hidecallerid = 0;
07337             if (chan->cid.cid_num)
07338                free(chan->cid.cid_num);
07339             chan->cid.cid_num = NULL;
07340             if (chan->cid.cid_name)
07341                free(chan->cid.cid_name);
07342             chan->cid.cid_name = NULL;
07343             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07344             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
07345             if (res) {
07346                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07347                   chan->name, strerror(errno));
07348             }
07349             len = 0;
07350             memset(exten, 0, sizeof(exten));
07351             timeout = firstdigittimeout;
07352          } else if (!strcmp(exten, "*0")) {
07353             struct ast_channel *nbridge = 
07354                p->subs[SUB_THREEWAY].owner;
07355             struct dahdi_pvt *pbridge = NULL;
07356               /* set up the private struct of the bridged one, if any */
07357             if (nbridge && ast_bridged_channel(nbridge)) 
07358                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07359             if (nbridge && pbridge && 
07360                 (nbridge->tech == chan_tech) && 
07361                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
07362                 ISTRUNK(pbridge)) {
07363                int func = DAHDI_FLASH;
07364                /* Clear out the dial buffer */
07365                p->dop.dialstr[0] = '\0';
07366                /* flash hookswitch */
07367                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07368                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
07369                      nbridge->name, strerror(errno));
07370                }
07371                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07372                unalloc_sub(p, SUB_THREEWAY);
07373                p->owner = p->subs[SUB_REAL].owner;
07374                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07375                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07376                ast_hangup(chan);
07377                goto quit;
07378             } else {
07379                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07380                dahdi_wait_event(p->subs[index].dfd);
07381                tone_zone_play_tone(p->subs[index].dfd, -1);
07382                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07383                unalloc_sub(p, SUB_THREEWAY);
07384                p->owner = p->subs[SUB_REAL].owner;
07385                ast_hangup(chan);
07386                goto quit;
07387             }              
07388          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07389                      ((exten[0] != '*') || (strlen(exten) > 2))) {
07390             if (option_debug)
07391                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);
07392             break;
07393          }
07394          if (!timeout)
07395             timeout = gendigittimeout;
07396          if (len && !ast_ignore_pattern(chan->context, exten))
07397             tone_zone_play_tone(p->subs[index].dfd, -1);
07398       }
07399       break;
07400    case SIG_FXSLS:
07401    case SIG_FXSGS:
07402    case SIG_FXSKS:
07403 #ifdef HAVE_PRI
07404       if (p->pri) {
07405          /* This is a GR-303 trunk actually.  Wait for the first ring... */
07406          struct ast_frame *f;
07407          int res;
07408          time_t start;
07409 
07410          time(&start);
07411          ast_setstate(chan, AST_STATE_RING);
07412          while (time(NULL) < start + 3) {
07413             res = ast_waitfor(chan, 1000);
07414             if (res) {
07415                f = ast_read(chan);
07416                if (!f) {
07417                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07418                   ast_hangup(chan);
07419                   goto quit;
07420                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07421                   res = 1;
07422                } else
07423                   res = 0;
07424                ast_frfree(f);
07425                if (res) {
07426                   ast_log(LOG_DEBUG, "Got ring!\n");
07427                   res = 0;
07428                   break;
07429                }
07430             }
07431          }
07432       }
07433 #endif
07434       /* check for SMDI messages */
07435       if (p->use_smdi && p->smdi_iface) {
07436          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07437 
07438          if (smdi_msg != NULL) {
07439             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07440 
07441             if (smdi_msg->type == 'B')
07442                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07443             else if (smdi_msg->type == 'N')
07444                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07445 
07446             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
07447          } else {
07448             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07449          }
07450       }
07451 
07452       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07453             number = smdi_msg->calling_st;
07454 
07455       /* If we want caller id, we're in a prering state due to a polarity reversal
07456        * and we're set to use a polarity reversal to trigger the start of caller id,
07457        * grab the caller id and wait for ringing to start... */
07458       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
07459                    (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_DTMF_NOALERT))) {
07460          /* If set to use DTMF CID signalling, listen for DTMF */
07461          if (p->cid_signalling == CID_SIG_DTMF) {
07462             int i = 0;
07463             cs = NULL;
07464             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
07465                "channel %s\n", chan->name);
07466             dahdi_setlinear(p->subs[index].dfd, 0);
07467             res = 2000;
07468             for (;;) {
07469                struct ast_frame *f;
07470                res = ast_waitfor(chan, res);
07471                if (res <= 0) {
07472                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07473                      "Exiting simple switch\n");
07474                   ast_hangup(chan);
07475                   goto quit;
07476                } 
07477                f = ast_read(chan);
07478                if (!f)
07479                   break;
07480                if (f->frametype == AST_FRAME_DTMF) {
07481                   dtmfbuf[i++] = f->subclass;
07482                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07483                   res = 2000;
07484                }
07485                ast_frfree(f);
07486                if (chan->_state == AST_STATE_RING ||
07487                    chan->_state == AST_STATE_RINGING) 
07488                   break; /* Got ring */
07489             }
07490             dtmfbuf[i] = '\0';
07491             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07492             /* Got cid and ring. */
07493             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
07494             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07495             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
07496                dtmfcid, flags);
07497             /* If first byte is NULL, we have no cid */
07498             if (!ast_strlen_zero(dtmfcid)) 
07499                number = dtmfcid;
07500             else
07501                number = NULL;
07502          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07503          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07504             cs = callerid_new(p->cid_signalling);
07505             if (cs) {
07506                samples = 0;
07507 #if 1
07508                bump_gains(p);
07509 #endif            
07510                /* Take out of linear mode for Caller*ID processing */
07511                dahdi_setlinear(p->subs[index].dfd, 0);
07512                
07513                /* First we wait and listen for the Caller*ID */
07514                for (;;) {  
07515                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07516                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07517                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07518                      callerid_free(cs);
07519                      ast_hangup(chan);
07520                      goto quit;
07521                   }
07522                   if (i & DAHDI_IOMUX_SIGEVENT) {
07523                      res = dahdi_get_event(p->subs[index].dfd);
07524                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07525 
07526                      if (p->cid_signalling == CID_SIG_V23_JP) {
07527 #ifdef DAHDI_EVENT_RINGBEGIN
07528                         if (res == DAHDI_EVENT_RINGBEGIN) {
07529                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07530                            usleep(1);
07531                         }
07532 #endif
07533                      } else {
07534                         res = 0;
07535                         break;
07536                      }
07537                   } else if (i & DAHDI_IOMUX_READ) {
07538                      res = read(p->subs[index].dfd, buf, sizeof(buf));
07539                      if (res < 0) {
07540                         if (errno != ELAST) {
07541                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07542                            callerid_free(cs);
07543                            ast_hangup(chan);
07544                            goto quit;
07545                         }
07546                         break;
07547                      }
07548                      samples += res;
07549 
07550                      if  (p->cid_signalling == CID_SIG_V23_JP) {
07551                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07552                      } else {
07553                         res = callerid_feed(cs, buf, res, AST_LAW(p));
07554                      }
07555 
07556                      if (res < 0) {
07557                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07558                         break;
07559                      } else if (res)
07560                         break;
07561                      else if (samples > (8000 * 10))
07562                         break;
07563                   }
07564                }
07565                if (res == 1) {
07566                   callerid_get(cs, &name, &number, &flags);
07567                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07568                }
07569 
07570                if (p->cid_signalling == CID_SIG_V23_JP) {
07571                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07572                   usleep(1);
07573                   res = 4000;
07574                } else {
07575 
07576                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
07577                   res = 2000;
07578                }
07579 
07580                for (;;) {
07581                   struct ast_frame *f;
07582                   res = ast_waitfor(chan, res);
07583                   if (res <= 0) {
07584                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07585                         "Exiting simple switch\n");
07586                      ast_hangup(chan);
07587                      goto quit;
07588                   } 
07589                   if (!(f = ast_read(chan))) {
07590                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07591                      ast_hangup(chan);
07592                      goto quit;
07593                   }
07594                   ast_frfree(f);
07595                   if (chan->_state == AST_STATE_RING ||
07596                       chan->_state == AST_STATE_RINGING) 
07597                      break; /* Got ring */
07598                }
07599    
07600                /* We must have a ring by now, so, if configured, lets try to listen for
07601                 * distinctive ringing */ 
07602                if (p->usedistinctiveringdetection) {
07603                   len = 0;
07604                   distMatches = 0;
07605                   /* Clear the current ring data array so we dont have old data in it. */
07606                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07607                      curRingData[receivedRingT] = 0;
07608                   receivedRingT = 0;
07609                   counter = 0;
07610                   counter1 = 0;
07611                   /* Check to see if context is what it should be, if not set to be. */
07612                   if (strcmp(p->context,p->defcontext) != 0) {
07613                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07614                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07615                   }
07616       
07617                   for (;;) {  
07618                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07619                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07620                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07621                         callerid_free(cs);
07622                         ast_hangup(chan);
07623                         goto quit;
07624                      }
07625                      if (i & DAHDI_IOMUX_SIGEVENT) {
07626                         res = dahdi_get_event(p->subs[index].dfd);
07627                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07628                         res = 0;
07629                         /* Let us detect distinctive ring */
07630       
07631                         curRingData[receivedRingT] = p->ringt;
07632       
07633                         if (p->ringt < p->ringt_base/2)
07634                            break;
07635                         /* Increment the ringT counter so we can match it against
07636                            values in chan_dahdi.conf for distinctive ring */
07637                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07638                            break;
07639                      } else if (i & DAHDI_IOMUX_READ) {
07640                         res = read(p->subs[index].dfd, buf, sizeof(buf));
07641                         if (res < 0) {
07642                            if (errno != ELAST) {
07643                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07644                               callerid_free(cs);
07645                               ast_hangup(chan);
07646                               goto quit;
07647                            }
07648                            break;
07649                         }
07650                         if (p->ringt) 
07651                            p->ringt--;
07652                         if (p->ringt == 1) {
07653                            res = -1;
07654                            break;
07655                         }
07656                      }
07657                   }
07658                   if (option_verbose > 2)
07659                      /* this only shows up if you have n of the dring patterns filled in */
07660                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07661    
07662                   for (counter = 0; counter < 3; counter++) {
07663                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07664                      channel */
07665                      distMatches = 0;
07666                      for (counter1 = 0; counter1 < 3; counter1++) {
07667                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07668                         (p->drings.ringnum[counter].ring[counter1]-10)) {
07669                            distMatches++;
07670                         }
07671                      }
07672                      if (distMatches == 3) {
07673                         /* The ring matches, set the context to whatever is for distinctive ring.. */
07674                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07675                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07676                         if (option_verbose > 2)
07677                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07678                         break;
07679                      }
07680                   }
07681                }
07682                /* Restore linear mode (if appropriate) for Caller*ID processing */
07683                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07684 #if 1
07685                restore_gains(p);
07686 #endif            
07687             } else
07688                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
07689          } else {
07690             ast_log(LOG_WARNING, "Channel %s in prering "
07691                "state, but I have nothing to do. "
07692                "Terminating simple switch, should be "
07693                "restarted by the actual ring.\n", 
07694                chan->name);
07695             ast_hangup(chan);
07696             goto quit;
07697          }
07698       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07699          /* FSK Bell202 callerID */
07700          cs = callerid_new(p->cid_signalling);
07701          if (cs) {
07702 #if 1
07703             bump_gains(p);
07704 #endif            
07705             samples = 0;
07706             len = 0;
07707             distMatches = 0;
07708             /* Clear the current ring data array so we dont have old data in it. */
07709             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
07710                curRingData[receivedRingT] = 0;
07711             receivedRingT = 0;
07712             counter = 0;
07713             counter1 = 0;
07714             /* Check to see if context is what it should be, if not set to be. */
07715             if (strcmp(p->context,p->defcontext) != 0) {
07716                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07717                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07718             }
07719 
07720             /* Take out of linear mode for Caller*ID processing */
07721             dahdi_setlinear(p->subs[index].dfd, 0);
07722             for (;;) {  
07723                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07724                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
07725                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07726                   callerid_free(cs);
07727                   ast_hangup(chan);
07728                   goto quit;
07729                }
07730                if (i & DAHDI_IOMUX_SIGEVENT) {
07731                   res = dahdi_get_event(p->subs[index].dfd);
07732                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07733                   /* If we get a PR event, they hung up while processing calerid */
07734                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07735                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07736                      p->polarity = POLARITY_IDLE;
07737                      callerid_free(cs);
07738                      ast_hangup(chan);
07739                      goto quit;
07740                   }
07741                   res = 0;
07742                   /* Let us detect callerid when the telco uses distinctive ring */
07743 
07744                   curRingData[receivedRingT] = p->ringt;
07745 
07746                   if (p->ringt < p->ringt_base/2)
07747                      break;
07748                   /* Increment the ringT counter so we can match it against
07749                      values in chan_dahdi.conf for distinctive ring */
07750                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07751                      break;
07752                } else if (i & DAHDI_IOMUX_READ) {
07753                   res = read(p->subs[index].dfd, buf, sizeof(buf));
07754                   if (res < 0) {
07755                      if (errno != ELAST) {
07756                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07757                         callerid_free(cs);
07758                         ast_hangup(chan);
07759                         goto quit;
07760                      }
07761                      break;
07762                   }
07763                   if (p->ringt) 
07764                      p->ringt--;
07765                   if (p->ringt == 1) {
07766                      res = -1;
07767                      break;
07768                   }
07769                   samples += res;
07770                   res = callerid_feed(cs, buf, res, AST_LAW(p));
07771                   if (res < 0) {
07772                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07773                      break;
07774                   } else if (res)
07775                      break;
07776                   else if (samples > (8000 * 10))
07777                      break;
07778                }
07779             }
07780             if (res == 1) {
07781                callerid_get(cs, &name, &number, &flags);
07782                if (option_debug)
07783                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07784             }
07785             if (distinctiveringaftercid == 1) {
07786                /* Clear the current ring data array so we dont have old data in it. */
07787                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07788                   curRingData[receivedRingT] = 0;
07789                }
07790                receivedRingT = 0;
07791                if (option_verbose > 2)
07792                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
07793                for (;;) {
07794                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07795                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
07796                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07797                      callerid_free(cs);
07798                      ast_hangup(chan);
07799                      goto quit;
07800                   }
07801                   if (i & DAHDI_IOMUX_SIGEVENT) {
07802                      res = dahdi_get_event(p->subs[index].dfd);
07803                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07804                      res = 0;
07805                      /* Let us detect callerid when the telco uses distinctive ring */
07806 
07807                      curRingData[receivedRingT] = p->ringt;
07808 
07809                      if (p->ringt < p->ringt_base/2)
07810                         break;
07811                      /* Increment the ringT counter so we can match it against
07812                         values in chan_dahdi.conf for distinctive ring */
07813                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
07814                         break;
07815                   } else if (i & DAHDI_IOMUX_READ) {
07816                      res = read(p->subs[index].dfd, buf, sizeof(buf));
07817                      if (res < 0) {
07818                         if (errno != ELAST) {
07819                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07820                            callerid_free(cs);
07821                            ast_hangup(chan);
07822                            goto quit;
07823                         }
07824                         break;
07825                      }
07826                   if (p->ringt)
07827                      p->ringt--;
07828                      if (p->ringt == 1) {
07829                         res = -1;
07830                         break;
07831                      }
07832                   }
07833                }
07834             }
07835             if (p->usedistinctiveringdetection) {
07836                if (option_verbose > 2)
07837                   /* this only shows up if you have n of the dring patterns filled in */
07838                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07839 
07840                for (counter = 0; counter < 3; counter++) {
07841                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07842                   channel */
07843                   if (option_verbose > 2)
07844                      /* this only shows up if you have n of the dring patterns filled in */
07845                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
07846                         p->drings.ringnum[counter].ring[0],
07847                         p->drings.ringnum[counter].ring[1],
07848                         p->drings.ringnum[counter].ring[2]);
07849                   distMatches = 0;
07850                   for (counter1 = 0; counter1 < 3; counter1++) {
07851                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
07852                      (p->drings.ringnum[counter].ring[counter1]-10)) {
07853                         distMatches++;
07854                      }
07855                   }
07856                   if (distMatches == 3) {
07857                      /* The ring matches, set the context to whatever is for distinctive ring.. */
07858                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07859                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07860                      if (option_verbose > 2)
07861                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
07862                      break;
07863                   }
07864                }
07865             }
07866             /* Restore linear mode (if appropriate) for Caller*ID processing */
07867             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
07868 #if 1
07869             restore_gains(p);
07870 #endif            
07871             if (res < 0) {
07872                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07873             }
07874          } else
07875             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07876       }
07877       else
07878          cs = NULL;
07879 
07880       if (number)
07881          ast_shrink_phone_number(number);
07882       ast_set_callerid(chan, number, name, number);
07883 
07884       if (smdi_msg)
07885          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07886 
07887       if (cs)
07888          callerid_free(cs);
07889 
07890       ast_setstate(chan, AST_STATE_RING);
07891       chan->rings = 1;
07892       p->ringt = p->ringt_base;
07893       res = ast_pbx_run(chan);
07894       if (res) {
07895          ast_hangup(chan);
07896          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07897       }
07898       goto quit;
07899    default:
07900       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07901       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07902       if (res < 0)
07903             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07904    }
07905    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07906    if (res < 0)
07907          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07908    ast_hangup(chan);
07909 quit:
07910    ast_mutex_lock(&ss_thread_lock);
07911    ss_thread_count--;
07912    ast_cond_signal(&ss_thread_complete);
07913    ast_mutex_unlock(&ss_thread_lock);
07914    return NULL;
07915 }
07916 
07917 static int calc_energy(const unsigned char *buf, int len, int law)
07918 {
07919    int x;
07920    int sum = 0;
07921 
07922    if (!len)
07923       return 0;
07924 
07925    for (x = 0; x < len; x++)
07926       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07927 
07928    return sum / len;
07929 }
07930 
07931 /* destroy a DAHDI channel, identified by its number */
07932 static int dahdi_destroy_channel_bynum(int channel)
07933 {
07934    struct dahdi_pvt *tmp = NULL;
07935    struct dahdi_pvt *prev = NULL;
07936 
07937    ast_mutex_lock(&iflock);
07938    tmp = iflist;
07939    while (tmp) {
07940       if (tmp->channel == channel) {
07941          int x = DAHDI_FLASH;
07942          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 */
07943          destroy_channel(prev, tmp, 1);
07944          ast_mutex_unlock(&iflock);
07945          ast_module_unref(ast_module_info->self);
07946          return RESULT_SUCCESS;
07947       }
07948       prev = tmp;
07949       tmp = tmp->next;
07950    }
07951    ast_mutex_unlock(&iflock);
07952    return RESULT_FAILURE;
07953 }
07954 
07955 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
07956 {
07957    int res;
07958    pthread_t threadid;
07959    pthread_attr_t attr;
07960    struct ast_channel *chan;
07961    pthread_attr_init(&attr);
07962    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07963    /* Handle an event on a given channel for the monitor thread. */
07964    switch (event) {
07965    case DAHDI_EVENT_NONE:
07966    case DAHDI_EVENT_BITSCHANGED:
07967       break;
07968    case DAHDI_EVENT_WINKFLASH:
07969    case DAHDI_EVENT_RINGOFFHOOK:
07970       if (i->inalarm) break;
07971       if (i->radio) break;
07972       /* Got a ring/answer.  What kind of channel are we? */
07973       switch (i->sig) {
07974       case SIG_FXOLS:
07975       case SIG_FXOGS:
07976       case SIG_FXOKS:
07977          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07978          if (res && (errno == EBUSY))
07979             break;
07980          if (i->cidspill) {
07981             /* Cancel VMWI spill */
07982             free(i->cidspill);
07983             i->cidspill = NULL;
07984          }
07985          if (i->immediate) {
07986             dahdi_enable_ec(i);
07987             /* The channel is immediately up.  Start right away */
07988             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07989             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07990             if (!chan) {
07991                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07992                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07993                if (res < 0)
07994                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07995             }
07996          } else {
07997             /* Check for callerid, digits, etc */
07998             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07999             if (chan) {
08000                if (has_voicemail(i))
08001                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08002                else
08003                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08004                if (res < 0) 
08005                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08006                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08007                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08008                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08009                   if (res < 0)
08010                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08011                   ast_hangup(chan);
08012                }
08013             } else
08014                ast_log(LOG_WARNING, "Unable to create channel\n");
08015          }
08016          break;
08017       case SIG_FXSLS:
08018       case SIG_FXSGS:
08019       case SIG_FXSKS:
08020             i->ringt = i->ringt_base;
08021             /* Fall through */
08022       case SIG_EMWINK:
08023       case SIG_FEATD:
08024       case SIG_FEATDMF:
08025       case SIG_FEATDMF_TA:
08026       case SIG_E911:
08027       case SIG_FGC_CAMA:
08028       case SIG_FGC_CAMAMF:
08029       case SIG_FEATB:
08030       case SIG_EM:
08031       case SIG_EM_E1:
08032       case SIG_SFWINK:
08033       case SIG_SF_FEATD:
08034       case SIG_SF_FEATDMF:
08035       case SIG_SF_FEATB:
08036       case SIG_SF:
08037             /* Check for callerid, digits, etc */
08038             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08039             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08040                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08041                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08042                if (res < 0)
08043                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08044                ast_hangup(chan);
08045             } else if (!chan) {
08046                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08047             }
08048             break;
08049       default:
08050          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08051          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08052          if (res < 0)
08053                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08054          pthread_attr_destroy(&attr);
08055          return NULL;
08056       }
08057       break;
08058    case DAHDI_EVENT_NOALARM:
08059       i->inalarm = 0;
08060       if (!i->unknown_alarm) {
08061          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08062          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08063                   "Channel: %d\r\n", i->channel);
08064       } else {
08065          i->unknown_alarm = 0;
08066       }
08067       break;
08068    case DAHDI_EVENT_ALARM:
08069       i->inalarm = 1;
08070       res = get_alarms(i);
08071       handle_alarms(i, res);
08072       /* fall thru intentionally */
08073    case DAHDI_EVENT_ONHOOK:
08074       if (i->radio)
08075          break;
08076       /* Back on hook.  Hang up. */
08077       switch (i->sig) {
08078       case SIG_FXOLS:
08079       case SIG_FXOGS:
08080       case SIG_FEATD:
08081       case SIG_FEATDMF:
08082       case SIG_FEATDMF_TA:
08083       case SIG_E911:
08084       case SIG_FGC_CAMA:
08085       case SIG_FGC_CAMAMF:
08086       case SIG_FEATB:
08087       case SIG_EM:
08088       case SIG_EM_E1:
08089       case SIG_EMWINK:
08090       case SIG_SF_FEATD:
08091       case SIG_SF_FEATDMF:
08092       case SIG_SF_FEATB:
08093       case SIG_SF:
08094       case SIG_SFWINK:
08095       case SIG_FXSLS:
08096       case SIG_FXSGS:
08097       case SIG_FXSKS:
08098       case SIG_GR303FXSKS:
08099          dahdi_disable_ec(i);
08100          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08101          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08102          break;
08103       case SIG_GR303FXOKS:
08104       case SIG_FXOKS:
08105          dahdi_disable_ec(i);
08106          /* Diddle the battery for the zhone */
08107 #ifdef ZHONE_HACK
08108          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08109          usleep(1);
08110 #endif         
08111          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08112          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08113          break;
08114       case SIG_PRI:
08115          dahdi_disable_ec(i);
08116          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08117          break;
08118       default:
08119          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08120          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08121          pthread_attr_destroy(&attr);
08122          return NULL;
08123       }
08124       break;
08125    case DAHDI_EVENT_POLARITY:
08126       switch (i->sig) {
08127       case SIG_FXSLS:
08128       case SIG_FXSKS:
08129       case SIG_FXSGS:
08130          /* We have already got a PR before the channel was 
08131             created, but it wasn't handled. We need polarity 
08132             to be REV for remote hangup detection to work. 
08133             At least in Spain */
08134          if (i->hanguponpolarityswitch)
08135             i->polarity = POLARITY_REV;
08136 
08137          if (i->cid_start == CID_START_POLARITY) {
08138             i->polarity = POLARITY_REV;
08139             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
08140                    "CID detection on channel %d\n",
08141                    i->channel);
08142             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08143             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
08144                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08145             }
08146          }
08147          break;
08148       default:
08149          ast_log(LOG_WARNING, "handle_init_event detected "
08150             "polarity reversal on non-FXO (SIG_FXS) "
08151             "interface %d\n", i->channel);
08152       }
08153       break;
08154    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
08155       ast_log(LOG_NOTICE, 
08156             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08157             i->channel);
08158       pthread_attr_destroy(&attr);
08159       return i;
08160    }
08161    pthread_attr_destroy(&attr);
08162    return NULL;
08163 }
08164 
08165 static void *do_monitor(void *data)
08166 {
08167    int count, res, res2, spoint, pollres=0;
08168    struct dahdi_pvt *i;
08169    struct dahdi_pvt *last = NULL;
08170    struct dahdi_pvt *doomed;
08171    time_t thispass = 0, lastpass = 0;
08172    int found;
08173    char buf[1024];
08174    struct pollfd *pfds=NULL;
08175    int lastalloc = -1;
08176    /* This thread monitors all the frame relay interfaces which are not yet in use
08177       (and thus do not have a separate thread) indefinitely */
08178    /* From here on out, we die whenever asked */
08179 #if 0
08180    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08181       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08182       return NULL;
08183    }
08184    ast_log(LOG_DEBUG, "Monitor starting...\n");
08185 #endif
08186    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08187 
08188    for (;;) {
08189       /* Lock the interface list */
08190       ast_mutex_lock(&iflock);
08191       if (!pfds || (lastalloc != ifcount)) {
08192          if (pfds) {
08193             free(pfds);
08194             pfds = NULL;
08195          }
08196          if (ifcount) {
08197             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08198                ast_mutex_unlock(&iflock);
08199                return NULL;
08200             }
08201          }
08202          lastalloc = ifcount;
08203       }
08204       /* Build the stuff we're going to poll on, that is the socket of every
08205          dahdi_pvt that does not have an associated owner channel */
08206       count = 0;
08207       i = iflist;
08208       while (i) {
08209          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
08210             if (!i->owner && !i->subs[SUB_REAL].owner) {
08211                /* This needs to be watched, as it lacks an owner */
08212                pfds[count].fd = i->subs[SUB_REAL].dfd;
08213                pfds[count].events = POLLPRI;
08214                pfds[count].revents = 0;
08215                /* Message waiting or r2 channels also get watched for reading */
08216                if (i->cidspill ||
08217                    (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
08218                   pfds[count].events |= POLLIN;
08219                }
08220                count++;
08221             }
08222          }
08223          i = i->next;
08224       }
08225       /* Okay, now that we know what to do, release the interface lock */
08226       ast_mutex_unlock(&iflock);
08227       
08228       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08229       pthread_testcancel();
08230       /* Wait at least a second for something to happen */
08231       res = poll(pfds, count, 1000);
08232       pthread_testcancel();
08233       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08234 
08235       /* Okay, poll has finished.  Let's see what happened.  */
08236       if (res < 0) {
08237          if ((errno != EAGAIN) && (errno != EINTR))
08238             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08239          continue;
08240       }
08241       /* Alright, lock the interface list again, and let's look and see what has
08242          happened */
08243       ast_mutex_lock(&iflock);
08244       found = 0;
08245       spoint = 0;
08246       lastpass = thispass;
08247       thispass = time(NULL);
08248       doomed = NULL;
08249       for (i = iflist;; i = i->next) {
08250          if (doomed) {
08251             int res;
08252             res = dahdi_destroy_channel_bynum(doomed->channel);
08253             if (!res) {
08254                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
08255             }
08256             doomed = NULL;
08257          }
08258          if (!i) {
08259             break;
08260          }
08261          if (thispass != lastpass) {
08262             if (!found && ((i == last) || ((i == iflist) && !last))) {
08263                last = i;
08264                if (last) {
08265                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08266                      (last->sig & __DAHDI_SIG_FXO)) {
08267                      res = ast_app_has_voicemail(last->mailbox, NULL);
08268                      if (last->msgstate != res) {
08269                         int x;
08270                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08271                         x = DAHDI_FLUSH_BOTH;
08272                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08273                         if (res2)
08274                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
08275                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08276                            /* Turn on on hook transfer for 4 seconds */
08277                            x = 4000;
08278                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08279                            last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08280                            last->cidpos = 0;
08281                            last->msgstate = res;
08282                            last->onhooktime = thispass;
08283                         }
08284                         found ++;
08285                      }
08286                   }
08287                   last = last->next;
08288                }
08289             }
08290          }
08291          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08292             if (i->radio && !i->owner)
08293             {
08294                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08295                if (res)
08296                {
08297                   if (option_debug)
08298                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08299                   /* Don't hold iflock while handling init events */
08300                   ast_mutex_unlock(&iflock);
08301                   doomed = handle_init_event(i, res);
08302                   ast_mutex_lock(&iflock);   
08303                }
08304                continue;
08305             }              
08306             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08307             if (pollres & POLLIN) {
08308                if (i->owner || i->subs[SUB_REAL].owner) {
08309 #ifdef HAVE_PRI
08310                   if (!i->pri)
08311 #endif                  
08312                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08313                   continue;
08314                }
08315                //             if (!i->cidspill) {
08316                // ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08317                // continue;
08318                //}
08319                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08320                if (res > 0) {
08321                   /* We read some number of bytes.  Write an equal amount of data */
08322 /*                   if (res > i->cidlen - i->cidpos)  */
08323 /*                      res = i->cidlen - i->cidpos; */
08324 /*                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); */
08325 /*                   if (res2 > 0) { */
08326 /*                      i->cidpos += res2; */
08327 /*                      if (i->cidpos >= i->cidlen) { */
08328 /*                         free(i->cidspill); */
08329 /*                         i->cidspill = 0; */
08330 /*                         i->cidpos = 0; */
08331 /*                         i->cidlen = 0; */
08332                   /* If configured to check for a DTMF CID spill that comes without alert (e.g no polarity reversal) */
08333                   if (i->cid_start == CID_START_DTMF_NOALERT) {
08334                      int energy;
08335                      struct timeval now;
08336                      /* State machine dtmfcid_holdoff_state allows for the line to settle
08337                       * before checking agin for dtmf energy.  Presently waits for 500 mS before checking again
08338                      */
08339                      if (1 == i->dtmfcid_holdoff_state) {
08340                         gettimeofday(&i->dtmfcid_delay, NULL);
08341                         i->dtmfcid_holdoff_state = 2;
08342                      } else if (2 == i->dtmfcid_holdoff_state) {
08343                         gettimeofday(&now, NULL);
08344                         if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
08345                            i->dtmfcid_holdoff_state = 0;
08346                         }
08347                      } else {
08348                         energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
08349                         if (energy > dtmfcid_level) {
08350                            pthread_t threadid;
08351                            struct ast_channel *chan;
08352                            ast_mutex_unlock(&iflock);
08353                            chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08354                            if (!chan) {
08355                               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08356                            } else {
08357                               pthread_attr_t attr;
08358                               pthread_attr_init(&attr);
08359                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08360                               res = ast_pthread_create(&threadid, &attr, ss_thread, chan);
08361                               if (res) {
08362                                  ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08363                               } else {
08364                                  i->dtmfcid_holdoff_state = 1;
08365                               }
08366                            }
08367                            ast_mutex_lock(&iflock);
08368                         }
08369                      }
08370 /*                   } else { */
08371 /*                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); */
08372 /*                      i->msgstate = -1; */
08373                   }
08374                } else {
08375                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08376                }
08377             }
08378             if (pollres & POLLPRI) {
08379                if (i->owner || i->subs[SUB_REAL].owner) {
08380 #ifdef HAVE_PRI
08381                   if (!i->pri)
08382 #endif                  
08383                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08384                   continue;
08385                }
08386                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08387                if (option_debug)
08388                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08389                /* Don't hold iflock while handling init events */
08390                ast_mutex_unlock(&iflock);
08391                doomed = handle_init_event(i, res);
08392                ast_mutex_lock(&iflock);   
08393             }
08394          }
08395       }
08396       ast_mutex_unlock(&iflock);
08397    }
08398    /* Never reached */
08399    return NULL;
08400    
08401 }
08402 
08403 static int restart_monitor(void)
08404 {
08405    pthread_attr_t attr;
08406    pthread_attr_init(&attr);
08407    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08408    /* If we're supposed to be stopped -- stay stopped */
08409    if (monitor_thread == AST_PTHREADT_STOP)
08410       return 0;
08411    ast_mutex_lock(&monlock);
08412    if (monitor_thread == pthread_self()) {
08413       ast_mutex_unlock(&monlock);
08414       ast_log(LOG_WARNING, "Cannot kill myself\n");
08415       return -1;
08416    }
08417    if (monitor_thread != AST_PTHREADT_NULL) {
08418       /* Wake up the thread */
08419       pthread_kill(monitor_thread, SIGURG);
08420    } else {
08421       /* Start a new monitor */
08422       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
08423          ast_mutex_unlock(&monlock);
08424          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08425          pthread_attr_destroy(&attr);
08426          return -1;
08427       }
08428    }
08429    ast_mutex_unlock(&monlock);
08430    pthread_attr_destroy(&attr);
08431    return 0;
08432 }
08433 
08434 #ifdef HAVE_OPENR2
08435 static struct dahdi_mfcr2 *mfcr2_get_context(int id)
08436 {
08437    if ((id < 0) || (id >= (sizeof(r2links)/sizeof(r2links[0])))) {
08438       ast_log(LOG_ERROR, "No more R2 links available!.\n");
08439       return NULL;
08440    }
08441    return &r2links[id];
08442 }
08443 #endif
08444 
08445 #ifdef HAVE_PRI
08446 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08447 {
08448    int x;
08449    int trunkgroup;
08450    /* Get appropriate trunk group if there is one */
08451    trunkgroup = pris[*span].mastertrunkgroup;
08452    if (trunkgroup) {
08453       /* Select a specific trunk group */
08454       for (x = 0; x < NUM_SPANS; x++) {
08455          if (pris[x].trunkgroup == trunkgroup) {
08456             *span = x;
08457             return 0;
08458          }
08459       }
08460       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08461       *span = -1;
08462    } else {
08463       if (pris[*span].trunkgroup) {
08464          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08465          *span = -1;
08466       } else if (pris[*span].mastertrunkgroup) {
08467          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08468          *span = -1;
08469       } else {
08470          if (si->totalchans == 31) {
08471             /* E1 */
08472             pris[*span].dchannels[0] = 16 + offset;
08473          } else if (si->totalchans == 24) {
08474             /* T1 or J1 */
08475             pris[*span].dchannels[0] = 24 + offset;
08476          } else if (si->totalchans == 3) {
08477             /* BRI */
08478             pris[*span].dchannels[0] = 3 + offset;
08479          } else {
08480             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);
08481             *span = -1;
08482             return 0;
08483          }
08484          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08485          pris[*span].offset = offset;
08486          pris[*span].span = *span + 1;
08487       }
08488    }
08489    return 0;
08490 }
08491 
08492 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08493 {
08494    struct dahdi_spaninfo si;
08495    struct dahdi_params p;
08496    int fd;
08497    int span;
08498    int ospan=0;
08499    int x,y;
08500    for (x = 0; x < NUM_SPANS; x++) {
08501       if (pris[x].trunkgroup == trunkgroup) {
08502          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08503          return -1;
08504       }
08505    }
08506    for (y = 0; y < NUM_DCHANS; y++) {
08507       if (!channels[y]) 
08508          break;
08509       memset(&si, 0, sizeof(si));
08510       memset(&p, 0, sizeof(p));
08511       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
08512       if (fd < 0) {
08513          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08514          return -1;
08515       }
08516       x = channels[y];
08517       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08518          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08519          close(fd);
08520          return -1;
08521       }
08522       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08523          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08524          return -1;
08525       }
08526       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08527          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08528          close(fd);
08529          return -1;
08530       }
08531       span = p.spanno - 1;
08532       if (pris[span].trunkgroup) {
08533          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08534          close(fd);
08535          return -1;
08536       }
08537       if (pris[span].pvts[0]) {
08538          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08539          close(fd);
08540          return -1;
08541       }
08542       if (!y) {
08543          pris[span].trunkgroup = trunkgroup;
08544          pris[span].offset = channels[y] - p.chanpos;
08545          ospan = span;
08546       }
08547       pris[ospan].dchannels[y] = channels[y];
08548       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08549       pris[span].span = span + 1;
08550       close(fd);
08551    }
08552    return 0;   
08553 }
08554 
08555 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08556 {
08557    if (pris[span].mastertrunkgroup) {
08558       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);
08559       return -1;
08560    }
08561    pris[span].mastertrunkgroup = trunkgroup;
08562    pris[span].prilogicalspan = logicalspan;
08563    return 0;
08564 }
08565 
08566 #endif
08567 
08568 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08569 {
08570    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
08571    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
08572    char fn[80];
08573 #if 1
08574    struct dahdi_bufferinfo bi;
08575 #endif
08576    int res;
08577    int span=0;
08578    int here = 0;
08579    int x;
08580    struct dahdi_pvt **wlist;
08581    struct dahdi_pvt **wend;
08582    struct dahdi_params p;
08583 
08584    wlist = &iflist;
08585    wend = &ifend;
08586 
08587 #ifdef HAVE_PRI
08588    if (pri) {
08589       wlist = &pri->crvs;
08590       wend = &pri->crvend;
08591    }
08592 #endif
08593 
08594    tmp2 = *wlist;
08595    prev = NULL;
08596 
08597    while (tmp2) {
08598       if (!tmp2->destroy) {
08599          if (tmp2->channel == channel) {
08600             tmp = tmp2;
08601             here = 1;
08602             break;
08603          }
08604          if (tmp2->channel > channel) {
08605             break;
08606          }
08607       }
08608       prev = tmp2;
08609       tmp2 = tmp2->next;
08610    }
08611 
08612    if (!here && reloading != 1) {
08613       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08614          if (tmp)
08615             free(tmp);
08616          return NULL;
08617       }
08618       ast_mutex_init(&tmp->lock);
08619       ifcount++;
08620       for (x = 0; x < 3; x++)
08621          tmp->subs[x].dfd = -1;
08622       tmp->channel = channel;
08623       tmp->priindication_oob = conf->chan.priindication_oob;
08624    }
08625 
08626    if (tmp) {
08627       int chan_sig = conf->chan.sig;
08628       if (!here) {
08629          if ((channel != CHAN_PSEUDO) && !pri) {
08630             int count = 0;
08631             snprintf(fn, sizeof(fn), "%d", channel);
08632             /* Open non-blocking */
08633             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08634             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 */
08635                usleep(1);
08636                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08637                count++;
08638             }
08639             /* Allocate a DAHDI structure */
08640             if (tmp->subs[SUB_REAL].dfd < 0) {
08641                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);
08642                destroy_dahdi_pvt(&tmp);
08643                return NULL;
08644             }
08645             memset(&p, 0, sizeof(p));
08646             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08647             if (res < 0) {
08648                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08649                destroy_dahdi_pvt(&tmp);
08650                return NULL;
08651             }
08652             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
08653                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));
08654                destroy_dahdi_pvt(&tmp);
08655                return NULL;
08656             }
08657             tmp->law = p.curlaw;
08658             tmp->span = p.spanno;
08659             span = p.spanno - 1;
08660          } else {
08661             if (channel == CHAN_PSEUDO)
08662                chan_sig = 0;
08663             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08664                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08665                return NULL;
08666             }
08667          }
08668 #ifdef HAVE_PRI
08669          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08670             int offset;
08671             int myswitchtype;
08672             int matchesdchan;
08673             int x,y;
08674             offset = 0;
08675             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08676                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08677                destroy_dahdi_pvt(&tmp);
08678                return NULL;
08679             }
08680             if (span >= NUM_SPANS) {
08681                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08682                destroy_dahdi_pvt(&tmp);
08683                return NULL;
08684             } else {
08685                struct dahdi_spaninfo si;
08686                si.spanno = 0;
08687                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08688                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08689                   destroy_dahdi_pvt(&tmp);
08690                   return NULL;
08691                }
08692                /* Store the logical span first based upon the real span */
08693                tmp->logicalspan = pris[span].prilogicalspan;
08694                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08695                if (span < 0) {
08696                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08697                   destroy_dahdi_pvt(&tmp);
08698                   return NULL;
08699                }
08700                if (chan_sig == SIG_PRI)
08701                   myswitchtype = conf->pri.switchtype;
08702                else
08703                   myswitchtype = PRI_SWITCH_GR303_TMC;
08704                /* Make sure this isn't a d-channel */
08705                matchesdchan=0;
08706                for (x = 0; x < NUM_SPANS; x++) {
08707                   for (y = 0; y < NUM_DCHANS; y++) {
08708                      if (pris[x].dchannels[y] == tmp->channel) {
08709                         matchesdchan = 1;
08710                         break;
08711                      }
08712                   }
08713                }
08714                offset = p.chanpos;
08715                if (!matchesdchan) {
08716                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08717                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08718                      destroy_dahdi_pvt(&tmp);
08719                      return NULL;
08720                   }
08721                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08722                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08723                      destroy_dahdi_pvt(&tmp);
08724                      return NULL;
08725                   }
08726                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08727                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08728                      destroy_dahdi_pvt(&tmp);
08729                      return NULL;
08730                   }
08731                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08732                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08733                      destroy_dahdi_pvt(&tmp);
08734                      return NULL;
08735                   }
08736                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08737                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08738                      destroy_dahdi_pvt(&tmp);
08739                      return NULL;
08740                   }
08741                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08742                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08743                      destroy_dahdi_pvt(&tmp);
08744                      return NULL;
08745                   }
08746                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08747                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08748                      destroy_dahdi_pvt(&tmp);
08749                      return NULL;
08750                   }
08751                   if (pris[span].numchans >= MAX_CHANNELS) {
08752                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08753                         pris[span].trunkgroup);
08754                      destroy_dahdi_pvt(&tmp);
08755                      return NULL;
08756                   }
08757                   pris[span].nodetype = conf->pri.nodetype;
08758                   pris[span].switchtype = myswitchtype;
08759                   pris[span].nsf = conf->pri.nsf;
08760                   pris[span].dialplan = conf->pri.dialplan;
08761                   pris[span].localdialplan = conf->pri.localdialplan;
08762                   pris[span].pvts[pris[span].numchans++] = tmp;
08763                   pris[span].minunused = conf->pri.minunused;
08764                   pris[span].minidle = conf->pri.minidle;
08765                   pris[span].overlapdial = conf->pri.overlapdial;
08766 #ifdef HAVE_PRI_INBANDDISCONNECT
08767                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08768 #endif
08769                   pris[span].facilityenable = conf->pri.facilityenable;
08770                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08771                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08772                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08773                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08774                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08775                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08776                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08777                   pris[span].resetinterval = conf->pri.resetinterval;
08778                   
08779                   tmp->pri = &pris[span];
08780                   tmp->prioffset = offset;
08781                   tmp->call = NULL;
08782                } else {
08783                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08784                   destroy_dahdi_pvt(&tmp);
08785                   return NULL;
08786                }
08787             }
08788          } else {
08789             tmp->prioffset = 0;
08790          }
08791 #endif
08792 #ifdef HAVE_OPENR2
08793          if (chan_sig == SIG_MFCR2 && reloading != 1) {
08794             char logdir[OR2_MAX_PATH];
08795             struct dahdi_mfcr2 *dahdi_r2;
08796             int threshold = 0;
08797             int snres = 0;
08798             dahdi_r2 = mfcr2_get_context(mfcr2_cur_context_index);
08799             if (!dahdi_r2) {
08800                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
08801             } else if (!dahdi_r2->protocol_context){
08802                char tmplogdir[] = "/tmp";
08803                dahdi_r2->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface, 
08804                      &dahdi_r2_transcode_iface, mfcr2_cur_variant, mfcr2_cur_max_ani, mfcr2_cur_max_dnis);
08805                if (!dahdi_r2->protocol_context) {
08806                   ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
08807                   destroy_dahdi_pvt(&tmp);
08808                   return NULL;
08809                } 
08810                openr2_context_set_log_level(dahdi_r2->protocol_context, mfcr2_cur_loglevel);
08811                openr2_context_set_ani_first(dahdi_r2->protocol_context, mfcr2_cur_get_ani_first);
08812                openr2_context_set_skip_category_request(dahdi_r2->protocol_context, mfcr2_cur_skip_category);
08813                openr2_context_set_mf_threshold(dahdi_r2->protocol_context, threshold);
08814                openr2_context_set_mf_back_timeout(dahdi_r2->protocol_context, mfcr2_cur_mfback_timeout);
08815                openr2_context_set_metering_pulse_timeout(dahdi_r2->protocol_context, mfcr2_cur_metering_pulse_timeout);
08816                openr2_context_set_double_answer(dahdi_r2->protocol_context, mfcr2_cur_double_answer);
08817                openr2_context_set_immediate_accept(dahdi_r2->protocol_context, mfcr2_cur_immediate_accept);
08818 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
08819                openr2_context_set_dtmf_dialing(dahdi_r2->protocol_context, mfcr2_cur_dtmf_dialing, mfcr2_cur_dtmf_time_on, mfcr2_cur_dtmf_time_off);
08820                openr2_context_set_dtmf_detection(dahdi_r2->protocol_context, mfcr2_cur_dtmf_detection);
08821 #endif
08822                if (ast_strlen_zero(mfcr2_cur_logdir)) {
08823                   if (openr2_context_set_log_directory(dahdi_r2->protocol_context, tmplogdir)) {
08824                      ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08825                   }
08826                } else {
08827                   snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", mfcr2_cur_logdir);
08828                   if (snres >= sizeof(logdir)) {
08829                      ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
08830                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08831                         ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
08832                      }
08833                   } else {
08834                      if (openr2_context_set_log_directory(dahdi_r2->protocol_context, logdir)) {
08835                         ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
08836                      }
08837                   }  
08838                }
08839                if (!ast_strlen_zero(mfcr2_cur_r2proto_file)) {
08840                   if (openr2_context_configure_from_advanced_file(dahdi_r2->protocol_context, mfcr2_cur_r2proto_file)) {
08841                      ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", mfcr2_cur_r2proto_file);
08842                   }
08843                }
08844             } 
08845             if (dahdi_r2) {
08846                /* TODO: should we check numchans overflow, or is it already done by DAHDI? */
08847                dahdi_r2->pvts[dahdi_r2->numchans++] = tmp;
08848                tmp->r2chan = openr2_chan_new_from_fd(dahdi_r2->protocol_context,
08849                      tmp->subs[SUB_REAL].dfd, NULL, NULL);
08850                if (!tmp->r2chan) {
08851                   openr2_liberr_t err = openr2_context_get_last_error(dahdi_r2->protocol_context);
08852                   ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
08853                   destroy_dahdi_pvt(&tmp);
08854                   return NULL;
08855                }
08856                openr2_chan_set_client_data(tmp->r2chan, tmp);
08857                /* cast seems to be needed to get rid of the annoying warning regarding format attribute */
08858                openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
08859                openr2_chan_set_log_level(tmp->r2chan, mfcr2_cur_loglevel);
08860                if (mfcr2_cur_call_files) {
08861                   openr2_chan_enable_call_files(tmp->r2chan);
08862                }
08863                tmp->mfcr2_category = mfcr2_cur_category;
08864                tmp->mfcr2 = dahdi_r2;
08865                tmp->mfcr2call = 0;
08866                tmp->mfcr2block = DAHDI_R2_REMOTE_BLOCK | DAHDI_R2_LOCAL_BLOCK;
08867                tmp->mfcr2_accept_on_offer = mfcr2_cur_accept_on_offer;
08868                tmp->mfcr2_charge_calls = mfcr2_cur_charge_calls;
08869                tmp->mfcr2_ani_index = 0;
08870                tmp->mfcr2_dnis_index = 0;
08871                tmp->mfcr2_allow_collect_calls = mfcr2_cur_allow_collect_calls;
08872                tmp->mfcr2_forced_release = mfcr2_cur_forced_release;
08873             }
08874          }
08875 #endif
08876       } else {
08877          chan_sig = tmp->sig;
08878          if (tmp->subs[SUB_REAL].dfd > -1) {
08879             memset(&p, 0, sizeof(p));
08880             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08881          }
08882       }
08883       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
08884       switch (chan_sig) {
08885       case SIG_FXSKS:
08886       case SIG_FXSLS:
08887       case SIG_EM:
08888       case SIG_EM_E1:
08889       case SIG_EMWINK:
08890       case SIG_FEATD:
08891       case SIG_FEATDMF:
08892       case SIG_FEATDMF_TA:
08893       case SIG_FEATB:
08894       case SIG_E911:
08895       case SIG_SF:
08896       case SIG_SFWINK:
08897       case SIG_FGC_CAMA:
08898       case SIG_FGC_CAMAMF:
08899       case SIG_SF_FEATD:
08900       case SIG_SF_FEATDMF:
08901       case SIG_SF_FEATB:
08902          p.starttime = 250;
08903          break;
08904       }
08905 
08906       if (tmp->radio) {
08907          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
08908          p.channo = channel;
08909          p.rxwinktime = 1;
08910          p.rxflashtime = 1;
08911          p.starttime = 1;
08912          p.debouncetime = 5;
08913       }
08914       if (!tmp->radio) {
08915          p.channo = channel;
08916          /* Override timing settings based on config file */
08917          if (conf->timing.prewinktime >= 0)
08918             p.prewinktime = conf->timing.prewinktime;
08919          if (conf->timing.preflashtime >= 0)
08920             p.preflashtime = conf->timing.preflashtime;
08921          if (conf->timing.winktime >= 0)
08922             p.winktime = conf->timing.winktime;
08923          if (conf->timing.flashtime >= 0)
08924             p.flashtime = conf->timing.flashtime;
08925          if (conf->timing.starttime >= 0)
08926             p.starttime = conf->timing.starttime;
08927          if (conf->timing.rxwinktime >= 0)
08928             p.rxwinktime = conf->timing.rxwinktime;
08929          if (conf->timing.rxflashtime >= 0)
08930             p.rxflashtime = conf->timing.rxflashtime;
08931          if (conf->timing.debouncetime >= 0)
08932             p.debouncetime = conf->timing.debouncetime;
08933       }
08934       
08935       /* dont set parms on a pseudo-channel (or CRV) */
08936       if (tmp->subs[SUB_REAL].dfd >= 0)
08937       {
08938          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08939          if (res < 0) {
08940             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08941             destroy_dahdi_pvt(&tmp);
08942             return NULL;
08943          }
08944       }
08945 #if 1
08946       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08947          memset(&bi, 0, sizeof(bi));
08948          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08949          if (!res) {
08950             bi.txbufpolicy = conf->chan.buf_policy;
08951             bi.rxbufpolicy = conf->chan.buf_policy;
08952             bi.numbufs = conf->chan.buf_no;
08953             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08954             if (res < 0) {
08955                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08956             }
08957          } else
08958             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08959       }
08960 #endif
08961       tmp->immediate = conf->chan.immediate;
08962       tmp->transfertobusy = conf->chan.transfertobusy;
08963       tmp->sig = chan_sig;
08964       tmp->outsigmod = conf->chan.outsigmod;
08965       tmp->ringt_base = ringt_base;
08966       tmp->firstradio = 0;
08967       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08968          tmp->permcallwaiting = conf->chan.callwaiting;
08969       else
08970          tmp->permcallwaiting = 0;
08971       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
08972       tmp->destroy = 0;
08973       tmp->drings = drings;
08974       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
08975       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08976       tmp->threewaycalling = conf->chan.threewaycalling;
08977       tmp->adsi = conf->chan.adsi;
08978       tmp->use_smdi = conf->chan.use_smdi;
08979       tmp->permhidecallerid = conf->chan.hidecallerid;
08980       tmp->callreturn = conf->chan.callreturn;
08981       tmp->echocancel = conf->chan.echocancel;
08982       tmp->echotraining = conf->chan.echotraining;
08983       tmp->pulse = conf->chan.pulse;
08984       if (tmp->echocancel)
08985          tmp->echocanbridged = conf->chan.echocanbridged;
08986       else {
08987          if (conf->chan.echocanbridged)
08988             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08989          tmp->echocanbridged = 0;
08990       }
08991       tmp->busydetect = conf->chan.busydetect;
08992       tmp->busycount = conf->chan.busycount;
08993       tmp->busycompare = conf->chan.busycompare;
08994       tmp->busytonelength = conf->chan.busytonelength;
08995       tmp->busyquietlength = conf->chan.busyquietlength;
08996       tmp->busyfuzziness = conf->chan.busyfuzziness;
08997       tmp->silencethreshold = conf->chan.silencethreshold;
08998       tmp->callprogress = conf->chan.callprogress;
08999       tmp->cancallforward = conf->chan.cancallforward;
09000       tmp->dtmfrelax = conf->chan.dtmfrelax;
09001       tmp->callwaiting = tmp->permcallwaiting;
09002       tmp->hidecallerid = tmp->permhidecallerid;
09003       tmp->channel = channel;
09004       tmp->stripmsd = conf->chan.stripmsd;
09005       tmp->use_callerid = conf->chan.use_callerid;
09006       tmp->cid_signalling = conf->chan.cid_signalling;
09007       tmp->cid_start = conf->chan.cid_start;
09008       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09009       tmp->restrictcid = conf->chan.restrictcid;
09010       tmp->use_callingpres = conf->chan.use_callingpres;
09011       tmp->priexclusive = conf->chan.priexclusive;
09012       if (tmp->usedistinctiveringdetection) {
09013          if (!tmp->use_callerid) {
09014             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09015             tmp->use_callerid = 1;
09016          }
09017       }
09018 
09019       if (tmp->cid_signalling == CID_SIG_SMDI) {
09020          if (!tmp->use_smdi) {
09021             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09022             tmp->use_smdi = 1;
09023          }
09024       }
09025       if (tmp->use_smdi) {
09026          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09027          if (!(tmp->smdi_iface)) {
09028             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09029             tmp->use_smdi = 0;
09030          }
09031       }
09032 
09033       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09034       tmp->amaflags = conf->chan.amaflags;
09035       if (!here) {
09036          tmp->confno = -1;
09037          tmp->propconfno = -1;
09038       }
09039       tmp->canpark = conf->chan.canpark;
09040       tmp->transfer = conf->chan.transfer;
09041       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09042       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09043       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09044       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09045       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09046       tmp->cid_ton = 0;
09047       if (chan_sig != SIG_PRI) {
09048          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09049          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09050       } else {
09051          tmp->cid_num[0] = '\0';
09052          tmp->cid_name[0] = '\0';
09053       }
09054       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09055       tmp->msgstate = -1;
09056       tmp->group = conf->chan.group;
09057       tmp->callgroup = conf->chan.callgroup;
09058       tmp->pickupgroup= conf->chan.pickupgroup;
09059       tmp->rxgain = conf->chan.rxgain;
09060       tmp->txgain = conf->chan.txgain;
09061       tmp->tonezone = conf->chan.tonezone;
09062       tmp->onhooktime = time(NULL);
09063       if (tmp->subs[SUB_REAL].dfd > -1) {
09064          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09065          if (tmp->dsp)
09066             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09067          update_conf(tmp);
09068          if (!here) {
09069             if ((chan_sig != SIG_PRI) && (chan_sig != SIG_MFCR2))
09070                /* Hang it up to be sure it's good */
09071                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09072          }
09073          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09074 #ifdef HAVE_PRI
09075          /* the dchannel is down so put the channel in alarm */
09076          if (tmp->pri && !pri_is_up(tmp->pri)) {
09077             tmp->inalarm = 1;
09078          }
09079 #endif            
09080          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09081             tmp->inalarm = 1;
09082             handle_alarms(tmp, res);
09083          } else {
09084             /* yes, this looks strange... the unknown_alarm flag is only used to
09085                control whether an 'alarm cleared' message gets generated when we
09086                get an indication that the channel is no longer in alarm status.
09087                however, the channel *could* be in an alarm status that we aren't
09088                aware of (since get_alarms() only reports span alarms, not channel
09089                alarms). setting this flag will cause any potential 'alarm cleared'
09090                message to be suppressed, but if a real alarm occurs before that
09091                happens, this flag will get cleared by it and the situation will
09092                be normal.
09093             */
09094             tmp->unknown_alarm = 1;
09095          }
09096       }
09097 
09098       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09099       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09100       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09101       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09102 
09103    }
09104    if (tmp && !here) {
09105       /* nothing on the iflist */
09106       if (!*wlist) {
09107          *wlist = tmp;
09108          tmp->prev = NULL;
09109          tmp->next = NULL;
09110          *wend = tmp;
09111       } else {
09112          /* at least one member on the iflist */
09113          struct dahdi_pvt *working = *wlist;
09114 
09115          /* check if we maybe have to put it on the begining */
09116          if (working->channel > tmp->channel) {
09117             tmp->next = *wlist;
09118             tmp->prev = NULL;
09119             (*wlist)->prev = tmp;
09120             *wlist = tmp;
09121          } else {
09122          /* go through all the members and put the member in the right place */
09123             while (working) {
09124                /* in the middle */
09125                if (working->next) {
09126                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09127                      tmp->next = working->next;
09128                      tmp->prev = working;
09129                      working->next->prev = tmp;
09130                      working->next = tmp;
09131                      break;
09132                   }
09133                } else {
09134                /* the last */
09135                   if (working->channel < tmp->channel) {
09136                      working->next = tmp;
09137                      tmp->next = NULL;
09138                      tmp->prev = working;
09139                      *wend = tmp;
09140                      break;
09141                   }
09142                }
09143                working = working->next;
09144             }
09145          }
09146       }
09147    }
09148    return tmp;
09149 }
09150 
09151 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09152 {
09153    int res;
09154    struct dahdi_params par;
09155 
09156    /* First, check group matching */
09157    if (groupmatch) {
09158       if ((p->group & groupmatch) != groupmatch)
09159          return 0;
09160       *groupmatched = 1;
09161    }
09162    /* Check to see if we have a channel match */
09163    if (channelmatch != -1) {
09164       if (p->channel != channelmatch)
09165          return 0;
09166       *channelmatched = 1;
09167    }
09168    /* We're at least busy at this point */
09169    if (busy) {
09170       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09171          *busy = 1;
09172    }
09173    /* If do not disturb, definitely not */
09174    if (p->dnd)
09175       return 0;
09176    /* If guard time, definitely not */
09177    if (p->guardtime && (time(NULL) < p->guardtime)) 
09178       return 0;
09179       
09180    /* If no owner definitely available */
09181    if (!p->owner) {
09182 #ifdef HAVE_PRI
09183       /* Trust PRI */
09184       if (p->pri) {
09185          if (p->resetting || p->call)
09186             return 0;
09187          else
09188             return 1;
09189       }
09190 #endif
09191 #ifdef HAVE_OPENR2
09192       /* Trust MFC/R2 */
09193       if (p->mfcr2) {
09194          if (p->mfcr2call || p->mfcr2block)
09195             return 0;
09196          else
09197             return 1;
09198       }
09199 #endif
09200       if (!(p->radio || (p->oprmode < 0)))
09201       {
09202          if (!p->sig || (p->sig == SIG_FXSLS))
09203             return 1;
09204          /* Check hook state */
09205          if (p->subs[SUB_REAL].dfd > -1) {
09206             memset(&par, 0, sizeof(par));
09207             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09208          } else {
09209             /* Assume not off hook on CVRS */
09210             res = 0;
09211             par.rxisoffhook = 0;
09212          }
09213          if (res) {
09214             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09215          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09216             /* When "onhook" that means no battery on the line, and thus
09217               it is out of service..., if it's on a TDM card... If it's a channel
09218               bank, there is no telling... */
09219             if (par.rxbits > -1)
09220                return 1;
09221             if (par.rxisoffhook)
09222                return 1;
09223             else
09224 #ifdef DAHDI_CHECK_HOOKSTATE
09225                return 0;
09226 #else
09227                return 1;
09228 #endif
09229          } else if (par.rxisoffhook) {
09230             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
09231             /* Not available when the other end is off hook */
09232             return 0;
09233          }
09234       }
09235       return 1;
09236    }
09237 
09238    /* If it's not an FXO, forget about call wait */
09239    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09240       return 0;
09241 
09242    if (!p->callwaiting) {
09243       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09244       return 0;
09245    }
09246 
09247    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09248       /* If there is already a call waiting call, then we can't take a second one */
09249       return 0;
09250    }
09251    
09252    if ((p->owner->_state != AST_STATE_UP) &&
09253        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09254       /* If the current call is not up, then don't allow the call */
09255       return 0;
09256    }
09257    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09258       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09259       return 0;
09260    }
09261    /* We're cool */
09262    return 1;
09263 }
09264 
09265 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09266 {
09267    struct dahdi_pvt *p;
09268    struct dahdi_bufferinfo bi;
09269    int res;
09270    
09271    if ((p = ast_malloc(sizeof(*p)))) {
09272       memcpy(p, src, sizeof(struct dahdi_pvt));
09273       ast_mutex_init(&p->lock);
09274       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
09275       /* Allocate a DAHDI structure */
09276       if (p->subs[SUB_REAL].dfd < 0) {
09277          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09278          destroy_dahdi_pvt(&p);
09279          return NULL;
09280       }
09281       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09282       if (!res) {
09283          bi.txbufpolicy = p->buf_policy;
09284          bi.rxbufpolicy = p->buf_policy;
09285          bi.numbufs = p->buf_no;
09286          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09287          if (res < 0) {
09288             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09289          }
09290       } else
09291          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09292    }
09293    p->destroy = 1;
09294    p->next = iflist;
09295    p->prev = NULL;
09296    iflist = p;
09297    if (iflist->next)
09298       iflist->next->prev = p;
09299    return p;
09300 }
09301    
09302 
09303 #ifdef HAVE_PRI
09304 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09305 {
09306    int x;
09307    if (backwards)
09308       x = pri->numchans;
09309    else
09310       x = 0;
09311    for (;;) {
09312       if (backwards && (x < 0))
09313          break;
09314       if (!backwards && (x >= pri->numchans))
09315          break;
09316       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09317          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
09318             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09319          return x;
09320       }
09321       if (backwards)
09322          x--;
09323       else
09324          x++;
09325    }
09326    return -1;
09327 }
09328 #endif
09329 
09330 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09331 {
09332    ast_group_t groupmatch = 0;
09333    int channelmatch = -1;
09334    int roundrobin = 0;
09335    int callwait = 0;
09336    int busy = 0;
09337    struct dahdi_pvt *p;
09338    struct ast_channel *tmp = NULL;
09339    char *dest=NULL;
09340    int x;
09341    char *s;
09342    char opt=0;
09343    int res=0, y=0;
09344    int backwards = 0;
09345 #ifdef HAVE_PRI
09346    int crv;
09347    int bearer = -1;
09348    int trunkgroup;
09349    struct dahdi_pri *pri=NULL;
09350 #endif   
09351    struct dahdi_pvt *exit, *start, *end;
09352    ast_mutex_t *lock;
09353    int channelmatched = 0;
09354    int groupmatched = 0;
09355    
09356    /*
09357     * data is ---v
09358     * Dial(DAHDI/pseudo[/extension])
09359     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09360     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09361     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09362     *
09363     * g - channel group allocation search forward
09364     * G - channel group allocation search backward
09365     * r - channel group allocation round robin search forward
09366     * R - channel group allocation round robin search backward
09367     *
09368     * c - Wait for DTMF digit to confirm answer
09369     * r<cadance#> - Set distintive ring cadance number
09370     * d - Force bearer capability for ISDN call to digital.
09371     */
09372 
09373    /* Assume we're locking the iflock */
09374    lock = &iflock;
09375    start = iflist;
09376    end = ifend;
09377    if (data) {
09378       dest = ast_strdupa((char *)data);
09379    } else {
09380       ast_log(LOG_WARNING, "Channel requested with no data\n");
09381       return NULL;
09382    }
09383    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09384       /* Retrieve the group number */
09385       char *stringp;
09386 
09387       stringp = dest + 1;
09388       s = strsep(&stringp, "/");
09389       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09390          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09391          return NULL;
09392       }
09393       groupmatch = ((ast_group_t) 1 << x);
09394       if (toupper(dest[0]) == 'G') {
09395          if (dest[0] == 'G') {
09396             backwards = 1;
09397             p = ifend;
09398          } else
09399             p = iflist;
09400       } else {
09401          if (dest[0] == 'R') {
09402             backwards = 1;
09403             p = round_robin[x]?round_robin[x]->prev:ifend;
09404             if (!p)
09405                p = ifend;
09406          } else {
09407             p = round_robin[x]?round_robin[x]->next:iflist;
09408             if (!p)
09409                p = iflist;
09410          }
09411          roundrobin = 1;
09412       }
09413    } else {
09414       char *stringp;
09415 
09416       stringp = dest;
09417       s = strsep(&stringp, "/");
09418       p = iflist;
09419       if (!strcasecmp(s, "pseudo")) {
09420          /* Special case for pseudo */
09421          x = CHAN_PSEUDO;
09422          channelmatch = x;
09423       } 
09424 #ifdef HAVE_PRI
09425       else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09426          if ((trunkgroup < 1) || (crv < 1)) {
09427             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09428             return NULL;
09429          }
09430          res--;
09431          for (x = 0; x < NUM_SPANS; x++) {
09432             if (pris[x].trunkgroup == trunkgroup) {
09433                pri = pris + x;
09434                lock = &pri->lock;
09435                start = pri->crvs;
09436                end = pri->crvend;
09437                break;
09438             }
09439          }
09440          if (!pri) {
09441             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09442             return NULL;
09443          }
09444          channelmatch = crv;
09445          p = pris[x].crvs;
09446       }
09447 #endif   
09448       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09449          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09450          return NULL;
09451       } else {
09452          channelmatch = x;
09453       }
09454    }
09455    /* Search for an unowned channel */
09456    ast_mutex_lock(lock);
09457    exit = p;
09458    while (p && !tmp) {
09459       if (roundrobin)
09460          round_robin[x] = p;
09461 #if 0
09462       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09463 #endif
09464 
09465       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09466          if (option_debug)
09467             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
09468             if (p->inalarm) 
09469                goto next;
09470 
09471          callwait = (p->owner != NULL);
09472 #ifdef HAVE_PRI
09473          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09474             if (p->sig != SIG_FXSKS) {
09475                /* Gotta find an actual channel to use for this
09476                   CRV if this isn't a callwait */
09477                bearer = pri_find_empty_chan(pri, 0);
09478                if (bearer < 0) {
09479                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09480                   p = NULL;
09481                   break;
09482                }
09483                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09484             } else {
09485                if (alloc_sub(p, 0)) {
09486                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09487                   p = NULL;
09488                   break;
09489                } else
09490                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
09491                p->pri = pri;
09492             }
09493          }
09494 #endif         
09495 #ifdef HAVE_OPENR2
09496          if (p->mfcr2) {
09497             ast_mutex_lock(&p->lock);
09498             if (p->mfcr2call) {
09499                ast_mutex_unlock(&p->lock);
09500                ast_log(LOG_NOTICE, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
09501                goto next;
09502             }
09503             if (p->mfcr2block) {
09504                ast_mutex_unlock(&p->lock);
09505                ast_log(LOG_NOTICE, "Yay!, channel %d just got blocked (%d).\n", p->channel, p->mfcr2block);
09506                goto next;
09507             }
09508             p->mfcr2call = 1;
09509             ast_mutex_unlock(&p->lock);
09510          }
09511 #endif
09512          if (p->channel == CHAN_PSEUDO) {
09513             p = chandup(p);
09514             if (!p) {
09515                break;
09516             }
09517          }
09518          if (p->owner) {
09519             if (alloc_sub(p, SUB_CALLWAIT)) {
09520                p = NULL;
09521                break;
09522             }
09523          }
09524          p->outgoing = 1;
09525          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09526          if (!tmp) {
09527             p->outgoing = 0;
09528          }
09529 #ifdef HAVE_PRI
09530          if (p->bearer) {
09531             /* Log owner to bearer channel, too */
09532             p->bearer->owner = tmp;
09533          }
09534 #endif         
09535          /* Make special notes */
09536          if (res > 1) {
09537             if (opt == 'c') {
09538                /* Confirm answer */
09539                p->confirmanswer = 1;
09540             } else if (opt == 'r') {
09541                /* Distinctive ring */
09542                if (res < 3)
09543                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09544                else
09545                   p->distinctivering = y;
09546             } else if (opt == 'd') {
09547                /* If this is an ISDN call, make it digital */
09548                p->digital = 1;
09549                if (tmp)
09550                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09551             } else {
09552                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09553             }
09554          }
09555          /* Note if the call is a call waiting call */
09556          if (tmp && callwait)
09557             tmp->cdrflags |= AST_CDR_CALLWAIT;
09558          break;
09559       }
09560 next:
09561       if (backwards) {
09562          p = p->prev;
09563          if (!p)
09564             p = end;
09565       } else {
09566          p = p->next;
09567          if (!p)
09568             p = start;
09569       }
09570       /* stop when you roll to the one that we started from */
09571       if (p == exit)
09572          break;
09573    }
09574    ast_mutex_unlock(lock);
09575    restart_monitor();
09576    if (callwait)
09577       *cause = AST_CAUSE_BUSY;
09578    else if (!tmp) {
09579       if (channelmatched) {
09580          if (busy)
09581             *cause = AST_CAUSE_BUSY;
09582       } else if (groupmatched) {
09583          *cause = AST_CAUSE_CONGESTION;
09584       }
09585    }
09586       
09587    return tmp;
09588 }
09589 
09590 #ifdef HAVE_OPENR2
09591 static void *mfcr2_monitor(void *data)
09592 {
09593    struct dahdi_pvt *p;
09594    struct dahdi_mfcr2 *mfcr2 = data;
09595    /* we should be using pthread_key_create
09596       and allocate pollers dynamically.
09597       I think do_monitor() could be leaking, since it
09598       could be cancelled at any time and is not
09599       using thread keys, why?, */
09600    struct pollfd pollers[sizeof(mfcr2->pvts)];
09601    int maxsleep = 20;
09602    int res = 0;
09603    int i = 0;
09604    int pollsize = 0;
09605    int oldstate = 0;
09606    int was_idle = 0;
09607    int quit_loop = 0;
09608    /* now that we're ready to get calls, unblock our side and
09609       get current line state */
09610    for (i = 0; i < mfcr2->numchans; i++) {
09611       p = mfcr2->pvts[i];
09612       if (openr2_chan_set_idle(p->r2chan)) {
09613          ast_log(LOG_ERROR, "Failed to set channel %d in IDLE\n", p->channel);
09614       } else {
09615          ast_mutex_lock(&p->lock);
09616          mfcr2->pvts[i]->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
09617          mfcr2->pvts[i]->mfcr2call = 0;
09618          ast_mutex_unlock(&p->lock);
09619       }
09620       openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
09621    }
09622    while(1) {
09623       /* we trust here that the mfcr2 channel list will not ever change once
09624          the module is loaded */
09625       pollsize = 0;
09626       for (i = 0; i < mfcr2->numchans; i++) {
09627          pollers[i].revents = 0;
09628          pollers[i].events = 0;
09629          if (mfcr2->pvts[i]->owner) {
09630             continue;
09631          }
09632          if (!mfcr2->pvts[i]->r2chan) {
09633             ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
09634             quit_loop = 1;
09635             break;
09636          }
09637          openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
09638          pollers[i].events = POLLIN | POLLPRI;
09639          pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
09640          pollsize++;
09641       }
09642       if (quit_loop) {
09643          break;
09644       }
09645 
09646       if (pollsize == 0) {
09647          if (!was_idle) {
09648             ast_log(LOG_NOTICE, "Monitor thread going idle since everybody has an owner\n");
09649             was_idle = 1;
09650          }
09651          poll(NULL, 0, maxsleep);
09652          continue;
09653       }
09654       was_idle = 0;
09655 
09656       /* probably poll() is a valid cancel point, lets just be on the safe side
09657          by calling pthread_testcancel */
09658       pthread_testcancel();
09659       res = poll(pollers, pollsize, maxsleep);
09660       pthread_testcancel();
09661       if ((res < 0) && (errno != EINTR)) {
09662          ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
09663          break;
09664       } 
09665       /* do we want to allow to cancel while processing events? */
09666       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
09667       for (i = 0; i < mfcr2->numchans; i++) {
09668          if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
09669             openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
09670          }
09671       }
09672       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
09673    }
09674    ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
09675    return 0;
09676 }
09677 #endif
09678 
09679 
09680 #ifdef HAVE_PRI
09681 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
09682 {
09683    struct dahdi_pvt *p;
09684    p = pri->crvs;
09685    while (p) {
09686       if (p->channel == crv)
09687          return p;
09688       p = p->next;
09689    }
09690    return NULL;
09691 }
09692 
09693 
09694 static int pri_find_principle(struct dahdi_pri *pri, int channel)
09695 {
09696    int x;
09697    int span = PRI_SPAN(channel);
09698    int spanfd;
09699    struct dahdi_params param;
09700    int principle = -1;
09701    int explicit = PRI_EXPLICIT(channel);
09702    channel = PRI_CHANNEL(channel);
09703 
09704    if (!explicit) {
09705       spanfd = pri_active_dchan_fd(pri);
09706       memset(&param, 0, sizeof(param));
09707       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
09708          return -1;
09709       span = pris[param.spanno - 1].prilogicalspan;
09710    }
09711 
09712    for (x = 0; x < pri->numchans; x++) {
09713       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
09714          principle = x;
09715          break;
09716       }
09717    }
09718    
09719    return principle;
09720 }
09721 
09722 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
09723 {
09724    int x;
09725    struct dahdi_pvt *crv;
09726    if (!c) {
09727       if (principle < 0)
09728          return -1;
09729       return principle;
09730    }
09731    if ((principle > -1) && 
09732       (principle < pri->numchans) && 
09733       (pri->pvts[principle]) && 
09734       (pri->pvts[principle]->call == c))
09735       return principle;
09736    /* First, check for other bearers */
09737    for (x = 0; x < pri->numchans; x++) {
09738       if (!pri->pvts[x])
09739          continue;
09740       if (pri->pvts[x]->call == c) {
09741          /* Found our call */
09742          if (principle != x) {
09743             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
09744 
09745             if (option_verbose > 2)
09746                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
09747                   old->channel, new->channel);
09748             if (new->owner) {
09749                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
09750                   old->channel, new->channel, new->channel);
09751                return -1;
09752             }
09753             /* Fix it all up now */
09754             new->owner = old->owner;
09755             old->owner = NULL;
09756             if (new->owner) {
09757                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
09758                new->owner->tech_pvt = new;
09759                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
09760                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
09761                old->subs[SUB_REAL].owner = NULL;
09762             } else
09763                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);
09764             new->call = old->call;
09765             old->call = NULL;
09766 
09767             /* Copy any DSP that may be present */
09768             new->dsp = old->dsp;
09769             new->dsp_features = old->dsp_features;
09770             old->dsp = NULL;
09771             old->dsp_features = 0;
09772          }
09773          return principle;
09774       }
09775    }
09776    /* Now check for a CRV with no bearer */
09777    crv = pri->crvs;
09778    while (crv) {
09779       if (crv->call == c) {
09780          /* This is our match...  Perform some basic checks */
09781          if (crv->bearer)
09782             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
09783          else if (pri->pvts[principle]->owner) 
09784             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
09785          else {
09786             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
09787                wakeup the potential sleeper */
09788             dahdi_close_sub(crv, SUB_REAL);
09789             pri->pvts[principle]->call = crv->call;
09790             pri_assign_bearer(crv, pri, pri->pvts[principle]);
09791             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
09792                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
09793                            pri->trunkgroup, crv->channel);
09794             wakeup_sub(crv, SUB_REAL, pri);
09795          }
09796          return principle;
09797       }
09798       crv = crv->next;
09799    }
09800    ast_log(LOG_WARNING, "Call specified, but not found?\n");
09801    return -1;
09802 }
09803 
09804 static void *do_idle_thread(void *vchan)
09805 {
09806    struct ast_channel *chan = vchan;
09807    struct dahdi_pvt *pvt = chan->tech_pvt;
09808    struct ast_frame *f;
09809    char ex[80];
09810    /* Wait up to 30 seconds for an answer */
09811    int newms, ms = 30000;
09812    if (option_verbose > 2) 
09813       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
09814    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
09815    if (ast_call(chan, ex, 0)) {
09816       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
09817       ast_hangup(chan);
09818       return NULL;
09819    }
09820    while ((newms = ast_waitfor(chan, ms)) > 0) {
09821       f = ast_read(chan);
09822       if (!f) {
09823          /* Got hangup */
09824          break;
09825       }
09826       if (f->frametype == AST_FRAME_CONTROL) {
09827          switch (f->subclass) {
09828          case AST_CONTROL_ANSWER:
09829             /* Launch the PBX */
09830             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
09831             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
09832             chan->priority = 1;
09833             if (option_verbose > 3) 
09834                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
09835             ast_pbx_run(chan);
09836             /* It's already hungup, return immediately */
09837             return NULL;
09838          case AST_CONTROL_BUSY:
09839             if (option_verbose > 3) 
09840                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
09841             break;
09842          case AST_CONTROL_CONGESTION:
09843             if (option_verbose > 3) 
09844                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
09845             break;
09846          };
09847       }
09848       ast_frfree(f);
09849       ms = newms;
09850    }
09851    /* Hangup the channel since nothing happend */
09852    ast_hangup(chan);
09853    return NULL;
09854 }
09855 
09856 #ifndef PRI_RESTART
09857 #error "Upgrade your libpri"
09858 #endif
09859 static void dahdi_pri_message(struct pri *pri, char *s)
09860 {
09861    int x, y;
09862    int dchan = -1, span = -1;
09863    int dchancount = 0;
09864 
09865    if (pri) {
09866       for (x = 0; x < NUM_SPANS; x++) {
09867          for (y = 0; y < NUM_DCHANS; y++) {
09868             if (pris[x].dchans[y])
09869                dchancount++;
09870 
09871             if (pris[x].dchans[y] == pri)
09872                dchan = y;
09873          }
09874          if (dchan >= 0) {
09875             span = x;
09876             break;
09877          }
09878          dchancount = 0;
09879       }
09880       if ((dchan >= 0) && (span >= 0)) {
09881          if (dchancount > 1)
09882             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
09883          else
09884             ast_verbose("%s", s);
09885       } else
09886          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09887    } else
09888       ast_verbose("%s", s);
09889 
09890    ast_mutex_lock(&pridebugfdlock);
09891 
09892    if (pridebugfd >= 0) {
09893       if (write(pridebugfd, s, strlen(s)) < 0) {
09894          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09895       }
09896    }
09897 
09898    ast_mutex_unlock(&pridebugfdlock);
09899 }
09900 
09901 static void dahdi_pri_error(struct pri *pri, char *s)
09902 {
09903    int x, y;
09904    int dchan = -1, span = -1;
09905    int dchancount = 0;
09906 
09907    if (pri) {
09908       for (x = 0; x < NUM_SPANS; x++) {
09909          for (y = 0; y < NUM_DCHANS; y++) {
09910             if (pris[x].dchans[y])
09911                dchancount++;
09912 
09913             if (pris[x].dchans[y] == pri)
09914                dchan = y;
09915          }
09916          if (dchan >= 0) {
09917             span = x;
09918             break;
09919          }
09920          dchancount = 0;
09921       }
09922       if ((dchan >= 0) && (span >= 0)) {
09923          if (dchancount > 1)
09924             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
09925          else
09926             ast_log(LOG_ERROR, "%s", s);
09927       } else
09928          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
09929    } else
09930       ast_log(LOG_ERROR, "%s", s);
09931 
09932    ast_mutex_lock(&pridebugfdlock);
09933 
09934    if (pridebugfd >= 0) {
09935       if (write(pridebugfd, s, strlen(s)) < 0) {
09936          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
09937       }
09938    }
09939 
09940    ast_mutex_unlock(&pridebugfdlock);
09941 }
09942 
09943 static int pri_check_restart(struct dahdi_pri *pri)
09944 {
09945    do {
09946       pri->resetpos++;
09947    } while ((pri->resetpos < pri->numchans) &&
09948        (!pri->pvts[pri->resetpos] ||
09949         pri->pvts[pri->resetpos]->call ||
09950         pri->pvts[pri->resetpos]->resetting));
09951    if (pri->resetpos < pri->numchans) {
09952       /* Mark the channel as resetting and restart it */
09953       pri->pvts[pri->resetpos]->resetting = 1;
09954       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
09955    } else {
09956       pri->resetting = 0;
09957       time(&pri->lastreset);
09958    }
09959    return 0;
09960 }
09961 
09962 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
09963 {
09964    int x;
09965    int redo;
09966    ast_mutex_unlock(&pri->lock);
09967    ast_mutex_lock(&p->lock);
09968    do {
09969       redo = 0;
09970       for (x = 0; x < 3; x++) {
09971          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
09972             redo++;
09973             DEADLOCK_AVOIDANCE(&p->lock);
09974          }
09975          if (p->subs[x].owner) {
09976             ast_queue_hangup(p->subs[x].owner);
09977             ast_mutex_unlock(&p->subs[x].owner->lock);
09978          }
09979       }
09980    } while (redo);
09981    ast_mutex_unlock(&p->lock);
09982    ast_mutex_lock(&pri->lock);
09983    return 0;
09984 }
09985 
09986 static char * redirectingreason2str(int redirectingreason)
09987 {
09988    switch (redirectingreason) {
09989    case 0:
09990       return "UNKNOWN";
09991    case 1:
09992       return "BUSY";
09993    case 2:
09994       return "NO_REPLY";
09995    case 0xF:
09996       return "UNCONDITIONAL";
09997    default:
09998       return "NOREDIRECT";
09999    }
10000 }
10001 
10002 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10003 {
10004    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10005       if (size) {
10006          *buf = '\0';
10007       }
10008       return;
10009    }
10010 
10011    switch (plan) {
10012    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10013       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10014       break;
10015    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10016       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10017       break;
10018    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10019       snprintf(buf, size, "%s%s", pri->localprefix, number);
10020       break;
10021    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10022       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10023       break;
10024    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10025       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10026       break;
10027    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10028       snprintf(buf, size, "%s", number);
10029       break;
10030    }
10031 }
10032 
10033 static int dahdi_setlaw(int dfd, int law)
10034 {
10035    int res;
10036    res = ioctl(dfd, DAHDI_SETLAW, &law);
10037    if (res)
10038       return res;
10039    return 0;
10040 }
10041 
10042 static void *pri_dchannel(void *vpri)
10043 {
10044    struct dahdi_pri *pri = vpri;
10045    pri_event *e;
10046    struct pollfd fds[NUM_DCHANS];
10047    int res;
10048    int chanpos = 0;
10049    int x;
10050    int haveidles;
10051    int activeidles;
10052    int nextidle = -1;
10053    struct ast_channel *c;
10054    struct timeval tv, lowest, *next;
10055    struct timeval lastidle = { 0, 0 };
10056    int doidling=0;
10057    char *cc;
10058    char idlen[80];
10059    struct ast_channel *idle;
10060    pthread_t p;
10061    time_t t;
10062    int i, which=-1;
10063    int numdchans;
10064    int cause=0;
10065    struct dahdi_pvt *crv;
10066    pthread_t threadid;
10067    pthread_attr_t attr;
10068    char ani2str[6];
10069    char plancallingnum[256];
10070    char plancallingani[256];
10071    char calledtonstr[10];
10072    
10073    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10074 
10075    gettimeofday(&lastidle, NULL);
10076    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10077       /* Need to do idle dialing, check to be sure though */
10078       cc = strchr(pri->idleext, '@');
10079       if (cc) {
10080          *cc = '\0';
10081          cc++;
10082          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10083 #if 0
10084          /* Extensions may not be loaded yet */
10085          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10086             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10087          else
10088 #endif
10089             doidling = 1;
10090       } else
10091          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10092    }
10093    for (;;) {
10094       for (i = 0; i < NUM_DCHANS; i++) {
10095          if (!pri->dchannels[i])
10096             break;
10097          fds[i].fd = pri->fds[i];
10098          fds[i].events = POLLIN | POLLPRI;
10099          fds[i].revents = 0;
10100       }
10101       numdchans = i;
10102       time(&t);
10103       ast_mutex_lock(&pri->lock);
10104       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10105          if (pri->resetting && pri_is_up(pri)) {
10106             if (pri->resetpos < 0)
10107                pri_check_restart(pri);
10108          } else {
10109             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
10110                pri->resetting = 1;
10111                pri->resetpos = -1;
10112             }
10113          }
10114       }
10115       /* Look for any idle channels if appropriate */
10116       if (doidling && pri_is_up(pri)) {
10117          nextidle = -1;
10118          haveidles = 0;
10119          activeidles = 0;
10120          for (x = pri->numchans; x >= 0; x--) {
10121             if (pri->pvts[x] && !pri->pvts[x]->owner && 
10122                 !pri->pvts[x]->call) {
10123                if (haveidles < pri->minunused) {
10124                   haveidles++;
10125                } else if (!pri->pvts[x]->resetting) {
10126                   nextidle = x;
10127                   break;
10128                }
10129             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10130                activeidles++;
10131          }
10132          if (nextidle > -1) {
10133             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10134                /* Don't create a new idle call more than once per second */
10135                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10136                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
10137                if (idle) {
10138                   pri->pvts[nextidle]->isidlecall = 1;
10139                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10140                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10141                      dahdi_hangup(idle);
10142                   }
10143                } else
10144                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10145                gettimeofday(&lastidle, NULL);
10146             }
10147          } else if ((haveidles < pri->minunused) &&
10148                (activeidles > pri->minidle)) {
10149             /* Mark something for hangup if there is something 
10150                that can be hungup */
10151             for (x = pri->numchans; x >= 0; x--) {
10152                /* find a candidate channel */
10153                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10154                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10155                   haveidles++;
10156                   /* Stop if we have enough idle channels or
10157                     can't spare any more active idle ones */
10158                   if ((haveidles >= pri->minunused) ||
10159                       (activeidles <= pri->minidle))
10160                      break;
10161                } 
10162             }
10163          }
10164       }
10165       /* Start with reasonable max */
10166       lowest = ast_tv(60, 0);
10167       for (i = 0; i < NUM_DCHANS; i++) {
10168          /* Find lowest available d-channel */
10169          if (!pri->dchannels[i])
10170             break;
10171          if ((next = pri_schedule_next(pri->dchans[i]))) {
10172             /* We need relative time here */
10173             tv = ast_tvsub(*next, ast_tvnow());
10174             if (tv.tv_sec < 0) {
10175                tv = ast_tv(0,0);
10176             }
10177             if (doidling || pri->resetting) {
10178                if (tv.tv_sec > 1) {
10179                   tv = ast_tv(1, 0);
10180                }
10181             } else {
10182                if (tv.tv_sec > 60) {
10183                   tv = ast_tv(60, 0);
10184                }
10185             }
10186          } else if (doidling || pri->resetting) {
10187             /* Make sure we stop at least once per second if we're
10188                monitoring idle channels */
10189             tv = ast_tv(1,0);
10190          } else {
10191             /* Don't poll for more than 60 seconds */
10192             tv = ast_tv(60, 0);
10193          }
10194          if (!i || ast_tvcmp(tv, lowest) < 0) {
10195             lowest = tv;
10196          }
10197       }
10198       ast_mutex_unlock(&pri->lock);
10199 
10200       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
10201       pthread_testcancel();
10202       e = NULL;
10203       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10204       pthread_testcancel();
10205       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10206 
10207       ast_mutex_lock(&pri->lock);
10208       if (!res) {
10209          for (which = 0; which < NUM_DCHANS; which++) {
10210             if (!pri->dchans[which])
10211                break;
10212             /* Just a timeout, run the scheduler */
10213             e = pri_schedule_run(pri->dchans[which]);
10214             if (e)
10215                break;
10216          }
10217       } else if (res > -1) {
10218          for (which = 0; which < NUM_DCHANS; which++) {
10219             if (!pri->dchans[which])
10220                break;
10221             if (fds[which].revents & POLLPRI) {
10222                /* Check for an event */
10223                x = 0;
10224                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10225                if (x) 
10226                   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);
10227                /* Keep track of alarm state */  
10228                if (x == DAHDI_EVENT_ALARM) {
10229                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10230                   pri_find_dchan(pri);
10231                } else if (x == DAHDI_EVENT_NOALARM) {
10232                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
10233                   pri_restart(pri->dchans[which]);
10234                }
10235             
10236                if (option_debug)
10237                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10238             } else if (fds[which].revents & POLLIN) {
10239                e = pri_check_event(pri->dchans[which]);
10240             }
10241             if (e)
10242                break;
10243          }
10244       } else if (errno != EINTR)
10245          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10246 
10247       if (e) {
10248          if (pri->debug)
10249             pri_dump_event(pri->dchans[which], e);
10250 
10251          if (e->e != PRI_EVENT_DCHAN_DOWN) {
10252             if (!(pri->dchanavail[which] & DCHAN_UP)) {
10253                if (option_verbose > 1) 
10254                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10255             }
10256             pri->dchanavail[which] |= DCHAN_UP;
10257          } else {
10258             if (pri->dchanavail[which] & DCHAN_UP) {
10259                if (option_verbose > 1) 
10260                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10261             }
10262             pri->dchanavail[which] &= ~DCHAN_UP;
10263          }
10264 
10265          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10266             /* Must be an NFAS group that has the secondary dchan active */
10267             pri->pri = pri->dchans[which];
10268 
10269          switch (e->e) {
10270          case PRI_EVENT_DCHAN_UP:
10271             if (!pri->pri) pri_find_dchan(pri);
10272 
10273             /* Note presense of D-channel */
10274             time(&pri->lastreset);
10275 
10276             /* Restart in 5 seconds */
10277             if (pri->resetinterval > -1) {
10278                pri->lastreset -= pri->resetinterval;
10279                pri->lastreset += 5;
10280             }
10281             pri->resetting = 0;
10282             /* Take the channels from inalarm condition */
10283             for (i = 0; i < pri->numchans; i++)
10284                if (pri->pvts[i]) {
10285                   pri->pvts[i]->inalarm = 0;
10286                }
10287             break;
10288          case PRI_EVENT_DCHAN_DOWN:
10289             pri_find_dchan(pri);
10290             if (!pri_is_up(pri)) {
10291                pri->resetting = 0;
10292                /* Hangup active channels and put them in alarm mode */
10293                for (i = 0; i < pri->numchans; i++) {
10294                   struct dahdi_pvt *p = pri->pvts[i];
10295                   if (p) {
10296                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10297                         /* T309 is not enabled : hangup calls when alarm occurs */
10298                         if (p->call) {
10299                            if (p->pri && p->pri->pri) {
10300                               pri_hangup(p->pri->pri, p->call, -1);
10301                               pri_destroycall(p->pri->pri, p->call);
10302                               p->call = NULL;
10303                            } else
10304                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10305                         }
10306                         if (p->realcall) {
10307                            pri_hangup_all(p->realcall, pri);
10308                         } else if (p->owner)
10309                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10310                      }
10311                      p->inalarm = 1;
10312                   }
10313                }
10314             }
10315             break;
10316          case PRI_EVENT_RESTART:
10317             if (e->restart.channel > -1) {
10318                chanpos = pri_find_principle(pri, e->restart.channel);
10319                if (chanpos < 0)
10320                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
10321                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10322                else {
10323                   if (option_verbose > 2)
10324                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
10325                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10326                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10327                   if (pri->pvts[chanpos]->call) {
10328                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10329                      pri->pvts[chanpos]->call = NULL;
10330                   }
10331                   /* Force soft hangup if appropriate */
10332                   if (pri->pvts[chanpos]->realcall) 
10333                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10334                   else if (pri->pvts[chanpos]->owner)
10335                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10336                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10337                }
10338             } else {
10339                if (option_verbose > 2)
10340                   ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
10341                for (x = 0; x < pri->numchans; x++)
10342                   if (pri->pvts[x]) {
10343                      ast_mutex_lock(&pri->pvts[x]->lock);
10344                      if (pri->pvts[x]->call) {
10345                         pri_destroycall(pri->pri, pri->pvts[x]->call);
10346                         pri->pvts[x]->call = NULL;
10347                      }
10348                      if (pri->pvts[x]->realcall) 
10349                         pri_hangup_all(pri->pvts[x]->realcall, pri);
10350                      else if (pri->pvts[x]->owner)
10351                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10352                      ast_mutex_unlock(&pri->pvts[x]->lock);
10353                   }
10354             }
10355             break;
10356          case PRI_EVENT_KEYPAD_DIGIT:
10357             chanpos = pri_find_principle(pri, e->digit.channel);
10358             if (chanpos < 0) {
10359                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
10360                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10361             } else {
10362                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10363                if (chanpos > -1) {
10364                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10365                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10366                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10367                      /* how to do that */
10368                      int digitlen = strlen(e->digit.digits);
10369                      char digit;
10370                      int i;               
10371                      for (i = 0; i < digitlen; i++) { 
10372                         digit = e->digit.digits[i];
10373                         {
10374                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
10375                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10376                         }
10377                      }
10378                   }
10379                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10380                }
10381             }
10382             break;
10383             
10384          case PRI_EVENT_INFO_RECEIVED:
10385             chanpos = pri_find_principle(pri, e->ring.channel);
10386             if (chanpos < 0) {
10387                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
10388                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10389             } else {
10390                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10391                if (chanpos > -1) {
10392                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10393                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10394                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10395                      /* how to do that */
10396                      int digitlen = strlen(e->ring.callednum);
10397                      char digit;
10398                      int i;               
10399                      for (i = 0; i < digitlen; i++) { 
10400                         digit = e->ring.callednum[i];
10401                         {
10402                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
10403                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10404                         }
10405                      }
10406                   }
10407                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10408                }
10409             }
10410             break;
10411          case PRI_EVENT_RING:
10412             crv = NULL;
10413             if (e->ring.channel == -1)
10414                chanpos = pri_find_empty_chan(pri, 1);
10415             else
10416                chanpos = pri_find_principle(pri, e->ring.channel);
10417             /* if no channel specified find one empty */
10418             if (chanpos < 0) {
10419                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
10420                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10421             } else {
10422                ast_mutex_lock(&pri->pvts[chanpos]->lock);
10423                if (pri->pvts[chanpos]->owner) {
10424                   if (pri->pvts[chanpos]->call == e->ring.call) {
10425                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
10426                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10427                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10428                      break;
10429                   } else {
10430                      /* This is where we handle initial glare */
10431                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
10432                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10433                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10434                      chanpos = -1;
10435                   }
10436                }
10437                if (chanpos > -1)
10438                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10439             }
10440             if ((chanpos < 0) && (e->ring.flexible))
10441                chanpos = pri_find_empty_chan(pri, 1);
10442             if (chanpos > -1) {
10443                ast_mutex_lock(&pri->pvts[chanpos]->lock);
10444                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10445                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
10446                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10447                   if (crv)
10448                      ast_mutex_lock(&crv->lock);
10449                   if (!crv || crv->owner) {
10450                      pri->pvts[chanpos]->call = NULL;
10451                      if (crv) {
10452                         if (crv->owner)
10453                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10454                         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);
10455                      } else
10456                         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);
10457                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10458                      if (crv)
10459                         ast_mutex_unlock(&crv->lock);
10460                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10461                      break;
10462                   }
10463                }
10464                pri->pvts[chanpos]->call = e->ring.call;
10465                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10466                if (pri->pvts[chanpos]->use_callerid) {
10467                   ast_shrink_phone_number(plancallingnum);
10468                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10469 #ifdef PRI_ANI
10470                   if (!ast_strlen_zero(e->ring.callingani)) {
10471                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10472                      ast_shrink_phone_number(plancallingani);
10473                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10474                   } else {
10475                      pri->pvts[chanpos]->cid_ani[0] = '\0';
10476                   }
10477 #endif
10478                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10479                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10480                } else {
10481                   pri->pvts[chanpos]->cid_num[0] = '\0';
10482                   pri->pvts[chanpos]->cid_ani[0] = '\0';
10483                   pri->pvts[chanpos]->cid_name[0] = '\0';
10484                   pri->pvts[chanpos]->cid_ton = 0;
10485                }
10486                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10487                           e->ring.redirectingnum, e->ring.callingplanrdnis);
10488                /* If immediate=yes go to s|1 */
10489                if (pri->pvts[chanpos]->immediate) {
10490                   if (option_verbose > 2)
10491                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
10492                   pri->pvts[chanpos]->exten[0] = 's';
10493                   pri->pvts[chanpos]->exten[1] = '\0';
10494                }
10495                /* Get called number */
10496                else if (!ast_strlen_zero(e->ring.callednum)) {
10497                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10498                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10499                } else if (pri->overlapdial)
10500                   pri->pvts[chanpos]->exten[0] = '\0';
10501                else {
10502                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
10503                   pri->pvts[chanpos]->exten[0] = 's';
10504                   pri->pvts[chanpos]->exten[1] = '\0';
10505                }
10506                /* Set DNID on all incoming calls -- even immediate */
10507                if (!ast_strlen_zero(e->ring.callednum))
10508                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10509                /* No number yet, but received "sending complete"? */
10510                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10511                   if (option_verbose > 2)
10512                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
10513                   pri->pvts[chanpos]->exten[0] = 's';
10514                   pri->pvts[chanpos]->exten[1] = '\0';
10515                }
10516 
10517                /* Make sure extension exists (or in overlap dial mode, can exist) */
10518                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10519                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10520                   /* Setup law */
10521                   int law;
10522                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10523                      /* Set to audio mode at this point */
10524                      law = 1;
10525                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10526                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10527                   }
10528                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10529                      law = DAHDI_LAW_ALAW;
10530                   else
10531                      law = DAHDI_LAW_MULAW;
10532                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10533                   if (res < 0) 
10534                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10535                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10536                   if (res < 0)
10537                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10538                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10539                      /* Just announce proceeding */
10540                      pri->pvts[chanpos]->proceeding = 1;
10541                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10542                   } else {
10543                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
10544                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10545                      else
10546                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10547                   }
10548                   /* Get the use_callingpres state */
10549                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10550                
10551                   /* Start PBX */
10552                   if (!e->ring.complete
10553                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
10554                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10555                      /*
10556                       * Release the PRI lock while we create the channel
10557                       * so other threads can send D channel messages.
10558                       */
10559                      ast_mutex_unlock(&pri->lock);
10560                      if (crv) {
10561                         /* Set bearer and such */
10562                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10563                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10564                         pri->pvts[chanpos]->owner = &inuse;
10565                         ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10566                      } else {
10567                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10568                      }
10569                      ast_mutex_lock(&pri->lock);
10570                      if (c) {
10571                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10572                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10573                         }
10574                         if (e->ring.ani2 >= 0) {
10575                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10576                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10577                         }
10578 
10579 #ifdef SUPPORT_USERUSER
10580                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
10581                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10582                         }
10583 #endif
10584 
10585                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10586                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10587                         if (e->ring.redirectingreason >= 0)
10588                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10589                      }
10590 
10591                      pthread_attr_init(&attr);
10592                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10593                      if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
10594                         if (option_verbose > 2)
10595                            ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10596                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10597                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10598                      } else {
10599                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10600                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10601                         if (c)
10602                            ast_hangup(c);
10603                         else {
10604                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10605                            pri->pvts[chanpos]->call = NULL;
10606                         }
10607                      }
10608                      pthread_attr_destroy(&attr);
10609                   } else {
10610                      /*
10611                       * Release the PRI lock while we create the channel
10612                       * so other threads can send D channel messages.
10613                       */
10614                      ast_mutex_unlock(&pri->lock);
10615                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
10616                      ast_mutex_lock(&pri->lock);
10617                      if (c) {
10618                         /*
10619                          * It is reasonably safe to set the following
10620                          * channel variables while the PRI and DAHDI private
10621                          * structures are locked.  The PBX has not been
10622                          * started yet and it is unlikely that any other task
10623                          * will do anything with the channel we have just
10624                          * created.
10625                          */
10626                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10627                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10628                         }
10629                         if (e->ring.ani2 >= 0) {
10630                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
10631                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10632                         }
10633 
10634 #ifdef SUPPORT_USERUSER
10635                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
10636                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10637                         }
10638 #endif
10639 
10640                         if (e->ring.redirectingreason >= 0)
10641                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10642 
10643                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10644                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10645                      }
10646                      if (c && !ast_pbx_start(c)) {
10647                         if (option_verbose > 2)
10648                            ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10649                               plancallingnum, pri->pvts[chanpos]->exten,
10650                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10651 
10652                         dahdi_enable_ec(pri->pvts[chanpos]);
10653                      } else {
10654                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10655                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10656                         if (c) {
10657                            ast_hangup(c);
10658                         } else {
10659                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10660                            pri->pvts[chanpos]->call = NULL;
10661                         }
10662                      }
10663                   }
10664                } else {
10665                   if (option_verbose > 2)
10666                      ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
10667                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
10668                            pri->pvts[chanpos]->prioffset, pri->span);
10669                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10670                   pri->pvts[chanpos]->call = NULL;
10671                   pri->pvts[chanpos]->exten[0] = '\0';
10672                }
10673                if (crv)
10674                   ast_mutex_unlock(&crv->lock);
10675                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10676             } else {
10677                if (e->ring.flexible)
10678                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10679                else
10680                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10681             }
10682             break;
10683          case PRI_EVENT_RINGING:
10684             chanpos = pri_find_principle(pri, e->ringing.channel);
10685             if (chanpos < 0) {
10686                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
10687                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10688             } else {
10689                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10690                if (chanpos < 0) {
10691                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
10692                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10693                } else {
10694                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10695                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10696                      dahdi_enable_ec(pri->pvts[chanpos]);
10697                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10698                      pri->pvts[chanpos]->alerting = 1;
10699                   } else
10700                      ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
10701 #ifdef PRI_PROGRESS_MASK
10702                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10703 #else
10704                   if (e->ringing.progress == 8) {
10705 #endif
10706                      /* Now we can do call progress detection */
10707                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10708                         /* RINGING detection isn't required because we got ALERTING signal */
10709                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10710                         pri->pvts[chanpos]->dsp_features = 0;
10711                      }
10712                   }
10713 
10714 #ifdef SUPPORT_USERUSER
10715                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10716                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10717                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10718                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10719                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10720                   }
10721 #endif
10722 
10723                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10724                }
10725             }
10726             break;
10727          case PRI_EVENT_PROGRESS:
10728             /* Get chan value if e->e is not PRI_EVNT_RINGING */
10729             chanpos = pri_find_principle(pri, e->proceeding.channel);
10730             if (chanpos > -1) {
10731 #ifdef PRI_PROGRESS_MASK
10732                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10733 #else
10734                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10735 #endif
10736                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10737 
10738                   if (e->proceeding.cause > -1) {
10739                      if (option_verbose > 2)
10740                         ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
10741 
10742                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
10743                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10744                         if (pri->pvts[chanpos]->owner) {
10745                            if (option_verbose > 2)
10746                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10747 
10748                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10749                            f.subclass = AST_CONTROL_BUSY;
10750                         }
10751                      }
10752                   }
10753                   
10754                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10755                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
10756                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10757                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10758 #ifdef PRI_PROGRESS_MASK
10759                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10760 #else
10761                   if (e->proceeding.progress == 8) {
10762 #endif
10763                      /* Now we can do call progress detection */
10764                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10765                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10766                         pri->pvts[chanpos]->dsp_features = 0;
10767                      }
10768                      /* Bring voice path up */
10769                      f.subclass = AST_CONTROL_PROGRESS;
10770                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10771                   }
10772                   pri->pvts[chanpos]->progress = 1;
10773                   pri->pvts[chanpos]->dialing = 0;
10774                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10775                }
10776             }
10777             break;
10778          case PRI_EVENT_PROCEEDING:
10779             chanpos = pri_find_principle(pri, e->proceeding.channel);
10780             if (chanpos > -1) {
10781                if (!pri->pvts[chanpos]->proceeding) {
10782                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10783                   
10784                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10785                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10786                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10787                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10788 #ifdef PRI_PROGRESS_MASK
10789                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10790 #else
10791                   if (e->proceeding.progress == 8) {
10792 #endif
10793                      /* Now we can do call progress detection */
10794                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10795                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10796                         pri->pvts[chanpos]->dsp_features = 0;
10797                      }
10798                      /* Bring voice path up */
10799                      f.subclass = AST_CONTROL_PROGRESS;
10800                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10801                   }
10802                   pri->pvts[chanpos]->proceeding = 1;
10803                   pri->pvts[chanpos]->dialing = 0;
10804                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10805                }
10806             }
10807             break;
10808          case PRI_EVENT_FACNAME:
10809             chanpos = pri_find_principle(pri, e->facname.channel);
10810             if (chanpos < 0) {
10811                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
10812                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10813             } else {
10814                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10815                if (chanpos < 0) {
10816                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
10817                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10818                } else {
10819                   /* Re-use *69 field for PRI */
10820                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10821                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10822                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10823                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10824                   dahdi_enable_ec(pri->pvts[chanpos]);
10825                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10826                }
10827             }
10828             break;            
10829          case PRI_EVENT_ANSWER:
10830             chanpos = pri_find_principle(pri, e->answer.channel);
10831             if (chanpos < 0) {
10832                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
10833                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10834             } else {
10835                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10836                if (chanpos < 0) {
10837                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
10838                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10839                } else {
10840                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10841                   /* Now we can do call progress detection */
10842 
10843                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
10844                    * By this time, we need DTMF detection and other features that were previously disabled
10845                    * -- Matt F */
10846                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10847                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10848                      pri->pvts[chanpos]->dsp_features = 0;
10849                   }
10850                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10851                      ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10852                      x = DAHDI_START;
10853                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10854                      if (res < 0) {
10855                         if (errno != EINPROGRESS) {
10856                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10857                         }
10858                      }
10859                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10860                      pri->pvts[chanpos]->dialing = 1;
10861                      /* Send any "w" waited stuff */
10862                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10863                      if (res < 0) {
10864                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10865                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10866                      } else 
10867                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10868                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10869                   } else if (pri->pvts[chanpos]->confirmanswer) {
10870                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10871                   } else {
10872                      pri->pvts[chanpos]->dialing = 0;
10873                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10874                      /* Enable echo cancellation if it's not on already */
10875                      dahdi_enable_ec(pri->pvts[chanpos]);
10876                   }
10877 
10878 #ifdef SUPPORT_USERUSER
10879                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
10880                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10881                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10882                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10883                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10884                   }
10885 #endif
10886 
10887                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10888                }
10889             }
10890             break;            
10891          case PRI_EVENT_HANGUP:
10892             chanpos = pri_find_principle(pri, e->hangup.channel);
10893             if (chanpos < 0) {
10894                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
10895                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10896             } else {
10897                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10898                if (chanpos > -1) {
10899                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10900                   if (!pri->pvts[chanpos]->alreadyhungup) {
10901                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
10902                      pri->pvts[chanpos]->alreadyhungup = 1;
10903                      if (pri->pvts[chanpos]->realcall) 
10904                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10905                      else if (pri->pvts[chanpos]->owner) {
10906                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
10907                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10908                         switch (pri->pvts[chanpos]->owner->_state) {
10909                         case AST_STATE_BUSY:
10910                         case AST_STATE_UP:
10911                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10912                            break;
10913                         default:
10914                            switch (e->hangup.cause) {
10915                               case PRI_CAUSE_USER_BUSY:
10916                                  pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10917                                  break;
10918                               case PRI_CAUSE_CALL_REJECTED:
10919                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10920                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10921                               case PRI_CAUSE_SWITCH_CONGESTION:
10922                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10923                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10924                                  pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10925                                  break;
10926                               default:
10927                                  pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10928                            }
10929                            break;
10930                         }
10931                      }
10932                      if (option_verbose > 2) 
10933                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
10934                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10935                   } else {
10936                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10937                      pri->pvts[chanpos]->call = NULL;
10938                   }
10939                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10940                      if (option_verbose > 2)
10941                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
10942                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10943                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10944                      pri->pvts[chanpos]->resetting = 1;
10945                   }
10946                   if (e->hangup.aoc_units > -1)
10947                      if (option_verbose > 2)
10948                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
10949                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
10950 
10951 #ifdef SUPPORT_USERUSER
10952                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10953                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
10954                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10955                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10956                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
10957                   }
10958 #endif
10959 
10960                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10961                } else {
10962                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
10963                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10964                }
10965             } 
10966             break;
10967 #ifndef PRI_EVENT_HANGUP_REQ
10968 #error please update libpri
10969 #endif
10970          case PRI_EVENT_HANGUP_REQ:
10971             chanpos = pri_find_principle(pri, e->hangup.channel);
10972             if (chanpos < 0) {
10973                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
10974                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10975             } else {
10976                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10977                if (chanpos > -1) {
10978                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
10979                   if (pri->pvts[chanpos]->realcall) 
10980                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10981                   else if (pri->pvts[chanpos]->owner) {
10982                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10983                      switch (pri->pvts[chanpos]->owner->_state) {
10984                      case AST_STATE_BUSY:
10985                      case AST_STATE_UP:
10986                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10987                         break;
10988                      default:
10989                         switch (e->hangup.cause) {
10990                            case PRI_CAUSE_USER_BUSY:
10991                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10992                               break;
10993                            case PRI_CAUSE_CALL_REJECTED:
10994                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10995                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10996                            case PRI_CAUSE_SWITCH_CONGESTION:
10997                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10998                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10999                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11000                               break;
11001                            default:
11002                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11003                         }
11004                         break;
11005                      }
11006                      if (option_verbose > 2) 
11007                         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);
11008                      if (e->hangup.aoc_units > -1)
11009                         if (option_verbose > 2)
11010                            ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11011                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11012                   } else {
11013                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11014                      pri->pvts[chanpos]->call = NULL;
11015                   }
11016                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11017                      if (option_verbose > 2)
11018                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
11019                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11020                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11021                      pri->pvts[chanpos]->resetting = 1;
11022                   }
11023 
11024 #ifdef SUPPORT_USERUSER
11025                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11026                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11027                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11028                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11029                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11030                   }
11031 #endif
11032 
11033                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11034                } else {
11035                   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);
11036                }
11037             } 
11038             break;
11039          case PRI_EVENT_HANGUP_ACK:
11040             chanpos = pri_find_principle(pri, e->hangup.channel);
11041             if (chanpos < 0) {
11042                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
11043                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11044             } else {
11045                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11046                if (chanpos > -1) {
11047                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11048                   pri->pvts[chanpos]->call = NULL;
11049                   pri->pvts[chanpos]->resetting = 0;
11050                   if (pri->pvts[chanpos]->owner) {
11051                      if (option_verbose > 2) 
11052                         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);
11053                   }
11054 
11055 #ifdef SUPPORT_USERUSER
11056                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11057                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11058                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11059                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11060                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11061                   }
11062 #endif
11063 
11064                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11065                }
11066             }
11067             break;
11068          case PRI_EVENT_CONFIG_ERR:
11069             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11070             break;
11071          case PRI_EVENT_RESTART_ACK:
11072             chanpos = pri_find_principle(pri, e->restartack.channel);
11073             if (chanpos < 0) {
11074                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11075                   channel number, so we have to figure it out...  This must be why
11076                   everybody resets exactly a channel at a time. */
11077                for (x = 0; x < pri->numchans; x++) {
11078                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
11079                      chanpos = x;
11080                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11081                      ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
11082                            pri->pvts[chanpos]->prioffset, pri->span);
11083                      if (pri->pvts[chanpos]->realcall) 
11084                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11085                      else if (pri->pvts[chanpos]->owner) {
11086                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
11087                            pri->pvts[chanpos]->prioffset, pri->span);
11088                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11089                      }
11090                      pri->pvts[chanpos]->resetting = 0;
11091                      if (option_verbose > 2)
11092                         ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
11093                            pri->pvts[chanpos]->prioffset, pri->span);
11094                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11095                      if (pri->resetting)
11096                         pri_check_restart(pri);
11097                      break;
11098                   }
11099                }
11100                if (chanpos < 0) {
11101                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
11102                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11103                }
11104             } else {
11105                if (pri->pvts[chanpos]) {
11106                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11107                   if (pri->pvts[chanpos]->realcall) 
11108                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11109                   else if (pri->pvts[chanpos]->owner) {
11110                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11111                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11112                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11113                   }
11114                   pri->pvts[chanpos]->resetting = 0;
11115                   if (option_verbose > 2)
11116                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
11117                            pri->pvts[chanpos]->prioffset, pri->span);
11118                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11119                   if (pri->resetting)
11120                      pri_check_restart(pri);
11121                }
11122             }
11123             break;
11124          case PRI_EVENT_SETUP_ACK:
11125             chanpos = pri_find_principle(pri, e->setup_ack.channel);
11126             if (chanpos < 0) {
11127                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
11128                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11129             } else {
11130                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11131                if (chanpos > -1) {
11132                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11133                   pri->pvts[chanpos]->setup_ack = 1;
11134                   /* Send any queued digits */
11135                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11136                      ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11137                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
11138                         pri->pvts[chanpos]->dialdest[x]);
11139                   }
11140                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11141                } else
11142                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11143             }
11144             break;
11145          case PRI_EVENT_NOTIFY:
11146             chanpos = pri_find_principle(pri, e->notify.channel);
11147             if (chanpos < 0) {
11148                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11149                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11150             } else {
11151                struct ast_frame f = { AST_FRAME_CONTROL, };
11152                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11153                switch (e->notify.info) {
11154                case PRI_NOTIFY_REMOTE_HOLD:
11155                   f.subclass = AST_CONTROL_HOLD;
11156                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11157                   break;
11158                case PRI_NOTIFY_REMOTE_RETRIEVAL:
11159                   f.subclass = AST_CONTROL_UNHOLD;
11160                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11161                   break;
11162                }
11163                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11164             }
11165             break;
11166          default:
11167             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
11168          }
11169       }  
11170       ast_mutex_unlock(&pri->lock);
11171    }
11172    /* Never reached */
11173    return NULL;
11174 }
11175 
11176 static int start_pri(struct dahdi_pri *pri)
11177 {
11178    int res, x;
11179    struct dahdi_params p;
11180    struct dahdi_bufferinfo bi;
11181    struct dahdi_spaninfo si;
11182    int i;
11183    
11184    for (i = 0; i < NUM_DCHANS; i++) {
11185       if (!pri->dchannels[i])
11186          break;
11187       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
11188       x = pri->dchannels[i];
11189       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11190          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11191          return -1;
11192       }
11193       memset(&p, 0, sizeof(p));
11194       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11195       if (res) {
11196          dahdi_close_pri_fd(pri, i);
11197          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11198          return -1;
11199       }
11200       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11201          dahdi_close_pri_fd(pri, i);
11202          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
11203          return -1;
11204       }
11205       memset(&si, 0, sizeof(si));
11206       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11207       if (res) {
11208          dahdi_close_pri_fd(pri, i);
11209          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11210       }
11211       if (!si.alarms)
11212          pri->dchanavail[i] |= DCHAN_NOTINALARM;
11213       else
11214          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11215       memset(&bi, 0, sizeof(bi));
11216       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11217       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11218       bi.numbufs = 32;
11219       bi.bufsize = 1024;
11220       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11221          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11222          dahdi_close_pri_fd(pri, i);
11223          return -1;
11224       }
11225       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11226       /* Force overlap dial if we're doing GR-303! */
11227       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11228          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11229       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11230 #ifdef HAVE_PRI_INBANDDISCONNECT
11231       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11232 #endif
11233       /* Enslave to master if appropriate */
11234       if (i)
11235          pri_enslave(pri->dchans[0], pri->dchans[i]);
11236       if (!pri->dchans[i]) {
11237          dahdi_close_pri_fd(pri, i);
11238          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11239          return -1;
11240       }
11241       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11242       pri_set_nsf(pri->dchans[i], pri->nsf);
11243 #ifdef PRI_GETSET_TIMERS
11244       for (x = 0; x < PRI_MAX_TIMERS; x++) {
11245          if (pritimers[x] != 0)
11246             pri_set_timer(pri->dchans[i], x, pritimers[x]);
11247       }
11248 #endif
11249    }
11250    /* Assume primary is the one we use */
11251    pri->pri = pri->dchans[0];
11252    pri->resetpos = -1;
11253    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11254       for (i = 0; i < NUM_DCHANS; i++) {
11255          if (!pri->dchannels[i])
11256             break;
11257          dahdi_close_pri_fd(pri, i);
11258       }
11259       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11260       return -1;
11261    }
11262    return 0;
11263 }
11264 
11265 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11266 {
11267    int which, span;
11268    char *ret = NULL;
11269 
11270    if (pos != rpos)
11271       return ret;
11272 
11273    for (which = span = 0; span < NUM_SPANS; span++) {
11274       if (pris[span].pri && ++which > state) {
11275          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
11276             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11277          }
11278          break;
11279       }
11280    }
11281    return ret;
11282 }
11283 
11284 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11285 {
11286    return complete_span_helper(line,word,pos,state,3);
11287 }
11288 
11289 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11290 {
11291    return complete_span_helper(line,word,pos,state,4);
11292 }
11293 
11294 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
11295 {
11296    int myfd;
11297 
11298    if (!strncasecmp(argv[1], "set", 3)) {
11299       if (argc < 5) 
11300          return RESULT_SHOWUSAGE;
11301 
11302       if (ast_strlen_zero(argv[4]))
11303          return RESULT_SHOWUSAGE;
11304 
11305       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
11306       if (myfd < 0) {
11307          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
11308          return RESULT_SUCCESS;
11309       }
11310 
11311       ast_mutex_lock(&pridebugfdlock);
11312 
11313       if (pridebugfd >= 0)
11314          close(pridebugfd);
11315 
11316       pridebugfd = myfd;
11317       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
11318       
11319       ast_mutex_unlock(&pridebugfdlock);
11320 
11321       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
11322    } else {
11323       /* Assume it is unset */
11324       ast_mutex_lock(&pridebugfdlock);
11325       close(pridebugfd);
11326       pridebugfd = -1;
11327       ast_cli(fd, "PRI debug output to file disabled\n");
11328       ast_mutex_unlock(&pridebugfdlock);
11329    }
11330 
11331    return RESULT_SUCCESS;
11332 }
11333 
11334 #ifdef HAVE_PRI_VERSION
11335 static int handle_pri_version(int fd, int agc, char *argv[]) {
11336    ast_cli(fd, "libpri version: %s\n", pri_get_version());
11337    return RESULT_SUCCESS;
11338 }
11339 #endif
11340 
11341 static int handle_pri_debug(int fd, int argc, char *argv[])
11342 {
11343    int span;
11344    int x;
11345    if (argc < 4) {
11346       return RESULT_SHOWUSAGE;
11347    }
11348    span = atoi(argv[3]);
11349    if ((span < 1) || (span > NUM_SPANS)) {
11350       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11351       return RESULT_SUCCESS;
11352    }
11353    if (!pris[span-1].pri) {
11354       ast_cli(fd, "No PRI running on span %d\n", span);
11355       return RESULT_SUCCESS;
11356    }
11357    for (x = 0; x < NUM_DCHANS; x++) {
11358       if (pris[span-1].dchans[x])
11359          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11360                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11361                                                PRI_DEBUG_Q921_STATE);
11362    }
11363    ast_cli(fd, "Enabled debugging on span %d\n", span);
11364    return RESULT_SUCCESS;
11365 }
11366 
11367 
11368 
11369 static int handle_pri_no_debug(int fd, int argc, char *argv[])
11370 {
11371    int span;
11372    int x;
11373    if (argc < 5)
11374       return RESULT_SHOWUSAGE;
11375    span = atoi(argv[4]);
11376    if ((span < 1) || (span > NUM_SPANS)) {
11377       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11378       return RESULT_SUCCESS;
11379    }
11380    if (!pris[span-1].pri) {
11381       ast_cli(fd, "No PRI running on span %d\n", span);
11382       return RESULT_SUCCESS;
11383    }
11384    for (x = 0; x < NUM_DCHANS; x++) {
11385       if (pris[span-1].dchans[x])
11386          pri_set_debug(pris[span-1].dchans[x], 0);
11387    }
11388    ast_cli(fd, "Disabled debugging on span %d\n", span);
11389    return RESULT_SUCCESS;
11390 }
11391 
11392 static int handle_pri_really_debug(int fd, int argc, char *argv[])
11393 {
11394    int span;
11395    int x;
11396    if (argc < 5)
11397       return RESULT_SHOWUSAGE;
11398    span = atoi(argv[4]);
11399    if ((span < 1) || (span > NUM_SPANS)) {
11400       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11401       return RESULT_SUCCESS;
11402    }
11403    if (!pris[span-1].pri) {
11404       ast_cli(fd, "No PRI running on span %d\n", span);
11405       return RESULT_SUCCESS;
11406    }
11407    for (x = 0; x < NUM_DCHANS; x++) {
11408       if (pris[span-1].dchans[x])
11409          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11410                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11411                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11412    }
11413    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11414    return RESULT_SUCCESS;
11415 }
11416 
11417 static void build_status(char *s, size_t len, int status, int active)
11418 {
11419    if (!s || len < 1) {
11420       return;
11421    }
11422    s[0] = '\0';
11423    if (status & DCHAN_PROVISIONED)
11424       strncat(s, "Provisioned, ", len - strlen(s) - 1);
11425    if (!(status & DCHAN_NOTINALARM))
11426       strncat(s, "In Alarm, ", len - strlen(s) - 1);
11427    if (status & DCHAN_UP)
11428       strncat(s, "Up", len - strlen(s) - 1);
11429    else
11430       strncat(s, "Down", len - strlen(s) - 1);
11431    if (active)
11432       strncat(s, ", Active", len - strlen(s) - 1);
11433    else
11434       strncat(s, ", Standby", len - strlen(s) - 1);
11435    s[len - 1] = '\0';
11436 }
11437 
11438 static int handle_pri_show_spans(int fd, int argc, char *argv[])
11439 {
11440    int span;
11441    int x;
11442    char status[256];
11443    if (argc != 3)
11444       return RESULT_SHOWUSAGE;
11445 
11446    for (span = 0; span < NUM_SPANS; span++) {
11447       if (pris[span].pri) {
11448          for (x = 0; x < NUM_DCHANS; x++) {
11449             if (pris[span].dchannels[x]) {
11450                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11451                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11452             }
11453          }
11454       }
11455    }
11456    return RESULT_SUCCESS;
11457 }
11458 
11459 static int handle_pri_show_span(int fd, int argc, char *argv[])
11460 {
11461    int span;
11462    int x;
11463    char status[256];
11464    if (argc < 4)
11465       return RESULT_SHOWUSAGE;
11466    span = atoi(argv[3]);
11467    if ((span < 1) || (span > NUM_SPANS)) {
11468       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11469       return RESULT_SUCCESS;
11470    }
11471    if (!pris[span-1].pri) {
11472       ast_cli(fd, "No PRI running on span %d\n", span);
11473       return RESULT_SUCCESS;
11474    }
11475    for (x = 0; x < NUM_DCHANS; x++) {
11476       if (pris[span-1].dchannels[x]) {
11477 #ifdef PRI_DUMP_INFO_STR
11478          char *info_str = NULL;
11479 #endif
11480          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11481          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11482          ast_cli(fd, "Status: %s\n", status);
11483 #ifdef PRI_DUMP_INFO_STR
11484          info_str = pri_dump_info_str(pris[span-1].pri);
11485          if (info_str) {
11486             ast_cli(fd, "%s", info_str);
11487             free(info_str);
11488          }
11489 #else
11490          pri_dump_info(pris[span-1].pri);
11491 #endif
11492          ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11493       }
11494    }
11495    return RESULT_SUCCESS;
11496 }
11497 
11498 static int handle_pri_show_debug(int fd, int argc, char *argv[])
11499 {
11500    int x;
11501    int span;
11502    int count=0;
11503    int debug=0;
11504 
11505    for (span = 0; span < NUM_SPANS; span++) {
11506            if (pris[span].pri) {
11507          for (x = 0; x < NUM_DCHANS; x++) {
11508             debug = 0;
11509                if (pris[span].dchans[x]) {
11510                   debug = pri_get_debug(pris[span].dchans[x]);
11511                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" );
11512                count++;
11513             }
11514          }
11515       }
11516 
11517    }
11518    ast_mutex_lock(&pridebugfdlock);
11519    if (pridebugfd >= 0) 
11520       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
11521    ast_mutex_unlock(&pridebugfdlock);
11522        
11523    if (!count) 
11524       ast_cli(fd, "No debug set or no PRI running\n");
11525    return RESULT_SUCCESS;
11526 }
11527 
11528 static const char pri_debug_help[] = 
11529    "Usage: pri debug span <span>\n"
11530    "       Enables debugging on a given PRI span\n";
11531    
11532 static const char pri_no_debug_help[] = 
11533    "Usage: pri no debug span <span>\n"
11534    "       Disables debugging on a given PRI span\n";
11535 
11536 static const char pri_really_debug_help[] = 
11537    "Usage: pri intensive debug span <span>\n"
11538    "       Enables debugging down to the Q.921 level\n";
11539 
11540 static const char pri_show_span_help[] = 
11541    "Usage: pri show span <span>\n"
11542    "       Displays PRI Information on a given PRI span\n";
11543 
11544 static const char pri_show_spans_help[] = 
11545    "Usage: pri show spans\n"
11546    "       Displays PRI Information\n";
11547 
11548 static struct ast_cli_entry dahdi_pri_cli[] = {
11549    { { "pri", "debug", "span", NULL },
11550    handle_pri_debug, "Enables PRI debugging on a span",
11551    pri_debug_help, complete_span_4 },
11552 
11553    { { "pri", "no", "debug", "span", NULL },
11554    handle_pri_no_debug, "Disables PRI debugging on a span",
11555    pri_no_debug_help, complete_span_5 },
11556 
11557    { { "pri", "intense", "debug", "span", NULL },
11558    handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
11559    pri_really_debug_help, complete_span_5 },
11560 
11561    { { "pri", "show", "spans", NULL },
11562    handle_pri_show_spans, "Displays PRI Information",
11563    pri_show_spans_help },
11564 
11565    { { "pri", "show", "span", NULL },
11566    handle_pri_show_span, "Displays PRI Information",
11567    pri_show_span_help, complete_span_4 },
11568 
11569    { { "pri", "show", "debug", NULL },
11570    handle_pri_show_debug, "Displays current PRI debug settings" },
11571 
11572    { { "pri", "set", "debug", "file", NULL },
11573    handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
11574 
11575    { { "pri", "unset", "debug", "file", NULL },
11576    handle_pri_set_debug_file, "Ends PRI debug output to file" },
11577 
11578 #ifdef HAVE_PRI_VERSION
11579    { { "pri", "show", "version", NULL },
11580    handle_pri_version, "Displays version of libpri" },
11581 #endif
11582 };
11583 
11584 #endif /* HAVE_PRI */
11585 
11586 #ifdef HAVE_OPENR2
11587 
11588 static int handle_mfcr2_version(int fd, int argc, char *argv[])
11589 {
11590    ast_cli(fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
11591    return RESULT_SUCCESS;
11592 }
11593 
11594 static int handle_mfcr2_show_variants(int fd, int argc, char *argv[]) 
11595 {
11596 #define FORMAT "%4s %40s\n"
11597    int numvariants = 0;
11598    int i;
11599    const openr2_variant_entry_t *variants;
11600    if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
11601       ast_cli(fd, "Failed to get list of variants.\n");
11602       return RESULT_FAILURE;
11603    }
11604    ast_cli(fd, FORMAT, "Variant Code", "Country");
11605    for (i = 0; i < numvariants; i++) {
11606       ast_cli(fd, FORMAT, variants[i].name, variants[i].country);
11607    }
11608    return RESULT_SUCCESS;
11609 #undef FORMAT
11610 }  
11611 
11612 static int handle_mfcr2_show_channels(int fd, int argc, char *argv[])
11613 {
11614 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
11615    int filtertype = 0;
11616    int targetnum = 0;
11617    char channo[5];
11618    char anino[5];
11619    char dnisno[5];
11620    struct dahdi_pvt *p;
11621    openr2_context_t *r2context;
11622    openr2_variant_t r2variant;
11623    if (!((argc == 3) || (argc == 5))) {
11624       return RESULT_SHOWUSAGE;
11625    }
11626    if (argc == 5) {
11627       if (!strcasecmp(argv[3], "group")) {
11628          targetnum = atoi(argv[4]);
11629          if ((targetnum < 0) || (targetnum > 63))
11630             return RESULT_SHOWUSAGE;
11631          targetnum = 1 << targetnum;
11632          filtertype = 1;
11633       } else if (!strcasecmp(argv[3], "context")) {
11634          filtertype = 2;
11635       } else {
11636          return RESULT_SHOWUSAGE;
11637       }
11638    }
11639    ast_cli(fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
11640    ast_mutex_lock(&iflock);
11641    p = iflist;
11642    while (p) {
11643       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11644          p = p->next;
11645          continue;
11646       }
11647       if (filtertype) {
11648          switch(filtertype) {
11649          case 1: /* mfcr2 show channels group <group> */
11650             if (p->group != targetnum) {
11651                p = p->next;
11652                continue;
11653             }
11654             break;
11655          case 2: /* mfcr2 show channels context <context> */
11656             if (strcasecmp(p->context, argv[4])) {
11657                p= p->next;
11658                continue;
11659             }
11660             break;
11661          default:
11662             ;
11663          }
11664       }
11665       r2context = openr2_chan_get_context(p->r2chan);
11666       r2variant = openr2_context_get_variant(r2context);
11667       snprintf(channo, sizeof(channo), "%d", p->channel);
11668       snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
11669       snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
11670       ast_cli(fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant), 
11671             anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",  
11672             openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
11673             openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
11674       p = p->next;
11675    }
11676    ast_mutex_unlock(&iflock);
11677    return RESULT_SUCCESS;
11678 #undef FORMAT
11679 }
11680 
11681 static int handle_mfcr2_set_debug(int fd, int argc, char *argv[])
11682 {
11683    struct dahdi_pvt *p = NULL;
11684    int channo = 0;
11685    char *toklevel = NULL;
11686    char *saveptr = NULL;
11687    char *logval = NULL;
11688    openr2_log_level_t loglevel = OR2_LOG_NOTHING;
11689    openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
11690    if (argc < 4) {
11691       return RESULT_SHOWUSAGE;
11692    }
11693    channo = (argc == 5) ? atoi(argv[4]) : -1;
11694    logval = ast_strdupa(argv[3]);
11695    toklevel = strtok_r(logval, ",", &saveptr);
11696    if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11697       ast_cli(fd, "Invalid MFC/R2 logging level '%s'.\n", argv[3]);
11698       return RESULT_FAILURE;
11699    } else if (OR2_LOG_NOTHING == tmplevel) {
11700       loglevel = tmplevel;
11701    } else {
11702       loglevel |= tmplevel;
11703       while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
11704          if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
11705             ast_cli(fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
11706             continue;
11707          }
11708          loglevel |= tmplevel;
11709       }
11710    }
11711    ast_mutex_lock(&iflock);
11712    p = iflist;
11713    while (p) {
11714       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11715          p = p->next;
11716          continue;
11717       }
11718       if ((channo != -1) && (p->channel != channo )) {
11719          p = p->next;
11720          continue;
11721       }
11722       openr2_chan_set_log_level(p->r2chan, loglevel);
11723       if (channo != -1) {
11724          ast_cli(fd, "MFC/R2 debugging set to '%s' for channel %d.\n", argv[3], p->channel);
11725          break;
11726       } else {
11727          p = p->next;
11728       }
11729    }
11730    if ((channo != -1) && !p) {
11731       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11732    }
11733    if (channo == -1) {
11734       ast_cli(fd, "MFC/R2 debugging set to '%s' for all channels.\n", argv[3]);
11735    }
11736    ast_mutex_unlock(&iflock);
11737    return RESULT_SUCCESS;
11738 }
11739 
11740 static int handle_mfcr2_call_files(int fd, int argc, char *argv[])
11741 {
11742    struct dahdi_pvt *p = NULL;
11743    int channo = 0;
11744    if (argc < 4) {
11745       return RESULT_SHOWUSAGE;
11746    }
11747    channo = (argc == 5) ? atoi(argv[4]) : -1;
11748    ast_mutex_lock(&iflock);
11749    p = iflist;
11750    while (p) {
11751       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11752          p = p->next;
11753          continue;
11754       }
11755       if ((channo != -1) && (p->channel != channo )) {
11756          p = p->next;
11757          continue;
11758       }
11759       if (ast_true(argv[3])) {
11760          openr2_chan_enable_call_files(p->r2chan);
11761       } else {
11762          openr2_chan_disable_call_files(p->r2chan);
11763       }
11764       if (channo != -1) {
11765          if (ast_true(argv[3])) {
11766             ast_cli(fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
11767          } else {
11768             ast_cli(fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
11769          }
11770          break;
11771       } else {
11772          p = p->next;
11773       }
11774    }
11775    if ((channo != -1) && !p) {
11776       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11777    }
11778    if (channo == -1) {
11779       if (ast_true(argv[3])) {
11780          ast_cli(fd, "MFC/R2 Call files enabled for all channels.\n");
11781       } else {
11782          ast_cli(fd, "MFC/R2 Call files disabled for all channels.\n");
11783       }  
11784    }
11785    ast_mutex_unlock(&iflock);
11786    return RESULT_SUCCESS;
11787 }  
11788 
11789 static int handle_mfcr2_set_idle(int fd, int argc, char *argv[])
11790 {
11791    struct dahdi_pvt *p = NULL;
11792    int channo = 0;
11793    channo = (argc == 4) ? atoi(argv[3]) : -1;
11794    ast_mutex_lock(&iflock);
11795    p = iflist;
11796    while (p) {
11797       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11798          p = p->next;
11799          continue;
11800       }
11801       if ((channo != -1) && (p->channel != channo )) {
11802          p = p->next;
11803          continue;
11804       }
11805       if (!openr2_chan_set_idle(p->r2chan)) {
11806          ast_mutex_lock(&p->lock);
11807          p->mfcr2call = 0;
11808          p->mfcr2block &= ~DAHDI_R2_LOCAL_BLOCK;
11809          ast_mutex_unlock(&p->lock);
11810       }
11811       if (channo != -1) {
11812          break;
11813       } else {
11814          p = p->next;
11815       }
11816    }
11817    if ((channo != -1) && !p) {
11818       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11819    }
11820    ast_mutex_unlock(&iflock);
11821    return RESULT_SUCCESS;
11822 }
11823 
11824 static int handle_mfcr2_set_blocked(int fd, int argc, char *argv[])
11825 {
11826    struct dahdi_pvt *p = NULL;
11827    int channo = 0;
11828    channo = (argc == 4) ? atoi(argv[3]) : -1;
11829    ast_mutex_lock(&iflock);
11830    p = iflist;
11831    while (p) {
11832       if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
11833          p = p->next;
11834          continue;
11835       }
11836       if ((channo != -1) && (p->channel != channo )) {
11837          p = p->next;
11838          continue;
11839       }
11840       if (!openr2_chan_set_blocked(p->r2chan)) {
11841          ast_mutex_lock(&p->lock);
11842          p->mfcr2block |= DAHDI_R2_LOCAL_BLOCK;
11843          ast_mutex_unlock(&p->lock);
11844       } else {
11845          ast_cli(fd, "MFC/R2 channel %d could not be blocked.\n", p->channel);
11846       }
11847       if (channo != -1) {
11848          break;
11849       } else {
11850          p = p->next;
11851       }
11852    }
11853    if ((channo != -1) && !p) {
11854       ast_cli(fd, "MFC/R2 channel %d not found.\n", channo);
11855    }
11856    ast_mutex_unlock(&iflock);
11857    return RESULT_SUCCESS;
11858 }
11859 
11860 static const char dahdi_r2_version_help[] = 
11861          "Usage: mfcr2 show version\n"
11862          "       Shows the version of the OpenR2 library being used.\n";
11863 static const char dahdi_r2_variants_help[] = 
11864          "Usage: mfcr2 show variants\n"
11865          "       Show supported MFC/R2 variants.\n";
11866 static const char dahdi_r2_showchannels_help[] =
11867          "Usage: mfcr2 show channels [group <group> | context <context>]\n"
11868          "       Shows the zap channels configured with MFC/R2 signaling.\n";
11869 static const char dahdi_r2_setdebug_help[] =
11870          "Usage: mfcr2 set debug <loglevel> <channel>\n"
11871          "       Set a new logging level for the specified channel.\n"
11872          "       If no channel is specified the logging level will be applied to all channels.\n";
11873 static const char dahdi_r2_callfiles_help[] =
11874          "Usage: mfcr2 call files [on|off] <channel>\n"
11875          "       Enable call files creation on the specified channel.\n"
11876          "       If no channel is specified call files creation policy will be applied to all channels.\n";
11877 static const char dahdi_r2_setidle_help[] =
11878          "Usage: mfcr2 set idle <channel>\n"
11879          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11880          "       Force the given channel into IDLE state.\n"
11881          "       If no channel is specified, all channels will be set to IDLE.\n";
11882 static const char dahdi_r2_setblocked_help[] =
11883          "Usage: mfcr2 set blocked <channel>\n"
11884          "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
11885          "       Force the given channel into BLOCKED state.\n"
11886          "       If no channel is specified, all channels will be set to BLOCKED.\n";
11887 
11888 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
11889    { { "mfcr2", "show", "version", NULL },
11890    handle_mfcr2_version, "Show OpenR2 library version",
11891    dahdi_r2_version_help },
11892 
11893    { { "mfcr2", "show", "variants", NULL },
11894    handle_mfcr2_show_variants, "Show supported MFC/R2 variants",
11895    dahdi_r2_variants_help },
11896 
11897    { { "mfcr2", "show", "channels", NULL },
11898    handle_mfcr2_show_channels, "Show MFC/R2 channels",
11899    dahdi_r2_showchannels_help },
11900 
11901    { { "mfcr2", "set", "debug", NULL },
11902    handle_mfcr2_set_debug, "Set MFC/R2 channel logging level",
11903    dahdi_r2_setdebug_help },
11904 
11905    { { "mfcr2", "call", "files", NULL },
11906    handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files",
11907    dahdi_r2_callfiles_help },
11908 
11909    { { "mfcr2", "set", "idle", NULL },
11910    handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE",
11911    dahdi_r2_setidle_help },
11912 
11913    { { "mfcr2", "set", "blocked", NULL },
11914    handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED",
11915    dahdi_r2_setblocked_help }
11916 
11917 };
11918 
11919 #endif /* HAVE_OPENR2 */
11920 
11921 static int dahdi_destroy_channel(int fd, int argc, char **argv)
11922 {
11923    int channel;
11924    
11925    if (argc != 4)
11926       return RESULT_SHOWUSAGE;
11927    
11928    channel = atoi(argv[3]);
11929 
11930    return dahdi_destroy_channel_bynum(channel);
11931 }
11932 
11933 static void dahdi_softhangup_all(void)
11934 {
11935    struct dahdi_pvt *p;
11936 retry:
11937    ast_mutex_lock(&iflock);
11938     for (p = iflist; p; p = p->next) {
11939       ast_mutex_lock(&p->lock);
11940         if (p->owner && !p->restartpending) {
11941          if (ast_channel_trylock(p->owner)) {
11942             if (option_debug > 2)
11943                ast_verbose("Avoiding deadlock\n");
11944             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11945             ast_mutex_unlock(&p->lock);
11946             ast_mutex_unlock(&iflock);
11947             goto retry;
11948          }
11949          if (option_debug > 2)
11950             ast_verbose("Softhanging up on %s\n", p->owner->name);
11951          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11952          p->restartpending = 1;
11953          num_restart_pending++;
11954          ast_channel_unlock(p->owner);
11955       }
11956       ast_mutex_unlock(&p->lock);
11957     }
11958    ast_mutex_unlock(&iflock);
11959 }
11960 
11961 static int setup_dahdi(int reload);
11962 static int dahdi_restart(void)
11963 {
11964 #ifdef HAVE_OPENR2
11965    int r;
11966 #endif
11967 #if defined(HAVE_PRI)
11968    int i, j;
11969 #endif
11970    int cancel_code;
11971    struct dahdi_pvt *p;
11972 
11973    ast_mutex_lock(&restart_lock);
11974  
11975    if (option_verbose)
11976       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11977    dahdi_softhangup_all();
11978    if (option_verbose > 3)
11979       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11980 
11981 #ifdef HAVE_OPENR2
11982    for (r = 0; r < NUM_SPANS; r++) {
11983       if (r2links[r].master != AST_PTHREADT_NULL) {
11984          ast_log(LOG_DEBUG, "Killing MFC/R2 monitor thread %p\n", &r2links[r].master);
11985          pthread_cancel(r2links[r].master);
11986          pthread_join(r2links[r].master, NULL);
11987          openr2_context_delete(r2links[r].protocol_context);
11988       }
11989    }
11990    init_mfcr2_globals();
11991 #endif
11992 
11993    #if defined(HAVE_PRI)
11994    for (i = 0; i < NUM_SPANS; i++) {
11995       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11996          cancel_code = pthread_cancel(pris[i].master);
11997          pthread_kill(pris[i].master, SIGURG);
11998          if (option_debug > 3)
11999             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12000             pthread_join(pris[i].master, NULL);
12001          if (option_debug > 3)
12002             ast_verbose("Joined thread of span %d\n", i);
12003       }
12004     }
12005    #endif
12006 
12007     ast_mutex_lock(&monlock);
12008     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12009       cancel_code = pthread_cancel(monitor_thread);
12010       pthread_kill(monitor_thread, SIGURG);
12011       if (option_debug > 3)
12012          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12013         pthread_join(monitor_thread, NULL);
12014       if (option_debug > 3)
12015          ast_verbose("Joined monitor thread\n");
12016     }
12017    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12018 
12019    ast_mutex_lock(&ss_thread_lock);
12020    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12021       int x = DAHDI_FLASH;
12022       if (option_debug > 2)
12023          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12024 
12025       for (p = iflist; p; p = p->next) {
12026          if (p->owner)
12027             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 */    
12028       }
12029       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12030    }
12031 
12032    /* ensure any created channels before monitor threads were stopped are hungup */
12033    dahdi_softhangup_all();
12034    if (option_verbose > 3)
12035       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
12036    destroy_all_channels();
12037    if (option_debug)
12038       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12039 
12040     ast_mutex_unlock(&monlock);
12041 
12042    #ifdef HAVE_PRI
12043    for (i = 0; i < NUM_SPANS; i++) {
12044       for (j = 0; j < NUM_DCHANS; j++)
12045             dahdi_close_pri_fd(&(pris[i]), j);
12046    }
12047 
12048    memset(pris, 0, sizeof(pris));
12049    for (i = 0; i < NUM_SPANS; i++) {
12050       ast_mutex_init(&pris[i].lock);
12051       pris[i].offset = -1;
12052       pris[i].master = AST_PTHREADT_NULL;
12053       for (j = 0; j < NUM_DCHANS; j++)
12054          pris[i].fds[j] = -1;
12055    }
12056    pri_set_error(dahdi_pri_error);
12057    pri_set_message(dahdi_pri_message);
12058    #endif
12059 
12060    if (setup_dahdi(2) != 0) {
12061       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12062       ast_mutex_unlock(&ss_thread_lock);
12063       return 1;
12064    }
12065    ast_mutex_unlock(&ss_thread_lock);
12066    ast_mutex_unlock(&restart_lock);
12067    return 0;
12068 }
12069 
12070 static int dahdi_restart_cmd(int fd, int argc, char **argv)
12071 {
12072    if (argc != 2) {
12073       return RESULT_SHOWUSAGE;
12074    }
12075 
12076    if (dahdi_restart() != 0)
12077       return RESULT_FAILURE;
12078    return RESULT_SUCCESS;
12079 }
12080 
12081 static int dahdi_show_channels(int fd, int argc, char **argv)
12082 {
12083 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12084 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
12085    struct dahdi_pvt *tmp = NULL;
12086    char tmps[20] = "";
12087    ast_mutex_t *lock;
12088    struct dahdi_pvt *start;
12089 #ifdef HAVE_PRI
12090    int trunkgroup;
12091    struct dahdi_pri *pri = NULL;
12092    int x;
12093 #endif
12094 
12095    lock = &iflock;
12096    start = iflist;
12097 
12098 #ifdef HAVE_PRI
12099    if (argc == 4) {
12100       if ((trunkgroup = atoi(argv[3])) < 1)
12101          return RESULT_SHOWUSAGE;
12102       for (x = 0; x < NUM_SPANS; x++) {
12103          if (pris[x].trunkgroup == trunkgroup) {
12104             pri = pris + x;
12105             break;
12106          }
12107       }
12108       if (pri) {
12109          start = pri->crvs;
12110          lock = &pri->lock;
12111       } else {
12112          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12113          return RESULT_FAILURE;
12114       }
12115    } else
12116 #endif
12117    if (argc != 3)
12118       return RESULT_SHOWUSAGE;
12119 
12120    ast_mutex_lock(lock);
12121 #ifdef HAVE_PRI
12122    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
12123 #else
12124    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
12125 #endif   
12126    
12127    tmp = start;
12128    while (tmp) {
12129       if (tmp->channel > 0) {
12130          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12131       } else
12132          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12133       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
12134       tmp = tmp->next;
12135    }
12136    ast_mutex_unlock(lock);
12137    return RESULT_SUCCESS;
12138 #undef FORMAT
12139 #undef FORMAT2
12140 }
12141 
12142 static int dahdi_show_channel(int fd, int argc, char **argv)
12143 {
12144    int channel;
12145    struct dahdi_pvt *tmp = NULL;
12146    struct dahdi_confinfo ci;
12147    struct dahdi_params ps;
12148    int x;
12149    ast_mutex_t *lock;
12150    struct dahdi_pvt *start;
12151 #ifdef HAVE_PRI
12152    char *c;
12153    int trunkgroup;
12154    struct dahdi_pri *pri=NULL;
12155 #endif
12156 
12157    lock = &iflock;
12158    start = iflist;
12159 
12160    if (argc != 4)
12161       return RESULT_SHOWUSAGE;
12162 #ifdef HAVE_PRI
12163    if ((c = strchr(argv[3], ':'))) {
12164       if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12165          return RESULT_SHOWUSAGE;
12166       if ((trunkgroup < 1) || (channel < 1))
12167          return RESULT_SHOWUSAGE;
12168       for (x = 0; x < NUM_SPANS; x++) {
12169          if (pris[x].trunkgroup == trunkgroup) {
12170             pri = pris + x;
12171             break;
12172          }
12173       }
12174       if (pri) {
12175          start = pri->crvs;
12176          lock = &pri->lock;
12177       } else {
12178          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
12179          return RESULT_FAILURE;
12180       }
12181    } else
12182 #endif
12183       channel = atoi(argv[3]);
12184 
12185    ast_mutex_lock(lock);
12186    tmp = start;
12187    while (tmp) {
12188       if (tmp->channel == channel) {
12189 #ifdef HAVE_PRI
12190          if (pri) 
12191             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12192          else
12193 #endif         
12194          ast_cli(fd, "Channel: %d\n", tmp->channel);
12195          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12196          ast_cli(fd, "Span: %d\n", tmp->span);
12197          ast_cli(fd, "Extension: %s\n", tmp->exten);
12198          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12199          ast_cli(fd, "Context: %s\n", tmp->context);
12200          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
12201          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
12202          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
12203          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
12204          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
12205          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12206          ast_cli(fd, "Radio: %d\n", tmp->radio);
12207          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12208          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)" : "");
12209          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)" : "");
12210          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)" : "");
12211          ast_cli(fd, "Confno: %d\n", tmp->confno);
12212          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
12213          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
12214          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12215          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12216          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12217          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12218          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12219          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12220          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
12221          if (tmp->master)
12222             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
12223          for (x = 0; x < MAX_SLAVES; x++) {
12224             if (tmp->slaves[x])
12225                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12226          }
12227 #ifdef HAVE_OPENR2
12228          if (tmp->mfcr2) {
12229             char calldir[OR2_MAX_PATH];
12230             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
12231             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
12232             ast_cli(fd, "MFC/R2 Call: %s\n", tmp->mfcr2call ? "Yes" : "No");
12233             ast_cli(fd, "MFC/R2 Blocked: %s\n", tmp->mfcr2block ? "Yes" : "No");
12234             ast_cli(fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
12235             ast_cli(fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
12236             ast_cli(fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
12237             ast_cli(fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
12238             ast_cli(fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
12239             ast_cli(fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
12240             ast_cli(fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
12241             ast_cli(fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
12242 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12243             ast_cli(fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
12244             ast_cli(fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
12245 #endif
12246             ast_cli(fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
12247             ast_cli(fd, "MFC/R2 Skip Category: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
12248             ast_cli(fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
12249             ast_cli(fd, "MFC/R2 Accept On Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
12250             ast_cli(fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
12251             ast_cli(fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
12252             ast_cli(fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
12253             ast_cli(fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
12254             ast_cli(fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
12255             ast_cli(fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
12256             ast_cli(fd, "MFC/R2 Tx CAS : %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
12257             ast_cli(fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
12258             ast_cli(fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
12259             ast_cli(fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
12260          }
12261 #endif
12262 #ifdef HAVE_PRI
12263          if (tmp->pri) {
12264             ast_cli(fd, "PRI Flags: ");
12265             if (tmp->resetting)
12266                ast_cli(fd, "Resetting ");
12267             if (tmp->call)
12268                ast_cli(fd, "Call ");
12269             if (tmp->bearer)
12270                ast_cli(fd, "Bearer ");
12271             ast_cli(fd, "\n");
12272             if (tmp->logicalspan) 
12273                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12274             else
12275                ast_cli(fd, "PRI Logical Span: Implicit\n");
12276          }
12277             
12278 #endif
12279          memset(&ci, 0, sizeof(ci));
12280          ps.channo = tmp->channel;
12281          if (tmp->subs[SUB_REAL].dfd > -1) {
12282             memset(&ci, 0, sizeof(ci));
12283             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12284                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12285             }
12286 #ifdef DAHDI_GETCONFMUTE
12287             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12288                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12289             }
12290 #endif
12291             memset(&ps, 0, sizeof(ps));
12292             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12293                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12294             } else {
12295                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12296             }
12297          }
12298          if (ISTRUNK(tmp)) {
12299             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
12300             if (!ast_strlen_zero(progzone))
12301                ast_cli(fd, "Progress Zone: %s\n", progzone);
12302             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
12303             if(tmp->busydetect) {
12304                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
12305                if(tmp->busytonelength > 0) {
12306                   ast_cli(fd, "Busy Pattern:\n");
12307                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12308                   if (tmp->busyquietlength > 0) 
12309                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12310                   else 
12311                      ast_cli(fd, " -- Detect Tone Only\n");
12312                   if(tmp->busyfuzziness > 0)
12313                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12314                }
12315             }
12316          }
12317          ast_mutex_unlock(lock);
12318          return RESULT_SUCCESS;
12319       }
12320       tmp = tmp->next;
12321    }
12322    
12323    ast_cli(fd, "Unable to find given channel %d\n", channel);
12324    ast_mutex_unlock(lock);
12325    return RESULT_FAILURE;
12326 }
12327 
12328 static char dahdi_show_cadences_usage[] =
12329 "Usage: dahdi show cadences\n"
12330 "       Shows all cadences currently defined\n";
12331 
12332 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
12333 {
12334    int i, j;
12335    for (i = 0; i < num_cadence; i++) {
12336       char output[1024];
12337       char tmp[16], tmp2[64];
12338       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12339       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12340 
12341       for (j = 0; j < 16; j++) {
12342          if (cadences[i].ringcadence[j] == 0)
12343             break;
12344          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12345          if (cidrings[i] * 2 - 1 == j)
12346             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12347          else
12348             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12349          if (j != 0)
12350             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12351          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12352       }
12353       ast_cli(fd,"%s\n",output);
12354    }
12355    return 0;
12356 }
12357 
12358 /* Based on irqmiss.c */
12359 static int dahdi_show_status(int fd, int argc, char *argv[]) {
12360    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12361    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12362 
12363    int span;
12364    int res;
12365    char alarms[50];
12366 
12367    int ctl;
12368    struct dahdi_spaninfo s;
12369 
12370    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
12371       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
12372       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
12373       return RESULT_FAILURE;
12374    }
12375    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
12376 
12377    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12378       s.spanno = span;
12379       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12380       if (res) {
12381          continue;
12382       }
12383       alarms[0] = '\0';
12384       if (s.alarms > 0) {
12385          if (s.alarms & DAHDI_ALARM_BLUE)
12386             strcat(alarms, "BLU/");
12387          if (s.alarms & DAHDI_ALARM_YELLOW)
12388             strcat(alarms, "YEL/");
12389          if (s.alarms & DAHDI_ALARM_RED)
12390             strcat(alarms, "RED/");
12391          if (s.alarms & DAHDI_ALARM_LOOPBACK)
12392             strcat(alarms, "LB/");
12393          if (s.alarms & DAHDI_ALARM_RECOVER)
12394             strcat(alarms, "REC/");
12395          if (s.alarms & DAHDI_ALARM_NOTOPEN)
12396             strcat(alarms, "NOP/");
12397          if (!strlen(alarms))
12398             strcat(alarms, "UUU/");
12399          if (strlen(alarms)) {
12400             /* Strip trailing / */
12401             alarms[strlen(alarms) - 1] = '\0';
12402          }
12403       } else {
12404          if (s.numchans)
12405             strcpy(alarms, "OK");
12406          else
12407             strcpy(alarms, "UNCONFIGURED");
12408       }
12409 
12410       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12411    }
12412    close(ctl);
12413 
12414    return RESULT_SUCCESS;
12415 #undef FORMAT
12416 #undef FORMAT2
12417 }
12418 
12419 static char show_channels_usage[] =
12420    "Usage: dahdi show channels\n"
12421    "  Shows a list of available channels\n";
12422 
12423 static char show_channel_usage[] =
12424    "Usage: dahdi show channel <chan num>\n"
12425    "  Detailed information about a given channel\n";
12426 
12427 static char dahdi_show_status_usage[] =
12428    "Usage: dahdi show status\n"
12429    "       Shows a list of DAHDI cards with status\n";
12430 
12431 static char destroy_channel_usage[] =
12432    "Usage: dahdi destroy channel <chan num>\n"
12433    "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12434 
12435 static char dahdi_restart_usage[] =
12436    "Usage: dahdi restart\n"
12437    "  Restarts the DAHDI channels: destroys them all and then\n"
12438    "  re-reads them from chan_dahdi.conf.\n"
12439    "  Note that this will STOP any running CALL on DAHDI channels.\n"
12440    "";
12441 
12442 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
12443    { "zap", "show", "cadences", NULL },
12444    handle_dahdi_show_cadences, NULL,
12445    NULL };
12446 
12447 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
12448    { "zap", "show", "channels", NULL },
12449    dahdi_show_channels, NULL,
12450    NULL };
12451 
12452 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
12453    { "zap", "show", "channel", NULL },
12454    dahdi_show_channel, NULL,
12455    NULL };
12456 
12457 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
12458    { "zap", "destroy", "channel", NULL },
12459    dahdi_destroy_channel, NULL,
12460    NULL };
12461 
12462 static struct ast_cli_entry cli_zap_restart_deprecated = {
12463    { "zap", "restart", NULL },
12464    dahdi_restart_cmd, NULL,
12465    NULL };
12466 
12467 static struct ast_cli_entry cli_zap_show_status_deprecated = {
12468    { "zap", "show", "status", NULL },
12469    dahdi_show_status, NULL,
12470    NULL };
12471 
12472 static struct ast_cli_entry dahdi_cli[] = {
12473    { { "dahdi", "show", "cadences", NULL },
12474    handle_dahdi_show_cadences, "List cadences",
12475    dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
12476 
12477    { { "dahdi", "show", "channels", NULL},
12478    dahdi_show_channels, "Show active DAHDI channels",
12479    show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
12480 
12481    { { "dahdi", "show", "channel", NULL},
12482    dahdi_show_channel, "Show information on a channel",
12483    show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
12484 
12485    { { "dahdi", "destroy", "channel", NULL},
12486    dahdi_destroy_channel, "Destroy a channel",
12487    destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
12488 
12489    { { "dahdi", "restart", NULL},
12490    dahdi_restart_cmd, "Fully restart DAHDI channels",
12491    dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
12492 
12493    { { "dahdi", "show", "status", NULL},
12494    dahdi_show_status, "Show all DAHDI cards status",
12495    dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
12496 };
12497 
12498 #define TRANSFER  0
12499 #define HANGUP    1
12500 
12501 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12502 {
12503    if (p) {
12504       switch (mode) {
12505          case TRANSFER:
12506             p->fake_event = DAHDI_EVENT_WINKFLASH;
12507             break;
12508          case HANGUP:
12509             p->fake_event = DAHDI_EVENT_ONHOOK;
12510             break;
12511          default:
12512             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
12513       }
12514    }
12515    return 0;
12516 }
12517 static struct dahdi_pvt *find_channel(int channel)
12518 {
12519    struct dahdi_pvt *p = iflist;
12520    while (p) {
12521       if (p->channel == channel) {
12522          break;
12523       }
12524       p = p->next;
12525    }
12526    return p;
12527 }
12528 
12529 #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)
12530 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12531 
12532 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
12533 {
12534    struct dahdi_pvt *p = NULL;
12535    const char *channel = local_astman_header(m, "Channel", zap_mode);
12536 
12537    if (ast_strlen_zero(channel)) {
12538       astman_send_error(s, m, "No channel specified");
12539       return 0;
12540    }
12541    if (!(p = find_channel(atoi(channel)))) {
12542       astman_send_error(s, m, "No such channel");
12543       return 0;
12544    }
12545    p->dnd = dnd;
12546    local_astman_ack(s, m, "DND", zap_mode);
12547 
12548    return 0;
12549 }
12550 
12551 static int zap_action_dndon(struct mansession *s, const struct message *m)
12552 {
12553    return __action_dnd(s, m, 1, 1);
12554 }
12555 
12556 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
12557 {
12558    return __action_dnd(s, m, 0, 1);
12559 }
12560 
12561 static int zap_action_dndoff(struct mansession *s, const struct message *m)
12562 {
12563    return __action_dnd(s, m, 1, 0);
12564 }
12565 
12566 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
12567 {
12568    return __action_dnd(s, m, 0, 0);
12569 }
12570 
12571 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
12572 {
12573    struct dahdi_pvt *p = NULL;
12574    const char *channel = local_astman_header(m, "Channel", zap_mode);
12575 
12576    if (ast_strlen_zero(channel)) {
12577       astman_send_error(s, m, "No channel specified");
12578       return 0;
12579    }
12580    if (!(p = find_channel(atoi(channel)))) {
12581       astman_send_error(s, m, "No such channel");
12582       return 0;
12583    }
12584    dahdi_fake_event(p,TRANSFER);
12585    local_astman_ack(s, m, "Transfer", zap_mode);
12586 
12587    return 0;
12588 }
12589 
12590 static int zap_action_transfer(struct mansession *s, const struct message *m)
12591 {
12592    return __action_transfer(s, m, 1);
12593 }
12594 
12595 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
12596 {
12597    return __action_transfer(s, m, 0);
12598 }
12599 
12600 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
12601 {
12602    struct dahdi_pvt *p = NULL;
12603    const char *channel = local_astman_header(m, "Channel", zap_mode);
12604 
12605    if (ast_strlen_zero(channel)) {
12606       astman_send_error(s, m, "No channel specified");
12607       return 0;
12608    }
12609    if (!(p = find_channel(atoi(channel)))) {
12610       astman_send_error(s, m, "No such channel");
12611       return 0;
12612    }
12613    dahdi_fake_event(p, HANGUP);
12614    local_astman_ack(s, m, "Hangup", zap_mode);
12615    return 0;
12616 }
12617 
12618 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
12619 {
12620    return __action_transferhangup(s, m, 1);
12621 }
12622 
12623 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
12624 {
12625    return __action_transferhangup(s, m, 0);
12626 }
12627 
12628 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
12629 {
12630    struct dahdi_pvt *p = NULL;
12631    const char *channel = local_astman_header(m, "Channel", zap_mode);
12632    const char *number = astman_get_header(m, "Number");
12633    int i;
12634 
12635    if (ast_strlen_zero(channel)) {
12636       astman_send_error(s, m, "No channel specified");
12637       return 0;
12638    }
12639    if (ast_strlen_zero(number)) {
12640       astman_send_error(s, m, "No number specified");
12641       return 0;
12642    }
12643    if (!(p = find_channel(atoi(channel)))) {
12644       astman_send_error(s, m, "No such channel");
12645       return 0;
12646    }
12647    if (!p->owner) {
12648       astman_send_error(s, m, "Channel does not have an owner");
12649       return 0;
12650    }
12651    for (i = 0; i < strlen(number); i++) {
12652       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12653 
12654       dahdi_queue_frame(p, &f, NULL); 
12655    }
12656    local_astman_ack(s, m, "DialOffHook", zap_mode);
12657 
12658    return 0;
12659 }
12660 
12661 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
12662 {
12663    return __action_dialoffhook(s, m, 1);
12664 }
12665 
12666 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
12667 {
12668    return __action_dialoffhook(s, m, 0);
12669 }
12670 
12671 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
12672 {
12673    struct dahdi_pvt *tmp = NULL;
12674    const char *id = astman_get_header(m, "ActionID");
12675    char idText[256] = "";
12676 
12677    local_astman_ack(s, m, " channel status will follow", zap_mode);
12678    if (!ast_strlen_zero(id))
12679       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12680 
12681    ast_mutex_lock(&iflock);
12682    
12683    tmp = iflist;
12684    while (tmp) {
12685       if (tmp->channel > 0) {
12686          int alarm = get_alarms(tmp);
12687          astman_append(s,
12688                   "Event: %sShowChannels\r\n"
12689                   "Channel: %d\r\n"
12690                   "Signalling: %s\r\n"
12691                   "Context: %s\r\n"
12692                   "DND: %s\r\n"
12693                   "Alarm: %s\r\n"
12694                   "%s"
12695                   "\r\n",
12696                   dahdi_chan_name,
12697                   tmp->channel, sig2str(tmp->sig), tmp->context, 
12698                   tmp->dnd ? "Enabled" : "Disabled",
12699                   alarm2str(alarm), idText);
12700       } 
12701 
12702       tmp = tmp->next;
12703    }
12704 
12705    ast_mutex_unlock(&iflock);
12706    
12707    astman_append(s, 
12708             "Event: %sShowChannelsComplete\r\n"
12709             "%s"
12710             "\r\n",
12711             dahdi_chan_name,
12712             idText);
12713    return 0;
12714 }
12715 
12716 static int zap_action_showchannels(struct mansession *s, const struct message *m)
12717 {
12718    return __action_showchannels(s, m, 1);
12719 }
12720 
12721 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
12722 {
12723    return __action_showchannels(s, m, 0);
12724 }
12725 
12726 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
12727 {
12728    if (dahdi_restart() != 0) {
12729       if (zap_mode) {
12730          astman_send_error(s, m, "Failed to restart Zap");
12731       } else {
12732          astman_send_error(s, m, "Failed to restart DAHDI");
12733       }
12734       return 1;
12735    }
12736    local_astman_ack(s, m, "Restart: Success", zap_mode);
12737    return 0;
12738 }
12739 
12740 static int zap_action_restart(struct mansession *s, const struct message *m)
12741 {
12742    return __action_restart(s, m, 1);
12743 }
12744 
12745 static int dahdi_action_restart(struct mansession *s, const struct message *m)
12746 {
12747    return __action_restart(s, m, 0);
12748 }
12749 
12750 #define local_astman_unregister(a) do { \
12751                if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12752                   ast_manager_unregister("DAHDI" a); \
12753                } \
12754                ast_manager_unregister("Zap" a); \
12755                } while (0)
12756 
12757 static int __unload_module(void)
12758 {
12759    struct dahdi_pvt *p;
12760 #ifdef HAVE_OPENR2
12761    int r;
12762 #endif
12763 #ifdef HAVE_PRI
12764    int i, j;
12765    for (i = 0; i < NUM_SPANS; i++) {
12766       if (pris[i].master != AST_PTHREADT_NULL) 
12767          pthread_cancel(pris[i].master);
12768    }
12769    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12770 
12771    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12772       ast_unregister_application(dahdi_send_keypad_facility_app);
12773    }
12774    ast_unregister_application(zap_send_keypad_facility_app);
12775 #endif
12776 #ifdef HAVE_OPENR2
12777    for (r = 0; r < NUM_SPANS; r++) {
12778       if (r2links[r].master != AST_PTHREADT_NULL) {
12779          pthread_cancel(r2links[r].master);
12780          pthread_join(r2links[r].master, NULL);
12781       }
12782    }
12783    ast_cli_unregister_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli) / sizeof(dahdi_mfcr2_cli[0]));
12784    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12785       ast_unregister_application(dahdi_accept_r2_call_app);
12786    }
12787    ast_unregister_application(zap_accept_r2_call_app);
12788 #endif
12789    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12790    local_astman_unregister("DialOffHook");
12791    local_astman_unregister("Hangup");
12792    local_astman_unregister("Transfer");
12793    local_astman_unregister("DNDoff");
12794    local_astman_unregister("DNDon");
12795    local_astman_unregister("ShowChannels");
12796    local_astman_unregister("Restart");
12797    ast_channel_unregister(chan_tech);
12798    ast_mutex_lock(&iflock);
12799    /* Hangup all interfaces if they have an owner */
12800    p = iflist;
12801    while (p) {
12802       if (p->owner)
12803          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12804       p = p->next;
12805    }
12806    ast_mutex_unlock(&iflock);
12807    ast_mutex_lock(&monlock);
12808    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12809       pthread_cancel(monitor_thread);
12810       pthread_kill(monitor_thread, SIGURG);
12811       pthread_join(monitor_thread, NULL);
12812    }
12813    monitor_thread = AST_PTHREADT_STOP;
12814    ast_mutex_unlock(&monlock);
12815 
12816    destroy_all_channels();
12817 #ifdef HAVE_PRI      
12818    for (i = 0; i < NUM_SPANS; i++) {
12819       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12820          pthread_join(pris[i].master, NULL);
12821       for (j = 0; j < NUM_DCHANS; j++) {
12822          dahdi_close_pri_fd(&(pris[i]), j);
12823       }
12824    }
12825 #endif
12826 #ifdef HAVE_OPENR2
12827    for (r = 0; r < NUM_SPANS; r++) {
12828       if (r2links[r].protocol_context) {
12829          openr2_context_delete(r2links[r].protocol_context);
12830       }
12831    }
12832 #endif
12833    ast_cond_destroy(&ss_thread_complete);
12834    return 0;
12835 }
12836 
12837 static int unload_module(void)
12838 {
12839 #ifdef HAVE_PRI      
12840    int y;
12841    for (y = 0; y < NUM_SPANS; y++)
12842       ast_mutex_destroy(&pris[y].lock);
12843 #endif
12844    return __unload_module();
12845 }
12846 
12847 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
12848 {
12849    char *c, *chan;
12850    int x, start, finish;
12851    struct dahdi_pvt *tmp;
12852 #ifdef HAVE_PRI
12853    struct dahdi_pri *pri;
12854    int trunkgroup, y;
12855 #endif
12856    
12857    if ((reload == 0) && (conf->chan.sig < 0)) {
12858       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12859       return -1;
12860    }
12861 
12862    c = ast_strdupa(value);
12863 
12864 #ifdef HAVE_PRI
12865    pri = NULL;
12866    if (iscrv) {
12867       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
12868          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12869          return -1;
12870       }
12871       if (trunkgroup < 1) {
12872          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12873          return -1;
12874       }
12875       c += y;
12876       for (y = 0; y < NUM_SPANS; y++) {
12877          if (pris[y].trunkgroup == trunkgroup) {
12878             pri = pris + y;
12879             break;
12880          }
12881       }
12882       if (!pri) {
12883          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12884          return -1;
12885       }
12886    }
12887 #endif         
12888 
12889    while ((chan = strsep(&c, ","))) {
12890       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
12891          /* Range */
12892       } else if (sscanf(chan, "%30d", &start)) {
12893          /* Just one */
12894          finish = start;
12895       } else if (!strcasecmp(chan, "pseudo")) {
12896          finish = start = CHAN_PSEUDO;
12897          if (found_pseudo)
12898             *found_pseudo = 1;
12899       } else {
12900          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12901          return -1;
12902       }
12903       if (finish < start) {
12904          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12905          x = finish;
12906          finish = start;
12907          start = x;
12908       }
12909 
12910       for (x = start; x <= finish; x++) {
12911 #ifdef HAVE_PRI
12912          tmp = mkintf(x, conf, pri, reload);
12913 #else       
12914          tmp = mkintf(x, conf, NULL, reload);
12915 #endif         
12916 
12917          if (tmp) {
12918             if (option_verbose > 2) {
12919 #ifdef HAVE_PRI
12920                if (pri)
12921                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12922                else
12923 #endif
12924                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12925             }
12926          } else {
12927             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12928                (reload == 1) ? "reconfigure" : "register", value);
12929             return -1;
12930          }
12931       }
12932 #ifdef HAVE_OPENR2
12933       if (reload != 1 && r2links[mfcr2_cur_context_index].protocol_context) {
12934          mfcr2_cur_context_index++;
12935       }  
12936 #endif
12937    }
12938 
12939    return 0;
12940 }
12941 
12942 /** The length of the parameters list of 'dahdichan'. 
12943  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
12944 #define MAX_CHANLIST_LEN 80
12945 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
12946 {
12947    struct dahdi_pvt *tmp;
12948    int y;
12949    int found_pseudo = 0;
12950         char dahdichan[MAX_CHANLIST_LEN] = {};
12951 
12952    for (; v; v = v->next) {
12953       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12954          continue;
12955 
12956       /* Create the interface list */
12957       if (!strcasecmp(v->name, "channel")
12958 #ifdef HAVE_PRI
12959           || !strcasecmp(v->name, "crv")
12960 #endif         
12961          ) {
12962          int iscrv;
12963          if (skipchannels)
12964             continue;
12965          iscrv = !strcasecmp(v->name, "crv");
12966          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12967                return -1;
12968       } else if (!strcasecmp(v->name, "buffers")) {
12969          int res;
12970          char policy[21] = "";
12971 
12972          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
12973          if (res != 2) {
12974             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
12975             confp->chan.buf_no = numbufs;
12976             continue;
12977          }
12978          if (confp->chan.buf_no < 0)
12979             confp->chan.buf_no = numbufs;
12980          if (!strcasecmp(policy, "full")) {
12981             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
12982          } else if (!strcasecmp(policy, "immediate")) {
12983             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
12984          } else {
12985             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
12986          }
12987       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
12988          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
12989          if (v->name[0] == 'z' || v->name[0] == 'Z') {
12990             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
12991          }
12992       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12993          if (ast_true(v->value))
12994             confp->chan.usedistinctiveringdetection = 1;
12995       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12996          if (ast_true(v->value))
12997             distinctiveringaftercid = 1;
12998       } else if (!strcasecmp(v->name, "dring1context")) {
12999          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
13000       } else if (!strcasecmp(v->name, "dring2context")) {
13001          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
13002       } else if (!strcasecmp(v->name, "dring3context")) {
13003          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
13004       } else if (!strcasecmp(v->name, "dring1")) {
13005          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
13006       } else if (!strcasecmp(v->name, "dring2")) {
13007          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
13008       } else if (!strcasecmp(v->name, "dring3")) {
13009          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
13010       } else if (!strcasecmp(v->name, "usecallerid")) {
13011          confp->chan.use_callerid = ast_true(v->value);
13012       } else if (!strcasecmp(v->name, "cidsignalling")) {
13013          if (!strcasecmp(v->value, "bell"))
13014             confp->chan.cid_signalling = CID_SIG_BELL;
13015          else if (!strcasecmp(v->value, "v23"))
13016             confp->chan.cid_signalling = CID_SIG_V23;
13017          else if (!strcasecmp(v->value, "dtmf"))
13018             confp->chan.cid_signalling = CID_SIG_DTMF;
13019          else if (!strcasecmp(v->value, "smdi"))
13020             confp->chan.cid_signalling = CID_SIG_SMDI;
13021          else if (!strcasecmp(v->value, "v23_jp"))
13022             confp->chan.cid_signalling = CID_SIG_V23_JP;
13023          else if (ast_true(v->value))
13024             confp->chan.cid_signalling = CID_SIG_BELL;
13025       } else if (!strcasecmp(v->name, "cidstart")) {
13026          if (!strcasecmp(v->value, "ring"))
13027             confp->chan.cid_start = CID_START_RING;
13028          else if (!strcasecmp(v->value, "polarity"))
13029             confp->chan.cid_start = CID_START_POLARITY;
13030          else if (!strcasecmp(v->value, "dtmf"))
13031             confp->chan.cid_start = CID_START_DTMF_NOALERT;
13032          else if (ast_true(v->value))
13033             confp->chan.cid_start = CID_START_RING;
13034       } else if (!strcasecmp(v->name, "threewaycalling")) {
13035          confp->chan.threewaycalling = ast_true(v->value);
13036       } else if (!strcasecmp(v->name, "cancallforward")) {
13037          confp->chan.cancallforward = ast_true(v->value);
13038       } else if (!strcasecmp(v->name, "relaxdtmf")) {
13039          if (ast_true(v->value)) 
13040             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
13041          else
13042             confp->chan.dtmfrelax = 0;
13043       } else if (!strcasecmp(v->name, "mailbox")) {
13044          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
13045       } else if (!strcasecmp(v->name, "hasvoicemail")) {
13046          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
13047             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
13048          }
13049       } else if (!strcasecmp(v->name, "adsi")) {
13050          confp->chan.adsi = ast_true(v->value);
13051       } else if (!strcasecmp(v->name, "usesmdi")) {
13052          confp->chan.use_smdi = ast_true(v->value);
13053       } else if (!strcasecmp(v->name, "smdiport")) {
13054          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
13055       } else if (!strcasecmp(v->name, "transfer")) {
13056          confp->chan.transfer = ast_true(v->value);
13057       } else if (!strcasecmp(v->name, "canpark")) {
13058          confp->chan.canpark = ast_true(v->value);
13059       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
13060          confp->chan.echocanbridged = ast_true(v->value);
13061       } else if (!strcasecmp(v->name, "busydetect")) {
13062          confp->chan.busydetect = ast_true(v->value);
13063       } else if (!strcasecmp(v->name, "busycount")) {
13064          confp->chan.busycount = atoi(v->value);
13065       } else if (!strcasecmp(v->name, "silencethreshold")) {
13066             confp->chan.silencethreshold = atoi(v->value);
13067       } else if (!strcasecmp(v->name, "busycompare")) {
13068             confp->chan.busycompare = ast_true(v->value);
13069       } else if (!strcasecmp(v->name, "busypattern")) {
13070          int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
13071          if (count == 1)
13072             confp->chan.busyquietlength = 0;
13073          else if (count < 1)
13074                ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
13075       } else if (!strcasecmp(v->name, "busyfuzziness")) {
13076             confp->chan.busyfuzziness = atoi(v->value);
13077       } else if (!strcasecmp(v->name, "callprogress")) {
13078          if (ast_true(v->value))
13079             confp->chan.callprogress |= 1;
13080          else
13081             confp->chan.callprogress &= ~1;
13082       } else if (!strcasecmp(v->name, "faxdetect")) {
13083          if (!strcasecmp(v->value, "incoming")) {
13084             confp->chan.callprogress |= 4;
13085             confp->chan.callprogress &= ~2;
13086          } else if (!strcasecmp(v->value, "outgoing")) {
13087             confp->chan.callprogress &= ~4;
13088             confp->chan.callprogress |= 2;
13089          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13090             confp->chan.callprogress |= 6;
13091          else
13092             confp->chan.callprogress &= ~6;
13093       } else if (!strcasecmp(v->name, "echocancel")) {
13094          if (!ast_strlen_zero(v->value)) {
13095             y = atoi(v->value);
13096          } else
13097             y = 0;
13098          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
13099             confp->chan.echocancel = y;
13100          else {
13101             confp->chan.echocancel = ast_true(v->value);
13102             if (confp->chan.echocancel)
13103                confp->chan.echocancel=128;
13104          }
13105       } else if (!strcasecmp(v->name, "echotraining")) {
13106          if (sscanf(v->value, "%30d", &y) == 1) {
13107             if ((y < 10) || (y > 4000)) {
13108                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
13109             } else {
13110                confp->chan.echotraining = y;
13111             }
13112          } else if (ast_true(v->value)) {
13113             confp->chan.echotraining = 400;
13114          } else
13115             confp->chan.echotraining = 0;
13116       } else if (!strcasecmp(v->name, "hidecallerid")) {
13117          confp->chan.hidecallerid = ast_true(v->value);
13118       } else if (!strcasecmp(v->name, "hidecalleridname")) {
13119          confp->chan.hidecalleridname = ast_true(v->value);
13120       } else if (!strcasecmp(v->name, "pulsedial")) {
13121          confp->chan.pulse = ast_true(v->value);
13122       } else if (!strcasecmp(v->name, "callreturn")) {
13123          confp->chan.callreturn = ast_true(v->value);
13124       } else if (!strcasecmp(v->name, "callwaiting")) {
13125          confp->chan.callwaiting = ast_true(v->value);
13126       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13127          confp->chan.callwaitingcallerid = ast_true(v->value);
13128       } else if (!strcasecmp(v->name, "context")) {
13129          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13130       } else if (!strcasecmp(v->name, "language")) {
13131          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13132       } else if (!strcasecmp(v->name, "progzone")) {
13133          ast_copy_string(progzone, v->value, sizeof(progzone));
13134       } else if (!strcasecmp(v->name, "mohinterpret") 
13135          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13136          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13137       } else if (!strcasecmp(v->name, "mohsuggest")) {
13138          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13139       } else if (!strcasecmp(v->name, "stripmsd")) {
13140          confp->chan.stripmsd = atoi(v->value);
13141       } else if (!strcasecmp(v->name, "jitterbuffers")) {
13142          numbufs = atoi(v->value);
13143       } else if (!strcasecmp(v->name, "group")) {
13144          confp->chan.group = ast_get_group(v->value);
13145       } else if (!strcasecmp(v->name, "callgroup")) {
13146          confp->chan.callgroup = ast_get_group(v->value);
13147       } else if (!strcasecmp(v->name, "pickupgroup")) {
13148          confp->chan.pickupgroup = ast_get_group(v->value);
13149       } else if (!strcasecmp(v->name, "immediate")) {
13150          confp->chan.immediate = ast_true(v->value);
13151       } else if (!strcasecmp(v->name, "transfertobusy")) {
13152          confp->chan.transfertobusy = ast_true(v->value);
13153       } else if (!strcasecmp(v->name, "rxgain")) {
13154          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
13155             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
13156          }
13157       } else if (!strcasecmp(v->name, "txgain")) {
13158          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
13159             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
13160          }
13161       } else if (!strcasecmp(v->name, "tonezone")) {
13162          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
13163             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
13164          }
13165       } else if (!strcasecmp(v->name, "callerid")) {
13166          if (!strcasecmp(v->value, "asreceived")) {
13167             confp->chan.cid_num[0] = '\0';
13168             confp->chan.cid_name[0] = '\0';
13169          } else {
13170             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13171          } 
13172       } else if (!strcasecmp(v->name, "fullname")) {
13173          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13174       } else if (!strcasecmp(v->name, "cid_number")) {
13175          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13176       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
13177          confp->chan.dahditrcallerid = ast_true(v->value);
13178          if (strstr(v->name, "zap")) {
13179             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
13180          }
13181       } else if (!strcasecmp(v->name, "restrictcid")) {
13182          confp->chan.restrictcid = ast_true(v->value);
13183       } else if (!strcasecmp(v->name, "usecallingpres")) {
13184          confp->chan.use_callingpres = ast_true(v->value);
13185       } else if (!strcasecmp(v->name, "accountcode")) {
13186          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13187       } else if (!strcasecmp(v->name, "amaflags")) {
13188          y = ast_cdr_amaflags2int(v->value);
13189          if (y < 0) 
13190             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
13191          else
13192             confp->chan.amaflags = y;
13193       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13194          confp->chan.polarityonanswerdelay = atoi(v->value);
13195       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13196          confp->chan.answeronpolarityswitch = ast_true(v->value);
13197       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13198          confp->chan.hanguponpolarityswitch = ast_true(v->value);
13199       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13200          confp->chan.sendcalleridafter = atoi(v->value);
13201       } else if (reload != 1) {
13202           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13203             confp->chan.outsigmod = -1;
13204             if (!strcasecmp(v->value, "em")) {
13205                confp->chan.sig = SIG_EM;
13206             } else if (!strcasecmp(v->value, "em_e1")) {
13207                confp->chan.sig = SIG_EM_E1;
13208             } else if (!strcasecmp(v->value, "em_w")) {
13209                confp->chan.sig = SIG_EMWINK;
13210                confp->chan.radio = 0;
13211             } else if (!strcasecmp(v->value, "fxs_ls")) {
13212                confp->chan.sig = SIG_FXSLS;
13213                confp->chan.radio = 0;
13214             } else if (!strcasecmp(v->value, "fxs_gs")) {
13215                confp->chan.sig = SIG_FXSGS;
13216                confp->chan.radio = 0;
13217             } else if (!strcasecmp(v->value, "fxs_ks")) {
13218                confp->chan.sig = SIG_FXSKS;
13219                confp->chan.radio = 0;
13220             } else if (!strcasecmp(v->value, "fxo_ls")) {
13221                confp->chan.sig = SIG_FXOLS;
13222                confp->chan.radio = 0;
13223             } else if (!strcasecmp(v->value, "fxo_gs")) {
13224                confp->chan.sig = SIG_FXOGS;
13225                confp->chan.radio = 0;
13226             } else if (!strcasecmp(v->value, "fxo_ks")) {
13227                confp->chan.sig = SIG_FXOKS;
13228                confp->chan.radio = 0;
13229             } else if (!strcasecmp(v->value, "fxs_rx")) {
13230                confp->chan.sig = SIG_FXSKS;
13231                confp->chan.radio = 1;
13232             } else if (!strcasecmp(v->value, "fxo_rx")) {
13233                confp->chan.sig = SIG_FXOLS;
13234                confp->chan.radio = 1;
13235             } else if (!strcasecmp(v->value, "fxs_tx")) {
13236                confp->chan.sig = SIG_FXSLS;
13237                confp->chan.radio = 1;
13238             } else if (!strcasecmp(v->value, "fxo_tx")) {
13239                confp->chan.sig = SIG_FXOGS;
13240                confp->chan.radio = 1;
13241             } else if (!strcasecmp(v->value, "em_rx")) {
13242                confp->chan.sig = SIG_EM;
13243                confp->chan.radio = 1;
13244             } else if (!strcasecmp(v->value, "em_tx")) {
13245                confp->chan.sig = SIG_EM;
13246                confp->chan.radio = 1;
13247             } else if (!strcasecmp(v->value, "em_rxtx")) {
13248                confp->chan.sig = SIG_EM;
13249                confp->chan.radio = 2;
13250             } else if (!strcasecmp(v->value, "em_txrx")) {
13251                confp->chan.sig = SIG_EM;
13252                confp->chan.radio = 2;
13253             } else if (!strcasecmp(v->value, "sf")) {
13254                confp->chan.sig = SIG_SF;
13255                confp->chan.radio = 0;
13256             } else if (!strcasecmp(v->value, "sf_w")) {
13257                confp->chan.sig = SIG_SFWINK;
13258                confp->chan.radio = 0;
13259             } else if (!strcasecmp(v->value, "sf_featd")) {
13260                confp->chan.sig = SIG_FEATD;
13261                confp->chan.radio = 0;
13262             } else if (!strcasecmp(v->value, "sf_featdmf")) {
13263                confp->chan.sig = SIG_FEATDMF;
13264                confp->chan.radio = 0;
13265             } else if (!strcasecmp(v->value, "sf_featb")) {
13266                confp->chan.sig = SIG_SF_FEATB;
13267                confp->chan.radio = 0;
13268             } else if (!strcasecmp(v->value, "sf")) {
13269                confp->chan.sig = SIG_SF;
13270                confp->chan.radio = 0;
13271             } else if (!strcasecmp(v->value, "sf_rx")) {
13272                confp->chan.sig = SIG_SF;
13273                confp->chan.radio = 1;
13274             } else if (!strcasecmp(v->value, "sf_tx")) {
13275                confp->chan.sig = SIG_SF;
13276                confp->chan.radio = 1;
13277             } else if (!strcasecmp(v->value, "sf_rxtx")) {
13278                confp->chan.sig = SIG_SF;
13279                confp->chan.radio = 2;
13280             } else if (!strcasecmp(v->value, "sf_txrx")) {
13281                confp->chan.sig = SIG_SF;
13282                confp->chan.radio = 2;
13283             } else if (!strcasecmp(v->value, "featd")) {
13284                confp->chan.sig = SIG_FEATD;
13285                confp->chan.radio = 0;
13286             } else if (!strcasecmp(v->value, "featdmf")) {
13287                confp->chan.sig = SIG_FEATDMF;
13288                confp->chan.radio = 0;
13289             } else if (!strcasecmp(v->value, "featdmf_ta")) {
13290                confp->chan.sig = SIG_FEATDMF_TA;
13291                confp->chan.radio = 0;
13292             } else if (!strcasecmp(v->value, "e911")) {
13293                confp->chan.sig = SIG_E911;
13294                confp->chan.radio = 0;
13295             } else if (!strcasecmp(v->value, "fgccama")) {
13296                confp->chan.sig = SIG_FGC_CAMA;
13297                confp->chan.radio = 0;
13298             } else if (!strcasecmp(v->value, "fgccamamf")) {
13299                confp->chan.sig = SIG_FGC_CAMAMF;
13300                confp->chan.radio = 0;
13301             } else if (!strcasecmp(v->value, "featb")) {
13302                confp->chan.sig = SIG_FEATB;
13303                confp->chan.radio = 0;
13304 #ifdef HAVE_OPENR2
13305             } else if (!strcasecmp(v->value, "mfcr2")) {
13306                confp->chan.sig = SIG_MFCR2;
13307 #endif
13308 #ifdef HAVE_PRI
13309             } else if (!strcasecmp(v->value, "pri_net")) {
13310                confp->chan.radio = 0;
13311                confp->chan.sig = SIG_PRI;
13312                confp->pri.nodetype = PRI_NETWORK;
13313             } else if (!strcasecmp(v->value, "pri_cpe")) {
13314                confp->chan.sig = SIG_PRI;
13315                confp->chan.radio = 0;
13316                confp->pri.nodetype = PRI_CPE;
13317             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13318                confp->chan.sig = SIG_GR303FXOKS;
13319                confp->chan.radio = 0;
13320                confp->pri.nodetype = PRI_NETWORK;
13321             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13322                confp->chan.sig = SIG_GR303FXSKS;
13323                confp->chan.radio = 0;
13324                confp->pri.nodetype = PRI_CPE;
13325 #endif
13326             } else {
13327                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13328             }
13329           } else if (!strcasecmp(v->name, "outsignalling")) {
13330             if (!strcasecmp(v->value, "em")) {
13331                confp->chan.outsigmod = SIG_EM;
13332             } else if (!strcasecmp(v->value, "em_e1")) {
13333                confp->chan.outsigmod = SIG_EM_E1;
13334             } else if (!strcasecmp(v->value, "em_w")) {
13335                confp->chan.outsigmod = SIG_EMWINK;
13336             } else if (!strcasecmp(v->value, "sf")) {
13337                confp->chan.outsigmod = SIG_SF;
13338             } else if (!strcasecmp(v->value, "sf_w")) {
13339                confp->chan.outsigmod = SIG_SFWINK;
13340             } else if (!strcasecmp(v->value, "sf_featd")) {
13341                confp->chan.outsigmod = SIG_FEATD;
13342             } else if (!strcasecmp(v->value, "sf_featdmf")) {
13343                confp->chan.outsigmod = SIG_FEATDMF;
13344             } else if (!strcasecmp(v->value, "sf_featb")) {
13345                confp->chan.outsigmod = SIG_SF_FEATB;
13346             } else if (!strcasecmp(v->value, "sf")) {
13347                confp->chan.outsigmod = SIG_SF;
13348             } else if (!strcasecmp(v->value, "featd")) {
13349                confp->chan.outsigmod = SIG_FEATD;
13350             } else if (!strcasecmp(v->value, "featdmf")) {
13351                confp->chan.outsigmod = SIG_FEATDMF;
13352             } else if (!strcasecmp(v->value, "featdmf_ta")) {
13353                confp->chan.outsigmod = SIG_FEATDMF_TA;
13354             } else if (!strcasecmp(v->value, "e911")) {
13355                confp->chan.outsigmod = SIG_E911;
13356             } else if (!strcasecmp(v->value, "fgccama")) {
13357                confp->chan.outsigmod = SIG_FGC_CAMA;
13358             } else if (!strcasecmp(v->value, "fgccamamf")) {
13359                confp->chan.outsigmod = SIG_FGC_CAMAMF;
13360             } else if (!strcasecmp(v->value, "featb")) {
13361                confp->chan.outsigmod = SIG_FEATB;
13362             } else {
13363                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
13364             }
13365 #ifdef HAVE_PRI
13366          } else if (!strcasecmp(v->name, "pridialplan")) {
13367             if (!strcasecmp(v->value, "national")) {
13368                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13369             } else if (!strcasecmp(v->value, "unknown")) {
13370                confp->pri.dialplan = PRI_UNKNOWN + 1;
13371             } else if (!strcasecmp(v->value, "private")) {
13372                confp->pri.dialplan = PRI_PRIVATE + 1;
13373             } else if (!strcasecmp(v->value, "international")) {
13374                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13375             } else if (!strcasecmp(v->value, "local")) {
13376                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13377             } else if (!strcasecmp(v->value, "dynamic")) {
13378                confp->pri.dialplan = -1;
13379             } else {
13380                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13381             }
13382          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13383             if (!strcasecmp(v->value, "national")) {
13384                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13385             } else if (!strcasecmp(v->value, "unknown")) {
13386                confp->pri.localdialplan = PRI_UNKNOWN + 1;
13387             } else if (!strcasecmp(v->value, "private")) {
13388                confp->pri.localdialplan = PRI_PRIVATE + 1;
13389             } else if (!strcasecmp(v->value, "international")) {
13390                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13391             } else if (!strcasecmp(v->value, "local")) {
13392                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13393             } else if (!strcasecmp(v->value, "dynamic")) {
13394                confp->pri.localdialplan = -1;
13395             } else {
13396                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13397             }
13398          } else if (!strcasecmp(v->name, "switchtype")) {
13399             if (!strcasecmp(v->value, "national")) 
13400                confp->pri.switchtype = PRI_SWITCH_NI2;
13401             else if (!strcasecmp(v->value, "ni1"))
13402                confp->pri.switchtype = PRI_SWITCH_NI1;
13403             else if (!strcasecmp(v->value, "dms100"))
13404                confp->pri.switchtype = PRI_SWITCH_DMS100;
13405             else if (!strcasecmp(v->value, "4ess"))
13406                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
13407             else if (!strcasecmp(v->value, "5ess"))
13408                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13409             else if (!strcasecmp(v->value, "euroisdn"))
13410                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13411             else if (!strcasecmp(v->value, "qsig"))
13412                confp->pri.switchtype = PRI_SWITCH_QSIG;
13413             else {
13414                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13415                return -1;
13416             }
13417          } else if (!strcasecmp(v->name, "nsf")) {
13418             if (!strcasecmp(v->value, "sdn"))
13419                confp->pri.nsf = PRI_NSF_SDN;
13420             else if (!strcasecmp(v->value, "megacom"))
13421                confp->pri.nsf = PRI_NSF_MEGACOM;
13422             else if (!strcasecmp(v->value, "tollfreemegacom"))
13423                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
13424             else if (!strcasecmp(v->value, "accunet"))
13425                confp->pri.nsf = PRI_NSF_ACCUNET;
13426             else if (!strcasecmp(v->value, "none"))
13427                confp->pri.nsf = PRI_NSF_NONE;
13428             else {
13429                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13430                confp->pri.nsf = PRI_NSF_NONE;
13431             }
13432          } else if (!strcasecmp(v->name, "priindication")) {
13433             if (!strcasecmp(v->value, "outofband"))
13434                confp->chan.priindication_oob = 1;
13435             else if (!strcasecmp(v->value, "inband"))
13436                confp->chan.priindication_oob = 0;
13437             else
13438                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
13439                   v->value, v->lineno);
13440          } else if (!strcasecmp(v->name, "priexclusive")) {
13441             confp->chan.priexclusive = ast_true(v->value);
13442          } else if (!strcasecmp(v->name, "internationalprefix")) {
13443             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13444          } else if (!strcasecmp(v->name, "nationalprefix")) {
13445             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13446          } else if (!strcasecmp(v->name, "localprefix")) {
13447             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13448          } else if (!strcasecmp(v->name, "privateprefix")) {
13449             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13450          } else if (!strcasecmp(v->name, "unknownprefix")) {
13451             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13452          } else if (!strcasecmp(v->name, "resetinterval")) {
13453             if (!strcasecmp(v->value, "never"))
13454                confp->pri.resetinterval = -1;
13455             else if (atoi(v->value) >= 60)
13456                confp->pri.resetinterval = atoi(v->value);
13457             else
13458                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13459                   v->value, v->lineno);
13460          } else if (!strcasecmp(v->name, "minunused")) {
13461             confp->pri.minunused = atoi(v->value);
13462          } else if (!strcasecmp(v->name, "minidle")) {
13463             confp->pri.minidle = atoi(v->value); 
13464          } else if (!strcasecmp(v->name, "idleext")) {
13465             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13466          } else if (!strcasecmp(v->name, "idledial")) {
13467             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13468          } else if (!strcasecmp(v->name, "overlapdial")) {
13469             if (ast_true(v->value)) {
13470                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13471             } else if (!strcasecmp(v->value, "incoming")) {
13472                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
13473             } else if (!strcasecmp(v->value, "outgoing")) {
13474                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
13475             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
13476                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
13477             } else {
13478                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
13479             }
13480 #ifdef HAVE_PRI_INBANDDISCONNECT
13481          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13482             confp->pri.inbanddisconnect = ast_true(v->value);
13483 #endif
13484          } else if (!strcasecmp(v->name, "pritimer")) {
13485 #ifdef PRI_GETSET_TIMERS
13486             char tmp[20];
13487             char *timerc;
13488             char *c;
13489             int timer;
13490             int timeridx;
13491 
13492             ast_copy_string(tmp, v->value, sizeof(tmp));
13493             c = tmp;
13494             timerc = strsep(&c, ",");
13495             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
13496                timeridx = pri_timer2idx(timerc);
13497                timer = atoi(c);
13498                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
13499                   ast_log(LOG_WARNING,
13500                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
13501                      v->lineno);
13502                } else if (!timer) {
13503                   ast_log(LOG_WARNING,
13504                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
13505                      c, timerc, v->lineno);
13506                } else {
13507                   pritimers[timeridx] = timer;
13508                }
13509             } else {
13510                ast_log(LOG_WARNING,
13511                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
13512                   v->value, v->lineno);
13513             }
13514 #endif /* PRI_GETSET_TIMERS */
13515          } else if (!strcasecmp(v->name, "facilityenable")) {
13516             confp->pri.facilityenable = ast_true(v->value);
13517 #endif /* HAVE_PRI */
13518 #ifdef HAVE_OPENR2
13519          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
13520             ast_copy_string(mfcr2_cur_r2proto_file, v->value, sizeof(mfcr2_cur_r2proto_file));
13521             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY  KNOW WHAT YOU ARE DOING*.\n", mfcr2_cur_r2proto_file);
13522          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
13523             ast_copy_string(mfcr2_cur_logdir, v->value, sizeof(mfcr2_cur_logdir));
13524          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
13525             mfcr2_cur_variant = openr2_proto_get_variant(v->value);
13526             if (OR2_VAR_UNKNOWN == mfcr2_cur_variant) {
13527                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d.\n", v->value, v->lineno);
13528             }
13529          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
13530             mfcr2_cur_mfback_timeout = atoi(v->value);
13531             if (!mfcr2_cur_mfback_timeout) {
13532                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
13533                mfcr2_cur_mfback_timeout = -1;
13534             } else if (mfcr2_cur_mfback_timeout > 0 && mfcr2_cur_mfback_timeout < 500) {
13535                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
13536             }
13537          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
13538             mfcr2_cur_metering_pulse_timeout = atoi(v->value);
13539             if (mfcr2_cur_metering_pulse_timeout > 500) {
13540                ast_log(LOG_WARNING, "mfcr2_metering_pulse_timeout greater than 500ms is not recommended, you have been warned!\n");
13541             }
13542 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
13543          } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
13544             mfcr2_cur_dtmf_detection = ast_true(v->value) ? 1 : 0;
13545          } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
13546             mfcr2_cur_dtmf_dialing = ast_true(v->value) ? 1 : 0;
13547          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
13548             mfcr2_cur_dtmf_time_on = atoi(v->value);
13549          } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
13550             mfcr2_cur_dtmf_time_off = atoi(v->value);
13551 #endif
13552          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
13553             mfcr2_cur_get_ani_first = ast_true(v->value) ? 1 : 0;
13554          } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
13555             mfcr2_cur_skip_category = ast_true(v->value) ? 1 : 0;
13556          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
13557             mfcr2_cur_double_answer = ast_true(v->value) ? 1 : 0;
13558          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
13559             mfcr2_cur_accept_on_offer = ast_true(v->value) ? 1 : 0;
13560          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
13561             mfcr2_cur_charge_calls = ast_true(v->value) ? 1 : 0;
13562          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
13563             mfcr2_cur_allow_collect_calls = ast_true(v->value) ? 1 : 0;
13564          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
13565             mfcr2_cur_forced_release= ast_true(v->value) ? 1 : 0;
13566          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
13567             mfcr2_cur_immediate_accept = ast_true(v->value) ? 1 : 0;
13568          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
13569             mfcr2_cur_call_files = ast_true(v->value) ? 1 : 0;
13570          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
13571             mfcr2_cur_max_ani = atoi(v->value);
13572             if (mfcr2_cur_max_ani >= AST_MAX_EXTENSION) {
13573                mfcr2_cur_max_ani = AST_MAX_EXTENSION - 1;
13574             }
13575          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
13576             mfcr2_cur_max_dnis = atoi(v->value);
13577             if (mfcr2_cur_max_dnis >= AST_MAX_EXTENSION) {
13578                mfcr2_cur_max_dnis = AST_MAX_EXTENSION - 1;
13579             }
13580          } else if (!strcasecmp(v->name, "mfcr2_category")) {
13581             mfcr2_cur_category = openr2_proto_get_category(v->value);
13582             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == mfcr2_cur_category) {
13583                mfcr2_cur_category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
13584                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 
13585                      v->value, v->lineno);
13586             }
13587          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
13588             openr2_log_level_t tmplevel;
13589             char *toklevel = NULL;
13590             char *saveptr = NULL;
13591             char *logval = ast_strdupa(v->value);
13592             toklevel = strtok_r(logval, ",", &saveptr);
13593             if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13594                ast_log(LOG_WARNING, "Invalid MFC/R2 logging level '%s' at line %d.\n", v->value, v->lineno);
13595             } else if (OR2_LOG_NOTHING == tmplevel) {
13596                mfcr2_cur_loglevel = tmplevel;
13597             } else {
13598                mfcr2_cur_loglevel |= tmplevel;
13599                while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
13600                   if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
13601                      ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", toklevel, v->lineno);
13602                      continue;
13603                   }
13604                   mfcr2_cur_loglevel |= tmplevel;
13605                }
13606             }
13607 #endif /* HAVE_OPENR2 */
13608 
13609          } else if (!strcasecmp(v->name, "cadence")) {
13610             /* setup to scan our argument */
13611             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13612             int i;
13613             struct dahdi_ring_cadence new_cadence;
13614             int cid_location = -1;
13615             int firstcadencepos = 0;
13616             char original_args[80];
13617             int cadence_is_ok = 1;
13618 
13619             ast_copy_string(original_args, v->value, sizeof(original_args));
13620             /* 16 cadences allowed (8 pairs) */
13621             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
13622    
13623             /* Cadence must be even (on/off) */
13624             if (element_count % 2 == 1) {
13625                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13626                cadence_is_ok = 0;
13627             }
13628    
13629             /* Ring cadences cannot be negative */
13630             for (i = 0; i < element_count; i++) {
13631                if (c[i] == 0) {
13632                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13633                   cadence_is_ok = 0;
13634                   break;
13635                } else if (c[i] < 0) {
13636                   if (i % 2 == 1) {
13637                      /* Silence duration, negative possibly okay */
13638                      if (cid_location == -1) {
13639                         cid_location = i;
13640                         c[i] *= -1;
13641                      } else {
13642                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13643                         cadence_is_ok = 0;
13644                         break;
13645                      }
13646                   } else {
13647                      if (firstcadencepos == 0) {
13648                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
13649                                  /* duration will be passed negative to the DAHDI driver */
13650                      } else {
13651                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13652                         cadence_is_ok = 0;
13653                         break;
13654                      }
13655                   }
13656                }
13657             }
13658    
13659             /* Substitute our scanned cadence */
13660             for (i = 0; i < 16; i++) {
13661                new_cadence.ringcadence[i] = c[i];
13662             }
13663    
13664             if (cadence_is_ok) {
13665                /* ---we scanned it without getting annoyed; now some sanity checks--- */
13666                if (element_count < 2) {
13667                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13668                } else {
13669                   if (cid_location == -1) {
13670                      /* user didn't say; default to first pause */
13671                      cid_location = 1;
13672                   } else {
13673                      /* convert element_index to cidrings value */
13674                      cid_location = (cid_location + 1) / 2;
13675                   }
13676                   /* ---we like their cadence; try to install it--- */
13677                   if (!user_has_defined_cadences++)
13678                      /* this is the first user-defined cadence; clear the default user cadences */
13679                      num_cadence = 0;
13680                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
13681                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13682                   else {
13683                      cadences[num_cadence] = new_cadence;
13684                      cidrings[num_cadence++] = cid_location;
13685                      if (option_verbose > 2)
13686                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13687                   }
13688                }
13689             }
13690          } else if (!strcasecmp(v->name, "ringtimeout")) {
13691             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13692          } else if (!strcasecmp(v->name, "prewink")) {
13693             confp->timing.prewinktime = atoi(v->value);
13694          } else if (!strcasecmp(v->name, "preflash")) {
13695             confp->timing.preflashtime = atoi(v->value);
13696          } else if (!strcasecmp(v->name, "wink")) {
13697             confp->timing.winktime = atoi(v->value);
13698          } else if (!strcasecmp(v->name, "flash")) {
13699             confp->timing.flashtime = atoi(v->value);
13700          } else if (!strcasecmp(v->name, "start")) {
13701             confp->timing.starttime = atoi(v->value);
13702          } else if (!strcasecmp(v->name, "rxwink")) {
13703             confp->timing.rxwinktime = atoi(v->value);
13704          } else if (!strcasecmp(v->name, "rxflash")) {
13705             confp->timing.rxflashtime = atoi(v->value);
13706          } else if (!strcasecmp(v->name, "debounce")) {
13707             confp->timing.debouncetime = atoi(v->value);
13708          } else if (!strcasecmp(v->name, "toneduration")) {
13709             int toneduration;
13710             int ctlfd;
13711             int res;
13712             struct dahdi_dialparams dps;
13713 
13714             ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
13715 
13716             if (ctlfd == -1) {
13717                ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
13718                return -1;
13719             }
13720 
13721             toneduration = atoi(v->value);
13722             if (toneduration > -1) {
13723                memset(&dps, 0, sizeof(dps));
13724 
13725                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13726                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13727                if (res < 0) {
13728                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13729                   return -1;
13730                }
13731             }
13732             close(ctlfd);
13733          } else if (!strcasecmp(v->name, "defaultcic")) {
13734             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13735          } else if (!strcasecmp(v->name, "defaultozz")) {
13736             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13737          } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
13738             dtmfcid_level = atoi(v->value);
13739          } 
13740       } else if (!skipchannels)
13741          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
13742    }
13743    if (dahdichan[0]) { 
13744       /* The user has set 'dahdichan' */
13745       /*< \todo pass proper line number instead of 0 */
13746       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13747          return -1;
13748       }
13749    }
13750    /*< \todo why check for the pseudo in the per-channel section.
13751     * Any actual use for manual setup of the pseudo channel? */
13752    if (!found_pseudo && reload != 1) {
13753       /* use the default configuration for a channel, so
13754          that any settings from real configured channels
13755          don't "leak" into the pseudo channel config
13756       */
13757       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13758 
13759       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
13760 
13761       if (tmp) {
13762          if (option_verbose > 2)
13763             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13764       } else {
13765          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13766       }
13767    }
13768    return 0;
13769 }
13770       
13771 static int setup_dahdi(int reload)
13772 {
13773    struct ast_config *cfg;
13774    struct ast_variable *v;
13775    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13776    int res;
13777 
13778 #ifdef HAVE_PRI
13779    char *c;
13780    int spanno;
13781    int i, x;
13782    int logicalspan;
13783    int trunkgroup;
13784    int dchannels[NUM_DCHANS];
13785 #endif
13786 
13787 #ifdef HAVE_ZAPTEL
13788    int load_from_zapata_conf = 1;
13789 #else
13790    int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
13791 #endif
13792 
13793    if (load_from_zapata_conf) {
13794       if (!(cfg = ast_config_load("zapata.conf"))) {
13795          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13796          return 0;
13797       }
13798    } else {
13799       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13800          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13801          return 0;
13802       }
13803    }
13804 
13805    /* It's a little silly to lock it, but we mind as well just to be sure */
13806    ast_mutex_lock(&iflock);
13807 #ifdef HAVE_PRI
13808    if (reload != 1) {
13809       /* Process trunkgroups first */
13810       v = ast_variable_browse(cfg, "trunkgroups");
13811       while (v) {
13812          if (!strcasecmp(v->name, "trunkgroup")) {
13813             trunkgroup = atoi(v->value);
13814             if (trunkgroup > 0) {
13815                if ((c = strchr(v->value, ','))) {
13816                   i = 0;
13817                   memset(dchannels, 0, sizeof(dchannels));
13818                   while (c && (i < NUM_DCHANS)) {
13819                      dchannels[i] = atoi(c + 1);
13820                      if (dchannels[i] < 0) {
13821                         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);
13822                      } else
13823                         i++;
13824                      c = strchr(c + 1, ',');
13825                   }
13826                   if (i) {
13827                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13828                         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);
13829                      } else if (option_verbose > 1)
13830                         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");
13831                   } else
13832                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13833                } else
13834                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13835             } else
13836                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13837          } else if (!strcasecmp(v->name, "spanmap")) {
13838             spanno = atoi(v->value);
13839             if (spanno > 0) {
13840                if ((c = strchr(v->value, ','))) {
13841                   trunkgroup = atoi(c + 1);
13842                   if (trunkgroup > 0) {
13843                      if ((c = strchr(c + 1, ','))) 
13844                         logicalspan = atoi(c + 1);
13845                      else
13846                         logicalspan = 0;
13847                      if (logicalspan >= 0) {
13848                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13849                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13850                         } else if (option_verbose > 1) 
13851                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13852                      } else
13853                         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);
13854                   } else
13855                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13856                } else
13857                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13858             } else
13859                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13860          } else {
13861             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13862          }
13863          v = v->next;
13864       }
13865    }
13866 #endif
13867    
13868    /* Copy the default jb config over global_jbconf */
13869    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13870 
13871    v = ast_variable_browse(cfg, "channels");
13872    res = process_dahdi(&conf, "", v, reload, 0);
13873    ast_mutex_unlock(&iflock);
13874    ast_config_destroy(cfg);
13875    if (res)
13876       return res;
13877    cfg = ast_config_load("users.conf");
13878    if (cfg) {
13879       char *cat;
13880       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13881       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13882          if (!strcasecmp(cat, "general"))
13883             continue;
13884          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
13885             struct dahdi_chan_conf sect_conf;
13886             memcpy(&sect_conf, &conf, sizeof(sect_conf));
13887 
13888             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13889          }
13890       }
13891       ast_config_destroy(cfg);
13892    }
13893 #ifdef HAVE_PRI
13894    if (reload != 1) {
13895       for (x = 0; x < NUM_SPANS; x++) {
13896          if (pris[x].pvts[0]) {
13897             if (start_pri(pris + x)) {
13898                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13899                return -1;
13900             } else if (option_verbose > 1)
13901                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13902          }
13903       }
13904    }
13905 #endif
13906 #ifdef HAVE_OPENR2
13907    if (reload != 1) {
13908       int x;
13909       for (x = 0; x < NUM_SPANS; x++) {
13910          if (r2links[x].protocol_context) {
13911             if (ast_pthread_create(&r2links[x].master, NULL, mfcr2_monitor, &r2links[x])) {
13912                ast_log(LOG_ERROR, "Unable to start R2 context on span %d\n", x + 1);
13913                return -1;
13914             } else {
13915                ast_verbose(VERBOSE_PREFIX_2 "Starting R2 context on span %d\n", x + 1);
13916             }
13917          }
13918       }
13919    }
13920 #endif
13921    /* And start the monitor for the first time */
13922    restart_monitor();
13923    return 0;
13924 }
13925 
13926 #define local_astman_register(a, b, c, d) do { \
13927                   if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13928                      ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13929                   } \
13930                   ast_manager_register("Zap" a, b, zap_ ## c, d); \
13931                  } while (0)
13932 
13933 static int load_module(void)
13934 {
13935    int res;
13936 
13937 #ifdef HAVE_PRI
13938    int y,i;
13939    memset(pris, 0, sizeof(pris));
13940    for (y = 0; y < NUM_SPANS; y++) {
13941       ast_mutex_init(&pris[y].lock);
13942       pris[y].offset = -1;
13943       pris[y].master = AST_PTHREADT_NULL;
13944       for (i = 0; i < NUM_DCHANS; i++)
13945          pris[y].fds[i] = -1;
13946    }
13947    pri_set_error(dahdi_pri_error);
13948    pri_set_message(dahdi_pri_message);
13949    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13950       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13951          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13952    }
13953    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13954       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13955 #endif
13956 #ifdef HAVE_OPENR2
13957    init_mfcr2_globals();
13958    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13959       ast_register_application(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec,
13960          dahdi_accept_r2_call_synopsis, dahdi_accept_r2_call_descrip);
13961    }
13962    ast_register_application(zap_accept_r2_call_app, zap_accept_r2_call_exec,
13963       zap_accept_r2_call_synopsis, zap_accept_r2_call_descrip);
13964 #endif
13965    if ((res = setup_dahdi(0))) {
13966       return AST_MODULE_LOAD_DECLINE;
13967    }
13968    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13969       chan_tech = &dahdi_tech;
13970    } else {
13971       chan_tech = &zap_tech;
13972    }
13973    if (ast_channel_register(chan_tech)) {
13974       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13975       __unload_module();
13976       return -1;
13977    }
13978 #ifdef HAVE_PRI
13979    ast_string_field_init(&inuse, 16);
13980    ast_string_field_set(&inuse, name, "GR-303InUse");
13981    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13982 #endif   
13983 #ifdef HAVE_OPENR2
13984    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
13985 #endif
13986    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13987    
13988    memset(round_robin, 0, sizeof(round_robin));
13989    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13990    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13991    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13992    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13993    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13994    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13995    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13996 
13997    ast_cond_init(&ss_thread_complete, NULL);
13998 
13999    return res;
14000 }
14001 
14002 static int dahdi_sendtext(struct ast_channel *c, const char *text)
14003 {
14004 #define  END_SILENCE_LEN 400
14005 #define  HEADER_MS 50
14006 #define  TRAILER_MS 5
14007 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14008 #define  ASCII_BYTES_PER_CHAR 80
14009 
14010    unsigned char *buf,*mybuf;
14011    struct dahdi_pvt *p = c->tech_pvt;
14012    struct pollfd fds[1];
14013    int size,res,fd,len,x;
14014    int bytes=0;
14015    /* Initial carrier (imaginary) */
14016    float cr = 1.0;
14017    float ci = 0.0;
14018    float scont = 0.0;
14019    int index;
14020 
14021    index = dahdi_get_index(c, p, 0);
14022    if (index < 0) {
14023       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
14024       return -1;
14025    }
14026    if (!text[0]) return(0); /* if nothing to send, dont */
14027    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
14028    if (p->mate) 
14029       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
14030    else
14031       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
14032    if (!buf)
14033       return -1;
14034    mybuf = buf;
14035    if (p->mate) {
14036       int codec = AST_LAW(p);
14037       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
14038          PUT_CLID_MARKMS;
14039       }
14040       /* Put actual message */
14041       for (x = 0; text[x]; x++) {
14042          PUT_CLID(text[x]);
14043       }
14044       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
14045          PUT_CLID_MARKMS;
14046       }
14047       len = bytes;
14048       buf = mybuf;
14049    } else {
14050       len = tdd_generate(p->tdd, buf, text);
14051       if (len < 1) {
14052          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
14053          free(mybuf);
14054          return -1;
14055       }
14056    }
14057    memset(buf + len, 0x7f, END_SILENCE_LEN);
14058    len += END_SILENCE_LEN;
14059    fd = p->subs[index].dfd;
14060    while (len) {
14061       if (ast_check_hangup(c)) {
14062          free(mybuf);
14063          return -1;
14064       }
14065       size = len;
14066       if (size > READ_SIZE)
14067          size = READ_SIZE;
14068       fds[0].fd = fd;
14069       fds[0].events = POLLOUT | POLLPRI;
14070       fds[0].revents = 0;
14071       res = poll(fds, 1, -1);
14072       if (!res) {
14073          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
14074          continue;
14075       }
14076         /* if got exception */
14077       if (fds[0].revents & POLLPRI) {
14078          ast_free(mybuf);
14079          return -1;
14080       }
14081       if (!(fds[0].revents & POLLOUT)) {
14082          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
14083          continue;
14084       }
14085       res = write(fd, buf, size);
14086       if (res != size) {
14087          if (res == -1) {
14088             free(mybuf);
14089             return -1;
14090          }
14091          if (option_debug)
14092             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14093          break;
14094       }
14095       len -= size;
14096       buf += size;
14097    }
14098    free(mybuf);
14099    return(0);
14100 }
14101 
14102 
14103 static int reload(void)
14104 {
14105    int res = 0;
14106 
14107    res = setup_dahdi(1);
14108    if (res) {
14109       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14110       return -1;
14111    }
14112    return 0;
14113 }
14114 
14115 /* This is a workaround so that menuselect displays a proper description
14116  * AST_MODULE_INFO(, , "DAHDI Telephony"
14117  */
14118 
14119 #ifdef HAVE_PRI
14120 #define tdesc "DAHDI Telephony w/PRI"
14121 #else
14122 #define tdesc "DAHDI Telephony"
14123 #endif
14124 
14125 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14126       .load = load_module,
14127       .unload = unload_module,
14128       .reload = reload,
14129           );
14130 
14131 

Generated on Tue Apr 6 15:45:27 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7