Mon Nov 24 15:34:10 2008

Asterisk developer's documentation


chan_dahdi.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief DAHDI Pseudo TDM interface 
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  * 
00025  * Connects to the DAHDI telephony library as well as 
00026  * libpri. Libpri is optional and needed only if you are
00027  * going to use ISDN connections.
00028  *
00029  * You need to install libraries before you attempt to compile
00030  * and install the DAHDI channel.
00031  *
00032  * \par See also
00033  * \arg \ref Config_dahdi
00034  *
00035  * \ingroup channel_drivers
00036  *
00037  * \todo Deprecate the "musiconhold" configuration option post 1.4
00038  */
00039 
00040 /*** MODULEINFO
00041    <depend>res_smdi</depend>
00042    <depend>dahdi</depend>
00043    <depend>tonezone</depend>
00044    <depend>res_features</depend>
00045    <use>pri</use>
00046  ***/
00047 
00048 #include "asterisk.h"
00049 
00050 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 140115 $")
00051 
00052 #include <stdio.h>
00053 #include <string.h>
00054 #ifdef __NetBSD__
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <errno.h>
00061 #include <stdlib.h>
00062 #if !defined(SOLARIS) && !defined(__FreeBSD__)
00063 #include <stdint.h>
00064 #endif
00065 #include <unistd.h>
00066 #include <sys/ioctl.h>
00067 #include <math.h>
00068 #include <ctype.h>
00069 
00070 #ifdef HAVE_PRI
00071 #include <libpri.h>
00072 #endif
00073 
00074 #include "asterisk/lock.h"
00075 #include "asterisk/channel.h"
00076 #include "asterisk/config.h"
00077 #include "asterisk/logger.h"
00078 #include "asterisk/module.h"
00079 #include "asterisk/pbx.h"
00080 #include "asterisk/options.h"
00081 #include "asterisk/file.h"
00082 #include "asterisk/ulaw.h"
00083 #include "asterisk/alaw.h"
00084 #include "asterisk/callerid.h"
00085 #include "asterisk/adsi.h"
00086 #include "asterisk/cli.h"
00087 #include "asterisk/cdr.h"
00088 #include "asterisk/features.h"
00089 #include "asterisk/musiconhold.h"
00090 #include "asterisk/say.h"
00091 #include "asterisk/tdd.h"
00092 #include "asterisk/app.h"
00093 #include "asterisk/dsp.h"
00094 #include "asterisk/astdb.h"
00095 #include "asterisk/manager.h"
00096 #include "asterisk/causes.h"
00097 #include "asterisk/term.h"
00098 #include "asterisk/utils.h"
00099 #include "asterisk/transcap.h"
00100 #include "asterisk/stringfields.h"
00101 #include "asterisk/abstract_jb.h"
00102 #include "asterisk/smdi.h"
00103 #include "asterisk/astobj.h"
00104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00105 
00106 #include "asterisk/dahdi_compat.h"
00107 #include "asterisk/tonezone_compat.h"
00108 
00109 /*! Global jitterbuffer configuration - by default, jb is disabled */
00110 static struct ast_jb_conf default_jbconf =
00111 {
00112    .flags = 0,
00113    .max_size = -1,
00114    .resync_threshold = -1,
00115    .impl = ""
00116 };
00117 static struct ast_jb_conf global_jbconf;
00118 
00119 #ifndef DAHDI_TONEDETECT
00120 /* Work around older code with no tone detect */
00121 #define DAHDI_EVENT_DTMFDOWN 0
00122 #define DAHDI_EVENT_DTMFUP 0
00123 #endif
00124 
00125 /* define this to send PRI user-user information elements */
00126 #undef SUPPORT_USERUSER
00127 
00128 /*! 
00129  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00130  * the user hangs up to reset the state machine so ring works properly.
00131  * This is used to be able to support kewlstart by putting the zhone in
00132  * groundstart mode since their forward disconnect supervision is entirely
00133  * broken even though their documentation says it isn't and their support
00134  * is entirely unwilling to provide any assistance with their channel banks
00135  * even though their web site says they support their products for life.
00136  */
00137 /* #define ZHONE_HACK */
00138 
00139 /*! \note
00140  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00141  * before dialing on it.  Certain FXO interfaces always think they're out of
00142  * service with this method however.
00143  */
00144 /* #define DAHDI_CHECK_HOOKSTATE */
00145 
00146 /*! \brief Typically, how many rings before we should send Caller*ID */
00147 #define DEFAULT_CIDRINGS 1
00148 
00149 #define CHANNEL_PSEUDO -12
00150 
00151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00152 
00153 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00154 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) 
00155 
00156 static const char tdesc[] = "DAHDI Telephony Driver"
00157 #ifdef HAVE_PRI
00158                " w/PRI"
00159 #endif
00160 ;
00161 
00162 #define SIG_EM    DAHDI_SIG_EM
00163 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00165 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00166 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00167 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00168 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00169 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00170 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00171 #define SIG_FXSLS DAHDI_SIG_FXSLS
00172 #define SIG_FXSGS DAHDI_SIG_FXSGS
00173 #define SIG_FXSKS DAHDI_SIG_FXSKS
00174 #define SIG_FXOLS DAHDI_SIG_FXOLS
00175 #define SIG_FXOGS DAHDI_SIG_FXOGS
00176 #define SIG_FXOKS DAHDI_SIG_FXOKS
00177 #define SIG_PRI      DAHDI_SIG_CLEAR
00178 #define  SIG_SF      DAHDI_SIG_SF
00179 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00181 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00182 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00184 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00185 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00186 
00187 #define NUM_SPANS       32
00188 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00189 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00190 
00191 #define CHAN_PSEUDO  -2
00192 
00193 #define DCHAN_PROVISIONED (1 << 0)
00194 #define DCHAN_NOTINALARM  (1 << 1)
00195 #define DCHAN_UP          (1 << 2)
00196 
00197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00198 
00199 static char defaultcic[64] = "";
00200 static char defaultozz[64] = "";
00201 
00202 static char progzone[10] = "";
00203 
00204 static int distinctiveringaftercid = 0;
00205 
00206 static int numbufs = 4;
00207 
00208 #ifdef HAVE_PRI
00209 static struct ast_channel inuse;
00210 #ifdef PRI_GETSET_TIMERS
00211 static int pritimers[PRI_MAX_TIMERS];
00212 #endif
00213 static int pridebugfd = -1;
00214 static char pridebugfilename[1024] = "";
00215 #endif
00216 
00217 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00218 static int firstdigittimeout = 16000;
00219 
00220 /*! \brief How long to wait for following digits (FXO logic) */
00221 static int gendigittimeout = 8000;
00222 
00223 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00224 static int matchdigittimeout = 3000;
00225 
00226 /*! \brief Protect the interface list (of dahdi_pvt's) */
00227 AST_MUTEX_DEFINE_STATIC(iflock);
00228 
00229 
00230 static int ifcount = 0;
00231 
00232 #ifdef HAVE_PRI
00233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00234 #endif
00235 
00236 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00237    when it's doing something critical. */
00238 AST_MUTEX_DEFINE_STATIC(monlock);
00239 
00240 /*! \brief This is the thread for the monitor which checks for input on the channels
00241    which are not currently in use. */
00242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00243 static ast_cond_t ss_thread_complete;
00244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00245 AST_MUTEX_DEFINE_STATIC(restart_lock);
00246 static int ss_thread_count = 0;
00247 static int num_restart_pending = 0;
00248 
00249 static int restart_monitor(void);
00250 
00251 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00252 
00253 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00254 
00255 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00256 static inline int dahdi_get_event(int fd)
00257 {
00258    int j;
00259    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00260       return -1;
00261    return j;
00262 }
00263 
00264 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00265 static inline int dahdi_wait_event(int fd)
00266 {
00267    int i, j = 0;
00268    i = DAHDI_IOMUX_SIGEVENT;
00269    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00270       return -1;
00271    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00272       return -1;
00273    return j;
00274 }
00275 
00276 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00277 #define READ_SIZE 160
00278 
00279 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00280 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00281 
00282 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00283 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00284 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00285 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00286 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00287 
00288 struct dahdi_pvt;
00289 
00290 static int ringt_base = DEFAULT_RINGT;
00291 
00292 #ifdef HAVE_PRI
00293 
00294 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00295 #define PRI_CHANNEL(p) ((p) & 0xff)
00296 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00297 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00298 
00299 struct dahdi_pri {
00300    pthread_t master;                /*!< Thread of master */
00301    ast_mutex_t lock;                /*!< Mutex */
00302    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00303    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00304    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00305    int minunused;                   /*!< Min # of channels to keep empty */
00306    int minidle;                     /*!< Min # of "idling" calls to keep active */
00307    int nodetype;                    /*!< Node type */
00308    int switchtype;                     /*!< Type of switch to emulate */
00309    int nsf;                   /*!< Network-Specific Facilities */
00310    int dialplan;                    /*!< Dialing plan */
00311    int localdialplan;                  /*!< Local dialing plan */
00312    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00313    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00314    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00315    char privateprefix[20];                /*!< for private dialplans */
00316    char unknownprefix[20];                /*!< for unknown dialplans */
00317    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00318    int trunkgroup;                     /*!< What our trunkgroup is */
00319    int mastertrunkgroup;                  /*!< What trunk group is our master */
00320    int prilogicalspan;                 /*!< Logical span number within trunk group */
00321    int numchans;                    /*!< Num of channels we represent */
00322    int overlapdial;                 /*!< In overlap dialing mode */
00323    int facilityenable;                 /*!< Enable facility IEs */
00324    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00325    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00326    struct pri *pri;                 /*!< Currently active D-channel */
00327    int debug;
00328    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00329    int offset;
00330    int span;
00331    int resetting;
00332    int resetpos;
00333 #ifdef HAVE_PRI_INBANDDISCONNECT
00334    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00335 #endif
00336    time_t lastreset;                /*!< time when unused channels were last reset */
00337    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00338    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00339    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00340    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00341 };
00342 
00343 
00344 static struct dahdi_pri pris[NUM_SPANS];
00345 
00346 #if 0
00347 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00348 #else
00349 #define DEFAULT_PRI_DEBUG 0
00350 #endif
00351 
00352 static inline void pri_rel(struct dahdi_pri *pri)
00353 {
00354    ast_mutex_unlock(&pri->lock);
00355 }
00356 
00357 #else
00358 /*! Shut up the compiler */
00359 struct dahdi_pri;
00360 #endif
00361 
00362 #define SUB_REAL  0        /*!< Active call */
00363 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00364 #define SUB_THREEWAY 2        /*!< Three-way call */
00365 
00366 /* Polarity states */
00367 #define POLARITY_IDLE   0
00368 #define POLARITY_REV    1
00369 
00370 
00371 static struct dahdi_distRings drings;
00372 
00373 struct distRingData {
00374    int ring[3];
00375 };
00376 struct ringContextData {
00377    char contextData[AST_MAX_CONTEXT];
00378 };
00379 struct dahdi_distRings {
00380    struct distRingData ringnum[3];
00381    struct ringContextData ringContext[3];
00382 };
00383 
00384 static char *subnames[] = {
00385    "Real",
00386    "Callwait",
00387    "Threeway"
00388 };
00389 
00390 struct dahdi_subchannel {
00391    int dfd;
00392    struct ast_channel *owner;
00393    int chan;
00394    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00395    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00396    unsigned int needringing:1;
00397    unsigned int needbusy:1;
00398    unsigned int needcongestion:1;
00399    unsigned int needcallerid:1;
00400    unsigned int needanswer:1;
00401    unsigned int needflash:1;
00402    unsigned int needhold:1;
00403    unsigned int needunhold:1;
00404    unsigned int linear:1;
00405    unsigned int inthreeway:1;
00406    struct dahdi_confinfo curconf;
00407 };
00408 
00409 #define CONF_USER_REAL     (1 << 0)
00410 #define CONF_USER_THIRDCALL   (1 << 1)
00411 
00412 #define MAX_SLAVES   4
00413 
00414 static struct dahdi_pvt {
00415    ast_mutex_t lock;
00416    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00417                      /*!< Up to three channels can be associated with this call */
00418       
00419    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00420    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00421    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00422 
00423    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00424    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00425    int inconference;          /*!< If our real should be in the conference */
00426    
00427    int buf_no;             /*!< Number of buffers */
00428    int buf_policy;            /*!< Buffer policy */
00429    int sig;             /*!< Signalling style */
00430    int radio;              /*!< radio type */
00431    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00432    int oprmode;               /*!< "Operator Services" mode */
00433    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00434    float rxgain;
00435    float txgain;
00436    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00437    struct dahdi_pvt *next;          /*!< Next channel in list */
00438    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00439 
00440    /* flags */
00441    unsigned int adsi:1;
00442    unsigned int answeronpolarityswitch:1;
00443    unsigned int busydetect:1;
00444    unsigned int callreturn:1;
00445    unsigned int callwaiting:1;
00446    unsigned int callwaitingcallerid:1;
00447    unsigned int cancallforward:1;
00448    unsigned int canpark:1;
00449    unsigned int confirmanswer:1;       /*!< Wait for '#' to confirm answer */
00450    unsigned int destroy:1;
00451    unsigned int didtdd:1;           /*!< flag to say its done it once */
00452    unsigned int dialednone:1;
00453    unsigned int dialing:1;
00454    unsigned int digital:1;
00455    unsigned int dnd:1;
00456    unsigned int echobreak:1;
00457    unsigned int echocanbridged:1;
00458    unsigned int echocanon:1;
00459    unsigned int faxhandled:1;       /*!< Has a fax tone already been handled? */
00460    unsigned int firstradio:1;
00461    unsigned int hanguponpolarityswitch:1;
00462    unsigned int hardwaredtmf:1;
00463    unsigned int hidecallerid:1;
00464    unsigned int hidecalleridname:1;      /*!< Hide just the name not the number for legacy PBX use */
00465    unsigned int ignoredtmf:1;
00466    unsigned int immediate:1;        /*!< Answer before getting digits? */
00467    unsigned int inalarm:1;
00468    unsigned int unknown_alarm:1;
00469    unsigned int mate:1;          /*!< flag to say its in MATE mode */
00470    unsigned int outgoing:1;
00471    unsigned int overlapdial:1;
00472    unsigned int permcallwaiting:1;
00473    unsigned int permhidecallerid:1;    /*!< Whether to hide our outgoing caller ID or not */
00474    unsigned int priindication_oob:1;
00475    unsigned int priexclusive:1;
00476    unsigned int pulse:1;
00477    unsigned int pulsedial:1;        /*!< whether a pulse dial phone is detected */
00478    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00479    unsigned int restrictcid:1;         /*!< Whether restrict the callerid -> only send ANI */
00480    unsigned int threewaycalling:1;
00481    unsigned int transfer:1;
00482    unsigned int use_callerid:1;        /*!< Whether or not to use caller id on this channel */
00483    unsigned int use_callingpres:1;        /*!< Whether to use the callingpres the calling switch sends */
00484    unsigned int usedistinctiveringdetection:1;
00485    unsigned int dahditrcallerid:1;        /*!< should we use the callerid from incoming call on dahdi transfer or not */
00486    unsigned int transfertobusy:1;         /*!< allow flash-transfers to busy channels */
00487 #if defined(HAVE_PRI)
00488    unsigned int alerting:1;
00489    unsigned int alreadyhungup:1;
00490    unsigned int isidlecall:1;
00491    unsigned int proceeding:1;
00492    unsigned int progress:1;
00493    unsigned int resetting:1;
00494    unsigned int setup_ack:1;
00495 #endif
00496    unsigned int use_smdi:1;      /* Whether to use SMDI on this channel */
00497    struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
00498 
00499    struct dahdi_distRings drings;
00500 
00501    char context[AST_MAX_CONTEXT];
00502    char defcontext[AST_MAX_CONTEXT];
00503    char exten[AST_MAX_EXTENSION];
00504    char language[MAX_LANGUAGE];
00505    char mohinterpret[MAX_MUSICCLASS];
00506    char mohsuggest[MAX_MUSICCLASS];
00507 #ifdef PRI_ANI
00508    char cid_ani[AST_MAX_EXTENSION];
00509 #endif
00510    char cid_num[AST_MAX_EXTENSION];
00511    int cid_ton;               /*!< Type Of Number (TON) */
00512    char cid_name[AST_MAX_EXTENSION];
00513    char lastcid_num[AST_MAX_EXTENSION];
00514    char lastcid_name[AST_MAX_EXTENSION];
00515    char *origcid_num;            /*!< malloced original callerid */
00516    char *origcid_name;           /*!< malloced original callerid */
00517    char callwait_num[AST_MAX_EXTENSION];
00518    char callwait_name[AST_MAX_EXTENSION];
00519    char rdnis[AST_MAX_EXTENSION];
00520    char dnid[AST_MAX_EXTENSION];
00521    ast_group_t group;
00522    int law;
00523    int confno;             /*!< Our conference */
00524    int confusers;             /*!< Who is using our conference */
00525    int propconfno;               /*!< Propagated conference number */
00526    ast_group_t callgroup;
00527    ast_group_t pickupgroup;
00528    int channel;               /*!< Channel Number or CRV */
00529    int span;               /*!< Span number */
00530    time_t guardtime;          /*!< Must wait this much time before using for new call */
00531    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
00532    int cid_start;             /*!< CID start indicator, polarity or ring */
00533    int callingpres;           /*!< The value of callling presentation that we're going to use when placing a PRI call */
00534    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
00535    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
00536    unsigned char *cidspill;
00537    int cidpos;
00538    int cidlen;
00539    int ringt;
00540    int ringt_base;
00541    int stripmsd;
00542    int callwaitcas;
00543    int callwaitrings;
00544    int echocancel;
00545    int echotraining;
00546    char echorest[20];
00547    int busycount;
00548    int busycompare;
00549    int busytonelength;
00550    int busyquietlength;
00551    int busyfuzziness;
00552    int silencethreshold;
00553    int callprogress;
00554    struct timeval flashtime;        /*!< Last flash-hook time */
00555    struct ast_dsp *dsp;
00556    int cref;               /*!< Call reference number */
00557    struct dahdi_dialoperation dop;
00558    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
00559    char finaldial[64];
00560    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
00561    int amaflags;              /*!< AMA Flags */
00562    struct tdd_state *tdd;           /*!< TDD flag */
00563    char call_forward[AST_MAX_EXTENSION];
00564    char mailbox[AST_MAX_EXTENSION];
00565    char dialdest[256];
00566    int onhooktime;
00567    int msgstate;
00568    int distinctivering;          /*!< Which distinctivering to use */
00569    int cidrings;              /*!< Which ring to deliver CID on */
00570    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
00571    int fake_event;
00572    int polarityonanswerdelay;
00573    struct timeval polaritydelaytv;
00574    int sendcalleridafter;
00575 #ifdef HAVE_PRI
00576    struct dahdi_pri *pri;
00577    struct dahdi_pvt *bearer;
00578    struct dahdi_pvt *realcall;
00579    q931_call *call;
00580    int prioffset;
00581    int logicalspan;
00582 #endif   
00583    int polarity;
00584    int dsp_features;
00585    char begindigit;
00586 } *iflist = NULL, *ifend = NULL;
00587 
00588 /*! \brief Channel configuration from chan_dahdi.conf .
00589  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
00590  * Generally there is a field here for every possible configuration item.
00591  *
00592  * The state of fields is saved along the parsing and whenever a 'channel'
00593  * statement is reached, the current dahdi_chan_conf is used to configure the 
00594  * channel (struct dahdi_pvt)
00595  *
00596  * @seealso dahdi_chan_init for the default values.
00597  */
00598 struct dahdi_chan_conf {
00599    struct dahdi_pvt chan;
00600 #ifdef HAVE_PRI
00601    struct dahdi_pri pri;
00602 #endif
00603    struct dahdi_params timing;
00604 
00605    char smdi_port[SMDI_MAX_FILENAME_LEN];
00606 };
00607 
00608 /** returns a new dahdi_chan_conf with default values (by-value) */
00609 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
00610    /* recall that if a field is not included here it is initialized
00611     * to 0 or equivalent
00612     */
00613    struct dahdi_chan_conf conf = {
00614 #ifdef HAVE_PRI
00615       .pri = {
00616          .nsf = PRI_NSF_NONE,
00617          .switchtype = PRI_SWITCH_NI2,
00618          .dialplan = PRI_NATIONAL_ISDN + 1,
00619          .localdialplan = PRI_NATIONAL_ISDN + 1,
00620          .nodetype = PRI_CPE,
00621 
00622          .minunused = 2,
00623          .idleext = "",
00624          .idledial = "",
00625          .internationalprefix = "",
00626          .nationalprefix = "",
00627          .localprefix = "",
00628          .privateprefix = "",
00629          .unknownprefix = "",
00630 
00631          .resetinterval = 3600
00632       },
00633 #endif
00634       .chan = {
00635          .context = "default",
00636          .cid_num = "",
00637          .cid_name = "",
00638          .mohinterpret = "default",
00639          .mohsuggest = "",
00640          .transfertobusy = 1,
00641 
00642          .cid_signalling = CID_SIG_BELL,
00643          .cid_start = CID_START_RING,
00644          .dahditrcallerid = 0,
00645          .use_callerid = 1,
00646          .sig = -1,
00647          .outsigmod = -1,
00648 
00649          .tonezone = -1,
00650 
00651          .echocancel = 1,
00652 
00653          .busycount = 3,
00654          .busycompare = 0,
00655          .busytonelength = 0,
00656          .busyquietlength = 0,
00657          .busyfuzziness = 0,
00658          .silencethreshold = 0,
00659 
00660          .accountcode = "",
00661 
00662          .mailbox = "",
00663 
00664 
00665          .polarityonanswerdelay = 600,
00666 
00667          .sendcalleridafter = DEFAULT_CIDRINGS,
00668 
00669          .buf_policy = DAHDI_POLICY_IMMEDIATE,
00670          .buf_no = numbufs
00671       },
00672       .timing = {
00673          .prewinktime = -1,
00674          .preflashtime = -1,
00675          .winktime = -1,
00676          .flashtime = -1,
00677          .starttime = -1,
00678          .rxwinktime = -1,
00679          .rxflashtime = -1,
00680          .debouncetime = -1
00681       },
00682       .smdi_port = "/dev/ttyS0",
00683    };
00684 
00685    return conf;
00686 }
00687 
00688 
00689 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
00690 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
00691 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00692 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00693 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
00694 static int dahdi_hangup(struct ast_channel *ast);
00695 static int dahdi_answer(struct ast_channel *ast);
00696 static struct ast_frame *dahdi_read(struct ast_channel *ast);
00697 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
00698 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
00699 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
00700 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00701 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
00702 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len); 
00703 
00704 static const struct ast_channel_tech dahdi_tech = {
00705    .type = "DAHDI",
00706    .description = tdesc,
00707    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
00708    .requester = dahdi_request,
00709    .send_digit_begin = dahdi_digit_begin,
00710    .send_digit_end = dahdi_digit_end,
00711    .send_text = dahdi_sendtext,
00712    .call = dahdi_call,
00713    .hangup = dahdi_hangup,
00714    .answer = dahdi_answer,
00715    .read = dahdi_read,
00716    .write = dahdi_write,
00717    .bridge = dahdi_bridge,
00718    .exception = dahdi_exception,
00719    .indicate = dahdi_indicate,
00720    .fixup = dahdi_fixup,
00721    .setoption = dahdi_setoption,
00722    .func_channel_read = dahdi_func_read,
00723 };
00724 
00725 static const struct ast_channel_tech zap_tech = {
00726    .type = "Zap",
00727    .description = tdesc,
00728    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
00729    .requester = dahdi_request,
00730    .send_digit_begin = dahdi_digit_begin,
00731    .send_digit_end = dahdi_digit_end,
00732    .send_text = dahdi_sendtext,
00733    .call = dahdi_call,
00734    .hangup = dahdi_hangup,
00735    .answer = dahdi_answer,
00736    .read = dahdi_read,
00737    .write = dahdi_write,
00738    .bridge = dahdi_bridge,
00739    .exception = dahdi_exception,
00740    .indicate = dahdi_indicate,
00741    .fixup = dahdi_fixup,
00742    .setoption = dahdi_setoption,
00743    .func_channel_read = dahdi_func_read,
00744 };
00745 
00746 static const struct ast_channel_tech *chan_tech;
00747 
00748 #ifdef HAVE_PRI
00749 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
00750 #else
00751 #define GET_CHANNEL(p) ((p)->channel)
00752 #endif
00753 
00754 struct dahdi_pvt *round_robin[32];
00755 
00756 #ifdef HAVE_PRI
00757 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
00758 {
00759    int res;
00760    /* Grab the lock first */
00761    do {
00762       res = ast_mutex_trylock(&pri->lock);
00763       if (res) {
00764          DEADLOCK_AVOIDANCE(&pvt->lock);
00765       }
00766    } while (res);
00767    /* Then break the poll */
00768    if (pri->master != AST_PTHREADT_NULL)
00769       pthread_kill(pri->master, SIGURG);
00770    return 0;
00771 }
00772 #endif
00773 
00774 #define NUM_CADENCE_MAX 25
00775 static int num_cadence = 4;
00776 static int user_has_defined_cadences = 0;
00777 
00778 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00779    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
00780    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
00781    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
00782    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
00783 };
00784 
00785 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
00786  * is 1, the second pause is 2 and so on.
00787  */
00788 
00789 static int cidrings[NUM_CADENCE_MAX] = {
00790    2,                            /*!< Right after first long ring */
00791    4,                            /*!< Right after long part */
00792    3,                            /*!< After third chirp */
00793    2,                            /*!< Second spell */
00794 };
00795 
00796 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00797          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00798 
00799 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00800 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
00801 
00802 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
00803 {
00804    int res;
00805    if (p->subs[SUB_REAL].owner == ast)
00806       res = 0;
00807    else if (p->subs[SUB_CALLWAIT].owner == ast)
00808       res = 1;
00809    else if (p->subs[SUB_THREEWAY].owner == ast)
00810       res = 2;
00811    else {
00812       res = -1;
00813       if (!nullok)
00814          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
00815    }
00816    return res;
00817 }
00818 
00819 #ifdef HAVE_PRI
00820 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
00821 #else
00822 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
00823 #endif
00824 {
00825 #ifdef HAVE_PRI
00826    if (pri)
00827       ast_mutex_unlock(&pri->lock);
00828 #endif         
00829    for (;;) {
00830       if (p->subs[a].owner) {
00831          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00832             DEADLOCK_AVOIDANCE(&p->lock);
00833          } else {
00834             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
00835             ast_mutex_unlock(&p->subs[a].owner->lock);
00836             break;
00837          }
00838       } else
00839          break;
00840    }
00841 #ifdef HAVE_PRI
00842    if (pri)
00843       ast_mutex_lock(&pri->lock);
00844 #endif         
00845 }
00846 
00847 #ifdef HAVE_PRI
00848 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
00849 #else
00850 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
00851 #endif
00852 {
00853    /* We must unlock the PRI to avoid the possibility of a deadlock */
00854 #ifdef HAVE_PRI
00855    if (pri)
00856       ast_mutex_unlock(&pri->lock);
00857 #endif      
00858    for (;;) {
00859       if (p->owner) {
00860          if (ast_mutex_trylock(&p->owner->lock)) {
00861             DEADLOCK_AVOIDANCE(&p->lock);
00862          } else {
00863             ast_queue_frame(p->owner, f);
00864             ast_mutex_unlock(&p->owner->lock);
00865             break;
00866          }
00867       } else
00868          break;
00869    }
00870 #ifdef HAVE_PRI
00871    if (pri)
00872       ast_mutex_lock(&pri->lock);
00873 #endif      
00874 }
00875 
00876 static int restore_gains(struct dahdi_pvt *p);
00877 
00878 static void swap_subs(struct dahdi_pvt *p, int a, int b)
00879 {
00880    int tchan;
00881    int tinthreeway;
00882    struct ast_channel *towner;
00883 
00884    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
00885 
00886    tchan = p->subs[a].chan;
00887    towner = p->subs[a].owner;
00888    tinthreeway = p->subs[a].inthreeway;
00889 
00890    p->subs[a].chan = p->subs[b].chan;
00891    p->subs[a].owner = p->subs[b].owner;
00892    p->subs[a].inthreeway = p->subs[b].inthreeway;
00893 
00894    p->subs[b].chan = tchan;
00895    p->subs[b].owner = towner;
00896    p->subs[b].inthreeway = tinthreeway;
00897 
00898    if (p->subs[a].owner) 
00899       p->subs[a].owner->fds[0] = p->subs[a].dfd;
00900    if (p->subs[b].owner) 
00901       p->subs[b].owner->fds[0] = p->subs[b].dfd;
00902    wakeup_sub(p, a, NULL);
00903    wakeup_sub(p, b, NULL);
00904 }
00905 
00906 static int dahdi_open(char *fn)
00907 {
00908    int fd;
00909    int isnum;
00910    int chan = 0;
00911    int bs;
00912    int x;
00913    isnum = 1;
00914    for (x = 0; x < strlen(fn); x++) {
00915       if (!isdigit(fn[x])) {
00916          isnum = 0;
00917          break;
00918       }
00919    }
00920    if (isnum) {
00921       chan = atoi(fn);
00922       if (chan < 1) {
00923          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
00924          return -1;
00925       }
00926 #ifdef HAVE_ZAPTEL
00927       fn = "/dev/zap/channel";
00928 #else
00929       fn = "/dev/dahdi/channel";
00930 #endif
00931    }
00932    fd = open(fn, O_RDWR | O_NONBLOCK);
00933    if (fd < 0) {
00934       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
00935       return -1;
00936    }
00937    if (chan) {
00938       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
00939          x = errno;
00940          close(fd);
00941          errno = x;
00942          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
00943          return -1;
00944       }
00945    }
00946    bs = READ_SIZE;
00947    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
00948       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
00949       x = errno;
00950       close(fd);
00951       errno = x;
00952       return -1;
00953    }
00954    return fd;
00955 }
00956 
00957 static void dahdi_close(int fd)
00958 {
00959    if (fd > 0)
00960       close(fd);
00961 }
00962 
00963 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
00964 {
00965    dahdi_close(chan_pvt->subs[sub_num].dfd);
00966    chan_pvt->subs[sub_num].dfd = -1;
00967 }
00968  
00969 #ifdef HAVE_PRI
00970 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
00971 {
00972    dahdi_close(pri->fds[fd_num]);
00973    pri->fds[fd_num] = -1;
00974 }
00975 #endif
00976 
00977 static int dahdi_setlinear(int dfd, int linear)
00978 {
00979    int res;
00980    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
00981    if (res)
00982       return res;
00983    return 0;
00984 }
00985 
00986 
00987 static int alloc_sub(struct dahdi_pvt *p, int x)
00988 {
00989    struct dahdi_bufferinfo bi;
00990    int res;
00991    if (p->subs[x].dfd < 0) {
00992 #ifdef HAVE_ZAPTEL
00993       p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
00994 #else
00995       p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
00996 #endif
00997       if (p->subs[x].dfd > -1) {
00998          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
00999          if (!res) {
01000             bi.txbufpolicy = p->buf_policy;
01001             bi.rxbufpolicy = p->buf_policy;
01002             bi.numbufs = p->buf_no;
01003             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01004             if (res < 0) {
01005                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01006             }
01007          } else 
01008             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01009          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01010             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01011             dahdi_close_sub(p, x);
01012             return -1;
01013          }
01014          if (option_debug)
01015             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01016          return 0;
01017       } else
01018          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01019       return -1;
01020    }
01021    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01022    return -1;
01023 }
01024 
01025 static int unalloc_sub(struct dahdi_pvt *p, int x)
01026 {
01027    if (!x) {
01028       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01029       return -1;
01030    }
01031    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01032    dahdi_close_sub(p, x);
01033    p->subs[x].linear = 0;
01034    p->subs[x].chan = 0;
01035    p->subs[x].owner = NULL;
01036    p->subs[x].inthreeway = 0;
01037    p->polarity = POLARITY_IDLE;
01038    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01039    return 0;
01040 }
01041 
01042 static int digit_to_dtmfindex(char digit)
01043 {
01044    if (isdigit(digit))
01045       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01046    else if (digit >= 'A' && digit <= 'D')
01047       return DAHDI_TONE_DTMF_A + (digit - 'A');
01048    else if (digit >= 'a' && digit <= 'd')
01049       return DAHDI_TONE_DTMF_A + (digit - 'a');
01050    else if (digit == '*')
01051       return DAHDI_TONE_DTMF_s;
01052    else if (digit == '#')
01053       return DAHDI_TONE_DTMF_p;
01054    else
01055       return -1;
01056 }
01057 
01058 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01059 {
01060    struct dahdi_pvt *pvt;
01061    int index;
01062    int dtmf = -1;
01063    
01064    pvt = chan->tech_pvt;
01065 
01066    ast_mutex_lock(&pvt->lock);
01067 
01068    index = dahdi_get_index(chan, pvt, 0);
01069 
01070    if ((index != SUB_REAL) || !pvt->owner)
01071       goto out;
01072 
01073 #ifdef HAVE_PRI
01074    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01075       if (pvt->setup_ack) {
01076          if (!pri_grab(pvt, pvt->pri)) {
01077             pri_information(pvt->pri->pri, pvt->call, digit);
01078             pri_rel(pvt->pri);
01079          } else
01080             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01081       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01082          int res;
01083          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01084          res = strlen(pvt->dialdest);
01085          pvt->dialdest[res++] = digit;
01086          pvt->dialdest[res] = '\0';
01087       }
01088       goto out;
01089    }
01090 #endif
01091    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01092       goto out;
01093 
01094    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01095       int res;
01096       struct dahdi_dialoperation zo = {
01097          .op = DAHDI_DIAL_OP_APPEND,
01098          .dialstr[0] = 'T',
01099          .dialstr[1] = digit,
01100          .dialstr[2] = 0,
01101       };
01102       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01103          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01104       else
01105          pvt->dialing = 1;
01106    } else {
01107       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01108       pvt->dialing = 1;
01109       pvt->begindigit = digit;
01110    }
01111 
01112 out:
01113    ast_mutex_unlock(&pvt->lock);
01114 
01115    return 0;
01116 }
01117 
01118 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01119 {
01120    struct dahdi_pvt *pvt;
01121    int res = 0;
01122    int index;
01123    int x;
01124    
01125    pvt = chan->tech_pvt;
01126 
01127    ast_mutex_lock(&pvt->lock);
01128    
01129    index = dahdi_get_index(chan, pvt, 0);
01130 
01131    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01132       goto out;
01133 
01134 #ifdef HAVE_PRI
01135    /* This means that the digit was already sent via PRI signalling */
01136    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01137       goto out;
01138 #endif
01139 
01140    if (pvt->begindigit) {
01141       x = -1;
01142       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01143       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01144       pvt->dialing = 0;
01145       pvt->begindigit = 0;
01146    }
01147 
01148 out:
01149    ast_mutex_unlock(&pvt->lock);
01150 
01151    return res;
01152 }
01153 
01154 static char *events[] = {
01155    "No event",
01156    "On hook",
01157    "Ring/Answered",
01158    "Wink/Flash",
01159    "Alarm",
01160    "No more alarm",
01161    "HDLC Abort",
01162    "HDLC Overrun",
01163    "HDLC Bad FCS",
01164    "Dial Complete",
01165    "Ringer On",
01166    "Ringer Off",
01167    "Hook Transition Complete",
01168    "Bits Changed",
01169    "Pulse Start",
01170    "Timer Expired",
01171    "Timer Ping",
01172    "Polarity Reversal",
01173    "Ring Begin",
01174 };
01175 
01176 static struct {
01177    int alarm;
01178    char *name;
01179 } alarms[] = {
01180    { DAHDI_ALARM_RED, "Red Alarm" },
01181    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01182    { DAHDI_ALARM_BLUE, "Blue Alarm" },
01183    { DAHDI_ALARM_RECOVER, "Recovering" },
01184    { DAHDI_ALARM_LOOPBACK, "Loopback" },
01185    { DAHDI_ALARM_NOTOPEN, "Not Open" },
01186    { DAHDI_ALARM_NONE, "None" },
01187 };
01188 
01189 static char *alarm2str(int alarm)
01190 {
01191    int x;
01192    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01193       if (alarms[x].alarm & alarm)
01194          return alarms[x].name;
01195    }
01196    return alarm ? "Unknown Alarm" : "No Alarm";
01197 }
01198 
01199 static char *event2str(int event)
01200 {
01201    static char buf[256];
01202    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01203       return events[event];
01204    sprintf(buf, "Event %d", event); /* safe */
01205    return buf;
01206 }
01207 
01208 #ifdef HAVE_PRI
01209 static char *dialplan2str(int dialplan)
01210 {
01211    if (dialplan == -1) {
01212       return("Dynamically set dialplan in ISDN");
01213    }
01214    return (pri_plan2str(dialplan));
01215 }
01216 #endif
01217 
01218 static char *dahdi_sig2str(int sig)
01219 {
01220    static char buf[256];
01221    switch (sig) {
01222    case SIG_EM:
01223       return "E & M Immediate";
01224    case SIG_EMWINK:
01225       return "E & M Wink";
01226    case SIG_EM_E1:
01227       return "E & M E1";
01228    case SIG_FEATD:
01229       return "Feature Group D (DTMF)";
01230    case SIG_FEATDMF:
01231       return "Feature Group D (MF)";
01232    case SIG_FEATDMF_TA:
01233       return "Feature Groud D (MF) Tandem Access";
01234    case SIG_FEATB:
01235       return "Feature Group B (MF)";
01236    case SIG_E911:
01237       return "E911 (MF)";
01238    case SIG_FGC_CAMA:
01239       return "FGC/CAMA (Dialpulse)";
01240    case SIG_FGC_CAMAMF:
01241       return "FGC/CAMA (MF)";
01242    case SIG_FXSLS:
01243       return "FXS Loopstart";
01244    case SIG_FXSGS:
01245       return "FXS Groundstart";
01246    case SIG_FXSKS:
01247       return "FXS Kewlstart";
01248    case SIG_FXOLS:
01249       return "FXO Loopstart";
01250    case SIG_FXOGS:
01251       return "FXO Groundstart";
01252    case SIG_FXOKS:
01253       return "FXO Kewlstart";
01254    case SIG_PRI:
01255       return "ISDN PRI";
01256    case SIG_SF:
01257       return "SF (Tone) Immediate";
01258    case SIG_SFWINK:
01259       return "SF (Tone) Wink";
01260    case SIG_SF_FEATD:
01261       return "SF (Tone) with Feature Group D (DTMF)";
01262    case SIG_SF_FEATDMF:
01263       return "SF (Tone) with Feature Group D (MF)";
01264    case SIG_SF_FEATB:
01265       return "SF (Tone) with Feature Group B (MF)";
01266    case SIG_GR303FXOKS:
01267       return "GR-303 with FXOKS";
01268    case SIG_GR303FXSKS:
01269       return "GR-303 with FXSKS";
01270    case 0:
01271       return "Pseudo";
01272    default:
01273       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01274       return buf;
01275    }
01276 }
01277 
01278 #define sig2str dahdi_sig2str
01279 
01280 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
01281 {
01282    /* If the conference already exists, and we're already in it
01283       don't bother doing anything */
01284    struct dahdi_confinfo zi;
01285    
01286    memset(&zi, 0, sizeof(zi));
01287    zi.chan = 0;
01288 
01289    if (slavechannel > 0) {
01290       /* If we have only one slave, do a digital mon */
01291       zi.confmode = DAHDI_CONF_DIGITALMON;
01292       zi.confno = slavechannel;
01293    } else {
01294       if (!index) {
01295          /* Real-side and pseudo-side both participate in conference */
01296          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01297             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01298       } else
01299          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01300       zi.confno = p->confno;
01301    }
01302    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01303       return 0;
01304    if (c->dfd < 0)
01305       return 0;
01306    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01307       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01308       return -1;
01309    }
01310    if (slavechannel < 1) {
01311       p->confno = zi.confno;
01312    }
01313    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01314    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01315    return 0;
01316 }
01317 
01318 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01319 {
01320    /* If they're listening to our channel, they're ours */  
01321    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01322       return 1;
01323    /* If they're a talker on our (allocated) conference, they're ours */
01324    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01325       return 1;
01326    return 0;
01327 }
01328 
01329 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
01330 {
01331    struct dahdi_confinfo zi;
01332    if (/* Can't delete if there's no dfd */
01333       (c->dfd < 0) ||
01334       /* Don't delete from the conference if it's not our conference */
01335       !isourconf(p, c)
01336       /* Don't delete if we don't think it's conferenced at all (implied) */
01337       ) return 0;
01338    memset(&zi, 0, sizeof(zi));
01339    zi.chan = 0;
01340    zi.confno = 0;
01341    zi.confmode = 0;
01342    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01343       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01344       return -1;
01345    }
01346    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01347    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01348    return 0;
01349 }
01350 
01351 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01352 {
01353    int x;
01354    int useslavenative;
01355    struct dahdi_pvt *slave = NULL;
01356    /* Start out optimistic */
01357    useslavenative = 1;
01358    /* Update conference state in a stateless fashion */
01359    for (x = 0; x < 3; x++) {
01360       /* Any three-way calling makes slave native mode *definitely* out
01361          of the question */
01362       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01363          useslavenative = 0;
01364    }
01365    /* If we don't have any 3-way calls, check to see if we have
01366       precisely one slave */
01367    if (useslavenative) {
01368       for (x = 0; x < MAX_SLAVES; x++) {
01369          if (p->slaves[x]) {
01370             if (slave) {
01371                /* Whoops already have a slave!  No 
01372                   slave native and stop right away */
01373                slave = NULL;
01374                useslavenative = 0;
01375                break;
01376             } else {
01377                /* We have one slave so far */
01378                slave = p->slaves[x];
01379             }
01380          }
01381       }
01382    }
01383    /* If no slave, slave native definitely out */
01384    if (!slave)
01385       useslavenative = 0;
01386    else if (slave->law != p->law) {
01387       useslavenative = 0;
01388       slave = NULL;
01389    }
01390    if (out)
01391       *out = slave;
01392    return useslavenative;
01393 }
01394 
01395 static int reset_conf(struct dahdi_pvt *p)
01396 {
01397    struct dahdi_confinfo zi;
01398    memset(&zi, 0, sizeof(zi));
01399    p->confno = -1;
01400    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01401    if (p->subs[SUB_REAL].dfd > -1) {
01402       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01403          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01404    }
01405    return 0;
01406 }
01407 
01408 static int update_conf(struct dahdi_pvt *p)
01409 {
01410    int needconf = 0;
01411    int x;
01412    int useslavenative;
01413    struct dahdi_pvt *slave = NULL;
01414 
01415    useslavenative = isslavenative(p, &slave);
01416    /* Start with the obvious, general stuff */
01417    for (x = 0; x < 3; x++) {
01418       /* Look for three way calls */
01419       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01420          conf_add(p, &p->subs[x], x, 0);
01421          needconf++;
01422       } else {
01423          conf_del(p, &p->subs[x], x);
01424       }
01425    }
01426    /* If we have a slave, add him to our conference now. or DAX
01427       if this is slave native */
01428    for (x = 0; x < MAX_SLAVES; x++) {
01429       if (p->slaves[x]) {
01430          if (useslavenative)
01431             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01432          else {
01433             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01434             needconf++;
01435          }
01436       }
01437    }
01438    /* If we're supposed to be in there, do so now */
01439    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01440       if (useslavenative)
01441          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01442       else {
01443          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01444          needconf++;
01445       }
01446    }
01447    /* If we have a master, add ourselves to his conference */
01448    if (p->master) {
01449       if (isslavenative(p->master, NULL)) {
01450          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01451       } else {
01452          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01453       }
01454    }
01455    if (!needconf) {
01456       /* Nobody is left (or should be left) in our conference.
01457          Kill it. */
01458       p->confno = -1;
01459    }
01460    if (option_debug)
01461       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01462    return 0;
01463 }
01464 
01465 static void dahdi_enable_ec(struct dahdi_pvt *p)
01466 {
01467    int x;
01468    int res;
01469    if (!p)
01470       return;
01471    if (p->echocanon) {
01472       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01473       return;
01474    }
01475    if (p->digital) {
01476       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01477       return;
01478    }
01479    if (p->echocancel) {
01480       if (p->sig == SIG_PRI) {
01481          x = 1;
01482          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01483          if (res)
01484             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01485       }
01486       x = p->echocancel;
01487       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01488       if (res) 
01489          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01490       else {
01491          p->echocanon = 1;
01492          if (option_debug)
01493             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01494       }
01495    } else if (option_debug)
01496       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01497 }
01498 
01499 static void dahdi_train_ec(struct dahdi_pvt *p)
01500 {
01501    int x;
01502    int res;
01503    if (p && p->echocancel && p->echotraining) {
01504       x = p->echotraining;
01505       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01506       if (res)
01507          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01508       else {
01509          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01510       }
01511    } else
01512       ast_log(LOG_DEBUG, "No echo training requested\n");
01513 }
01514 
01515 static void dahdi_disable_ec(struct dahdi_pvt *p)
01516 {
01517    int x;
01518    int res;
01519    if (p->echocancel) {
01520       x = 0;
01521       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01522       if (res)
01523          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01524       else if (option_debug)
01525          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01526    }
01527    p->echocanon = 0;
01528 }
01529 
01530 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
01531 {
01532    int j;
01533    int k;
01534    float linear_gain = pow(10.0, gain / 20.0);
01535 
01536    switch (law) {
01537    case DAHDI_LAW_ALAW:
01538       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01539          if (gain) {
01540             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01541             if (k > 32767) k = 32767;
01542             if (k < -32767) k = -32767;
01543             g->txgain[j] = AST_LIN2A(k);
01544          } else {
01545             g->txgain[j] = j;
01546          }
01547       }
01548       break;
01549    case DAHDI_LAW_MULAW:
01550       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01551          if (gain) {
01552             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01553             if (k > 32767) k = 32767;
01554             if (k < -32767) k = -32767;
01555             g->txgain[j] = AST_LIN2MU(k);
01556          } else {
01557             g->txgain[j] = j;
01558          }
01559       }
01560       break;
01561    }
01562 }
01563 
01564 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
01565 {
01566    int j;
01567    int k;
01568    float linear_gain = pow(10.0, gain / 20.0);
01569 
01570    switch (law) {
01571    case DAHDI_LAW_ALAW:
01572       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01573          if (gain) {
01574             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01575             if (k > 32767) k = 32767;
01576             if (k < -32767) k = -32767;
01577             g->rxgain[j] = AST_LIN2A(k);
01578          } else {
01579             g->rxgain[j] = j;
01580          }
01581       }
01582       break;
01583    case DAHDI_LAW_MULAW:
01584       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01585          if (gain) {
01586             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01587             if (k > 32767) k = 32767;
01588             if (k < -32767) k = -32767;
01589             g->rxgain[j] = AST_LIN2MU(k);
01590          } else {
01591             g->rxgain[j] = j;
01592          }
01593       }
01594       break;
01595    }
01596 }
01597 
01598 static int set_actual_txgain(int fd, int chan, float gain, int law)
01599 {
01600    struct dahdi_gains g;
01601    int res;
01602 
01603    memset(&g, 0, sizeof(g));
01604    g.chan = chan;
01605    res = ioctl(fd, DAHDI_GETGAINS, &g);
01606    if (res) {
01607       if (option_debug)
01608          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01609       return res;
01610    }
01611 
01612    fill_txgain(&g, gain, law);
01613 
01614    return ioctl(fd, DAHDI_SETGAINS, &g);
01615 }
01616 
01617 static int set_actual_rxgain(int fd, int chan, float gain, int law)
01618 {
01619    struct dahdi_gains g;
01620    int res;
01621 
01622    memset(&g, 0, sizeof(g));
01623    g.chan = chan;
01624    res = ioctl(fd, DAHDI_GETGAINS, &g);
01625    if (res) {
01626       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01627       return res;
01628    }
01629 
01630    fill_rxgain(&g, gain, law);
01631 
01632    return ioctl(fd, DAHDI_SETGAINS, &g);
01633 }
01634 
01635 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
01636 {
01637    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01638 }
01639 
01640 static int bump_gains(struct dahdi_pvt *p)
01641 {
01642    int res;
01643 
01644    /* Bump receive gain by 5.0db */
01645    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01646    if (res) {
01647       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01648       return -1;
01649    }
01650 
01651    return 0;
01652 }
01653 
01654 static int restore_gains(struct dahdi_pvt *p)
01655 {
01656    int res;
01657 
01658    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01659    if (res) {
01660       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01661       return -1;
01662    }
01663 
01664    return 0;
01665 }
01666 
01667 static inline int dahdi_set_hook(int fd, int hs)
01668 {
01669    int x, res;
01670 
01671    x = hs;
01672    res = ioctl(fd, DAHDI_HOOK, &x);
01673 
01674    if (res < 0) {
01675       if (errno == EINPROGRESS)
01676          return 0;
01677       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01678       /* will expectedly fail if phone is off hook during operation, such as during a restart */
01679    }
01680 
01681    return res;
01682 }
01683 
01684 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
01685 {
01686    int x, y, res;
01687    x = muted;
01688    if (p->sig == SIG_PRI) {
01689       y = 1;
01690       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01691       if (res)
01692          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
01693    }
01694    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
01695    if (res < 0)
01696       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
01697    return res;
01698 }
01699 
01700 static int save_conference(struct dahdi_pvt *p)
01701 {
01702    struct dahdi_confinfo c;
01703    int res;
01704    if (p->saveconf.confmode) {
01705       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
01706       return -1;
01707    }
01708    p->saveconf.chan = 0;
01709    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
01710    if (res) {
01711       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
01712       p->saveconf.confmode = 0;
01713       return -1;
01714    }
01715    c.chan = 0;
01716    c.confno = 0;
01717    c.confmode = DAHDI_CONF_NORMAL;
01718    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
01719    if (res) {
01720       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
01721       return -1;
01722    }
01723    if (option_debug)
01724       ast_log(LOG_DEBUG, "Disabled conferencing\n");
01725    return 0;
01726 }
01727 
01728 static int restore_conference(struct dahdi_pvt *p)
01729 {
01730    int res;
01731    if (p->saveconf.confmode) {
01732       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
01733       p->saveconf.confmode = 0;
01734       if (res) {
01735          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
01736          return -1;
01737       }
01738    }
01739    if (option_debug)
01740       ast_log(LOG_DEBUG, "Restored conferencing\n");
01741    return 0;
01742 }
01743 
01744 static int send_callerid(struct dahdi_pvt *p);
01745 
01746 static int send_cwcidspill(struct dahdi_pvt *p)
01747 {
01748    p->callwaitcas = 0;
01749    p->cidcwexpire = 0;
01750    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
01751       return -1;
01752    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
01753    /* Make sure we account for the end */
01754    p->cidlen += READ_SIZE * 4;
01755    p->cidpos = 0;
01756    send_callerid(p);
01757    if (option_verbose > 2)
01758       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
01759    return 0;
01760 }
01761 
01762 static int has_voicemail(struct dahdi_pvt *p)
01763 {
01764 
01765    return ast_app_has_voicemail(p->mailbox, NULL);
01766 }
01767 
01768 static int send_callerid(struct dahdi_pvt *p)
01769 {
01770    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
01771    int res;
01772    /* Take out of linear mode if necessary */
01773    if (p->subs[SUB_REAL].linear) {
01774       p->subs[SUB_REAL].linear = 0;
01775       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
01776    }
01777    while (p->cidpos < p->cidlen) {
01778       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
01779       if (res < 0) {
01780          if (errno == EAGAIN)
01781             return 0;
01782          else {
01783             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
01784             return -1;
01785          }
01786       }
01787       if (!res)
01788          return 0;
01789       p->cidpos += res;
01790    }
01791    free(p->cidspill);
01792    p->cidspill = NULL;
01793    if (p->callwaitcas) {
01794       /* Wait for CID/CW to expire */
01795       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
01796    } else
01797       restore_conference(p);
01798    return 0;
01799 }
01800 
01801 static int dahdi_callwait(struct ast_channel *ast)
01802 {
01803    struct dahdi_pvt *p = ast->tech_pvt;
01804    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01805    if (p->cidspill) {
01806       ast_log(LOG_WARNING, "Spill already exists?!?\n");
01807       free(p->cidspill);
01808    }
01809    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
01810       return -1;
01811    save_conference(p);
01812    /* Silence */
01813    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01814    if (!p->callwaitrings && p->callwaitingcallerid) {
01815       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01816       p->callwaitcas = 1;
01817       p->cidlen = 2400 + 680 + READ_SIZE * 4;
01818    } else {
01819       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01820       p->callwaitcas = 0;
01821       p->cidlen = 2400 + READ_SIZE * 4;
01822    }
01823    p->cidpos = 0;
01824    send_callerid(p);
01825    
01826    return 0;
01827 }
01828 
01829 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
01830 {
01831    struct dahdi_pvt *p = ast->tech_pvt;
01832    int x, res, index,mysig;
01833    char *c, *n, *l;
01834 #ifdef HAVE_PRI
01835    char *s = NULL;
01836 #endif
01837    char dest[256]; /* must be same length as p->dialdest */
01838    ast_mutex_lock(&p->lock);
01839    ast_copy_string(dest, rdest, sizeof(dest));
01840    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
01841    if ((ast->_state == AST_STATE_BUSY)) {
01842       p->subs[SUB_REAL].needbusy = 1;
01843       ast_mutex_unlock(&p->lock);
01844       return 0;
01845    }
01846    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01847       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
01848       ast_mutex_unlock(&p->lock);
01849       return -1;
01850    }
01851    p->dialednone = 0;
01852    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
01853    {
01854       /* Special pseudo -- automatically up */
01855       ast_setstate(ast, AST_STATE_UP); 
01856       ast_mutex_unlock(&p->lock);
01857       return 0;
01858    }
01859    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
01860    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
01861    if (res)
01862       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
01863    p->outgoing = 1;
01864 
01865    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01866 
01867    mysig = p->sig;
01868    if (p->outsigmod > -1)
01869       mysig = p->outsigmod;
01870 
01871    switch (mysig) {
01872    case SIG_FXOLS:
01873    case SIG_FXOGS:
01874    case SIG_FXOKS:
01875       if (p->owner == ast) {
01876          /* Normal ring, on hook */
01877          
01878          /* Don't send audio while on hook, until the call is answered */
01879          p->dialing = 1;
01880          if (p->use_callerid) {
01881             /* Generate the Caller-ID spill if desired */
01882             if (p->cidspill) {
01883                ast_log(LOG_WARNING, "cidspill already exists??\n");
01884                free(p->cidspill);
01885             }
01886             p->callwaitcas = 0;
01887             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01888                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
01889                p->cidpos = 0;
01890                send_callerid(p);
01891             }
01892          }
01893          /* Choose proper cadence */
01894          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
01895             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
01896                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
01897             p->cidrings = cidrings[p->distinctivering - 1];
01898          } else {
01899             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
01900                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
01901             p->cidrings = p->sendcalleridafter;
01902          }
01903 
01904          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
01905          c = strchr(dest, '/');
01906          if (c)
01907             c++;
01908          if (c && (strlen(c) < p->stripmsd)) {
01909             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01910             c = NULL;
01911          }
01912          if (c) {
01913             p->dop.op = DAHDI_DIAL_OP_REPLACE;
01914             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
01915             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
01916          } else {
01917             p->dop.dialstr[0] = '\0';
01918          }
01919          x = DAHDI_RING;
01920          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
01921             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
01922             ast_mutex_unlock(&p->lock);
01923             return -1;
01924          }
01925          p->dialing = 1;
01926       } else {
01927          /* Call waiting call */
01928          p->callwaitrings = 0;
01929          if (ast->cid.cid_num)
01930             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
01931          else
01932             p->callwait_num[0] = '\0';
01933          if (ast->cid.cid_name)
01934             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
01935          else
01936             p->callwait_name[0] = '\0';
01937          /* Call waiting tone instead */
01938          if (dahdi_callwait(ast)) {
01939             ast_mutex_unlock(&p->lock);
01940             return -1;
01941          }
01942          /* Make ring-back */
01943          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
01944             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
01945             
01946       }
01947       n = ast->cid.cid_name;
01948       l = ast->cid.cid_num;
01949       if (l)
01950          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
01951       else
01952          p->lastcid_num[0] = '\0';
01953       if (n)
01954          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
01955       else
01956          p->lastcid_name[0] = '\0';
01957       ast_setstate(ast, AST_STATE_RINGING);
01958       index = dahdi_get_index(ast, p, 0);
01959       if (index > -1) {
01960          p->subs[index].needringing = 1;
01961       }
01962       break;
01963    case SIG_FXSLS:
01964    case SIG_FXSGS:
01965    case SIG_FXSKS:
01966    case SIG_EMWINK:
01967    case SIG_EM:
01968    case SIG_EM_E1:
01969    case SIG_FEATD:
01970    case SIG_FEATDMF:
01971    case SIG_E911:
01972    case SIG_FGC_CAMA:
01973    case SIG_FGC_CAMAMF:
01974    case SIG_FEATB:
01975    case SIG_SFWINK:
01976    case SIG_SF:
01977    case SIG_SF_FEATD:
01978    case SIG_SF_FEATDMF:
01979    case SIG_FEATDMF_TA:
01980    case SIG_SF_FEATB:
01981       c = strchr(dest, '/');
01982       if (c)
01983          c++;
01984       else
01985          c = "";
01986       if (strlen(c) < p->stripmsd) {
01987          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
01988          ast_mutex_unlock(&p->lock);
01989          return -1;
01990       }
01991 #ifdef HAVE_PRI
01992       /* Start the trunk, if not GR-303 */
01993       if (!p->pri) {
01994 #endif
01995          x = DAHDI_START;
01996          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
01997          if (res < 0) {
01998             if (errno != EINPROGRESS) {
01999                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02000                ast_mutex_unlock(&p->lock);
02001                return -1;
02002             }
02003          }
02004 #ifdef HAVE_PRI
02005       }
02006 #endif
02007       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02008       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02009 
02010       c += p->stripmsd;
02011 
02012       switch (mysig) {
02013       case SIG_FEATD:
02014          l = ast->cid.cid_num;
02015          if (l) 
02016             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02017          else
02018             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02019          break;
02020       case SIG_FEATDMF:
02021          l = ast->cid.cid_num;
02022          if (l) 
02023             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02024          else
02025             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02026          break;
02027       case SIG_FEATDMF_TA:
02028       {
02029          const char *cic, *ozz;
02030 
02031          /* If you have to go through a Tandem Access point you need to use this */
02032          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02033          if (!ozz)
02034             ozz = defaultozz;
02035          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02036          if (!cic)
02037             cic = defaultcic;
02038          if (!ozz || !cic) {
02039             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02040             ast_mutex_unlock(&p->lock);
02041             return -1;
02042          }
02043          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02044          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02045          p->whichwink = 0;
02046       }
02047          break;
02048       case SIG_E911:
02049          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02050          break;
02051       case SIG_FGC_CAMA:
02052          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02053          break;
02054       case SIG_FGC_CAMAMF:
02055       case SIG_FEATB:
02056          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02057          break;
02058       default:
02059          if (p->pulse)
02060             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02061          else
02062             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02063          break;
02064       }
02065 
02066       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02067          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02068          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02069          p->echorest[sizeof(p->echorest) - 1] = '\0';
02070          p->echobreak = 1;
02071          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02072       } else
02073          p->echobreak = 0;
02074       if (!res) {
02075          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02076             int saveerr = errno;
02077 
02078             x = DAHDI_ONHOOK;
02079             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02080             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02081             ast_mutex_unlock(&p->lock);
02082             return -1;
02083          }
02084       } else
02085          ast_log(LOG_DEBUG, "Deferring dialing...\n");
02086       p->dialing = 1;
02087       if (ast_strlen_zero(c))
02088          p->dialednone = 1;
02089       ast_setstate(ast, AST_STATE_DIALING);
02090       break;
02091    case 0:
02092       /* Special pseudo -- automatically up*/
02093       ast_setstate(ast, AST_STATE_UP);
02094       break;      
02095    case SIG_PRI:
02096       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02097       p->dialdest[0] = '\0';
02098       break;
02099    default:
02100       ast_log(LOG_DEBUG, "not yet implemented\n");
02101       ast_mutex_unlock(&p->lock);
02102       return -1;
02103    }
02104 #ifdef HAVE_PRI
02105    if (p->pri) {
02106       struct pri_sr *sr;
02107 #ifdef SUPPORT_USERUSER
02108       const char *useruser;
02109 #endif
02110       int pridialplan;
02111       int dp_strip;
02112       int prilocaldialplan;
02113       int ldp_strip;
02114       int exclusive;
02115       const char *rr_str;
02116       int redirect_reason;
02117 
02118       c = strchr(dest, '/');
02119       if (c)
02120          c++;
02121       else
02122          c = dest;
02123 
02124       l = NULL;
02125       n = NULL;
02126 
02127       if (!p->hidecallerid) {
02128          l = ast->cid.cid_num;
02129          if (!p->hidecalleridname) {
02130             n = ast->cid.cid_name;
02131          }
02132       }
02133 
02134 
02135       if (strlen(c) < p->stripmsd) {
02136          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02137          ast_mutex_unlock(&p->lock);
02138          return -1;
02139       }
02140       if (mysig != SIG_FXSKS) {
02141          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02142          s = strchr(c + p->stripmsd, 'w');
02143          if (s) {
02144             if (strlen(s) > 1)
02145                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02146             else
02147                p->dop.dialstr[0] = '\0';
02148             *s = '\0';
02149          } else {
02150             p->dop.dialstr[0] = '\0';
02151          }
02152       }
02153       if (pri_grab(p, p->pri)) {
02154          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02155          ast_mutex_unlock(&p->lock);
02156          return -1;
02157       }
02158       if (!(p->call = pri_new_call(p->pri->pri))) {
02159          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02160          pri_rel(p->pri);
02161          ast_mutex_unlock(&p->lock);
02162          return -1;
02163       }
02164       if (!(sr = pri_sr_new())) {
02165          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02166          pri_destroycall(p->pri->pri, p->call);
02167          p->call = NULL;
02168          pri_rel(p->pri);
02169          ast_mutex_unlock(&p->lock);
02170          return -1;
02171       }
02172       if (p->bearer || (mysig == SIG_FXSKS)) {
02173          if (p->bearer) {
02174             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);
02175             p->bearer->call = p->call;
02176          } else
02177             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02178          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02179       }
02180       p->digital = IS_DIGITAL(ast->transfercapability);
02181       /* Add support for exclusive override */
02182       if (p->priexclusive)
02183          exclusive = 1;
02184       else {
02185       /* otherwise, traditional behavior */
02186          if (p->pri->nodetype == PRI_NETWORK)
02187             exclusive = 0;
02188          else
02189             exclusive = 1;
02190       }
02191       
02192       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02193       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02194                (p->digital ? -1 : 
02195                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02196       if (p->pri->facilityenable)
02197          pri_facility_enable(p->pri->pri);
02198 
02199       if (option_verbose > 2)
02200          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02201       dp_strip = 0;
02202       pridialplan = p->pri->dialplan - 1;
02203       if (pridialplan == -2) { /* compute dynamically */
02204          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02205             dp_strip = strlen(p->pri->internationalprefix);
02206             pridialplan = PRI_INTERNATIONAL_ISDN;
02207          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02208             dp_strip = strlen(p->pri->nationalprefix);
02209             pridialplan = PRI_NATIONAL_ISDN;
02210          } else {
02211             pridialplan = PRI_LOCAL_ISDN;
02212          }
02213       }
02214       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02215 
02216       ldp_strip = 0;
02217       prilocaldialplan = p->pri->localdialplan - 1;
02218       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
02219          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02220             ldp_strip = strlen(p->pri->internationalprefix);
02221             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02222          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02223             ldp_strip = strlen(p->pri->nationalprefix);
02224             prilocaldialplan = PRI_NATIONAL_ISDN;
02225          } else {
02226             prilocaldialplan = PRI_LOCAL_ISDN;
02227          }
02228       }
02229       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02230          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02231       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02232          if (!strcasecmp(rr_str, "UNKNOWN"))
02233             redirect_reason = 0;
02234          else if (!strcasecmp(rr_str, "BUSY"))
02235             redirect_reason = 1;
02236          else if (!strcasecmp(rr_str, "NO_REPLY"))
02237             redirect_reason = 2;
02238          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02239             redirect_reason = 15;
02240          else
02241             redirect_reason = PRI_REDIR_UNCONDITIONAL;
02242       } else
02243          redirect_reason = PRI_REDIR_UNCONDITIONAL;
02244       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02245 
02246 #ifdef SUPPORT_USERUSER
02247       /* User-user info */
02248       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02249 
02250       if (useruser)
02251          pri_sr_set_useruser(sr, useruser);
02252 #endif
02253 
02254       if (pri_setup(p->pri->pri, p->call, sr)) {
02255          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
02256             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02257          pri_rel(p->pri);
02258          ast_mutex_unlock(&p->lock);
02259          pri_sr_free(sr);
02260          return -1;
02261       }
02262       pri_sr_free(sr);
02263       ast_setstate(ast, AST_STATE_DIALING);
02264       pri_rel(p->pri);
02265    }
02266 #endif      
02267    ast_mutex_unlock(&p->lock);
02268    return 0;
02269 }
02270 
02271 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
02272 {
02273    struct dahdi_pvt *p = *pvt;
02274    /* Remove channel from the list */
02275    if (p->prev)
02276       p->prev->next = p->next;
02277    if (p->next)
02278       p->next->prev = p->prev;
02279    if (p->use_smdi)
02280       ast_smdi_interface_unref(p->smdi_iface);
02281    ast_mutex_destroy(&p->lock);
02282    dahdi_close_sub(p, SUB_REAL);
02283    if (p->owner)
02284       p->owner->tech_pvt = NULL;
02285    free(p);
02286    *pvt = NULL;
02287 }
02288 
02289 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
02290 {
02291    int owned = 0;
02292    int i = 0;
02293 
02294    if (!now) {
02295       if (cur->owner) {
02296          owned = 1;
02297       }
02298 
02299       for (i = 0; i < 3; i++) {
02300          if (cur->subs[i].owner) {
02301             owned = 1;
02302          }
02303       }
02304       if (!owned) {
02305          if (prev) {
02306             prev->next = cur->next;
02307             if (prev->next)
02308                prev->next->prev = prev;
02309             else
02310                ifend = prev;
02311          } else {
02312             iflist = cur->next;
02313             if (iflist)
02314                iflist->prev = NULL;
02315             else
02316                ifend = NULL;
02317          }
02318          destroy_dahdi_pvt(&cur);
02319       }
02320    } else {
02321       if (prev) {
02322          prev->next = cur->next;
02323          if (prev->next)
02324             prev->next->prev = prev;
02325          else
02326             ifend = prev;
02327       } else {
02328          iflist = cur->next;
02329          if (iflist)
02330             iflist->prev = NULL;
02331          else
02332             ifend = NULL;
02333       }
02334       destroy_dahdi_pvt(&cur);
02335    }
02336    return 0;
02337 }
02338 
02339 static void destroy_all_channels(void)
02340 {
02341    int x;
02342    struct dahdi_pvt *p, *pl;
02343 
02344    while (num_restart_pending) {
02345       usleep(1);
02346    }
02347 
02348    ast_mutex_lock(&iflock);
02349    /* Destroy all the interfaces and free their memory */
02350    p = iflist;
02351    while (p) {
02352       /* Free any callerid */
02353       if (p->cidspill)
02354          ast_free(p->cidspill);
02355       pl = p;
02356       p = p->next;
02357       x = pl->channel;
02358       /* Free associated memory */
02359       if (pl)
02360          destroy_dahdi_pvt(&pl);
02361       if (option_verbose > 2) 
02362          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02363    }
02364    iflist = NULL;
02365    ifcount = 0;
02366    ast_mutex_unlock(&iflock);
02367 }
02368 
02369 #ifdef HAVE_PRI
02370 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
02371 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
02372 
02373 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02374 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
02375 
02376 static char *dahdi_send_keypad_facility_descrip = 
02377 "  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02378 "  IE over the current channel.\n";
02379 static char *zap_send_keypad_facility_descrip = 
02380 "  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
02381 "  IE over the current channel.\n";
02382 
02383 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
02384 {
02385    /* Data will be our digit string */
02386    struct dahdi_pvt *p;
02387    char *digits = (char *) data;
02388 
02389    if (ast_strlen_zero(digits)) {
02390       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02391       return -1;
02392    }
02393 
02394    p = (struct dahdi_pvt *)chan->tech_pvt;
02395 
02396    if (!p) {
02397       ast_log(LOG_DEBUG, "Unable to find technology private\n");
02398       return -1;
02399    }
02400 
02401    ast_mutex_lock(&p->lock);
02402 
02403    if (!p->pri || !p->call) {
02404       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02405       ast_mutex_unlock(&p->lock);
02406       return -1;
02407    }
02408 
02409    if (!pri_grab(p, p->pri)) {
02410       pri_keypad_facility(p->pri->pri, p->call, digits);
02411       pri_rel(p->pri);
02412    } else {
02413       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02414       ast_mutex_unlock(&p->lock);
02415       return -1;
02416    }
02417 
02418    ast_mutex_unlock(&p->lock);
02419 
02420    return 0;
02421 }
02422 
02423 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02424 {
02425    return send_keypad_facility_exec(chan, data);
02426 }
02427 
02428 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
02429 {
02430    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);  
02431    return send_keypad_facility_exec(chan, data);
02432 }
02433 
02434 static int pri_is_up(struct dahdi_pri *pri)
02435 {
02436    int x;
02437    for (x = 0; x < NUM_DCHANS; x++) {
02438       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02439          return 1;
02440    }
02441    return 0;
02442 }
02443 
02444 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
02445 {
02446    bearer->owner = &inuse;
02447    bearer->realcall = crv;
02448    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02449    if (crv->subs[SUB_REAL].owner)
02450       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02451    crv->bearer = bearer;
02452    crv->call = bearer->call;
02453    crv->pri = pri;
02454    return 0;
02455 }
02456 
02457 static char *pri_order(int level)
02458 {
02459    switch (level) {
02460    case 0:
02461       return "Primary";
02462    case 1:
02463       return "Secondary";
02464    case 2:
02465       return "Tertiary";
02466    case 3:
02467       return "Quaternary";
02468    default:
02469       return "<Unknown>";
02470    }     
02471 }
02472 
02473 /* Returns fd of the active dchan */
02474 static int pri_active_dchan_fd(struct dahdi_pri *pri)
02475 {
02476    int x = -1;
02477 
02478    for (x = 0; x < NUM_DCHANS; x++) {
02479       if ((pri->dchans[x] == pri->pri))
02480          break;
02481    }
02482 
02483    return pri->fds[x];
02484 }
02485 
02486 static int pri_find_dchan(struct dahdi_pri *pri)
02487 {
02488    int oldslot = -1;
02489    struct pri *old;
02490    int newslot = -1;
02491    int x;
02492    old = pri->pri;
02493    for (x = 0; x < NUM_DCHANS; x++) {
02494       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02495          newslot = x;
02496       if (pri->dchans[x] == old) {
02497          oldslot = x;
02498       }
02499    }
02500    if (newslot < 0) {
02501       newslot = 0;
02502       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
02503          pri->dchannels[newslot]);
02504    }
02505    if (old && (oldslot != newslot))
02506       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02507          pri->dchannels[oldslot], pri->dchannels[newslot]);
02508    pri->pri = pri->dchans[newslot];
02509    return 0;
02510 }
02511 #endif
02512 
02513 static int dahdi_hangup(struct ast_channel *ast)
02514 {
02515    int res;
02516    int index,x, law;
02517    /*static int restore_gains(struct dahdi_pvt *p);*/
02518    struct dahdi_pvt *p = ast->tech_pvt;
02519    struct dahdi_pvt *tmp = NULL;
02520    struct dahdi_pvt *prev = NULL;
02521    struct dahdi_params par;
02522 
02523    if (option_debug)
02524       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02525    if (!ast->tech_pvt) {
02526       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02527       return 0;
02528    }
02529    
02530    ast_mutex_lock(&p->lock);
02531    
02532    index = dahdi_get_index(ast, p, 1);
02533 
02534    if (p->sig == SIG_PRI) {
02535       x = 1;
02536       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02537    }
02538 
02539    x = 0;
02540    dahdi_confmute(p, 0);
02541    restore_gains(p);
02542    if (p->origcid_num) {
02543       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02544       free(p->origcid_num);
02545       p->origcid_num = NULL;
02546    }  
02547    if (p->origcid_name) {
02548       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02549       free(p->origcid_name);
02550       p->origcid_name = NULL;
02551    }  
02552    if (p->dsp)
02553       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02554    if (p->exten)
02555       p->exten[0] = '\0';
02556 
02557    if (option_debug)
02558       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02559       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02560    p->ignoredtmf = 0;
02561    
02562    if (index > -1) {
02563       /* Real channel, do some fixup */
02564       p->subs[index].owner = NULL;
02565       p->subs[index].needanswer = 0;
02566       p->subs[index].needflash = 0;
02567       p->subs[index].needringing = 0;
02568       p->subs[index].needbusy = 0;
02569       p->subs[index].needcongestion = 0;
02570       p->subs[index].linear = 0;
02571       p->subs[index].needcallerid = 0;
02572       p->polarity = POLARITY_IDLE;
02573       dahdi_setlinear(p->subs[index].dfd, 0);
02574       if (index == SUB_REAL) {
02575          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02576             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02577             if (p->subs[SUB_CALLWAIT].inthreeway) {
02578                /* We had flipped over to answer a callwait and now it's gone */
02579                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02580                /* Move to the call-wait, but un-own us until they flip back. */
02581                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02582                unalloc_sub(p, SUB_CALLWAIT);
02583                p->owner = NULL;
02584             } else {
02585                /* The three way hung up, but we still have a call wait */
02586                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02587                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02588                unalloc_sub(p, SUB_THREEWAY);
02589                if (p->subs[SUB_REAL].inthreeway) {
02590                   /* This was part of a three way call.  Immediately make way for
02591                      another call */
02592                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02593                   p->owner = p->subs[SUB_REAL].owner;
02594                } else {
02595                   /* This call hasn't been completed yet...  Set owner to NULL */
02596                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02597                   p->owner = NULL;
02598                }
02599                p->subs[SUB_REAL].inthreeway = 0;
02600             }
02601          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02602             /* Move to the call-wait and switch back to them. */
02603             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02604             unalloc_sub(p, SUB_CALLWAIT);
02605             p->owner = p->subs[SUB_REAL].owner;
02606             if (p->owner->_state != AST_STATE_UP)
02607                p->subs[SUB_REAL].needanswer = 1;
02608             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02609                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02610          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02611             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02612             unalloc_sub(p, SUB_THREEWAY);
02613             if (p->subs[SUB_REAL].inthreeway) {
02614                /* This was part of a three way call.  Immediately make way for
02615                   another call */
02616                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02617                p->owner = p->subs[SUB_REAL].owner;
02618             } else {
02619                /* This call hasn't been completed yet...  Set owner to NULL */
02620                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02621                p->owner = NULL;
02622             }
02623             p->subs[SUB_REAL].inthreeway = 0;
02624          }
02625       } else if (index == SUB_CALLWAIT) {
02626          /* Ditch the holding callwait call, and immediately make it availabe */
02627          if (p->subs[SUB_CALLWAIT].inthreeway) {
02628             /* This is actually part of a three way, placed on hold.  Place the third part
02629                on music on hold now */
02630             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02631                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02632                   S_OR(p->mohsuggest, NULL),
02633                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02634             }
02635             p->subs[SUB_THREEWAY].inthreeway = 0;
02636             /* Make it the call wait now */
02637             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02638             unalloc_sub(p, SUB_THREEWAY);
02639          } else
02640             unalloc_sub(p, SUB_CALLWAIT);
02641       } else if (index == SUB_THREEWAY) {
02642          if (p->subs[SUB_CALLWAIT].inthreeway) {
02643             /* The other party of the three way call is currently in a call-wait state.
02644                Start music on hold for them, and take the main guy out of the third call */
02645             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02646                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02647                   S_OR(p->mohsuggest, NULL),
02648                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02649             }
02650             p->subs[SUB_CALLWAIT].inthreeway = 0;
02651          }
02652          p->subs[SUB_REAL].inthreeway = 0;
02653          /* If this was part of a three way call index, let us make
02654             another three way call */
02655          unalloc_sub(p, SUB_THREEWAY);
02656       } else {
02657          /* This wasn't any sort of call, but how are we an index? */
02658          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02659       }
02660    }
02661 
02662    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02663       p->owner = NULL;
02664       p->ringt = 0;
02665       p->distinctivering = 0;
02666       p->confirmanswer = 0;
02667       p->cidrings = 1;
02668       p->outgoing = 0;
02669       p->digital = 0;
02670       p->faxhandled = 0;
02671       p->pulsedial = 0;
02672       p->onhooktime = time(NULL);
02673 #ifdef HAVE_PRI
02674       p->proceeding = 0;
02675       p->progress = 0;
02676       p->alerting = 0;
02677       p->setup_ack = 0;
02678 #endif      
02679       if (p->dsp) {
02680          ast_dsp_free(p->dsp);
02681          p->dsp = NULL;
02682       }
02683 
02684       law = DAHDI_LAW_DEFAULT;
02685       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02686       if (res < 0) 
02687          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02688       /* Perform low level hangup if no owner left */
02689 #ifdef HAVE_PRI
02690       if (p->pri) {
02691 #ifdef SUPPORT_USERUSER
02692          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02693 #endif
02694 
02695          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
02696          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02697             if (!pri_grab(p, p->pri)) {
02698                if (p->alreadyhungup) {
02699                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
02700 
02701 #ifdef SUPPORT_USERUSER
02702                   pri_call_set_useruser(p->call, useruser);
02703 #endif
02704 
02705                   pri_hangup(p->pri->pri, p->call, -1);
02706                   p->call = NULL;
02707                   if (p->bearer) 
02708                      p->bearer->call = NULL;
02709                } else {
02710                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
02711                   int icause = ast->hangupcause ? ast->hangupcause : -1;
02712                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
02713 
02714 #ifdef SUPPORT_USERUSER
02715                   pri_call_set_useruser(p->call, useruser);
02716 #endif
02717 
02718                   p->alreadyhungup = 1;
02719                   if (p->bearer)
02720                      p->bearer->alreadyhungup = 1;
02721                   if (cause) {
02722                      if (atoi(cause))
02723                         icause = atoi(cause);
02724                   }
02725                   pri_hangup(p->pri->pri, p->call, icause);
02726                }
02727                if (res < 0) 
02728                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
02729                pri_rel(p->pri);        
02730             } else {
02731                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02732                res = -1;
02733             }
02734          } else {
02735             if (p->bearer)
02736                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
02737             p->call = NULL;
02738             res = 0;
02739          }
02740       }
02741 #endif
02742       if (p->sig && (p->sig != SIG_PRI))
02743          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
02744       if (res < 0) {
02745          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
02746       }
02747       switch (p->sig) {
02748       case SIG_FXOGS:
02749       case SIG_FXOLS:
02750       case SIG_FXOKS:
02751          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02752          if (!res) {
02753 #if 0
02754             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
02755 #endif
02756             /* If they're off hook, try playing congestion */
02757             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
02758                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
02759             else
02760                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02761          }
02762          break;
02763       case SIG_FXSGS:
02764       case SIG_FXSLS:
02765       case SIG_FXSKS:
02766          /* Make sure we're not made available for at least two seconds assuming
02767             we were actually used for an inbound or outbound call. */
02768          if (ast->_state != AST_STATE_RESERVED) {
02769             time(&p->guardtime);
02770             p->guardtime += 2;
02771          }
02772          break;
02773       default:
02774          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
02775       }
02776       if (p->cidspill)
02777          free(p->cidspill);
02778       if (p->sig)
02779          dahdi_disable_ec(p);
02780       x = 0;
02781       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
02782       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
02783       p->didtdd = 0;
02784       p->cidspill = NULL;
02785       p->callwaitcas = 0;
02786       p->callwaiting = p->permcallwaiting;
02787       p->hidecallerid = p->permhidecallerid;
02788       p->dialing = 0;
02789       p->rdnis[0] = '\0';
02790       update_conf(p);
02791       reset_conf(p);
02792       /* Restore data mode */
02793       if (p->sig == SIG_PRI) {
02794          x = 0;
02795          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02796       }
02797 #ifdef HAVE_PRI
02798       if (p->bearer) {
02799          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
02800          /* Free up the bearer channel as well, and
02801             don't use its file descriptor anymore */
02802          update_conf(p->bearer);
02803          reset_conf(p->bearer);
02804          p->bearer->owner = NULL;
02805          p->bearer->realcall = NULL;
02806          p->bearer = NULL;
02807          p->subs[SUB_REAL].dfd = -1;
02808          p->pri = NULL;
02809       }
02810 #endif
02811       if (num_restart_pending == 0)
02812          restart_monitor();
02813    }
02814 
02815    p->callwaitingrepeat = 0;
02816    p->cidcwexpire = 0;
02817    p->oprmode = 0;
02818    ast->tech_pvt = NULL;
02819    ast_mutex_unlock(&p->lock);
02820    ast_module_unref(ast_module_info->self);
02821    if (option_verbose > 2) 
02822       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
02823 
02824    ast_mutex_lock(&iflock);
02825 
02826    if (p->restartpending) {
02827       num_restart_pending--;
02828    }
02829 
02830    tmp = iflist;
02831    prev = NULL;
02832    if (p->destroy) {
02833       while (tmp) {
02834          if (tmp == p) {
02835             destroy_channel(prev, tmp, 0);
02836             break;
02837          } else {
02838             prev = tmp;
02839             tmp = tmp->next;
02840          }
02841       }
02842    }
02843    ast_mutex_unlock(&iflock);
02844    return 0;
02845 }
02846 
02847 static int dahdi_answer(struct ast_channel *ast)
02848 {
02849    struct dahdi_pvt *p = ast->tech_pvt;
02850    int res = 0;
02851    int index;
02852    int oldstate = ast->_state;
02853    ast_setstate(ast, AST_STATE_UP);
02854    ast_mutex_lock(&p->lock);
02855    index = dahdi_get_index(ast, p, 0);
02856    if (index < 0)
02857       index = SUB_REAL;
02858    /* nothing to do if a radio channel */
02859    if ((p->radio || (p->oprmode < 0))) {
02860       ast_mutex_unlock(&p->lock);
02861       return 0;
02862    }
02863    switch (p->sig) {
02864    case SIG_FXSLS:
02865    case SIG_FXSGS:
02866    case SIG_FXSKS:
02867       p->ringt = 0;
02868       /* Fall through */
02869    case SIG_EM:
02870    case SIG_EM_E1:
02871    case SIG_EMWINK:
02872    case SIG_FEATD:
02873    case SIG_FEATDMF:
02874    case SIG_FEATDMF_TA:
02875    case SIG_E911:
02876    case SIG_FGC_CAMA:
02877    case SIG_FGC_CAMAMF:
02878    case SIG_FEATB:
02879    case SIG_SF:
02880    case SIG_SFWINK:
02881    case SIG_SF_FEATD:
02882    case SIG_SF_FEATDMF:
02883    case SIG_SF_FEATB:
02884    case SIG_FXOLS:
02885    case SIG_FXOGS:
02886    case SIG_FXOKS:
02887       /* Pick up the line */
02888       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
02889       if (p->hanguponpolarityswitch) {
02890          gettimeofday(&p->polaritydelaytv, NULL);
02891       }
02892       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02893       tone_zone_play_tone(p->subs[index].dfd, -1);
02894       p->dialing = 0;
02895       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
02896          if (oldstate == AST_STATE_RINGING) {
02897             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
02898             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
02899             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02900             p->owner = p->subs[SUB_REAL].owner;
02901          }
02902       }
02903       if (p->sig & __DAHDI_SIG_FXS) {
02904          dahdi_enable_ec(p);
02905          dahdi_train_ec(p);
02906       }
02907       break;
02908 #ifdef HAVE_PRI
02909    case SIG_PRI:
02910       /* Send a pri acknowledge */
02911       if (!pri_grab(p, p->pri)) {
02912          p->proceeding = 1;
02913          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
02914          pri_rel(p->pri);
02915       } else {
02916          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
02917          res = -1;
02918       }
02919       break;
02920 #endif
02921    case 0:
02922       ast_mutex_unlock(&p->lock);
02923       return 0;
02924    default:
02925       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
02926       res = -1;
02927    }
02928    ast_mutex_unlock(&p->lock);
02929    return res;
02930 }
02931 
02932 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
02933 {
02934    char *cp;
02935    signed char *scp;
02936    int x;
02937    int index;
02938    struct dahdi_pvt *p = chan->tech_pvt, *pp;
02939    struct oprmode *oprmode;
02940    
02941 
02942    /* all supported options require data */
02943    if (!data || (datalen < 1)) {
02944       errno = EINVAL;
02945       return -1;
02946    }
02947 
02948    switch (option) {
02949    case AST_OPTION_TXGAIN:
02950       scp = (signed char *) data;
02951       index = dahdi_get_index(chan, p, 0);
02952       if (index < 0) {
02953          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
02954          return -1;
02955       }
02956       if (option_debug)
02957          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
02958       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
02959    case AST_OPTION_RXGAIN:
02960       scp = (signed char *) data;
02961       index = dahdi_get_index(chan, p, 0);
02962       if (index < 0) {
02963          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
02964          return -1;
02965       }
02966       if (option_debug)
02967          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
02968       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
02969    case AST_OPTION_TONE_VERIFY:
02970       if (!p->dsp)
02971          break;
02972       cp = (char *) data;
02973       switch (*cp) {
02974       case 1:
02975          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
02976          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
02977          break;
02978       case 2:
02979          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
02980          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
02981          break;
02982       default:
02983          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
02984          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
02985          break;
02986       }
02987       break;
02988    case AST_OPTION_TDD:
02989       /* turn on or off TDD */
02990       cp = (char *) data;
02991       p->mate = 0;
02992       if (!*cp) { /* turn it off */
02993          if (option_debug)
02994             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
02995          if (p->tdd)
02996             tdd_free(p->tdd);
02997          p->tdd = 0;
02998          break;
02999       }
03000       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03001          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03002       dahdi_disable_ec(p);
03003       /* otherwise, turn it on */
03004       if (!p->didtdd) { /* if havent done it yet */
03005          unsigned char mybuf[41000], *buf;
03006          int size, res, fd, len;
03007          struct pollfd fds[1];
03008 
03009          buf = mybuf;
03010          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03011          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03012          len = 40000;
03013          index = dahdi_get_index(chan, p, 0);
03014          if (index < 0) {
03015             ast_log(LOG_WARNING, "No index in TDD?\n");
03016             return -1;
03017          }
03018          fd = p->subs[index].dfd;
03019          while (len) {
03020             if (ast_check_hangup(chan))
03021                return -1;
03022             size = len;
03023             if (size > READ_SIZE)
03024                size = READ_SIZE;
03025             fds[0].fd = fd;
03026             fds[0].events = POLLPRI | POLLOUT;
03027             fds[0].revents = 0;
03028             res = poll(fds, 1, -1);
03029             if (!res) {
03030                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03031                continue;
03032             }
03033             /* if got exception */
03034             if (fds[0].revents & POLLPRI)
03035                return -1;
03036             if (!(fds[0].revents & POLLOUT)) {
03037                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03038                continue;
03039             }
03040             res = write(fd, buf, size);
03041             if (res != size) {
03042                if (res == -1) return -1;
03043                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03044                break;
03045             }
03046             len -= size;
03047             buf += size;
03048          }
03049          p->didtdd = 1; /* set to have done it now */    
03050       }
03051       if (*cp == 2) { /* Mate mode */
03052          if (p->tdd)
03053             tdd_free(p->tdd);
03054          p->tdd = 0;
03055          p->mate = 1;
03056          break;
03057       }     
03058       if (!p->tdd) { /* if we dont have one yet */
03059          p->tdd = tdd_new(); /* allocate one */
03060       }     
03061       break;
03062    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03063       if (!p->dsp)
03064          break;
03065       cp = (char *) data;
03066       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03067          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03068                 p->dtmfrelax = 0;
03069                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03070                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03071       break;
03072    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03073       cp = (char *) data;
03074       if (!*cp) {    
03075          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03076          x = 0;
03077          dahdi_disable_ec(p);
03078       } else {    
03079          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03080          x = 1;
03081       }
03082       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03083          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03084       break;
03085    case AST_OPTION_OPRMODE:  /* Operator services mode */
03086       oprmode = (struct oprmode *) data;
03087       pp = oprmode->peer->tech_pvt;
03088       p->oprmode = pp->oprmode = 0;
03089       /* setup peers */
03090       p->oprpeer = pp;
03091       pp->oprpeer = p;
03092       /* setup modes, if any */
03093       if (oprmode->mode) 
03094       {
03095          pp->oprmode = oprmode->mode;
03096          p->oprmode = -oprmode->mode;
03097       }
03098       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03099          oprmode->mode, chan->name,oprmode->peer->name);;
03100       break;
03101    case AST_OPTION_ECHOCAN:
03102       cp = (char *) data;
03103       if (*cp) {
03104          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03105          dahdi_enable_ec(p);
03106       } else {
03107          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03108          dahdi_disable_ec(p);
03109       }
03110       break;
03111    }
03112    errno = 0;
03113 
03114    return 0;
03115 }
03116 
03117 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
03118 {
03119    struct dahdi_pvt *p = chan->tech_pvt;
03120    
03121    if (!strcasecmp(data, "rxgain")) {
03122       ast_mutex_lock(&p->lock);
03123       snprintf(buf, len, "%f", p->rxgain);
03124       ast_mutex_unlock(&p->lock);   
03125    } else if (!strcasecmp(data, "txgain")) {
03126       ast_mutex_lock(&p->lock);
03127       snprintf(buf, len, "%f", p->txgain);
03128       ast_mutex_unlock(&p->lock);   
03129    } else {
03130       ast_copy_string(buf, "", len);
03131    }
03132    return 0;
03133 }
03134 
03135 
03136 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
03137 {
03138    /* Unlink a specific slave or all slaves/masters from a given master */
03139    int x;
03140    int hasslaves;
03141    if (!master)
03142       return;
03143    if (needlock) {
03144       ast_mutex_lock(&master->lock);
03145       if (slave) {
03146          while (ast_mutex_trylock(&slave->lock)) {
03147             DEADLOCK_AVOIDANCE(&master->lock);
03148          }
03149       }
03150    }
03151    hasslaves = 0;
03152    for (x = 0; x < MAX_SLAVES; x++) {
03153       if (master->slaves[x]) {
03154          if (!slave || (master->slaves[x] == slave)) {
03155             /* Take slave out of the conference */
03156             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03157             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03158             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03159             master->slaves[x]->master = NULL;
03160             master->slaves[x] = NULL;
03161          } else
03162             hasslaves = 1;
03163       }
03164       if (!hasslaves)
03165          master->inconference = 0;
03166    }
03167    if (!slave) {
03168       if (master->master) {
03169          /* Take master out of the conference */
03170          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03171          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03172          hasslaves = 0;
03173          for (x = 0; x < MAX_SLAVES; x++) {
03174             if (master->master->slaves[x] == master)
03175                master->master->slaves[x] = NULL;
03176             else if (master->master->slaves[x])
03177                hasslaves = 1;
03178          }
03179          if (!hasslaves)
03180             master->master->inconference = 0;
03181       }
03182       master->master = NULL;
03183    }
03184    update_conf(master);
03185    if (needlock) {
03186       if (slave)
03187          ast_mutex_unlock(&slave->lock);
03188       ast_mutex_unlock(&master->lock);
03189    }
03190 }
03191 
03192 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
03193    int x;
03194    if (!slave || !master) {
03195       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03196       return;
03197    }
03198    for (x = 0; x < MAX_SLAVES; x++) {
03199       if (!master->slaves[x]) {
03200          master->slaves[x] = slave;
03201          break;
03202       }
03203    }
03204    if (x >= MAX_SLAVES) {
03205       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03206       master->slaves[MAX_SLAVES - 1] = slave;
03207    }
03208    if (slave->master) 
03209       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03210    slave->master = master;
03211    
03212    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03213 }
03214 
03215 static void disable_dtmf_detect(struct dahdi_pvt *p)
03216 {
03217 #ifdef DAHDI_TONEDETECT
03218    int val;
03219 #endif
03220 
03221    p->ignoredtmf = 1;
03222 
03223 #ifdef DAHDI_TONEDETECT
03224    val = 0;
03225    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03226 #endif      
03227    if (!p->hardwaredtmf && p->dsp) {
03228       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03229       ast_dsp_set_features(p->dsp, p->dsp_features);
03230    }
03231 }
03232 
03233 static void enable_dtmf_detect(struct dahdi_pvt *p)
03234 {
03235 #ifdef DAHDI_TONEDETECT
03236    int val;
03237 #endif
03238 
03239    if (p->channel == CHAN_PSEUDO)
03240       return;
03241 
03242    p->ignoredtmf = 0;
03243 
03244 #ifdef DAHDI_TONEDETECT
03245    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03246    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03247 #endif      
03248    if (!p->hardwaredtmf && p->dsp) {
03249       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03250       ast_dsp_set_features(p->dsp, p->dsp_features);
03251    }
03252 }
03253 
03254 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)
03255 {
03256    struct ast_channel *who;
03257    struct dahdi_pvt *p0, *p1, *op0, *op1;
03258    struct dahdi_pvt *master = NULL, *slave = NULL;
03259    struct ast_frame *f;
03260    int inconf = 0;
03261    int nothingok = 1;
03262    int ofd0, ofd1;
03263    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03264    int os0 = -1, os1 = -1;
03265    int priority = 0;
03266    struct ast_channel *oc0, *oc1;
03267    enum ast_bridge_result res;
03268 
03269 #ifdef PRI_2BCT
03270    int triedtopribridge = 0;
03271    q931_call *q931c0 = NULL, *q931c1 = NULL;
03272 #endif
03273 
03274    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03275       There is code below to handle it properly until DTMF is actually seen,
03276       but due to currently unresolved issues it's ignored...
03277    */
03278 
03279    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03280       return AST_BRIDGE_FAILED_NOWARN;
03281 
03282    ast_mutex_lock(&c0->lock);
03283    while (ast_mutex_trylock(&c1->lock)) {
03284       DEADLOCK_AVOIDANCE(&c0->lock);
03285    }
03286 
03287    p0 = c0->tech_pvt;
03288    p1 = c1->tech_pvt;
03289    /* cant do pseudo-channels here */
03290    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03291       ast_mutex_unlock(&c0->lock);
03292       ast_mutex_unlock(&c1->lock);
03293       return AST_BRIDGE_FAILED_NOWARN;
03294    }
03295 
03296    oi0 = dahdi_get_index(c0, p0, 0);
03297    oi1 = dahdi_get_index(c1, p1, 0);
03298    if ((oi0 < 0) || (oi1 < 0)) {
03299       ast_mutex_unlock(&c0->lock);
03300       ast_mutex_unlock(&c1->lock);
03301       return AST_BRIDGE_FAILED;
03302    }
03303 
03304    op0 = p0 = c0->tech_pvt;
03305    op1 = p1 = c1->tech_pvt;
03306    ofd0 = c0->fds[0];
03307    ofd1 = c1->fds[0];
03308    oc0 = p0->owner;
03309    oc1 = p1->owner;
03310 
03311    if (ast_mutex_trylock(&p0->lock)) {
03312       /* Don't block, due to potential for deadlock */
03313       ast_mutex_unlock(&c0->lock);
03314       ast_mutex_unlock(&c1->lock);
03315       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03316       return AST_BRIDGE_RETRY;
03317    }
03318    if (ast_mutex_trylock(&p1->lock)) {
03319       /* Don't block, due to potential for deadlock */
03320       ast_mutex_unlock(&p0->lock);
03321       ast_mutex_unlock(&c0->lock);
03322       ast_mutex_unlock(&c1->lock);
03323       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03324       return AST_BRIDGE_RETRY;
03325    }
03326 
03327    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03328       if (p0->owner && p1->owner) {
03329          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03330          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03331             master = p0;
03332             slave = p1;
03333             inconf = 1;
03334          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03335             master = p1;
03336             slave = p0;
03337             inconf = 1;
03338          } else {
03339             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03340             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03341                p0->channel,
03342                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03343                p0->subs[SUB_REAL].inthreeway, p0->channel,
03344                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03345                p1->subs[SUB_REAL].inthreeway);
03346          }
03347          nothingok = 0;
03348       }
03349    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03350       if (p1->subs[SUB_THREEWAY].inthreeway) {
03351          master = p1;
03352          slave = p0;
03353          nothingok = 0;
03354       }
03355    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03356       if (p0->subs[SUB_THREEWAY].inthreeway) {
03357          master = p0;
03358          slave = p1;
03359          nothingok = 0;
03360       }
03361    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03362       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03363          don't put us in anything */
03364       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03365          master = p1;
03366          slave = p0;
03367          nothingok = 0;
03368       }
03369    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03370       /* Same as previous */
03371       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03372          master = p0;
03373          slave = p1;
03374          nothingok = 0;
03375       }
03376    }
03377    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03378       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03379    if (master && slave) {
03380       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03381          in an active threeway call with a channel that is ringing, we should
03382          indicate ringing. */
03383       if ((oi1 == SUB_THREEWAY) && 
03384           p1->subs[SUB_THREEWAY].inthreeway && 
03385           p1->subs[SUB_REAL].owner && 
03386           p1->subs[SUB_REAL].inthreeway && 
03387           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03388          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03389          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03390          os1 = p1->subs[SUB_REAL].owner->_state;
03391       } else {
03392          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03393          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03394       }
03395       if ((oi0 == SUB_THREEWAY) && 
03396           p0->subs[SUB_THREEWAY].inthreeway && 
03397           p0->subs[SUB_REAL].owner && 
03398           p0->subs[SUB_REAL].inthreeway && 
03399           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03400          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03401          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03402          os0 = p0->subs[SUB_REAL].owner->_state;
03403       } else {
03404          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03405          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03406       }
03407       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03408          if (!p0->echocanbridged || !p1->echocanbridged) {
03409             /* Disable echo cancellation if appropriate */
03410             dahdi_disable_ec(p0);
03411             dahdi_disable_ec(p1);
03412          }
03413       }
03414       dahdi_link(slave, master);
03415       master->inconference = inconf;
03416    } else if (!nothingok)
03417       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03418 
03419    update_conf(p0);
03420    update_conf(p1);
03421    t0 = p0->subs[SUB_REAL].inthreeway;
03422    t1 = p1->subs[SUB_REAL].inthreeway;
03423 
03424    ast_mutex_unlock(&p0->lock);
03425    ast_mutex_unlock(&p1->lock);
03426 
03427    ast_mutex_unlock(&c0->lock);
03428    ast_mutex_unlock(&c1->lock);
03429 
03430    /* Native bridge failed */
03431    if ((!master || !slave) && !nothingok) {
03432       dahdi_enable_ec(p0);
03433       dahdi_enable_ec(p1);
03434       return AST_BRIDGE_FAILED;
03435    }
03436    
03437    if (option_verbose > 2) 
03438       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03439 
03440    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03441       disable_dtmf_detect(op0);
03442 
03443    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03444       disable_dtmf_detect(op1);
03445 
03446    for (;;) {
03447       struct ast_channel *c0_priority[2] = {c0, c1};
03448       struct ast_channel *c1_priority[2] = {c1, c0};
03449 
03450       /* Here's our main loop...  Start by locking things, looking for private parts, 
03451          and then balking if anything is wrong */
03452       ast_mutex_lock(&c0->lock);
03453       while (ast_mutex_trylock(&c1->lock)) {
03454          DEADLOCK_AVOIDANCE(&c0->lock);
03455       }
03456 
03457       p0 = c0->tech_pvt;
03458       p1 = c1->tech_pvt;
03459 
03460       if (op0 == p0)
03461          i0 = dahdi_get_index(c0, p0, 1);
03462       if (op1 == p1)
03463          i1 = dahdi_get_index(c1, p1, 1);
03464       ast_mutex_unlock(&c0->lock);
03465       ast_mutex_unlock(&c1->lock);
03466 
03467       if (!timeoutms || 
03468           (op0 != p0) ||
03469           (op1 != p1) || 
03470           (ofd0 != c0->fds[0]) || 
03471           (ofd1 != c1->fds[0]) ||
03472           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03473           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03474           (oc0 != p0->owner) || 
03475           (oc1 != p1->owner) ||
03476           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03477           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03478           (oi0 != i0) ||
03479           (oi1 != i1)) {
03480          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03481             op0->channel, oi0, op1->channel, oi1);
03482          res = AST_BRIDGE_RETRY;
03483          goto return_from_bridge;
03484       }
03485 
03486 #ifdef PRI_2BCT
03487       q931c0 = p0->call;
03488       q931c1 = p1->call;
03489       if (p0->transfer && p1->transfer 
03490           && q931c0 && q931c1 
03491           && !triedtopribridge) {
03492          pri_channel_bridge(q931c0, q931c1);
03493          triedtopribridge = 1;
03494       }
03495 #endif
03496 
03497       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03498       if (!who) {
03499          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03500          continue;
03501       }
03502       f = ast_read(who);
03503       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03504          *fo = f;
03505          *rc = who;
03506          res = AST_BRIDGE_COMPLETE;
03507          goto return_from_bridge;
03508       }
03509       if (f->frametype == AST_FRAME_DTMF) {
03510          if ((who == c0) && p0->pulsedial) {
03511             ast_write(c1, f);
03512          } else if ((who == c1) && p1->pulsedial) {
03513             ast_write(c0, f);
03514          } else {
03515             *fo = f;
03516             *rc = who;
03517             res = AST_BRIDGE_COMPLETE;
03518             goto return_from_bridge;
03519          }
03520       }
03521       ast_frfree(f);
03522       
03523       /* Swap who gets priority */
03524       priority = !priority;
03525    }
03526 
03527 return_from_bridge:
03528    if (op0 == p0)
03529       dahdi_enable_ec(p0);
03530 
03531    if (op1 == p1)
03532       dahdi_enable_ec(p1);
03533 
03534    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03535       enable_dtmf_detect(op0);
03536 
03537    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03538       enable_dtmf_detect(op1);
03539 
03540    dahdi_unlink(slave, master, 1);
03541 
03542    return res;
03543 }
03544 
03545 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
03546 {
03547    struct dahdi_pvt *p = newchan->tech_pvt;
03548    int x;
03549    ast_mutex_lock(&p->lock);
03550    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03551    if (p->owner == oldchan) {
03552       p->owner = newchan;
03553    }
03554    for (x = 0; x < 3; x++)
03555       if (p->subs[x].owner == oldchan) {
03556          if (!x)
03557             dahdi_unlink(NULL, p, 0);
03558          p->subs[x].owner = newchan;
03559       }
03560    if (newchan->_state == AST_STATE_RINGING) 
03561       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03562    update_conf(p);
03563    ast_mutex_unlock(&p->lock);
03564    return 0;
03565 }
03566 
03567 static int dahdi_ring_phone(struct dahdi_pvt *p)
03568 {
03569    int x;
03570    int res;
03571    /* Make sure our transmit state is on hook */
03572    x = 0;
03573    x = DAHDI_ONHOOK;
03574    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03575    do {
03576       x = DAHDI_RING;
03577       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03578       if (res) {
03579          switch (errno) {
03580          case EBUSY:
03581          case EINTR:
03582             /* Wait just in case */
03583             usleep(10000);
03584             continue;
03585          case EINPROGRESS:
03586             res = 0;
03587             break;
03588          default:
03589             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03590             res = 0;
03591          }
03592       }
03593    } while (res);
03594    return res;
03595 }
03596 
03597 static void *ss_thread(void *data);
03598 
03599 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
03600 
03601 static int attempt_transfer(struct dahdi_pvt *p)
03602 {
03603    /* In order to transfer, we need at least one of the channels to
03604       actually be in a call bridge.  We can't conference two applications
03605       together (but then, why would we want to?) */
03606    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03607       /* The three-way person we're about to transfer to could still be in MOH, so
03608          stop if now if appropriate */
03609       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03610          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03611       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03612          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03613       }
03614       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03615          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03616       }
03617        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03618          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03619                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03620          return -1;
03621       }
03622       /* Orphan the channel after releasing the lock */
03623       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03624       unalloc_sub(p, SUB_THREEWAY);
03625    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03626       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03627       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03628          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03629       }
03630       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03631          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03632       }
03633       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03634          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03635                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03636          return -1;
03637       }
03638       /* Three-way is now the REAL */
03639       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03640       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03641       unalloc_sub(p, SUB_THREEWAY);
03642       /* Tell the caller not to hangup */
03643       return 1;
03644    } else {
03645       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03646                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03647       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03648       return -1;
03649    }
03650    return 0;
03651 }
03652 
03653 static int check_for_conference(struct dahdi_pvt *p)
03654 {
03655    struct dahdi_confinfo ci;
03656    /* Fine if we already have a master, etc */
03657    if (p->master || (p->confno > -1))
03658       return 0;
03659    memset(&ci, 0, sizeof(ci));
03660    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03661       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03662       return 0;
03663    }
03664    /* If we have no master and don't have a confno, then 
03665       if we're in a conference, it's probably a MeetMe room or
03666       some such, so don't let us 3-way out! */
03667    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03668       if (option_verbose > 2) 
03669          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03670       return 1;
03671    }
03672    return 0;
03673 }
03674 
03675 static int get_alarms(struct dahdi_pvt *p)
03676 {
03677    int res;
03678    struct dahdi_spaninfo zi;
03679 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
03680    /*
03681     * The conditional compilation is needed only in asterisk-1.4 for
03682     * backward compatibility with old zaptel drivers that don't have
03683     * a DAHDI_PARAMS.chan_alarms field.
03684     */
03685    struct dahdi_params params;
03686 #endif
03687 
03688    memset(&zi, 0, sizeof(zi));
03689    zi.spanno = p->span;
03690 
03691    /* First check for span alarms */
03692    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
03693       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
03694       return 0;
03695    }
03696    if (zi.alarms != DAHDI_ALARM_NONE)
03697       return zi.alarms;
03698 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
03699    /* No alarms on the span. Check for channel alarms. */
03700    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
03701       return params.chan_alarms;
03702    /* ioctl failed */
03703    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
03704 #endif
03705    return DAHDI_ALARM_NONE;
03706 }
03707 
03708 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
03709 {
03710    struct dahdi_pvt *p = ast->tech_pvt;
03711    struct ast_frame *f = *dest;
03712 
03713    if (option_debug)
03714       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
03715 
03716    if (p->confirmanswer) {
03717       if (option_debug)
03718          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
03719       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
03720          of a DTMF digit */
03721       p->subs[index].f.frametype = AST_FRAME_CONTROL;
03722       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03723       *dest = &p->subs[index].f;
03724       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
03725       p->confirmanswer = 0;
03726    } else if (p->callwaitcas) {
03727       if ((f->subclass == 'A') || (f->subclass == 'D')) {
03728          if (option_debug)
03729             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
03730          if (p->cidspill)
03731             free(p->cidspill);
03732          send_cwcidspill(p);
03733       }
03734       if ((f->subclass != 'm') && (f->subclass != 'u')) 
03735          p->callwaitcas = 0;
03736       p->subs[index].f.frametype = AST_FRAME_NULL;
03737       p->subs[index].f.subclass = 0;
03738       *dest = &p->subs[index].f;
03739    } else if (f->subclass == 'f') {
03740       /* Fax tone -- Handle and return NULL */
03741       if ((p->callprogress & 0x6) && !p->faxhandled) {
03742          p->faxhandled++;
03743          if (strcmp(ast->exten, "fax")) {
03744             const char *target_context = S_OR(ast->macrocontext, ast->context);
03745 
03746             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
03747                if (option_verbose > 2)
03748                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
03749                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
03750                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
03751                if (ast_async_goto(ast, target_context, "fax", 1))
03752                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
03753             } else
03754                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
03755          } else if (option_debug)
03756             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
03757       } else if (option_debug)
03758             ast_log(LOG_DEBUG, "Fax already handled\n");
03759       dahdi_confmute(p, 0);
03760       p->subs[index].f.frametype = AST_FRAME_NULL;
03761       p->subs[index].f.subclass = 0;
03762       *dest = &p->subs[index].f;
03763    } else if (f->subclass == 'm') {
03764       /* Confmute request */
03765       dahdi_confmute(p, 1);
03766       p->subs[index].f.frametype = AST_FRAME_NULL;
03767       p->subs[index].f.subclass = 0;
03768       *dest = &p->subs[index].f;    
03769    } else if (f->subclass == 'u') {
03770       /* Unmute */
03771       dahdi_confmute(p, 0);
03772       p->subs[index].f.frametype = AST_FRAME_NULL;
03773       p->subs[index].f.subclass = 0;
03774       *dest = &p->subs[index].f;    
03775    } else
03776       dahdi_confmute(p, 0);
03777 }
03778          
03779 static void handle_alarms(struct dahdi_pvt *p, int alarms)
03780 {
03781    const char *alarm_str = alarm2str(alarms);
03782    
03783    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
03784     * doesn't know what to do with it.  Don't confuse users with log messages. */
03785    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
03786       p->unknown_alarm = 1;
03787       return;
03788    } else {
03789       p->unknown_alarm = 0;
03790    }
03791    
03792    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
03793    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
03794             "Alarm: %s\r\n"
03795             "Channel: %d\r\n",
03796             alarm_str, p->channel);
03797 }
03798 
03799 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
03800 {
03801    int res, x;
03802    int index, mysig;
03803    char *c;
03804    struct dahdi_pvt *p = ast->tech_pvt;
03805    pthread_t threadid;
03806    pthread_attr_t attr;
03807    struct ast_channel *chan;
03808    struct ast_frame *f;
03809 
03810    index = dahdi_get_index(ast, p, 0);
03811    mysig = p->sig;
03812    if (p->outsigmod > -1)
03813       mysig = p->outsigmod;
03814    p->subs[index].f.frametype = AST_FRAME_NULL;
03815    p->subs[index].f.subclass = 0;
03816    p->subs[index].f.datalen = 0;
03817    p->subs[index].f.samples = 0;
03818    p->subs[index].f.mallocd = 0;
03819    p->subs[index].f.offset = 0;
03820    p->subs[index].f.src = "dahdi_handle_event";
03821    p->subs[index].f.data = NULL;
03822    f = &p->subs[index].f;
03823 
03824    if (index < 0)
03825       return &p->subs[index].f;
03826    if (p->fake_event) {
03827       res = p->fake_event;
03828       p->fake_event = 0;
03829    } else
03830       res = dahdi_get_event(p->subs[index].dfd);
03831 
03832    if (option_debug)
03833       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
03834 
03835    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
03836       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
03837 
03838       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
03839 #ifdef HAVE_PRI
03840       if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
03841          /* absorb event */
03842       } else {
03843 #endif
03844          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
03845          p->subs[index].f.subclass = res & 0xff;
03846 #ifdef HAVE_PRI
03847       }
03848 #endif
03849       dahdi_handle_dtmfup(ast, index, &f);
03850       return f;
03851    }
03852 
03853    if (res & DAHDI_EVENT_DTMFDOWN) {
03854       if (option_debug)
03855          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
03856       /* Mute conference */
03857       dahdi_confmute(p, 1);
03858       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
03859       p->subs[index].f.subclass = res & 0xff;
03860       return &p->subs[index].f;
03861    }
03862 
03863    switch (res) {
03864 #ifdef DAHDI_EVENT_EC_DISABLED
03865       case DAHDI_EVENT_EC_DISABLED:
03866          if (option_verbose > 2) 
03867             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
03868          p->echocanon = 0;
03869          break;
03870 #endif
03871       case DAHDI_EVENT_BITSCHANGED:
03872          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
03873       case DAHDI_EVENT_PULSE_START:
03874          /* Stop tone if there's a pulse start and the PBX isn't started */
03875          if (!ast->pbx)
03876             tone_zone_play_tone(p->subs[index].dfd, -1);
03877          break;   
03878       case DAHDI_EVENT_DIALCOMPLETE:
03879          if (p->inalarm) break;
03880          if ((p->radio || (p->oprmode < 0))) break;
03881          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
03882             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
03883             return NULL;
03884          }
03885          if (!x) { /* if not still dialing in driver */
03886             dahdi_enable_ec(p);
03887             if (p->echobreak) {
03888                dahdi_train_ec(p);
03889                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
03890                p->dop.op = DAHDI_DIAL_OP_REPLACE;
03891                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
03892                p->echobreak = 0;
03893             } else {
03894                p->dialing = 0;
03895                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
03896                   /* if thru with dialing after offhook */
03897                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
03898                      ast_setstate(ast, AST_STATE_UP);
03899                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03900                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03901                      break;
03902                   } else { /* if to state wait for offhook to dial rest */
03903                      /* we now wait for off hook */
03904                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
03905                   }
03906                }
03907                if (ast->_state == AST_STATE_DIALING) {
03908                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03909                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
03910                   } 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)))) {
03911                      ast_setstate(ast, AST_STATE_RINGING);
03912                   } else if (!p->answeronpolarityswitch) {
03913                      ast_setstate(ast, AST_STATE_UP);
03914                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
03915                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
03916                      /* If aops=0 and hops=1, this is necessary */
03917                      p->polarity = POLARITY_REV;
03918                   } else {
03919                      /* Start clean, so we can catch the change to REV polarity when party answers */
03920                      p->polarity = POLARITY_IDLE;
03921                   }
03922                }
03923             }
03924          }
03925          break;
03926       case DAHDI_EVENT_ALARM:
03927 #ifdef HAVE_PRI
03928          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
03929             /* T309 is not enabled : hangup calls when alarm occurs */
03930             if (p->call) {
03931                if (p->pri && p->pri->pri) {
03932                   if (!pri_grab(p, p->pri)) {
03933                      pri_hangup(p->pri->pri, p->call, -1);
03934                      pri_destroycall(p->pri->pri, p->call);
03935                      p->call = NULL;
03936                      pri_rel(p->pri);
03937                   } else
03938                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03939                } else
03940                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
03941             }
03942             if (p->owner)
03943                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03944          }
03945          if (p->bearer)
03946             p->bearer->inalarm = 1;
03947          else
03948 #endif
03949          p->inalarm = 1;
03950          res = get_alarms(p);
03951          handle_alarms(p, res);
03952 #ifdef HAVE_LIBPRI
03953          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
03954             /* fall through intentionally */
03955          } else {
03956             break;
03957          }
03958 #endif
03959       case DAHDI_EVENT_ONHOOK:
03960          if (p->radio) {
03961             p->subs[index].f.frametype = AST_FRAME_CONTROL;
03962             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
03963             break;
03964          }
03965          if (p->oprmode < 0)
03966          {
03967             if (p->oprmode != -1) break;
03968             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
03969             {
03970                /* Make sure it starts ringing */
03971                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
03972                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
03973                save_conference(p->oprpeer);
03974                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03975             }
03976             break;
03977          }
03978          switch (p->sig) {
03979          case SIG_FXOLS:
03980          case SIG_FXOGS:
03981          case SIG_FXOKS:
03982             p->onhooktime = time(NULL);
03983             p->msgstate = -1;
03984             /* Check for some special conditions regarding call waiting */
03985             if (index == SUB_REAL) {
03986                /* The normal line was hung up */
03987                if (p->subs[SUB_CALLWAIT].owner) {
03988                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
03989                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03990                   if (option_verbose > 2) 
03991                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
03992                   unalloc_sub(p, SUB_CALLWAIT); 
03993 #if 0
03994                   p->subs[index].needanswer = 0;
03995                   p->subs[index].needringing = 0;
03996 #endif                  
03997                   p->callwaitingrepeat = 0;
03998                   p->cidcwexpire = 0;
03999                   p->owner = NULL;
04000                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04001                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04002                      p->dialing = 1;
04003                   dahdi_ring_phone(p);
04004                } else if (p->subs[SUB_THREEWAY].owner) {
04005                   unsigned int mssinceflash;
04006                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04007                      the private structure -- not especially easy or clean */
04008                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04009                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04010                      ast_mutex_unlock(&p->lock);
04011                      DEADLOCK_AVOIDANCE(&ast->lock);
04012                      /* We can grab ast and p in that order, without worry.  We should make sure
04013                         nothing seriously bad has happened though like some sort of bizarre double
04014                         masquerade! */
04015                      ast_mutex_lock(&p->lock);
04016                      if (p->owner != ast) {
04017                         ast_log(LOG_WARNING, "This isn't good...\n");
04018                         return NULL;
04019                      }
04020                   }
04021                   if (!p->subs[SUB_THREEWAY].owner) {
04022                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04023                      return NULL;
04024                   }
04025                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04026                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04027                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04028                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04029                         hanging up.  Hangup both channels now */
04030                      if (p->subs[SUB_THREEWAY].owner)
04031                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04032                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04033                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04034                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04035                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04036                      if (p->transfer) {
04037                         /* In any case this isn't a threeway call anymore */
04038                         p->subs[SUB_REAL].inthreeway = 0;
04039                         p->subs[SUB_THREEWAY].inthreeway = 0;
04040                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04041                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04042                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04043                            /* Swap subs and dis-own channel */
04044                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04045                            p->owner = NULL;
04046                            /* Ring the phone */
04047                            dahdi_ring_phone(p);
04048                         } else {
04049                            if ((res = attempt_transfer(p)) < 0) {
04050                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04051                               if (p->subs[SUB_THREEWAY].owner)
04052                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04053                            } else if (res) {
04054                               /* Don't actually hang up at this point */
04055                               if (p->subs[SUB_THREEWAY].owner)
04056                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04057                               break;
04058                            }
04059                         }
04060                      } else {
04061                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04062                         if (p->subs[SUB_THREEWAY].owner)
04063                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04064                      }
04065                   } else {
04066                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04067                      /* Swap subs and dis-own channel */
04068                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04069                      p->owner = NULL;
04070                      /* Ring the phone */
04071                      dahdi_ring_phone(p);
04072                   }
04073                }
04074             } else {
04075                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04076             }
04077             /* Fall through */
04078          default:
04079             dahdi_disable_ec(p);
04080             return NULL;
04081          }
04082          break;
04083       case DAHDI_EVENT_RINGOFFHOOK:
04084          if (p->inalarm) break;
04085          if (p->oprmode < 0)
04086          {
04087             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04088             {
04089                /* Make sure it stops ringing */
04090                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04091                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04092                restore_conference(p->oprpeer);
04093             }
04094             break;
04095          }
04096          if (p->radio)
04097          {
04098             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04099             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04100             break;
04101          }
04102          /* for E911, its supposed to wait for offhook then dial
04103             the second half of the dial string */
04104          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04105             c = strchr(p->dialdest, '/');
04106             if (c)
04107                c++;
04108             else
04109                c = p->dialdest;
04110             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04111             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04112             if (strlen(p->dop.dialstr) > 4) {
04113                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04114                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04115                p->echorest[sizeof(p->echorest) - 1] = '\0';
04116                p->echobreak = 1;
04117                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04118             } else
04119                p->echobreak = 0;
04120             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04121                int saveerr = errno;
04122 
04123                x = DAHDI_ONHOOK;
04124                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04125                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04126                return NULL;
04127                }
04128             p->dialing = 1;
04129             return &p->subs[index].f;
04130          }
04131          switch (p->sig) {
04132          case SIG_FXOLS:
04133          case SIG_FXOGS:
04134          case SIG_FXOKS:
04135             switch (ast->_state) {
04136             case AST_STATE_RINGING:
04137                dahdi_enable_ec(p);
04138                dahdi_train_ec(p);
04139                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04140                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04141                /* Make sure it stops ringing */
04142                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04143                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04144                if (p->cidspill) {
04145                   /* Cancel any running CallerID spill */
04146                   free(p->cidspill);
04147                   p->cidspill = NULL;
04148                }
04149                p->dialing = 0;
04150                p->callwaitcas = 0;
04151                if (p->confirmanswer) {
04152                   /* Ignore answer if "confirm answer" is enabled */
04153                   p->subs[index].f.frametype = AST_FRAME_NULL;
04154                   p->subs[index].f.subclass = 0;
04155                } else if (!ast_strlen_zero(p->dop.dialstr)) {
04156                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
04157                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04158                   if (res < 0) {
04159                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04160                      p->dop.dialstr[0] = '\0';
04161                      return NULL;
04162                   } else {
04163                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04164                      p->subs[index].f.frametype = AST_FRAME_NULL;
04165                      p->subs[index].f.subclass = 0;
04166                      p->dialing = 1;
04167                   }
04168                   p->dop.dialstr[0] = '\0';
04169                   ast_setstate(ast, AST_STATE_DIALING);
04170                } else
04171                   ast_setstate(ast, AST_STATE_UP);
04172                return &p->subs[index].f;
04173             case AST_STATE_DOWN:
04174                ast_setstate(ast, AST_STATE_RING);
04175                ast->rings = 1;
04176                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04177                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04178                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04179                return &p->subs[index].f;
04180             case AST_STATE_UP:
04181                /* Make sure it stops ringing */
04182                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04183                /* Okay -- probably call waiting*/
04184                if (ast_bridged_channel(p->owner))
04185                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04186                p->subs[index].needunhold = 1;
04187                break;
04188             case AST_STATE_RESERVED:
04189                /* Start up dialtone */
04190                if (has_voicemail(p))
04191                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04192                else
04193                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04194                break;
04195             default:
04196                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04197             }
04198             break;
04199          case SIG_FXSLS:
04200          case SIG_FXSGS:
04201          case SIG_FXSKS:
04202             if (ast->_state == AST_STATE_RING) {
04203                p->ringt = p->ringt_base;
04204             }
04205 
04206             /* Fall through */
04207          case SIG_EM:
04208          case SIG_EM_E1:
04209          case SIG_EMWINK:
04210          case SIG_FEATD:
04211          case SIG_FEATDMF:
04212          case SIG_FEATDMF_TA:
04213          case SIG_E911:
04214          case SIG_FGC_CAMA:
04215          case SIG_FGC_CAMAMF:
04216          case SIG_FEATB:
04217          case SIG_SF:
04218          case SIG_SFWINK:
04219          case SIG_SF_FEATD:
04220          case SIG_SF_FEATDMF:
04221          case SIG_SF_FEATB:
04222             if (ast->_state == AST_STATE_PRERING)
04223                ast_setstate(ast, AST_STATE_RING);
04224             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04225                if (option_debug)
04226                   ast_log(LOG_DEBUG, "Ring detected\n");
04227                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04228                p->subs[index].f.subclass = AST_CONTROL_RING;
04229             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04230                if (option_debug)
04231                   ast_log(LOG_DEBUG, "Line answered\n");
04232                if (p->confirmanswer) {
04233                   p->subs[index].f.frametype = AST_FRAME_NULL;
04234                   p->subs[index].f.subclass = 0;
04235                } else {
04236                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
04237                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04238                   ast_setstate(ast, AST_STATE_UP);
04239                }
04240             } else if (ast->_state != AST_STATE_RING)
04241                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04242             break;
04243          default:
04244             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04245          }
04246          break;
04247 #ifdef DAHDI_EVENT_RINGBEGIN
04248       case DAHDI_EVENT_RINGBEGIN:
04249          switch (p->sig) {
04250          case SIG_FXSLS:
04251          case SIG_FXSGS:
04252          case SIG_FXSKS:
04253             if (ast->_state == AST_STATE_RING) {
04254                p->ringt = p->ringt_base;
04255             }
04256             break;
04257          }
04258          break;
04259 #endif         
04260       case DAHDI_EVENT_RINGEROFF:
04261          if (p->inalarm) break;
04262          if ((p->radio || (p->oprmode < 0))) break;
04263          ast->rings++;
04264          if ((ast->rings > p->cidrings) && (p->cidspill)) {
04265             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
04266             free(p->cidspill);
04267             p->cidspill = NULL;
04268             p->callwaitcas = 0;
04269          }
04270          p->subs[index].f.frametype = AST_FRAME_CONTROL;
04271          p->subs[index].f.subclass = AST_CONTROL_RINGING;
04272          break;
04273       case DAHDI_EVENT_RINGERON:
04274          break;
04275       case DAHDI_EVENT_NOALARM:
04276          p->inalarm = 0;
04277 #ifdef HAVE_PRI
04278          /* Extremely unlikely but just in case */
04279          if (p->bearer)
04280             p->bearer->inalarm = 0;
04281 #endif            
04282          if (!p->unknown_alarm) {
04283             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04284             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04285                "Channel: %d\r\n", p->channel);
04286          } else {
04287             p->unknown_alarm = 0;
04288          }
04289          break;
04290       case DAHDI_EVENT_WINKFLASH:
04291          if (p->inalarm) break;
04292          if (p->radio) break;
04293          if (p->oprmode < 0) break;
04294          if (p->oprmode > 1)
04295          {
04296             struct dahdi_params par;
04297 
04298             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04299             {
04300                if (!par.rxisoffhook)
04301                {
04302                   /* Make sure it stops ringing */
04303                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04304                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04305                   save_conference(p);
04306                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04307                }
04308             }
04309             break;
04310          }
04311          /* Remember last time we got a flash-hook */
04312          gettimeofday(&p->flashtime, NULL);
04313          switch (mysig) {
04314          case SIG_FXOLS:
04315          case SIG_FXOGS:
04316          case SIG_FXOKS:
04317             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04318                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04319             p->callwaitcas = 0;
04320 
04321             if (index != SUB_REAL) {
04322                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04323                goto winkflashdone;
04324             }
04325             
04326             if (p->subs[SUB_CALLWAIT].owner) {
04327                /* Swap to call-wait */
04328                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04329                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04330                p->owner = p->subs[SUB_REAL].owner;
04331                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04332                if (p->owner->_state == AST_STATE_RINGING) {
04333                   ast_setstate(p->owner, AST_STATE_UP);
04334                   p->subs[SUB_REAL].needanswer = 1;
04335                }
04336                p->callwaitingrepeat = 0;
04337                p->cidcwexpire = 0;
04338                /* Start music on hold if appropriate */
04339                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04340                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04341                      S_OR(p->mohsuggest, NULL),
04342                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04343                }
04344                p->subs[SUB_CALLWAIT].needhold = 1;
04345                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04346                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04347                      S_OR(p->mohsuggest, NULL),
04348                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04349                }
04350                p->subs[SUB_REAL].needunhold = 1;
04351             } else if (!p->subs[SUB_THREEWAY].owner) {
04352                char cid_num[256];
04353                char cid_name[256];
04354 
04355                if (!p->threewaycalling) {
04356                   /* Just send a flash if no 3-way calling */
04357                   p->subs[SUB_REAL].needflash = 1;
04358                   goto winkflashdone;
04359                } else if (!check_for_conference(p)) {
04360                   if (p->dahditrcallerid && p->owner) {
04361                      if (p->owner->cid.cid_num)
04362                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04363                      if (p->owner->cid.cid_name)
04364                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04365                   }
04366                   /* XXX This section needs much more error checking!!! XXX */
04367                   /* Start a 3-way call if feasible */
04368                   if (!((ast->pbx) ||
04369                         (ast->_state == AST_STATE_UP) ||
04370                         (ast->_state == AST_STATE_RING))) {
04371                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04372                         goto winkflashdone;
04373                   }
04374                   if (alloc_sub(p, SUB_THREEWAY)) {
04375                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04376                      goto winkflashdone;
04377                   }
04378                   /* Make new channel */
04379                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04380                   if (p->dahditrcallerid) {
04381                      if (!p->origcid_num)
04382                         p->origcid_num = ast_strdup(p->cid_num);
04383                      if (!p->origcid_name)
04384                         p->origcid_name = ast_strdup(p->cid_name);
04385                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04386                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04387                   }
04388                   /* Swap things around between the three-way and real call */
04389                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
04390                   /* Disable echo canceller for better dialing */
04391                   dahdi_disable_ec(p);
04392                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04393                   if (res)
04394                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04395                   p->owner = chan;
04396                   pthread_attr_init(&attr);
04397                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04398                   if (!chan) {
04399                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04400                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04401                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04402                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04403                      dahdi_enable_ec(p);
04404                      ast_hangup(chan);
04405                   } else {
04406                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04407                      int way3bridge = 0, cdr3way = 0;
04408                      
04409                      if (!other) {
04410                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04411                      } else
04412                         way3bridge = 1;
04413                      
04414                      if (p->subs[SUB_THREEWAY].owner->cdr)
04415                         cdr3way = 1;
04416                      
04417                      if (option_verbose > 2) 
04418                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04419                      /* Start music on hold if appropriate */
04420                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04421                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04422                            S_OR(p->mohsuggest, NULL),
04423                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04424                      }
04425                      p->subs[SUB_THREEWAY].needhold = 1;
04426                   }
04427                   pthread_attr_destroy(&attr);
04428                }
04429             } else {
04430                /* Already have a 3 way call */
04431                if (p->subs[SUB_THREEWAY].inthreeway) {
04432                   /* Call is already up, drop the last person */
04433                   if (option_debug)
04434                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04435                   /* If the primary call isn't answered yet, use it */
04436                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04437                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
04438                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04439                      p->owner = p->subs[SUB_REAL].owner;
04440                   }
04441                   /* Drop the last call and stop the conference */
04442                   if (option_verbose > 2)
04443                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04444                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04445                   p->subs[SUB_REAL].inthreeway = 0;
04446                   p->subs[SUB_THREEWAY].inthreeway = 0;
04447                } else {
04448                   /* Lets see what we're up to */
04449                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
04450                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04451                      int otherindex = SUB_THREEWAY;
04452                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04453                      int way3bridge = 0, cdr3way = 0;
04454                      
04455                      if (!other) {
04456                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04457                      } else
04458                         way3bridge = 1;
04459                      
04460                      if (p->subs[SUB_THREEWAY].owner->cdr)
04461                         cdr3way = 1;
04462 
04463                      if (option_verbose > 2)
04464                         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);
04465                      /* Put them in the threeway, and flip */
04466                      p->subs[SUB_THREEWAY].inthreeway = 1;
04467                      p->subs[SUB_REAL].inthreeway = 1;
04468                      if (ast->_state == AST_STATE_UP) {
04469                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
04470                         otherindex = SUB_REAL;
04471                      }
04472                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04473                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04474                      p->subs[otherindex].needunhold = 1;
04475                      p->owner = p->subs[SUB_REAL].owner;
04476                      if (ast->_state == AST_STATE_RINGING) {
04477                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04478                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04479                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04480                      }
04481                   } else {
04482                      if (option_verbose > 2)
04483                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04484                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04485                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04486                      p->owner = p->subs[SUB_REAL].owner;
04487                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04488                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04489                      p->subs[SUB_REAL].needunhold = 1;
04490                      dahdi_enable_ec(p);
04491                   }
04492                      
04493                }
04494             }
04495          winkflashdone:              
04496             update_conf(p);
04497             break;
04498          case SIG_EM:
04499          case SIG_EM_E1:
04500          case SIG_EMWINK:
04501          case SIG_FEATD:
04502          case SIG_SF:
04503          case SIG_SFWINK:
04504          case SIG_SF_FEATD:
04505          case SIG_FXSLS:
04506          case SIG_FXSGS:
04507             if (p->dialing)
04508                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04509             else
04510                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04511             break;
04512          case SIG_FEATDMF_TA:
04513             switch (p->whichwink) {
04514             case 0:
04515                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04516                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04517                break;
04518             case 1:
04519                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04520                break;
04521             case 2:
04522                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04523                return NULL;
04524             }
04525             p->whichwink++;
04526             /* Fall through */
04527          case SIG_FEATDMF:
04528          case SIG_E911:
04529          case SIG_FGC_CAMAMF:
04530          case SIG_FGC_CAMA:
04531          case SIG_FEATB:
04532          case SIG_SF_FEATDMF:
04533          case SIG_SF_FEATB:
04534             /* FGD MF *Must* wait for wink */
04535             if (!ast_strlen_zero(p->dop.dialstr)) {
04536                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04537                if (res < 0) {
04538                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04539                   p->dop.dialstr[0] = '\0';
04540                   return NULL;
04541                } else 
04542                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04543             }
04544             p->dop.dialstr[0] = '\0';
04545             break;
04546          default:
04547             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04548          }
04549          break;
04550       case DAHDI_EVENT_HOOKCOMPLETE:
04551          if (p->inalarm) break;
04552          if ((p->radio || (p->oprmode < 0))) break;
04553          switch (mysig) {
04554          case SIG_FXSLS:  /* only interesting for FXS */
04555          case SIG_FXSGS:
04556          case SIG_FXSKS:
04557          case SIG_EM:
04558          case SIG_EM_E1:
04559          case SIG_EMWINK:
04560          case SIG_FEATD:
04561          case SIG_SF:
04562          case SIG_SFWINK:
04563          case SIG_SF_FEATD:
04564             if (!ast_strlen_zero(p->dop.dialstr)) {
04565                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04566                if (res < 0) {
04567                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04568                   p->dop.dialstr[0] = '\0';
04569                   return NULL;
04570                } else 
04571                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04572             }
04573             p->dop.dialstr[0] = '\0';
04574             p->dop.op = DAHDI_DIAL_OP_REPLACE;
04575             break;
04576          case SIG_FEATDMF:
04577          case SIG_FEATDMF_TA:
04578          case SIG_E911:
04579          case SIG_FGC_CAMA:
04580          case SIG_FGC_CAMAMF:
04581          case SIG_FEATB:
04582          case SIG_SF_FEATDMF:
04583          case SIG_SF_FEATB:
04584             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04585             break;
04586          default:
04587             break;
04588          }
04589          break;
04590       case DAHDI_EVENT_POLARITY:
04591          /*
04592           * If we get a Polarity Switch event, check to see
04593           * if we should change the polarity state and
04594           * mark the channel as UP or if this is an indication
04595           * of remote end disconnect.
04596           */
04597          if (p->polarity == POLARITY_IDLE) {
04598             p->polarity = POLARITY_REV;
04599             if (p->answeronpolarityswitch &&
04600                 ((ast->_state == AST_STATE_DIALING) ||
04601                 (ast->_state == AST_STATE_RINGING))) {
04602                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04603                ast_setstate(p->owner, AST_STATE_UP);
04604                if (p->hanguponpolarityswitch) {
04605                   gettimeofday(&p->polaritydelaytv, NULL);
04606                }
04607             } else
04608                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04609          } 
04610          /* Removed else statement from here as it was preventing hangups from ever happening*/
04611          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
04612          if (p->hanguponpolarityswitch &&
04613             (p->polarityonanswerdelay > 0) &&
04614                 (p->polarity == POLARITY_REV) &&
04615             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04616                                 /* Added log_debug information below to provide a better indication of what is going on */
04617             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) );
04618          
04619             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04620                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04621                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04622                p->polarity = POLARITY_IDLE;
04623             } else {
04624                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);
04625             }
04626          } else {
04627             p->polarity = POLARITY_IDLE;
04628             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04629          }
04630                         /* Added more log_debug information below to provide a better indication of what is going on */
04631          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) );
04632          break;
04633       default:
04634          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04635    }
04636    return &p->subs[index].f;
04637 }
04638 
04639 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
04640 {
04641    struct dahdi_pvt *p = ast->tech_pvt;
04642    int res;
04643    int usedindex=-1;
04644    int index;
04645    struct ast_frame *f;
04646 
04647 
04648    index = dahdi_get_index(ast, p, 1);
04649    
04650    p->subs[index].f.frametype = AST_FRAME_NULL;
04651    p->subs[index].f.datalen = 0;
04652    p->subs[index].f.samples = 0;
04653    p->subs[index].f.mallocd = 0;
04654    p->subs[index].f.offset = 0;
04655    p->subs[index].f.subclass = 0;
04656    p->subs[index].f.delivery = ast_tv(0,0);
04657    p->subs[index].f.src = "dahdi_exception";
04658    p->subs[index].f.data = NULL;
04659    
04660    
04661    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04662       /* If nobody owns us, absorb the event appropriately, otherwise
04663          we loop indefinitely.  This occurs when, during call waiting, the
04664          other end hangs up our channel so that it no longer exists, but we
04665          have neither FLASH'd nor ONHOOK'd to signify our desire to
04666          change to the other channel. */
04667       if (p->fake_event) {
04668          res = p->fake_event;
04669          p->fake_event = 0;
04670       } else
04671          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04672       /* Switch to real if there is one and this isn't something really silly... */
04673       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04674          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04675          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04676          p->owner = p->subs[SUB_REAL].owner;
04677          if (p->owner && ast_bridged_channel(p->owner))
04678             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04679          p->subs[SUB_REAL].needunhold = 1;
04680       }
04681       switch (res) {
04682       case DAHDI_EVENT_ONHOOK:
04683          dahdi_disable_ec(p);
04684          if (p->owner) {
04685             if (option_verbose > 2) 
04686                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
04687             dahdi_ring_phone(p);
04688             p->callwaitingrepeat = 0;
04689             p->cidcwexpire = 0;
04690          } else
04691             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04692          update_conf(p);
04693          break;
04694       case DAHDI_EVENT_RINGOFFHOOK:
04695          dahdi_enable_ec(p);
04696          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04697          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
04698             p->subs[SUB_REAL].needanswer = 1;
04699             p->dialing = 0;
04700          }
04701          break;
04702       case DAHDI_EVENT_HOOKCOMPLETE:
04703       case DAHDI_EVENT_RINGERON:
04704       case DAHDI_EVENT_RINGEROFF:
04705          /* Do nothing */
04706          break;
04707       case DAHDI_EVENT_WINKFLASH:
04708          gettimeofday(&p->flashtime, NULL);
04709          if (p->owner) {
04710             if (option_verbose > 2) 
04711                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
04712             if (p->owner->_state != AST_STATE_UP) {
04713                /* Answer if necessary */
04714                usedindex = dahdi_get_index(p->owner, p, 0);
04715                if (usedindex > -1) {
04716                   p->subs[usedindex].needanswer = 1;
04717                }
04718                ast_setstate(p->owner, AST_STATE_UP);
04719             }
04720             p->callwaitingrepeat = 0;
04721             p->cidcwexpire = 0;
04722             if (ast_bridged_channel(p->owner))
04723                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04724             p->subs[SUB_REAL].needunhold = 1;
04725          } else
04726             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
04727          update_conf(p);
04728          break;
04729       default:
04730          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
04731       }
04732       f = &p->subs[index].f;
04733       return f;
04734    }
04735    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
04736       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
04737    /* If it's not us, return NULL immediately */
04738    if (ast != p->owner) {
04739       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
04740       f = &p->subs[index].f;
04741       return f;
04742    }
04743    f = dahdi_handle_event(ast);
04744    return f;
04745 }
04746 
04747 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
04748 {
04749    struct dahdi_pvt *p = ast->tech_pvt;
04750    struct ast_frame *f;
04751    ast_mutex_lock(&p->lock);
04752    f = __dahdi_exception(ast);
04753    ast_mutex_unlock(&p->lock);
04754    return f;
04755 }
04756 
04757 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
04758 {
04759    struct dahdi_pvt *p = ast->tech_pvt;
04760    int res;
04761    int index;
04762    void *readbuf;
04763    struct ast_frame *f;
04764 
04765    while (ast_mutex_trylock(&p->lock)) {
04766       DEADLOCK_AVOIDANCE(&ast->lock);
04767    }
04768 
04769    index = dahdi_get_index(ast, p, 0);
04770    
04771    /* Hang up if we don't really exist */
04772    if (index < 0) {
04773       ast_log(LOG_WARNING, "We dont exist?\n");
04774       ast_mutex_unlock(&p->lock);
04775       return NULL;
04776    }
04777    
04778    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
04779 
04780    p->subs[index].f.frametype = AST_FRAME_NULL;
04781    p->subs[index].f.datalen = 0;
04782    p->subs[index].f.samples = 0;
04783    p->subs[index].f.mallocd = 0;
04784    p->subs[index].f.offset = 0;
04785    p->subs[index].f.subclass = 0;
04786    p->subs[index].f.delivery = ast_tv(0,0);
04787    p->subs[index].f.src = "dahdi_read";
04788    p->subs[index].f.data = NULL;
04789    
04790    /* make sure it sends initial key state as first frame */
04791    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
04792    {
04793       struct dahdi_params ps;
04794 
04795       ps.channo = p->channel;
04796       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
04797          ast_mutex_unlock(&p->lock);
04798          return NULL;
04799       }
04800       p->firstradio = 1;
04801       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04802       if (ps.rxisoffhook)
04803       {
04804          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04805       }
04806       else
04807       {
04808          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04809       }
04810       ast_mutex_unlock(&p->lock);
04811       return &p->subs[index].f;
04812    }
04813    if (p->ringt == 1) {
04814       ast_mutex_unlock(&p->lock);
04815       return NULL;
04816    }
04817    else if (p->ringt > 0) 
04818       p->ringt--;
04819 
04820    if (p->subs[index].needringing) {
04821       /* Send ringing frame if requested */
04822       p->subs[index].needringing = 0;
04823       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04824       p->subs[index].f.subclass = AST_CONTROL_RINGING;
04825       ast_setstate(ast, AST_STATE_RINGING);
04826       ast_mutex_unlock(&p->lock);
04827       return &p->subs[index].f;
04828    }
04829 
04830    if (p->subs[index].needbusy) {
04831       /* Send busy frame if requested */
04832       p->subs[index].needbusy = 0;
04833       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04834       p->subs[index].f.subclass = AST_CONTROL_BUSY;
04835       ast_mutex_unlock(&p->lock);
04836       return &p->subs[index].f;
04837    }
04838 
04839    if (p->subs[index].needcongestion) {
04840       /* Send congestion frame if requested */
04841       p->subs[index].needcongestion = 0;
04842       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04843       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
04844       ast_mutex_unlock(&p->lock);
04845       return &p->subs[index].f;
04846    }
04847 
04848    if (p->subs[index].needcallerid) {
04849       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
04850                      S_OR(p->lastcid_name, NULL),
04851                      S_OR(p->lastcid_num, NULL)
04852                      );
04853       p->subs[index].needcallerid = 0;
04854    }
04855    
04856    if (p->subs[index].needanswer) {
04857       /* Send answer frame if requested */
04858       p->subs[index].needanswer = 0;
04859       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04860       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04861       ast_mutex_unlock(&p->lock);
04862       return &p->subs[index].f;
04863    }  
04864    
04865    if (p->subs[index].needflash) {
04866       /* Send answer frame if requested */
04867       p->subs[index].needflash = 0;
04868       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04869       p->subs[index].f.subclass = AST_CONTROL_FLASH;
04870       ast_mutex_unlock(&p->lock);
04871       return &p->subs[index].f;
04872    }  
04873    
04874    if (p->subs[index].needhold) {
04875       /* Send answer frame if requested */
04876       p->subs[index].needhold = 0;
04877       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04878       p->subs[index].f.subclass = AST_CONTROL_HOLD;
04879       ast_mutex_unlock(&p->lock);
04880       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
04881       return &p->subs[index].f;
04882    }  
04883    
04884    if (p->subs[index].needunhold) {
04885       /* Send answer frame if requested */
04886       p->subs[index].needunhold = 0;
04887       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04888       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
04889       ast_mutex_unlock(&p->lock);
04890       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
04891       return &p->subs[index].f;
04892    }  
04893    
04894    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
04895       if (!p->subs[index].linear) {
04896          p->subs[index].linear = 1;
04897          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04898          if (res) 
04899             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
04900       }
04901    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
04902          (ast->rawreadformat == AST_FORMAT_ALAW)) {
04903       if (p->subs[index].linear) {
04904          p->subs[index].linear = 0;
04905          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
04906          if (res) 
04907             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
04908       }
04909    } else {
04910       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
04911       ast_mutex_unlock(&p->lock);
04912       return NULL;
04913    }
04914    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
04915    CHECK_BLOCKING(ast);
04916    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04917    ast_clear_flag(ast, AST_FLAG_BLOCKING);
04918    /* Check for hangup */
04919    if (res < 0) {
04920       f = NULL;
04921       if (res == -1)  {
04922          if (errno == EAGAIN) {
04923             /* Return "NULL" frame if there is nobody there */
04924             ast_mutex_unlock(&p->lock);
04925             return &p->subs[index].f;
04926          } else if (errno == ELAST) {
04927             f = __dahdi_exception(ast);
04928          } else
04929             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
04930       }
04931       ast_mutex_unlock(&p->lock);
04932       return f;
04933    }
04934    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
04935       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
04936       f = __dahdi_exception(ast);
04937       ast_mutex_unlock(&p->lock);
04938       return f;
04939    }
04940    if (p->tdd) { /* if in TDD mode, see if we receive that */
04941       int c;
04942 
04943       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
04944       if (c < 0) {
04945          ast_log(LOG_DEBUG,"tdd_feed failed\n");
04946          ast_mutex_unlock(&p->lock);
04947          return NULL;
04948       }
04949       if (c) { /* if a char to return */
04950          p->subs[index].f.subclass = 0;
04951          p->subs[index].f.frametype = AST_FRAME_TEXT;
04952          p->subs[index].f.mallocd = 0;
04953          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04954          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
04955          p->subs[index].f.datalen = 1;
04956          *((char *) p->subs[index].f.data) = c;
04957          ast_mutex_unlock(&p->lock);
04958          return &p->subs[index].f;
04959       }
04960    }
04961    /* Ensure the CW timer decrements only on a single subchannel */
04962    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
04963       p->callwaitingrepeat--;
04964    }
04965    if (p->cidcwexpire)
04966       p->cidcwexpire--;
04967    /* Repeat callwaiting */
04968    if (p->callwaitingrepeat == 1) {
04969       p->callwaitrings++;
04970       dahdi_callwait(ast);
04971    }
04972    /* Expire CID/CW */
04973    if (p->cidcwexpire == 1) {
04974       if (option_verbose > 2)
04975          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
04976       restore_conference(p);
04977    }
04978    if (p->subs[index].linear) {
04979       p->subs[index].f.datalen = READ_SIZE * 2;
04980    } else 
04981       p->subs[index].f.datalen = READ_SIZE;
04982 
04983    /* Handle CallerID Transmission */
04984    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
04985       send_callerid(p);
04986    }
04987 
04988    p->subs[index].f.frametype = AST_FRAME_VOICE;
04989    p->subs[index].f.subclass = ast->rawreadformat;
04990    p->subs[index].f.samples = READ_SIZE;
04991    p->subs[index].f.mallocd = 0;
04992    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
04993    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
04994 #if 0
04995    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
04996 #endif   
04997    if (p->dialing || /* Transmitting something */
04998       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
04999       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05000       ) {
05001       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05002          don't send anything */
05003       p->subs[index].f.frametype = AST_FRAME_NULL;
05004       p->subs[index].f.subclass = 0;
05005       p->subs[index].f.samples = 0;
05006       p->subs[index].f.mallocd = 0;
05007       p->subs[index].f.offset = 0;
05008       p->subs[index].f.data = NULL;
05009       p->subs[index].f.datalen= 0;
05010    }
05011    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
05012       /* Perform busy detection. etc on the dahdi line */
05013       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05014       if (f) {
05015          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05016             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05017                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05018                   a busy  */
05019                f = NULL;
05020             }
05021          } else if (f->frametype == AST_FRAME_DTMF) {
05022 #ifdef HAVE_PRI
05023             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05024                /* Don't accept in-band DTMF when in overlap dial mode */
05025                f->frametype = AST_FRAME_NULL;
05026                f->subclass = 0;
05027             }
05028 #endif            
05029             /* DSP clears us of being pulse */
05030             p->pulsedial = 0;
05031          }
05032       }
05033    } else 
05034       f = &p->subs[index].f; 
05035 
05036    if (f && (f->frametype == AST_FRAME_DTMF))
05037       dahdi_handle_dtmfup(ast, index, &f);
05038 
05039    /* If we have a fake_event, trigger exception to handle it */
05040    if (p->fake_event)
05041       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05042 
05043    ast_mutex_unlock(&p->lock);
05044    return f;
05045 }
05046 
05047 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
05048 {
05049    int sent=0;
05050    int size;
05051    int res;
05052    int fd;
05053    fd = p->subs[index].dfd;
05054    while (len) {
05055       size = len;
05056       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05057          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05058       res = write(fd, buf, size);
05059       if (res != size) {
05060          if (option_debug)
05061             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05062          return sent;
05063       }
05064       len -= size;
05065       buf += size;
05066    }
05067    return sent;
05068 }
05069 
05070 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05071 {
05072    struct dahdi_pvt *p = ast->tech_pvt;
05073    int res;
05074    int index;
05075    index = dahdi_get_index(ast, p, 0);
05076    if (index < 0) {
05077       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05078       return -1;
05079    }
05080 
05081 #if 0
05082 #ifdef HAVE_PRI
05083    ast_mutex_lock(&p->lock);
05084    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05085       if (p->pri->pri) {      
05086          if (!pri_grab(p, p->pri)) {
05087                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05088                pri_rel(p->pri);
05089          } else
05090                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05091       }
05092       p->proceeding=1;
05093    }
05094    ast_mutex_unlock(&p->lock);
05095 #endif
05096 #endif
05097    /* Write a frame of (presumably voice) data */
05098    if (frame->frametype != AST_FRAME_VOICE) {
05099       if (frame->frametype != AST_FRAME_IMAGE)
05100          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05101       return 0;
05102    }
05103    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
05104        (frame->subclass != AST_FORMAT_ULAW) &&
05105        (frame->subclass != AST_FORMAT_ALAW)) {
05106       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05107       return -1;
05108    }
05109    if (p->dialing) {
05110       if (option_debug)
05111          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05112       return 0;
05113    }
05114    if (!p->owner) {
05115       if (option_debug)
05116          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05117       return 0;
05118    }
05119    if (p->cidspill) {
05120       if (option_debug)
05121          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05122       return 0;
05123    }
05124    /* Return if it's not valid data */
05125    if (!frame->data || !frame->datalen)
05126       return 0;
05127 
05128    if (frame->subclass == AST_FORMAT_SLINEAR) {
05129       if (!p->subs[index].linear) {
05130          p->subs[index].linear = 1;
05131          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05132          if (res)
05133             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05134       }
05135       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05136    } else {
05137       /* x-law already */
05138       if (p->subs[index].linear) {
05139          p->subs[index].linear = 0;
05140          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05141          if (res)
05142             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05143       }
05144       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05145    }
05146    if (res < 0) {
05147       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05148       return -1;
05149    } 
05150    return 0;
05151 }
05152 
05153 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
05154 {
05155    struct dahdi_pvt *p = chan->tech_pvt;
05156    int res=-1;
05157    int index;
05158    int func = DAHDI_FLASH;
05159    ast_mutex_lock(&p->lock);
05160    index = dahdi_get_index(chan, p, 0);
05161    if (option_debug)
05162       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05163    if (index == SUB_REAL) {
05164       switch (condition) {
05165       case AST_CONTROL_BUSY:
05166 #ifdef HAVE_PRI
05167          if (p->priindication_oob && p->sig == SIG_PRI) {
05168             chan->hangupcause = AST_CAUSE_USER_BUSY;
05169             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05170             res = 0;
05171          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05172             if (p->pri->pri) {      
05173                if (!pri_grab(p, p->pri)) {
05174                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05175                   pri_rel(p->pri);
05176                }
05177                else
05178                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05179             }
05180             p->progress = 1;
05181             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05182          } else
05183 #endif
05184             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05185          break;
05186       case AST_CONTROL_RINGING:
05187 #ifdef HAVE_PRI
05188          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05189             if (p->pri->pri) {      
05190                if (!pri_grab(p, p->pri)) {
05191                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05192                   pri_rel(p->pri);
05193                }
05194                else
05195                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05196             }
05197             p->alerting = 1;
05198          }
05199 #endif
05200          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05201          if (chan->_state != AST_STATE_UP) {
05202             if ((chan->_state != AST_STATE_RING) ||
05203                ((p->sig != SIG_FXSKS) &&
05204                 (p->sig != SIG_FXSLS) &&
05205                 (p->sig != SIG_FXSGS)))
05206                ast_setstate(chan, AST_STATE_RINGING);
05207          }
05208          break;
05209       case AST_CONTROL_PROCEEDING:
05210          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05211 #ifdef HAVE_PRI
05212          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05213             if (p->pri->pri) {      
05214                if (!pri_grab(p, p->pri)) {
05215                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05216                   pri_rel(p->pri);
05217                }
05218                else
05219                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05220             }
05221             p->proceeding = 1;
05222          }
05223 #endif
05224          /* don't continue in ast_indicate */
05225          res = 0;
05226          break;
05227       case AST_CONTROL_PROGRESS:
05228          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05229 #ifdef HAVE_PRI
05230          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05231          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05232             if (p->pri->pri) {      
05233                if (!pri_grab(p, p->pri)) {
05234                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05235                   pri_rel(p->pri);
05236                }
05237                else
05238                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05239             }
05240             p->progress = 1;
05241          }
05242 #endif
05243          /* don't continue in ast_indicate */
05244          res = 0;
05245          break;
05246       case AST_CONTROL_CONGESTION:
05247          chan->hangupcause = AST_CAUSE_CONGESTION;
05248 #ifdef HAVE_PRI
05249          if (p->priindication_oob && p->sig == SIG_PRI) {
05250             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05251             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05252             res = 0;
05253          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05254             if (p->pri) {     
05255                if (!pri_grab(p, p->pri)) {
05256                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05257                   pri_rel(p->pri);
05258                } else
05259                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05260             }
05261             p->progress = 1;
05262             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05263          } else
05264 #endif
05265             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05266          break;
05267       case AST_CONTROL_HOLD:
05268 #ifdef HAVE_PRI
05269          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05270             if (!pri_grab(p, p->pri)) {
05271                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05272                pri_rel(p->pri);
05273             } else
05274                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05275          } else
05276 #endif
05277             ast_moh_start(chan, data, p->mohinterpret);
05278          break;
05279       case AST_CONTROL_UNHOLD:
05280 #ifdef HAVE_PRI
05281          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05282             if (!pri_grab(p, p->pri)) {
05283                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05284                pri_rel(p->pri);
05285             } else
05286                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05287          } else
05288 #endif
05289             ast_moh_stop(chan);
05290          break;
05291       case AST_CONTROL_RADIO_KEY:
05292          if (p->radio) 
05293              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05294          res = 0;
05295          break;
05296       case AST_CONTROL_RADIO_UNKEY:
05297          if (p->radio)
05298              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05299          res = 0;
05300          break;
05301       case AST_CONTROL_FLASH:
05302          /* flash hookswitch */
05303          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05304             /* Clear out the dial buffer */
05305             p->dop.dialstr[0] = '\0';
05306             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05307                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05308                   chan->name, strerror(errno));
05309             } else
05310                res = 0;
05311          } else
05312             res = 0;
05313          break;
05314       case AST_CONTROL_SRCUPDATE:
05315          res = 0;
05316          break;
05317       case -1:
05318          res = tone_zone_play_tone(p->subs[index].dfd, -1);
05319          break;
05320       }
05321    } else
05322       res = 0;
05323    ast_mutex_unlock(&p->lock);
05324    return res;
05325 }
05326 
05327 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
05328 {
05329    struct ast_channel *tmp;
05330    int deflaw;
05331    int res;
05332    int x,y;
05333    int features;
05334    char *b2 = NULL;
05335    struct dahdi_params ps;
05336    char chanprefix[*dahdi_chan_name_len + 4];
05337 
05338    if (i->subs[index].owner) {
05339       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05340       return NULL;
05341    }
05342    y = 1;
05343    do {
05344       if (b2)
05345          free(b2);
05346 #ifdef HAVE_PRI
05347       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05348          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05349       else
05350 #endif
05351       if (i->channel == CHAN_PSEUDO)
05352          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05353       else  
05354          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05355       for (x = 0; x < 3; x++) {
05356          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05357             break;
05358       }
05359       y++;
05360    } while (x < 3);
05361    strcpy(chanprefix, dahdi_chan_name);
05362    strcat(chanprefix, "/%s");
05363    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05364    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05365       free(b2);
05366    if (!tmp)
05367       return NULL;
05368    tmp->tech = chan_tech;
05369    ps.channo = i->channel;
05370    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05371    if (res) {
05372       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05373       ps.curlaw = DAHDI_LAW_MULAW;
05374    }
05375    if (ps.curlaw == DAHDI_LAW_ALAW)
05376       deflaw = AST_FORMAT_ALAW;
05377    else
05378       deflaw = AST_FORMAT_ULAW;
05379    if (law) {
05380       if (law == DAHDI_LAW_ALAW)
05381          deflaw = AST_FORMAT_ALAW;
05382       else
05383          deflaw = AST_FORMAT_ULAW;
05384    }
05385    tmp->fds[0] = i->subs[index].dfd;
05386    tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
05387    /* Start out assuming ulaw since it's smaller :) */
05388    tmp->rawreadformat = deflaw;
05389    tmp->readformat = deflaw;
05390    tmp->rawwriteformat = deflaw;
05391    tmp->writeformat = deflaw;
05392    i->subs[index].linear = 0;
05393    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05394    features = 0;
05395    if (index == SUB_REAL) {
05396       if (i->busydetect && CANBUSYDETECT(i))
05397          features |= DSP_FEATURE_BUSY_DETECT;
05398       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05399          features |= DSP_FEATURE_CALL_PROGRESS;
05400       if ((!i->outgoing && (i->callprogress & 4)) || 
05401           (i->outgoing && (i->callprogress & 2))) {
05402          features |= DSP_FEATURE_FAX_DETECT;
05403       }
05404 #ifdef DAHDI_TONEDETECT
05405       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05406       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05407 #endif      
05408          i->hardwaredtmf = 0;
05409          features |= DSP_FEATURE_DTMF_DETECT;
05410 #ifdef DAHDI_TONEDETECT
05411       } else if (NEED_MFDETECT(i)) {
05412          i->hardwaredtmf = 1;
05413          features |= DSP_FEATURE_DTMF_DETECT;
05414       }
05415 #endif
05416    }
05417    if (features) {
05418       if (i->dsp) {
05419          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05420       } else {
05421          if (i->channel != CHAN_PSEUDO)
05422             i->dsp = ast_dsp_new();
05423          else
05424             i->dsp = NULL;
05425          if (i->dsp) {
05426             i->dsp_features = features;
05427 #ifdef HAVE_PRI
05428             /* We cannot do progress detection until receives PROGRESS message */
05429             if (i->outgoing && (i->sig == SIG_PRI)) {
05430                /* Remember requested DSP features, don't treat
05431                   talking as ANSWER */
05432                i->dsp_features = features & ~DSP_PROGRESS_TALK;
05433                features = 0;
05434             }
05435 #endif
05436             ast_dsp_set_features(i->dsp, features);
05437             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05438             if (!ast_strlen_zero(progzone))
05439                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05440             if (i->busydetect && CANBUSYDETECT(i)) {
05441                if(i->silencethreshold > 0)
05442                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05443                ast_dsp_set_busy_count(i->dsp, i->busycount);
05444                if(i->busytonelength > 0)
05445                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05446                if((i->busytonelength == i->busyquietlength) && i->busycompare)
05447                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05448             }
05449          }
05450       }
05451    }
05452       
05453    if (state == AST_STATE_RING)
05454       tmp->rings = 1;
05455    tmp->tech_pvt = i;
05456    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05457       /* Only FXO signalled stuff can be picked up */
05458       tmp->callgroup = i->callgroup;
05459       tmp->pickupgroup = i->pickupgroup;
05460    }
05461    if (!ast_strlen_zero(i->language))
05462       ast_string_field_set(tmp, language, i->language);
05463    if (!i->owner)
05464       i->owner = tmp;
05465    if (!ast_strlen_zero(i->accountcode))
05466       ast_string_field_set(tmp, accountcode, i->accountcode);
05467    if (i->amaflags)
05468       tmp->amaflags = i->amaflags;
05469    i->subs[index].owner = tmp;
05470    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05471    ast_string_field_set(tmp, call_forward, i->call_forward);
05472    /* If we've been told "no ADSI" then enforce it */
05473    if (!i->adsi)
05474       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05475    if (!ast_strlen_zero(i->exten))
05476       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05477    if (!ast_strlen_zero(i->rdnis))
05478       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05479    if (!ast_strlen_zero(i->dnid))
05480       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05481 
05482    /* Don't use ast_set_callerid() here because it will
05483     * generate a needless NewCallerID event */
05484 #ifdef PRI_ANI
05485    if (!ast_strlen_zero(i->cid_ani))
05486       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05487    else  
05488       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05489 #else
05490    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05491 #endif
05492    tmp->cid.cid_pres = i->callingpres;
05493    tmp->cid.cid_ton = i->cid_ton;
05494 #ifdef HAVE_PRI
05495    tmp->transfercapability = transfercapability;
05496    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05497    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05498       i->digital = 1;
05499    /* Assume calls are not idle calls unless we're told differently */
05500    i->isidlecall = 0;
05501    i->alreadyhungup = 0;
05502 #endif
05503    /* clear the fake event in case we posted one before we had ast_channel */
05504    i->fake_event = 0;
05505    /* Assure there is no confmute on this channel */
05506    dahdi_confmute(i, 0);
05507    /* Configure the new channel jb */
05508    ast_jb_configure(tmp, &global_jbconf);
05509    if (startpbx) {
05510       if (ast_pbx_start(tmp)) {
05511          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05512          ast_hangup(tmp);
05513          i->owner = NULL;
05514          return NULL;
05515       }
05516    }
05517 
05518    ast_module_ref(ast_module_info->self);
05519    
05520    return tmp;
05521 }
05522 
05523 
05524 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
05525 {
05526    char c;
05527 
05528    *str = 0; /* start with empty output buffer */
05529    for (;;)
05530    {
05531       /* Wait for the first digit (up to specified ms). */
05532       c = ast_waitfordigit(chan, ms);
05533       /* if timeout, hangup or error, return as such */
05534       if (c < 1)
05535          return c;
05536       *str++ = c;
05537       *str = 0;
05538       if (strchr(term, c))
05539          return 1;
05540    }
05541 }
05542 
05543 static int dahdi_wink(struct dahdi_pvt *p, int index)
05544 {
05545    int j;
05546    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05547    for (;;)
05548    {
05549          /* set bits of interest */
05550       j = DAHDI_IOMUX_SIGEVENT;
05551           /* wait for some happening */
05552       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05553          /* exit loop if we have it */
05554       if (j & DAHDI_IOMUX_SIGEVENT) break;
05555    }
05556      /* get the event info */
05557    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05558    return 0;
05559 }
05560 
05561 static void *ss_thread(void *data)
05562 {
05563    struct ast_channel *chan = data;
05564    struct dahdi_pvt *p = chan->tech_pvt;
05565    char exten[AST_MAX_EXTENSION] = "";
05566    char exten2[AST_MAX_EXTENSION] = "";
05567    unsigned char buf[256];
05568    char dtmfcid[300];
05569    char dtmfbuf[300];
05570    struct callerid_state *cs = NULL;
05571    char *name = NULL, *number = NULL;
05572    int distMatches;
05573    int curRingData[3];
05574    int receivedRingT;
05575    int counter1;
05576    int counter;
05577    int samples = 0;
05578    struct ast_smdi_md_message *smdi_msg = NULL;
05579    int flags;
05580    int i;
05581    int timeout;
05582    int getforward = 0;
05583    char *s1, *s2;
05584    int len = 0;
05585    int res;
05586    int index;
05587 
05588    ast_mutex_lock(&ss_thread_lock);
05589    ss_thread_count++;
05590    ast_mutex_unlock(&ss_thread_lock);
05591    /* in the bizarre case where the channel has become a zombie before we
05592       even get started here, abort safely
05593    */
05594    if (!p) {
05595       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05596       ast_hangup(chan);
05597       goto quit;
05598    }
05599    if (option_verbose > 2) 
05600       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05601    index = dahdi_get_index(chan, p, 1);
05602    if (index < 0) {
05603       ast_log(LOG_WARNING, "Huh?\n");
05604       ast_hangup(chan);
05605       goto quit;
05606    }
05607    if (p->dsp)
05608       ast_dsp_digitreset(p->dsp);
05609    switch (p->sig) {
05610 #ifdef HAVE_PRI
05611    case SIG_PRI:
05612       /* Now loop looking for an extension */
05613       ast_copy_string(exten, p->exten, sizeof(exten));
05614       len = strlen(exten);
05615       res = 0;
05616       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05617          if (len && !ast_ignore_pattern(chan->context, exten))
05618             tone_zone_play_tone(p->subs[index].dfd, -1);
05619          else
05620             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05621          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05622             timeout = matchdigittimeout;
05623          else
05624             timeout = gendigittimeout;
05625          res = ast_waitfordigit(chan, timeout);
05626          if (res < 0) {
05627             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05628             ast_hangup(chan);
05629             goto quit;
05630          } else if (res) {
05631             exten[len++] = res;
05632             exten[len] = '\0';
05633          } else
05634             break;
05635       }
05636       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
05637       if (ast_strlen_zero(exten)) {
05638          if (option_verbose > 2)
05639             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05640          exten[0] = 's';
05641          exten[1] = '\0';
05642       }
05643       tone_zone_play_tone(p->subs[index].dfd, -1);
05644       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05645          /* Start the real PBX */
05646          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05647          if (p->dsp) ast_dsp_digitreset(p->dsp);
05648          dahdi_enable_ec(p);
05649          ast_setstate(chan, AST_STATE_RING);
05650          res = ast_pbx_run(chan);
05651          if (res) {
05652             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05653          }
05654       } else {
05655          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05656          chan->hangupcause = AST_CAUSE_UNALLOCATED;
05657          ast_hangup(chan);
05658          p->exten[0] = '\0';
05659          /* Since we send release complete here, we won't get one */
05660          p->call = NULL;
05661       }
05662       goto quit;
05663       break;
05664 #endif
05665    case SIG_FEATD:
05666    case SIG_FEATDMF:
05667    case SIG_FEATDMF_TA:
05668    case SIG_E911:
05669    case SIG_FGC_CAMAMF:
05670    case SIG_FEATB:
05671    case SIG_EMWINK:
05672    case SIG_SF_FEATD:
05673    case SIG_SF_FEATDMF:
05674    case SIG_SF_FEATB:
05675    case SIG_SFWINK:
05676       if (dahdi_wink(p, index))  
05677          goto quit;
05678       /* Fall through */
05679    case SIG_EM:
05680    case SIG_EM_E1:
05681    case SIG_SF:
05682    case SIG_FGC_CAMA:
05683       res = tone_zone_play_tone(p->subs[index].dfd, -1);
05684       if (p->dsp)
05685          ast_dsp_digitreset(p->dsp);
05686       /* set digit mode appropriately */
05687       if (p->dsp) {
05688          if (NEED_MFDETECT(p))
05689             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
05690          else 
05691             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05692       }
05693       memset(dtmfbuf, 0, sizeof(dtmfbuf));
05694       /* Wait for the first digit only if immediate=no */
05695       if (!p->immediate)
05696          /* Wait for the first digit (up to 5 seconds). */
05697          res = ast_waitfordigit(chan, 5000);
05698       else
05699          res = 0;
05700       if (res > 0) {
05701          /* save first char */
05702          dtmfbuf[0] = res;
05703          switch (p->sig) {
05704          case SIG_FEATD:
05705          case SIG_SF_FEATD:
05706             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05707             if (res > 0)
05708                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05709             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05710             break;
05711          case SIG_FEATDMF_TA:
05712             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05713             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05714             if (dahdi_wink(p, index)) goto quit;
05715             dtmfbuf[0] = 0;
05716             /* Wait for the first digit (up to 5 seconds). */
05717             res = ast_waitfordigit(chan, 5000);
05718             if (res <= 0) break;
05719             dtmfbuf[0] = res;
05720             /* fall through intentionally */
05721          case SIG_FEATDMF:
05722          case SIG_E911:
05723          case SIG_FGC_CAMAMF:
05724          case SIG_SF_FEATDMF:
05725             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05726             /* if international caca, do it again to get real ANO */
05727             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
05728             {
05729                if (dahdi_wink(p, index)) goto quit;
05730                dtmfbuf[0] = 0;
05731                /* Wait for the first digit (up to 5 seconds). */
05732                res = ast_waitfordigit(chan, 5000);
05733                if (res <= 0) break;
05734                dtmfbuf[0] = res;
05735                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05736             }
05737             if (res > 0) {
05738                /* if E911, take off hook */
05739                if (p->sig == SIG_E911)
05740                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05741                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
05742             }
05743             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05744             break;
05745          case SIG_FEATB:
05746          case SIG_SF_FEATB:
05747             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
05748             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05749             break;
05750          case SIG_EMWINK:
05751             /* if we received a '*', we are actually receiving Feature Group D
05752                dial syntax, so use that mode; otherwise, fall through to normal
05753                mode
05754             */
05755             if (res == '*') {
05756                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
05757                if (res > 0)
05758                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
05759                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
05760                break;
05761             }
05762          default:
05763             /* If we got the first digit, get the rest */
05764             len = 1;
05765             dtmfbuf[len] = '\0';
05766             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05767                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
05768                   timeout = matchdigittimeout;
05769                } else {
05770                   timeout = gendigittimeout;
05771                }
05772                res = ast_waitfordigit(chan, timeout);
05773                if (res < 0) {
05774                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05775                   ast_hangup(chan);
05776                   goto quit;
05777                } else if (res) {
05778                   dtmfbuf[len++] = res;
05779                   dtmfbuf[len] = '\0';
05780                } else {
05781                   break;
05782                }
05783             }
05784             break;
05785          }
05786       }
05787       if (res == -1) {
05788          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
05789          ast_hangup(chan);
05790          goto quit;
05791       } else if (res < 0) {
05792          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
05793          ast_hangup(chan);
05794          goto quit;
05795       }
05796 
05797       if (p->sig == SIG_FGC_CAMA) {
05798          char anibuf[100];
05799 
05800          if (ast_safe_sleep(chan,1000) == -1) {
05801                            ast_hangup(chan);
05802                            goto quit;
05803          }
05804                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05805                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
05806                         res = my_getsigstr(chan, anibuf, "#", 10000);
05807                         if ((res > 0) && (strlen(anibuf) > 2)) {
05808             if (anibuf[strlen(anibuf) - 1] == '#')
05809                anibuf[strlen(anibuf) - 1] = 0;
05810             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
05811          }
05812                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
05813       }
05814 
05815       ast_copy_string(exten, dtmfbuf, sizeof(exten));
05816       if (ast_strlen_zero(exten))
05817          ast_copy_string(exten, "s", sizeof(exten));
05818       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
05819          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
05820          if (exten[0] == '*') {
05821             char *stringp=NULL;
05822             ast_copy_string(exten2, exten, sizeof(exten2));
05823             /* Parse out extension and callerid */
05824             stringp=exten2 +1;
05825             s1 = strsep(&stringp, "*");
05826             s2 = strsep(&stringp, "*");
05827             if (s2) {
05828                if (!ast_strlen_zero(p->cid_num))
05829                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05830                else
05831                   ast_set_callerid(chan, s1, NULL, s1);
05832                ast_copy_string(exten, s2, sizeof(exten));
05833             } else
05834                ast_copy_string(exten, s1, sizeof(exten));
05835          } else if (p->sig == SIG_FEATD)
05836             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05837       }
05838       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05839          if (exten[0] == '*') {
05840             char *stringp=NULL;
05841             ast_copy_string(exten2, exten, sizeof(exten2));
05842             /* Parse out extension and callerid */
05843             stringp=exten2 +1;
05844             s1 = strsep(&stringp, "#");
05845             s2 = strsep(&stringp, "#");
05846             if (s2) {
05847                if (!ast_strlen_zero(p->cid_num))
05848                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
05849                else
05850                   if (*(s1 + 2))
05851                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
05852                ast_copy_string(exten, s2 + 1, sizeof(exten));
05853             } else
05854                ast_copy_string(exten, s1 + 2, sizeof(exten));
05855          } else
05856             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05857       }
05858       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
05859          if (exten[0] == '*') {
05860             char *stringp=NULL;
05861             ast_copy_string(exten2, exten, sizeof(exten2));
05862             /* Parse out extension and callerid */
05863             stringp=exten2 +1;
05864             s1 = strsep(&stringp, "#");
05865             s2 = strsep(&stringp, "#");
05866             if (s2 && (*(s2 + 1) == '0')) {
05867                if (*(s2 + 2))
05868                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
05869             }
05870             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
05871             else ast_copy_string(exten, "911", sizeof(exten));
05872          } else
05873             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05874       }
05875       if (p->sig == SIG_FEATB) {
05876          if (exten[0] == '*') {
05877             char *stringp=NULL;
05878             ast_copy_string(exten2, exten, sizeof(exten2));
05879             /* Parse out extension and callerid */
05880             stringp=exten2 +1;
05881             s1 = strsep(&stringp, "#");
05882             ast_copy_string(exten, exten2 + 1, sizeof(exten));
05883          } else
05884             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
05885       }
05886       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
05887          dahdi_wink(p, index);
05888                         /* some switches require a minimum guard time between
05889                            the last FGD wink and something that answers
05890                            immediately. This ensures it */
05891                         if (ast_safe_sleep(chan,100)) goto quit;
05892       }
05893       dahdi_enable_ec(p);
05894       if (NEED_MFDETECT(p)) {
05895          if (p->dsp) {
05896             if (!p->hardwaredtmf)
05897                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
05898             else {
05899                ast_dsp_free(p->dsp);
05900                p->dsp = NULL;
05901             }
05902          }
05903       }
05904 
05905       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
05906          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05907          if (p->dsp) ast_dsp_digitreset(p->dsp);
05908          res = ast_pbx_run(chan);
05909          if (res) {
05910             ast_log(LOG_WARNING, "PBX exited non-zero\n");
05911             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05912          }
05913          goto quit;
05914       } else {
05915          if (option_verbose > 2)
05916             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
05917          sleep(2);
05918          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
05919          if (res < 0)
05920             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
05921          else
05922             sleep(1);
05923          res = ast_streamfile(chan, "ss-noservice", chan->language);
05924          if (res >= 0)
05925             ast_waitstream(chan, "");
05926          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05927          ast_hangup(chan);
05928          goto quit;
05929       }
05930       break;
05931    case SIG_FXOLS:
05932    case SIG_FXOGS:
05933    case SIG_FXOKS:
05934       /* Read the first digit */
05935       timeout = firstdigittimeout;
05936       /* If starting a threeway call, never timeout on the first digit so someone
05937          can use flash-hook as a "hold" feature */
05938       if (p->subs[SUB_THREEWAY].owner) 
05939          timeout = 999999;
05940       while (len < AST_MAX_EXTENSION-1) {
05941          /* Read digit unless it's supposed to be immediate, in which case the
05942             only answer is 's' */
05943          if (p->immediate) 
05944             res = 's';
05945          else
05946             res = ast_waitfordigit(chan, timeout);
05947          timeout = 0;
05948          if (res < 0) {
05949             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05950             res = tone_zone_play_tone(p->subs[index].dfd, -1);
05951             ast_hangup(chan);
05952             goto quit;
05953          } else if (res)  {
05954             exten[len++]=res;
05955             exten[len] = '\0';
05956          }
05957          if (!ast_ignore_pattern(chan->context, exten))
05958             tone_zone_play_tone(p->subs[index].dfd, -1);
05959          else
05960             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05961          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
05962             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05963                if (getforward) {
05964                   /* Record this as the forwarding extension */
05965                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
05966                   if (option_verbose > 2)
05967                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
05968                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
05969                   if (res)
05970                      break;
05971                   usleep(500000);
05972                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
05973                   sleep(1);
05974                   memset(exten, 0, sizeof(exten));
05975                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05976                   len = 0;
05977                   getforward = 0;
05978                } else  {
05979                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
05980                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05981                   if (!ast_strlen_zero(p->cid_num)) {
05982                      if (!p->hidecallerid)
05983                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
05984                      else
05985                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
05986                   }
05987                   if (!ast_strlen_zero(p->cid_name)) {
05988                      if (!p->hidecallerid)
05989                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
05990                   }
05991                   ast_setstate(chan, AST_STATE_RING);
05992                   dahdi_enable_ec(p);
05993                   res = ast_pbx_run(chan);
05994                   if (res) {
05995                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
05996                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05997                   }
05998                   goto quit;
05999                }
06000             } else {
06001                /* It's a match, but they just typed a digit, and there is an ambiguous match,
06002                   so just set the timeout to matchdigittimeout and wait some more */
06003                timeout = matchdigittimeout;
06004             }
06005          } else if (res == 0) {
06006             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06007             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06008             dahdi_wait_event(p->subs[index].dfd);
06009             ast_hangup(chan);
06010             goto quit;
06011          } else if (p->callwaiting && !strcmp(exten, "*70")) {
06012             if (option_verbose > 2) 
06013                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06014             /* Disable call waiting if enabled */
06015             p->callwaiting = 0;
06016             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06017             if (res) {
06018                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06019                   chan->name, strerror(errno));
06020             }
06021             len = 0;
06022             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06023             memset(exten, 0, sizeof(exten));
06024             timeout = firstdigittimeout;
06025                
06026          } else if (!strcmp(exten,ast_pickup_ext())) {
06027             /* Scan all channels and see if there are any
06028              * ringing channels that have call groups
06029              * that equal this channels pickup group  
06030              */
06031             if (index == SUB_REAL) {
06032                /* Switch us from Third call to Call Wait */
06033                if (p->subs[SUB_THREEWAY].owner) {
06034                   /* If you make a threeway call and the *8# a call, it should actually 
06035                      look like a callwait */
06036                   alloc_sub(p, SUB_CALLWAIT);   
06037                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06038                   unalloc_sub(p, SUB_THREEWAY);
06039                }
06040                dahdi_enable_ec(p);
06041                if (ast_pickup_call(chan)) {
06042                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
06043                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06044                   dahdi_wait_event(p->subs[index].dfd);
06045                }
06046                ast_hangup(chan);
06047                goto quit;
06048             } else {
06049                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
06050                ast_hangup(chan);
06051                goto quit;
06052             }
06053             
06054          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06055             if (option_verbose > 2) 
06056                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06057             /* Disable Caller*ID if enabled */
06058             p->hidecallerid = 1;
06059             if (chan->cid.cid_num)
06060                free(chan->cid.cid_num);
06061             chan->cid.cid_num = NULL;
06062             if (chan->cid.cid_name)
06063                free(chan->cid.cid_name);
06064             chan->cid.cid_name = NULL;
06065             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06066             if (res) {
06067                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06068                   chan->name, strerror(errno));
06069             }
06070             len = 0;
06071             memset(exten, 0, sizeof(exten));
06072             timeout = firstdigittimeout;
06073          } else if (p->callreturn && !strcmp(exten, "*69")) {
06074             res = 0;
06075             if (!ast_strlen_zero(p->lastcid_num)) {
06076                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06077             }
06078             if (!res)
06079                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06080             break;
06081          } else if (!strcmp(exten, "*78")) {
06082             /* Do not disturb */
06083             if (option_verbose > 2)
06084                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06085             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06086                      "Channel: %s/%d\r\n"
06087                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
06088             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06089             p->dnd = 1;
06090             getforward = 0;
06091             memset(exten, 0, sizeof(exten));
06092             len = 0;
06093          } else if (!strcmp(exten, "*79")) {
06094             /* Do not disturb */
06095             if (option_verbose > 2)
06096                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06097             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06098                      "Channel: %s/%d\r\n"
06099                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
06100             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06101             p->dnd = 0;
06102             getforward = 0;
06103             memset(exten, 0, sizeof(exten));
06104             len = 0;
06105          } else if (p->cancallforward && !strcmp(exten, "*72")) {
06106             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06107             getforward = 1;
06108             memset(exten, 0, sizeof(exten));
06109             len = 0;
06110          } else if (p->cancallforward && !strcmp(exten, "*73")) {
06111             if (option_verbose > 2)
06112                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06113             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06114             memset(p->call_forward, 0, sizeof(p->call_forward));
06115             getforward = 0;
06116             memset(exten, 0, sizeof(exten));
06117             len = 0;
06118          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
06119                   p->subs[SUB_THREEWAY].owner &&
06120                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06121             /* This is a three way call, the main call being a real channel, 
06122                and we're parking the first call. */
06123             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06124             if (option_verbose > 2)
06125                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06126             break;
06127          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06128             if (option_verbose > 2)
06129                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06130             res = ast_db_put("blacklist", p->lastcid_num, "1");
06131             if (!res) {
06132                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06133                memset(exten, 0, sizeof(exten));
06134                len = 0;
06135             }
06136          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06137             if (option_verbose > 2) 
06138                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06139             /* Enable Caller*ID if enabled */
06140             p->hidecallerid = 0;
06141             if (chan->cid.cid_num)
06142                free(chan->cid.cid_num);
06143             chan->cid.cid_num = NULL;
06144             if (chan->cid.cid_name)
06145                free(chan->cid.cid_name);
06146             chan->cid.cid_name = NULL;
06147             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06148             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06149             if (res) {
06150                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06151                   chan->name, strerror(errno));
06152             }
06153             len = 0;
06154             memset(exten, 0, sizeof(exten));
06155             timeout = firstdigittimeout;
06156          } else if (!strcmp(exten, "*0")) {
06157             struct ast_channel *nbridge = 
06158                p->subs[SUB_THREEWAY].owner;
06159             struct dahdi_pvt *pbridge = NULL;
06160               /* set up the private struct of the bridged one, if any */
06161             if (nbridge && ast_bridged_channel(nbridge)) 
06162                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06163             if (nbridge && pbridge && 
06164                 (nbridge->tech == chan_tech) && 
06165                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06166                 ISTRUNK(pbridge)) {
06167                int func = DAHDI_FLASH;
06168                /* Clear out the dial buffer */
06169                p->dop.dialstr[0] = '\0';
06170                /* flash hookswitch */
06171                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06172                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06173                      nbridge->name, strerror(errno));
06174                }
06175                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06176                unalloc_sub(p, SUB_THREEWAY);
06177                p->owner = p->subs[SUB_REAL].owner;
06178                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06179                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06180                ast_hangup(chan);
06181                goto quit;
06182             } else {
06183                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06184                dahdi_wait_event(p->subs[index].dfd);
06185                tone_zone_play_tone(p->subs[index].dfd, -1);
06186                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06187                unalloc_sub(p, SUB_THREEWAY);
06188                p->owner = p->subs[SUB_REAL].owner;
06189                ast_hangup(chan);
06190                goto quit;
06191             }              
06192          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06193                      ((exten[0] != '*') || (strlen(exten) > 2))) {
06194             if (option_debug)
06195                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);
06196             break;
06197          }
06198          if (!timeout)
06199             timeout = gendigittimeout;
06200          if (len && !ast_ignore_pattern(chan->context, exten))
06201             tone_zone_play_tone(p->subs[index].dfd, -1);
06202       }
06203       break;
06204    case SIG_FXSLS:
06205    case SIG_FXSGS:
06206    case SIG_FXSKS:
06207 #ifdef HAVE_PRI
06208       if (p->pri) {
06209          /* This is a GR-303 trunk actually.  Wait for the first ring... */
06210          struct ast_frame *f;
06211          int res;
06212          time_t start;
06213 
06214          time(&start);
06215          ast_setstate(chan, AST_STATE_RING);
06216          while (time(NULL) < start + 3) {
06217             res = ast_waitfor(chan, 1000);
06218             if (res) {
06219                f = ast_read(chan);
06220                if (!f) {
06221                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06222                   ast_hangup(chan);
06223                   goto quit;
06224                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06225                   res = 1;
06226                } else
06227                   res = 0;
06228                ast_frfree(f);
06229                if (res) {
06230                   ast_log(LOG_DEBUG, "Got ring!\n");
06231                   res = 0;
06232                   break;
06233                }
06234             }
06235          }
06236       }
06237 #endif
06238       /* check for SMDI messages */
06239       if (p->use_smdi && p->smdi_iface) {
06240          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06241 
06242          if (smdi_msg != NULL) {
06243             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06244 
06245             if (smdi_msg->type == 'B')
06246                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06247             else if (smdi_msg->type == 'N')
06248                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06249 
06250             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06251          } else {
06252             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06253          }
06254       }
06255 
06256       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06257             number = smdi_msg->calling_st;
06258 
06259       /* If we want caller id, we're in a prering state due to a polarity reversal
06260        * and we're set to use a polarity reversal to trigger the start of caller id,
06261        * grab the caller id and wait for ringing to start... */
06262       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06263          /* If set to use DTMF CID signalling, listen for DTMF */
06264          if (p->cid_signalling == CID_SIG_DTMF) {
06265             int i = 0;
06266             cs = NULL;
06267             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06268                "channel %s\n", chan->name);
06269             dahdi_setlinear(p->subs[index].dfd, 0);
06270             res = 2000;
06271             for (;;) {
06272                struct ast_frame *f;
06273                res = ast_waitfor(chan, res);
06274                if (res <= 0) {
06275                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06276                      "Exiting simple switch\n");
06277                   ast_hangup(chan);
06278                   goto quit;
06279                } 
06280                f = ast_read(chan);
06281                if (!f)
06282                   break;
06283                if (f->frametype == AST_FRAME_DTMF) {
06284                   dtmfbuf[i++] = f->subclass;
06285                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06286                   res = 2000;
06287                }
06288                ast_frfree(f);
06289                if (chan->_state == AST_STATE_RING ||
06290                    chan->_state == AST_STATE_RINGING) 
06291                   break; /* Got ring */
06292             }
06293             dtmfbuf[i] = '\0';
06294             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06295             /* Got cid and ring. */
06296             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06297             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06298             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
06299                dtmfcid, flags);
06300             /* If first byte is NULL, we have no cid */
06301             if (!ast_strlen_zero(dtmfcid)) 
06302                number = dtmfcid;
06303             else
06304                number = NULL;
06305          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
06306          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06307             cs = callerid_new(p->cid_signalling);
06308             if (cs) {
06309                samples = 0;
06310 #if 1
06311                bump_gains(p);
06312 #endif            
06313                /* Take out of linear mode for Caller*ID processing */
06314                dahdi_setlinear(p->subs[index].dfd, 0);
06315                
06316                /* First we wait and listen for the Caller*ID */
06317                for (;;) {  
06318                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06319                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06320                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06321                      callerid_free(cs);
06322                      ast_hangup(chan);
06323                      goto quit;
06324                   }
06325                   if (i & DAHDI_IOMUX_SIGEVENT) {
06326                      res = dahdi_get_event(p->subs[index].dfd);
06327                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06328 
06329                      if (p->cid_signalling == CID_SIG_V23_JP) {
06330 #ifdef DAHDI_EVENT_RINGBEGIN
06331                         if (res == DAHDI_EVENT_RINGBEGIN) {
06332                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06333                            usleep(1);
06334                         }
06335 #endif
06336                      } else {
06337                         res = 0;
06338                         break;
06339                      }
06340                   } else if (i & DAHDI_IOMUX_READ) {
06341                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06342                      if (res < 0) {
06343                         if (errno != ELAST) {
06344                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06345                            callerid_free(cs);
06346                            ast_hangup(chan);
06347                            goto quit;
06348                         }
06349                         break;
06350                      }
06351                      samples += res;
06352 
06353                      if  (p->cid_signalling == CID_SIG_V23_JP) {
06354                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06355                      } else {
06356                         res = callerid_feed(cs, buf, res, AST_LAW(p));
06357                      }
06358 
06359                      if (res < 0) {
06360                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06361                         break;
06362                      } else if (res)
06363                         break;
06364                      else if (samples > (8000 * 10))
06365                         break;
06366                   }
06367                }
06368                if (res == 1) {
06369                   callerid_get(cs, &name, &number, &flags);
06370                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06371                }
06372 
06373                if (p->cid_signalling == CID_SIG_V23_JP) {
06374                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06375                   usleep(1);
06376                   res = 4000;
06377                } else {
06378 
06379                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
06380                   res = 2000;
06381                }
06382 
06383                for (;;) {
06384                   struct ast_frame *f;
06385                   res = ast_waitfor(chan, res);
06386                   if (res <= 0) {
06387                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06388                         "Exiting simple switch\n");
06389                      ast_hangup(chan);
06390                      goto quit;
06391                   } 
06392                   if (!(f = ast_read(chan))) {
06393                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06394                      ast_hangup(chan);
06395                      goto quit;
06396                   }
06397                   ast_frfree(f);
06398                   if (chan->_state == AST_STATE_RING ||
06399                       chan->_state == AST_STATE_RINGING) 
06400                      break; /* Got ring */
06401                }
06402    
06403                /* We must have a ring by now, so, if configured, lets try to listen for
06404                 * distinctive ringing */ 
06405                if (p->usedistinctiveringdetection == 1) {
06406                   len = 0;
06407                   distMatches = 0;
06408                   /* Clear the current ring data array so we dont have old data in it. */
06409                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06410                      curRingData[receivedRingT] = 0;
06411                   receivedRingT = 0;
06412                   counter = 0;
06413                   counter1 = 0;
06414                   /* Check to see if context is what it should be, if not set to be. */
06415                   if (strcmp(p->context,p->defcontext) != 0) {
06416                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06417                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06418                   }
06419       
06420                   for (;;) {  
06421                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06422                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06423                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06424                         callerid_free(cs);
06425                         ast_hangup(chan);
06426                         goto quit;
06427                      }
06428                      if (i & DAHDI_IOMUX_SIGEVENT) {
06429                         res = dahdi_get_event(p->subs[index].dfd);
06430                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06431                         res = 0;
06432                         /* Let us detect distinctive ring */
06433       
06434                         curRingData[receivedRingT] = p->ringt;
06435       
06436                         if (p->ringt < p->ringt_base/2)
06437                            break;
06438                         /* Increment the ringT counter so we can match it against
06439                            values in chan_dahdi.conf for distinctive ring */
06440                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06441                            break;
06442                      } else if (i & DAHDI_IOMUX_READ) {
06443                         res = read(p->subs[index].dfd, buf, sizeof(buf));
06444                         if (res < 0) {
06445                            if (errno != ELAST) {
06446                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06447                               callerid_free(cs);
06448                               ast_hangup(chan);
06449                               goto quit;
06450                            }
06451                            break;
06452                         }
06453                         if (p->ringt) 
06454                            p->ringt--;
06455                         if (p->ringt == 1) {
06456                            res = -1;
06457                            break;
06458                         }
06459                      }
06460                   }
06461                   if (option_verbose > 2)
06462                      /* this only shows up if you have n of the dring patterns filled in */
06463                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06464    
06465                   for (counter = 0; counter < 3; counter++) {
06466                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06467                      channel */
06468                      distMatches = 0;
06469                      for (counter1 = 0; counter1 < 3; counter1++) {
06470                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06471                         (p->drings.ringnum[counter].ring[counter1]-10)) {
06472                            distMatches++;
06473                         }
06474                      }
06475                      if (distMatches == 3) {
06476                         /* The ring matches, set the context to whatever is for distinctive ring.. */
06477                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06478                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06479                         if (option_verbose > 2)
06480                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06481                         break;
06482                      }
06483                   }
06484                }
06485                /* Restore linear mode (if appropriate) for Caller*ID processing */
06486                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06487 #if 1
06488                restore_gains(p);
06489 #endif            
06490             } else
06491                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
06492          } else {
06493             ast_log(LOG_WARNING, "Channel %s in prering "
06494                "state, but I have nothing to do. "
06495                "Terminating simple switch, should be "
06496                "restarted by the actual ring.\n", 
06497                chan->name);
06498             ast_hangup(chan);
06499             goto quit;
06500          }
06501       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06502          /* FSK Bell202 callerID */
06503          cs = callerid_new(p->cid_signalling);
06504          if (cs) {
06505 #if 1
06506             bump_gains(p);
06507 #endif            
06508             samples = 0;
06509             len = 0;
06510             distMatches = 0;
06511             /* Clear the current ring data array so we dont have old data in it. */
06512             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06513                curRingData[receivedRingT] = 0;
06514             receivedRingT = 0;
06515             counter = 0;
06516             counter1 = 0;
06517             /* Check to see if context is what it should be, if not set to be. */
06518             if (strcmp(p->context,p->defcontext) != 0) {
06519                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06520                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06521             }
06522 
06523             /* Take out of linear mode for Caller*ID processing */
06524             dahdi_setlinear(p->subs[index].dfd, 0);
06525             for (;;) {  
06526                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06527                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06528                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06529                   callerid_free(cs);
06530                   ast_hangup(chan);
06531                   goto quit;
06532                }
06533                if (i & DAHDI_IOMUX_SIGEVENT) {
06534                   res = dahdi_get_event(p->subs[index].dfd);
06535                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06536                   /* If we get a PR event, they hung up while processing calerid */
06537                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06538                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06539                      p->polarity = POLARITY_IDLE;
06540                      callerid_free(cs);
06541                      ast_hangup(chan);
06542                      goto quit;
06543                   }
06544                   res = 0;
06545                   /* Let us detect callerid when the telco uses distinctive ring */
06546 
06547                   curRingData[receivedRingT] = p->ringt;
06548 
06549                   if (p->ringt < p->ringt_base/2)
06550                      break;
06551                   /* Increment the ringT counter so we can match it against
06552                      values in chan_dahdi.conf for distinctive ring */
06553                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06554                      break;
06555                } else if (i & DAHDI_IOMUX_READ) {
06556                   res = read(p->subs[index].dfd, buf, sizeof(buf));
06557                   if (res < 0) {
06558                      if (errno != ELAST) {
06559                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06560                         callerid_free(cs);
06561                         ast_hangup(chan);
06562                         goto quit;
06563                      }
06564                      break;
06565                   }
06566                   if (p->ringt) 
06567                      p->ringt--;
06568                   if (p->ringt == 1) {
06569                      res = -1;
06570                      break;
06571                   }
06572                   samples += res;
06573                   res = callerid_feed(cs, buf, res, AST_LAW(p));
06574                   if (res < 0) {
06575                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06576                      break;
06577                   } else if (res)
06578                      break;
06579                   else if (samples > (8000 * 10))
06580                      break;
06581                }
06582             }
06583             if (res == 1) {
06584                callerid_get(cs, &name, &number, &flags);
06585                if (option_debug)
06586                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06587             }
06588             if (distinctiveringaftercid == 1) {
06589                /* Clear the current ring data array so we dont have old data in it. */
06590                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06591                   curRingData[receivedRingT] = 0;
06592                }
06593                receivedRingT = 0;
06594                if (option_verbose > 2)
06595                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06596                for (;;) {
06597                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06598                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
06599                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06600                      callerid_free(cs);
06601                      ast_hangup(chan);
06602                      goto quit;
06603                   }
06604                   if (i & DAHDI_IOMUX_SIGEVENT) {
06605                      res = dahdi_get_event(p->subs[index].dfd);
06606                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06607                      res = 0;
06608                      /* Let us detect callerid when the telco uses distinctive ring */
06609 
06610                      curRingData[receivedRingT] = p->ringt;
06611 
06612                      if (p->ringt < p->ringt_base/2)
06613                         break;
06614                      /* Increment the ringT counter so we can match it against
06615                         values in chan_dahdi.conf for distinctive ring */
06616                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06617                         break;
06618                   } else if (i & DAHDI_IOMUX_READ) {
06619                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06620                      if (res < 0) {
06621                         if (errno != ELAST) {
06622                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06623                            callerid_free(cs);
06624                            ast_hangup(chan);
06625                            goto quit;
06626                         }
06627                         break;
06628                      }
06629                   if (p->ringt)
06630                      p->ringt--;
06631                      if (p->ringt == 1) {
06632                         res = -1;
06633                         break;
06634                      }
06635                   }
06636                }
06637             }
06638             if (p->usedistinctiveringdetection == 1) {
06639                if (option_verbose > 2)
06640                   /* this only shows up if you have n of the dring patterns filled in */
06641                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06642 
06643                for (counter = 0; counter < 3; counter++) {
06644                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06645                   channel */
06646                   if (option_verbose > 2)
06647                      /* this only shows up if you have n of the dring patterns filled in */
06648                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06649                         p->drings.ringnum[counter].ring[0],
06650                         p->drings.ringnum[counter].ring[1],
06651                         p->drings.ringnum[counter].ring[2]);
06652                   distMatches = 0;
06653                   for (counter1 = 0; counter1 < 3; counter1++) {
06654                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06655                      (p->drings.ringnum[counter].ring[counter1]-10)) {
06656                         distMatches++;
06657                      }
06658                   }
06659                   if (distMatches == 3) {
06660                      /* The ring matches, set the context to whatever is for distinctive ring.. */
06661                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06662                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06663                      if (option_verbose > 2)
06664                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06665                      break;
06666                   }
06667                }
06668             }
06669             /* Restore linear mode (if appropriate) for Caller*ID processing */
06670             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06671 #if 1
06672             restore_gains(p);
06673 #endif            
06674             if (res < 0) {
06675                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06676             }
06677          } else
06678             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
06679       }
06680       else
06681          cs = NULL;
06682 
06683       if (number)
06684          ast_shrink_phone_number(number);
06685       ast_set_callerid(chan, number, name, number);
06686 
06687       if (smdi_msg)
06688          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
06689 
06690       if (cs)
06691          callerid_free(cs);
06692 
06693       ast_setstate(chan, AST_STATE_RING);
06694       chan->rings = 1;
06695       p->ringt = p->ringt_base;
06696       res = ast_pbx_run(chan);
06697       if (res) {
06698          ast_hangup(chan);
06699          ast_log(LOG_WARNING, "PBX exited non-zero\n");
06700       }
06701       goto quit;
06702    default:
06703       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
06704       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06705       if (res < 0)
06706             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06707    }
06708    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06709    if (res < 0)
06710          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
06711    ast_hangup(chan);
06712 quit:
06713    ast_mutex_lock(&ss_thread_lock);
06714    ss_thread_count--;
06715    ast_cond_signal(&ss_thread_complete);
06716    ast_mutex_unlock(&ss_thread_lock);
06717    return NULL;
06718 }
06719 
06720 /* destroy a DAHDI channel, identified by its number */
06721 static int dahdi_destroy_channel_bynum(int channel)
06722 {
06723    struct dahdi_pvt *tmp = NULL;
06724    struct dahdi_pvt *prev = NULL;
06725 
06726    tmp = iflist;
06727    while (tmp) {
06728       if (tmp->channel == channel) {
06729          int x = DAHDI_FLASH;
06730          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 */
06731          destroy_channel(prev, tmp, 1);
06732          ast_module_unref(ast_module_info->self);
06733          return RESULT_SUCCESS;
06734       }
06735       prev = tmp;
06736       tmp = tmp->next;
06737    }
06738    return RESULT_FAILURE;
06739 }
06740 
06741 static int handle_init_event(struct dahdi_pvt *i, int event)
06742 {
06743    int res;
06744    pthread_t threadid;
06745    pthread_attr_t attr;
06746    struct ast_channel *chan;
06747    pthread_attr_init(&attr);
06748    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06749    /* Handle an event on a given channel for the monitor thread. */
06750    switch (event) {
06751    case DAHDI_EVENT_NONE:
06752    case DAHDI_EVENT_BITSCHANGED:
06753       break;
06754    case DAHDI_EVENT_WINKFLASH:
06755    case DAHDI_EVENT_RINGOFFHOOK:
06756       if (i->inalarm) break;
06757       if (i->radio) break;
06758       /* Got a ring/answer.  What kind of channel are we? */
06759       switch (i->sig) {
06760       case SIG_FXOLS:
06761       case SIG_FXOGS:
06762       case SIG_FXOKS:
06763          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06764          if (res && (errno == EBUSY))
06765             break;
06766          if (i->cidspill) {
06767             /* Cancel VMWI spill */
06768             free(i->cidspill);
06769             i->cidspill = NULL;
06770          }
06771          if (i->immediate) {
06772             dahdi_enable_ec(i);
06773             /* The channel is immediately up.  Start right away */
06774             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06775             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
06776             if (!chan) {
06777                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
06778                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06779                if (res < 0)
06780                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06781             }
06782          } else {
06783             /* Check for callerid, digits, etc */
06784             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
06785             if (chan) {
06786                if (has_voicemail(i))
06787                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06788                else
06789                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06790                if (res < 0) 
06791                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
06792                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06793                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06794                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06795                   if (res < 0)
06796                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06797                   ast_hangup(chan);
06798                }
06799             } else
06800                ast_log(LOG_WARNING, "Unable to create channel\n");
06801          }
06802          break;
06803       case SIG_FXSLS:
06804       case SIG_FXSGS:
06805       case SIG_FXSKS:
06806             i->ringt = i->ringt_base;
06807             /* Fall through */
06808       case SIG_EMWINK:
06809       case SIG_FEATD:
06810       case SIG_FEATDMF:
06811       case SIG_FEATDMF_TA:
06812       case SIG_E911:
06813       case SIG_FGC_CAMA:
06814       case SIG_FGC_CAMAMF:
06815       case SIG_FEATB:
06816       case SIG_EM:
06817       case SIG_EM_E1:
06818       case SIG_SFWINK:
06819       case SIG_SF_FEATD:
06820       case SIG_SF_FEATDMF:
06821       case SIG_SF_FEATB:
06822       case SIG_SF:
06823             /* Check for callerid, digits, etc */
06824             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
06825             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06826                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06827                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06828                if (res < 0)
06829                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06830                ast_hangup(chan);
06831             } else if (!chan) {
06832                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
06833             }
06834             break;
06835       default:
06836          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06837          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06838          if (res < 0)
06839                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
06840          return -1;
06841       }
06842       break;
06843    case DAHDI_EVENT_NOALARM:
06844       i->inalarm = 0;
06845       if (!i->unknown_alarm) {
06846          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
06847          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06848                   "Channel: %d\r\n", i->channel);
06849       } else {
06850          i->unknown_alarm = 0;
06851       }
06852       break;
06853    case DAHDI_EVENT_ALARM:
06854       i->inalarm = 1;
06855       res = get_alarms(i);
06856       handle_alarms(i, res);
06857       /* fall thru intentionally */
06858    case DAHDI_EVENT_ONHOOK:
06859       if (i->radio)
06860          break;
06861       /* Back on hook.  Hang up. */
06862       switch (i->sig) {
06863       case SIG_FXOLS:
06864       case SIG_FXOGS:
06865       case SIG_FEATD:
06866       case SIG_FEATDMF:
06867       case SIG_FEATDMF_TA:
06868       case SIG_E911:
06869       case SIG_FGC_CAMA:
06870       case SIG_FGC_CAMAMF:
06871       case SIG_FEATB:
06872       case SIG_EM:
06873       case SIG_EM_E1:
06874       case SIG_EMWINK:
06875       case SIG_SF_FEATD:
06876       case SIG_SF_FEATDMF:
06877       case SIG_SF_FEATB:
06878       case SIG_SF:
06879       case SIG_SFWINK:
06880       case SIG_FXSLS:
06881       case SIG_FXSGS:
06882       case SIG_FXSKS:
06883       case SIG_GR303FXSKS:
06884          dahdi_disable_ec(i);
06885          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06886          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06887          break;
06888       case SIG_GR303FXOKS:
06889       case SIG_FXOKS:
06890          dahdi_disable_ec(i);
06891          /* Diddle the battery for the zhone */
06892 #ifdef ZHONE_HACK
06893          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06894          usleep(1);
06895 #endif         
06896          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06897          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06898          break;
06899       case SIG_PRI:
06900          dahdi_disable_ec(i);
06901          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06902          break;
06903       default:
06904          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
06905          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
06906          return -1;
06907       }
06908       break;
06909    case DAHDI_EVENT_POLARITY:
06910       switch (i->sig) {
06911       case SIG_FXSLS:
06912       case SIG_FXSKS:
06913       case SIG_FXSGS:
06914          /* We have already got a PR before the channel was 
06915             created, but it wasn't handled. We need polarity 
06916             to be REV for remote hangup detection to work. 
06917             At least in Spain */
06918          if (i->hanguponpolarityswitch)
06919             i->polarity = POLARITY_REV;
06920 
06921          if (i->cid_start == CID_START_POLARITY) {
06922             i->polarity = POLARITY_REV;
06923             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
06924                    "CID detection on channel %d\n",
06925                    i->channel);
06926             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
06927             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
06928                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
06929             }
06930          }
06931          break;
06932       default:
06933          ast_log(LOG_WARNING, "handle_init_event detected "
06934             "polarity reversal on non-FXO (SIG_FXS) "
06935             "interface %d\n", i->channel);
06936       }
06937       break;
06938    case DAHDI_EVENT_REMOVED: /* destroy channel */
06939       ast_log(LOG_NOTICE, 
06940             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
06941             i->channel);
06942       dahdi_destroy_channel_bynum(i->channel);
06943       break;
06944    }
06945    pthread_attr_destroy(&attr);
06946    return 0;
06947 }
06948 
06949 static void *do_monitor(void *data)
06950 {
06951    int count, res, res2, spoint, pollres=0;
06952    struct dahdi_pvt *i;
06953    struct dahdi_pvt *last = NULL;
06954    time_t thispass = 0, lastpass = 0;
06955    int found;
06956    char buf[1024];
06957    struct pollfd *pfds=NULL;
06958    int lastalloc = -1;
06959    /* This thread monitors all the frame relay interfaces which are not yet in use
06960       (and thus do not have a separate thread) indefinitely */
06961    /* From here on out, we die whenever asked */
06962 #if 0
06963    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
06964       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
06965       return NULL;
06966    }
06967    ast_log(LOG_DEBUG, "Monitor starting...\n");
06968 #endif
06969    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
06970 
06971    for (;;) {
06972       /* Lock the interface list */
06973       ast_mutex_lock(&iflock);
06974       if (!pfds || (lastalloc != ifcount)) {
06975          if (pfds) {
06976             free(pfds);
06977             pfds = NULL;
06978          }
06979          if (ifcount) {
06980             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
06981                ast_mutex_unlock(&iflock);
06982                return NULL;
06983             }
06984          }
06985          lastalloc = ifcount;
06986       }
06987       /* Build the stuff we're going to poll on, that is the socket of every
06988          dahdi_pvt that does not have an associated owner channel */
06989       count = 0;
06990       i = iflist;
06991       while (i) {
06992          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
06993             if (!i->owner && !i->subs[SUB_REAL].owner) {
06994                /* This needs to be watched, as it lacks an owner */
06995                pfds[count].fd = i->subs[SUB_REAL].dfd;
06996                pfds[count].events = POLLPRI;
06997                pfds[count].revents = 0;
06998                /* Message waiting or r2 channels also get watched for reading */
06999                if (i->cidspill)
07000                   pfds[count].events |= POLLIN;
07001                count++;
07002             }
07003          }
07004          i = i->next;
07005       }
07006       /* Okay, now that we know what to do, release the interface lock */
07007       ast_mutex_unlock(&iflock);
07008       
07009       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07010       pthread_testcancel();
07011       /* Wait at least a second for something to happen */
07012       res = poll(pfds, count, 1000);
07013       pthread_testcancel();
07014       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07015 
07016       /* Okay, poll has finished.  Let's see what happened.  */
07017       if (res < 0) {
07018          if ((errno != EAGAIN) && (errno != EINTR))
07019             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07020          continue;
07021       }
07022       /* Alright, lock the interface list again, and let's look and see what has
07023          happened */
07024       ast_mutex_lock(&iflock);
07025       found = 0;
07026       spoint = 0;
07027       lastpass = thispass;
07028       thispass = time(NULL);
07029       i = iflist;
07030       while (i) {
07031          if (thispass != lastpass) {
07032             if (!found && ((i == last) || ((i == iflist) && !last))) {
07033                last = i;
07034                if (last) {
07035                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07036                      (last->sig & __DAHDI_SIG_FXO)) {
07037                      res = ast_app_has_voicemail(last->mailbox, NULL);
07038                      if (last->msgstate != res) {
07039                         int x;
07040                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07041                         x = DAHDI_FLUSH_BOTH;
07042                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07043                         if (res2)
07044                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07045                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07046                            /* Turn on on hook transfer for 4 seconds */
07047                            x = 4000;
07048                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07049                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07050                            last->cidpos = 0;
07051                            last->msgstate = res;
07052                            last->onhooktime = thispass;
07053                         }
07054                         found ++;
07055                      }
07056                   }
07057                   last = last->next;
07058                }
07059             }
07060          }
07061          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07062             if (i->radio && !i->owner)
07063             {
07064                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07065                if (res)
07066                {
07067                   if (option_debug)
07068                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07069                   /* Don't hold iflock while handling init events */
07070                   ast_mutex_unlock(&iflock);
07071                   handle_init_event(i, res);
07072                   ast_mutex_lock(&iflock);   
07073                }
07074                i = i->next;
07075                continue;
07076             }              
07077             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07078             if (pollres & POLLIN) {
07079                if (i->owner || i->subs[SUB_REAL].owner) {
07080 #ifdef HAVE_PRI
07081                   if (!i->pri)
07082 #endif                  
07083                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07084                   i = i->next;
07085                   continue;
07086                }
07087                if (!i->cidspill) {
07088                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07089                   i = i->next;
07090                   continue;
07091                }
07092                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07093                if (res > 0) {
07094                   /* We read some number of bytes.  Write an equal amount of data */
07095                   if (res > i->cidlen - i->cidpos) 
07096                      res = i->cidlen - i->cidpos;
07097                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07098                   if (res2 > 0) {
07099                      i->cidpos += res2;
07100                      if (i->cidpos >= i->cidlen) {
07101                         free(i->cidspill);
07102                         i->cidspill = 0;
07103                         i->cidpos = 0;
07104                         i->cidlen = 0;
07105                      }
07106                   } else {
07107                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07108                      i->msgstate = -1;
07109                   }
07110                } else {
07111                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07112                }
07113             }
07114             if (pollres & POLLPRI) {
07115                if (i->owner || i->subs[SUB_REAL].owner) {
07116 #ifdef HAVE_PRI
07117                   if (!i->pri)
07118 #endif                  
07119                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07120                   i = i->next;
07121                   continue;
07122                }
07123                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07124                if (option_debug)
07125                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07126                /* Don't hold iflock while handling init events */
07127                ast_mutex_unlock(&iflock);
07128                handle_init_event(i, res);
07129                ast_mutex_lock(&iflock);   
07130             }
07131          }
07132          i=i->next;
07133       }
07134       ast_mutex_unlock(&iflock);
07135    }
07136    /* Never reached */
07137    return NULL;
07138    
07139 }
07140 
07141 static int restart_monitor(void)
07142 {
07143    pthread_attr_t attr;
07144    pthread_attr_init(&attr);
07145    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07146    /* If we're supposed to be stopped -- stay stopped */
07147    if (monitor_thread == AST_PTHREADT_STOP)
07148       return 0;
07149    ast_mutex_lock(&monlock);
07150    if (monitor_thread == pthread_self()) {
07151       ast_mutex_unlock(&monlock);
07152       ast_log(LOG_WARNING, "Cannot kill myself\n");
07153       return -1;
07154    }
07155    if (monitor_thread != AST_PTHREADT_NULL) {
07156       /* Wake up the thread */
07157       pthread_kill(monitor_thread, SIGURG);
07158    } else {
07159       /* Start a new monitor */
07160       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07161          ast_mutex_unlock(&monlock);
07162          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07163          pthread_attr_destroy(&attr);
07164          return -1;
07165       }
07166    }
07167    ast_mutex_unlock(&monlock);
07168    pthread_attr_destroy(&attr);
07169    return 0;
07170 }
07171 
07172 #ifdef HAVE_PRI
07173 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
07174 {
07175    int x;
07176    int trunkgroup;
07177    /* Get appropriate trunk group if there is one */
07178    trunkgroup = pris[*span].mastertrunkgroup;
07179    if (trunkgroup) {
07180       /* Select a specific trunk group */
07181       for (x = 0; x < NUM_SPANS; x++) {
07182          if (pris[x].trunkgroup == trunkgroup) {
07183             *span = x;
07184             return 0;
07185          }
07186       }
07187       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07188       *span = -1;
07189    } else {
07190       if (pris[*span].trunkgroup) {
07191          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07192          *span = -1;
07193       } else if (pris[*span].mastertrunkgroup) {
07194          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07195          *span = -1;
07196       } else {
07197          if (si->totalchans == 31) {
07198             /* E1 */
07199             pris[*span].dchannels[0] = 16 + offset;
07200          } else if (si->totalchans == 24) {
07201             /* T1 or J1 */
07202             pris[*span].dchannels[0] = 24 + offset;
07203          } else if (si->totalchans == 3) {
07204             /* BRI */
07205             pris[*span].dchannels[0] = 3 + offset;
07206          } else {
07207             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);
07208             *span = -1;
07209             return 0;
07210          }
07211          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07212          pris[*span].offset = offset;
07213          pris[*span].span = *span + 1;
07214       }
07215    }
07216    return 0;
07217 }
07218 
07219 static int pri_create_trunkgroup(int trunkgroup, int *channels)
07220 {
07221    struct dahdi_spaninfo si;
07222    struct dahdi_params p;
07223    int fd;
07224    int span;
07225    int ospan=0;
07226    int x,y;
07227    for (x = 0; x < NUM_SPANS; x++) {
07228       if (pris[x].trunkgroup == trunkgroup) {
07229          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07230          return -1;
07231       }
07232    }
07233    for (y = 0; y < NUM_DCHANS; y++) {
07234       if (!channels[y]) 
07235          break;
07236       memset(&si, 0, sizeof(si));
07237       memset(&p, 0, sizeof(p));
07238 #ifdef HAVE_ZAPTEL
07239       fd = open("/dev/zap/channel", O_RDWR);
07240 #else
07241       fd = open("/dev/dahdi/channel", O_RDWR);
07242 #endif
07243       if (fd < 0) {
07244          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07245          return -1;
07246       }
07247       x = channels[y];
07248       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07249          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07250          close(fd);
07251          return -1;
07252       }
07253       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07254          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07255          return -1;
07256       }
07257       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07258          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07259          close(fd);
07260          return -1;
07261       }
07262       span = p.spanno - 1;
07263       if (pris[span].trunkgroup) {
07264          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07265          close(fd);
07266          return -1;
07267       }
07268       if (pris[span].pvts[0]) {
07269          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07270          close(fd);
07271          return -1;
07272       }
07273       if (!y) {
07274          pris[span].trunkgroup = trunkgroup;
07275          pris[span].offset = channels[y] - p.chanpos;
07276          ospan = span;
07277       }
07278       pris[ospan].dchannels[y] = channels[y];
07279       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07280       pris[span].span = span + 1;
07281       close(fd);
07282    }
07283    return 0;   
07284 }
07285 
07286 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
07287 {
07288    if (pris[span].mastertrunkgroup) {
07289       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);
07290       return -1;
07291    }
07292    pris[span].mastertrunkgroup = trunkgroup;
07293    pris[span].prilogicalspan = logicalspan;
07294    return 0;
07295 }
07296 
07297 #endif
07298 
07299 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
07300 {
07301    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
07302    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
07303    char fn[80];
07304 #if 1
07305    struct dahdi_bufferinfo bi;
07306 #endif
07307    int res;
07308    int span=0;
07309    int here = 0;
07310    int x;
07311    struct dahdi_pvt **wlist;
07312    struct dahdi_pvt **wend;
07313    struct dahdi_params p;
07314 
07315    wlist = &iflist;
07316    wend = &ifend;
07317 
07318 #ifdef HAVE_PRI
07319    if (pri) {
07320       wlist = &pri->crvs;
07321       wend = &pri->crvend;
07322    }
07323 #endif
07324 
07325    tmp2 = *wlist;
07326    prev = NULL;
07327 
07328    while (tmp2) {
07329       if (!tmp2->destroy) {
07330          if (tmp2->channel == channel) {
07331             tmp = tmp2;
07332             here = 1;
07333             break;
07334          }
07335          if (tmp2->channel > channel) {
07336             break;
07337          }
07338       }
07339       prev = tmp2;
07340       tmp2 = tmp2->next;
07341    }
07342 
07343    if (!here && reloading != 1) {
07344       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07345          if (tmp)
07346             free(tmp);
07347          return NULL;
07348       }
07349       ast_mutex_init(&tmp->lock);
07350       ifcount++;
07351       for (x = 0; x < 3; x++)
07352          tmp->subs[x].dfd = -1;
07353       tmp->channel = channel;
07354    }
07355 
07356    if (tmp) {
07357       int chan_sig = conf->chan.sig;
07358       if (!here) {
07359          if ((channel != CHAN_PSEUDO) && !pri) {
07360             int count = 0;
07361             snprintf(fn, sizeof(fn), "%d", channel);
07362             /* Open non-blocking */
07363             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07364             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 */
07365                usleep(1);
07366                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07367                count++;
07368             }
07369             /* Allocate a DAHDI structure */
07370             if (tmp->subs[SUB_REAL].dfd < 0) {
07371                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);
07372                destroy_dahdi_pvt(&tmp);
07373                return NULL;
07374             }
07375             memset(&p, 0, sizeof(p));
07376             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07377             if (res < 0) {
07378                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07379                destroy_dahdi_pvt(&tmp);
07380                return NULL;
07381             }
07382             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07383                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));
07384                destroy_dahdi_pvt(&tmp);
07385                return NULL;
07386             }
07387             tmp->law = p.curlaw;
07388             tmp->span = p.spanno;
07389             span = p.spanno - 1;
07390          } else {
07391             if (channel == CHAN_PSEUDO)
07392                chan_sig = 0;
07393             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07394                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07395                return NULL;
07396             }
07397          }
07398 #ifdef HAVE_PRI
07399          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07400             int offset;
07401             int myswitchtype;
07402             int matchesdchan;
07403             int x,y;
07404             offset = 0;
07405             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07406                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07407                destroy_dahdi_pvt(&tmp);
07408                return NULL;
07409             }
07410             if (span >= NUM_SPANS) {
07411                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07412                destroy_dahdi_pvt(&tmp);
07413                return NULL;
07414             } else {
07415                struct dahdi_spaninfo si;
07416                si.spanno = 0;
07417                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07418                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07419                   destroy_dahdi_pvt(&tmp);
07420                   return NULL;
07421                }
07422                /* Store the logical span first based upon the real span */
07423                tmp->logicalspan = pris[span].prilogicalspan;
07424                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07425                if (span < 0) {
07426                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07427                   destroy_dahdi_pvt(&tmp);
07428                   return NULL;
07429                }
07430                if (chan_sig == SIG_PRI)
07431                   myswitchtype = conf->pri.switchtype;
07432                else
07433                   myswitchtype = PRI_SWITCH_GR303_TMC;
07434                /* Make sure this isn't a d-channel */
07435                matchesdchan=0;
07436                for (x = 0; x < NUM_SPANS; x++) {
07437                   for (y = 0; y < NUM_DCHANS; y++) {
07438                      if (pris[x].dchannels[y] == tmp->channel) {
07439                         matchesdchan = 1;
07440                         break;
07441                      }
07442                   }
07443                }
07444                offset = p.chanpos;
07445                if (!matchesdchan) {
07446                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07447                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07448                      destroy_dahdi_pvt(&tmp);
07449                      return NULL;
07450                   }
07451                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07452                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07453                      destroy_dahdi_pvt(&tmp);
07454                      return NULL;
07455                   }
07456                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07457                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07458                      destroy_dahdi_pvt(&tmp);
07459                      return NULL;
07460                   }
07461                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07462                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07463                      destroy_dahdi_pvt(&tmp);
07464                      return NULL;
07465                   }
07466                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07467                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07468                      destroy_dahdi_pvt(&tmp);
07469                      return NULL;
07470                   }
07471                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07472                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07473                      destroy_dahdi_pvt(&tmp);
07474                      return NULL;
07475                   }
07476                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07477                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07478                      destroy_dahdi_pvt(&tmp);
07479                      return NULL;
07480                   }
07481                   if (pris[span].numchans >= MAX_CHANNELS) {
07482                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07483                         pris[span].trunkgroup);
07484                      destroy_dahdi_pvt(&tmp);
07485                      return NULL;
07486                   }
07487                   pris[span].nodetype = conf->pri.nodetype;
07488                   pris[span].switchtype = myswitchtype;
07489                   pris[span].nsf = conf->pri.nsf;
07490                   pris[span].dialplan = conf->pri.dialplan;
07491                   pris[span].localdialplan = conf->pri.localdialplan;
07492                   pris[span].pvts[pris[span].numchans++] = tmp;
07493                   pris[span].minunused = conf->pri.minunused;
07494                   pris[span].minidle = conf->pri.minidle;
07495                   pris[span].overlapdial = conf->pri.overlapdial;
07496 #ifdef HAVE_PRI_INBANDDISCONNECT
07497                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07498 #endif
07499                   pris[span].facilityenable = conf->pri.facilityenable;
07500                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07501                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07502                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07503                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07504                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07505                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07506                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07507                   pris[span].resetinterval = conf->pri.resetinterval;
07508                   
07509                   tmp->pri = &pris[span];
07510                   tmp->prioffset = offset;
07511                   tmp->call = NULL;
07512                } else {
07513                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07514                   destroy_dahdi_pvt(&tmp);
07515                   return NULL;
07516                }
07517             }
07518          } else {
07519             tmp->prioffset = 0;
07520          }
07521 #endif
07522       } else {
07523          chan_sig = tmp->sig;
07524          memset(&p, 0, sizeof(p));
07525          if (tmp->subs[SUB_REAL].dfd > -1)
07526             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07527       }
07528       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
07529       switch (chan_sig) {
07530       case SIG_FXSKS:
07531       case SIG_FXSLS:
07532       case SIG_EM:
07533       case SIG_EM_E1:
07534       case SIG_EMWINK:
07535       case SIG_FEATD:
07536       case SIG_FEATDMF:
07537       case SIG_FEATDMF_TA:
07538       case SIG_FEATB:
07539       case SIG_E911:
07540       case SIG_SF:
07541       case SIG_SFWINK:
07542       case SIG_FGC_CAMA:
07543       case SIG_FGC_CAMAMF:
07544       case SIG_SF_FEATD:
07545       case SIG_SF_FEATDMF:
07546       case SIG_SF_FEATB:
07547          p.starttime = 250;
07548          break;
07549       }
07550 
07551       if (tmp->radio) {
07552          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
07553          p.channo = channel;
07554          p.rxwinktime = 1;
07555          p.rxflashtime = 1;
07556          p.starttime = 1;
07557          p.debouncetime = 5;
07558       }
07559       if (!tmp->radio) {
07560          p.channo = channel;
07561          /* Override timing settings based on config file */
07562          if (conf->timing.prewinktime >= 0)
07563             p.prewinktime = conf->timing.prewinktime;
07564          if (conf->timing.preflashtime >= 0)
07565             p.preflashtime = conf->timing.preflashtime;
07566          if (conf->timing.winktime >= 0)
07567             p.winktime = conf->timing.winktime;
07568          if (conf->timing.flashtime >= 0)
07569             p.flashtime = conf->timing.flashtime;
07570          if (conf->timing.starttime >= 0)
07571             p.starttime = conf->timing.starttime;
07572          if (conf->timing.rxwinktime >= 0)
07573             p.rxwinktime = conf->timing.rxwinktime;
07574          if (conf->timing.rxflashtime >= 0)
07575             p.rxflashtime = conf->timing.rxflashtime;
07576          if (conf->timing.debouncetime >= 0)
07577             p.debouncetime = conf->timing.debouncetime;
07578       }
07579       
07580       /* dont set parms on a pseudo-channel (or CRV) */
07581       if (tmp->subs[SUB_REAL].dfd >= 0)
07582       {
07583          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07584          if (res < 0) {
07585             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07586             destroy_dahdi_pvt(&tmp);
07587             return NULL;
07588          }
07589       }
07590 #if 1
07591       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07592          memset(&bi, 0, sizeof(bi));
07593          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07594          if (!res) {
07595             bi.txbufpolicy = conf->chan.buf_policy;
07596             bi.rxbufpolicy = conf->chan.buf_policy;
07597             bi.numbufs = conf->chan.buf_no;
07598             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07599             if (res < 0) {
07600                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07601             }
07602          } else
07603             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07604       }
07605 #endif
07606       tmp->immediate = conf->chan.immediate;
07607       tmp->transfertobusy = conf->chan.transfertobusy;
07608       tmp->sig = chan_sig;
07609       tmp->outsigmod = conf->chan.outsigmod;
07610       tmp->ringt_base = ringt_base;
07611       tmp->firstradio = 0;
07612       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07613          tmp->permcallwaiting = conf->chan.callwaiting;
07614       else
07615          tmp->permcallwaiting = 0;
07616       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
07617       tmp->destroy = 0;
07618       tmp->drings = drings;
07619       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07620       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07621       tmp->threewaycalling = conf->chan.threewaycalling;
07622       tmp->adsi = conf->chan.adsi;
07623       tmp->use_smdi = conf->chan.use_smdi;
07624       tmp->permhidecallerid = conf->chan.hidecallerid;
07625       tmp->callreturn = conf->chan.callreturn;
07626       tmp->echocancel = conf->chan.echocancel;
07627       tmp->echotraining = conf->chan.echotraining;
07628       tmp->pulse = conf->chan.pulse;
07629       if (tmp->echocancel)
07630          tmp->echocanbridged = conf->chan.echocanbridged;
07631       else {
07632          if (conf->chan.echocanbridged)
07633             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07634          tmp->echocanbridged = 0;
07635       }
07636       tmp->busydetect = conf->chan.busydetect;
07637       tmp->busycount = conf->chan.busycount;
07638       tmp->busycompare = conf->chan.busycompare;
07639       tmp->busytonelength = conf->chan.busytonelength;
07640       tmp->busyquietlength = conf->chan.busyquietlength;
07641       tmp->busyfuzziness = conf->chan.busyfuzziness;
07642       tmp->silencethreshold = conf->chan.silencethreshold;
07643       tmp->callprogress = conf->chan.callprogress;
07644       tmp->cancallforward = conf->chan.cancallforward;
07645       tmp->dtmfrelax = conf->chan.dtmfrelax;
07646       tmp->callwaiting = tmp->permcallwaiting;
07647       tmp->hidecallerid = tmp->permhidecallerid;
07648       tmp->channel = channel;
07649       tmp->stripmsd = conf->chan.stripmsd;
07650       tmp->use_callerid = conf->chan.use_callerid;
07651       tmp->cid_signalling = conf->chan.cid_signalling;
07652       tmp->cid_start = conf->chan.cid_start;
07653       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07654       tmp->restrictcid = conf->chan.restrictcid;
07655       tmp->use_callingpres = conf->chan.use_callingpres;
07656       tmp->priindication_oob = conf->chan.priindication_oob;
07657       tmp->priexclusive = conf->chan.priexclusive;
07658       if (tmp->usedistinctiveringdetection) {
07659          if (!tmp->use_callerid) {
07660             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07661             tmp->use_callerid = 1;
07662          }
07663       }
07664 
07665       if (tmp->cid_signalling == CID_SIG_SMDI) {
07666          if (!tmp->use_smdi) {
07667             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07668             tmp->use_smdi = 1;
07669          }
07670       }
07671       if (tmp->use_smdi) {
07672          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07673          if (!(tmp->smdi_iface)) {
07674             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07675             tmp->use_smdi = 0;
07676          }
07677       }
07678 
07679       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
07680       tmp->amaflags = conf->chan.amaflags;
07681       if (!here) {
07682          tmp->confno = -1;
07683          tmp->propconfno = -1;
07684       }
07685       tmp->canpark = conf->chan.canpark;
07686       tmp->transfer = conf->chan.transfer;
07687       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
07688       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
07689       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
07690       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
07691       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
07692       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
07693       tmp->cid_ton = 0;
07694       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
07695       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
07696       tmp->msgstate = -1;
07697       tmp->group = conf->chan.group;
07698       tmp->callgroup = conf->chan.callgroup;
07699       tmp->pickupgroup= conf->chan.pickupgroup;
07700       tmp->rxgain = conf->chan.rxgain;
07701       tmp->txgain = conf->chan.txgain;
07702       tmp->tonezone = conf->chan.tonezone;
07703       tmp->onhooktime = time(NULL);
07704       if (tmp->subs[SUB_REAL].dfd > -1) {
07705          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
07706          if (tmp->dsp)
07707             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
07708          update_conf(tmp);
07709          if (!here) {
07710             if (chan_sig != SIG_PRI)
07711                /* Hang it up to be sure it's good */
07712                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07713          }
07714          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
07715 #ifdef HAVE_PRI
07716          /* the dchannel is down so put the channel in alarm */
07717          if (tmp->pri && !pri_is_up(tmp->pri)) {
07718             tmp->inalarm = 1;
07719          }
07720 #endif            
07721          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
07722             tmp->inalarm = 1;
07723             handle_alarms(tmp, res);
07724          } else {
07725             /* yes, this looks strange... the unknown_alarm flag is only used to
07726                control whether an 'alarm cleared' message gets generated when we
07727                get an indication that the channel is no longer in alarm status.
07728                however, the channel *could* be in an alarm status that we aren't
07729                aware of (since get_alarms() only reports span alarms, not channel
07730                alarms). setting this flag will cause any potential 'alarm cleared'
07731                message to be suppressed, but if a real alarm occurs before that
07732                happens, this flag will get cleared by it and the situation will
07733                be normal.
07734             */
07735             tmp->unknown_alarm = 1;
07736          }
07737       }
07738 
07739       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
07740       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
07741       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
07742       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
07743 
07744    }
07745    if (tmp && !here) {
07746       /* nothing on the iflist */
07747       if (!*wlist) {
07748          *wlist = tmp;
07749          tmp->prev = NULL;
07750          tmp->next = NULL;
07751          *wend = tmp;
07752       } else {
07753          /* at least one member on the iflist */
07754          struct dahdi_pvt *working = *wlist;
07755 
07756          /* check if we maybe have to put it on the begining */
07757          if (working->channel > tmp->channel) {
07758             tmp->next = *wlist;
07759             tmp->prev = NULL;
07760             (*wlist)->prev = tmp;
07761             *wlist = tmp;
07762          } else {
07763          /* go through all the members and put the member in the right place */
07764             while (working) {
07765                /* in the middle */
07766                if (working->next) {
07767                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
07768                      tmp->next = working->next;
07769                      tmp->prev = working;
07770                      working->next->prev = tmp;
07771                      working->next = tmp;
07772                      break;
07773                   }
07774                } else {
07775                /* the last */
07776                   if (working->channel < tmp->channel) {
07777                      working->next = tmp;
07778                      tmp->next = NULL;
07779                      tmp->prev = working;
07780                      *wend = tmp;
07781                      break;
07782                   }
07783                }
07784                working = working->next;
07785             }
07786          }
07787       }
07788    }
07789    return tmp;
07790 }
07791 
07792 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
07793 {
07794    int res;
07795    struct dahdi_params par;
07796 
07797    /* First, check group matching */
07798    if (groupmatch) {
07799       if ((p->group & groupmatch) != groupmatch)
07800          return 0;
07801       *groupmatched = 1;
07802    }
07803    /* Check to see if we have a channel match */
07804    if (channelmatch != -1) {
07805       if (p->channel != channelmatch)
07806          return 0;
07807       *channelmatched = 1;
07808    }
07809    /* We're at least busy at this point */
07810    if (busy) {
07811       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
07812          *busy = 1;
07813    }
07814    /* If do not disturb, definitely not */
07815    if (p->dnd)
07816       return 0;
07817    /* If guard time, definitely not */
07818    if (p->guardtime && (time(NULL) < p->guardtime)) 
07819       return 0;
07820       
07821    /* If no owner definitely available */
07822    if (!p->owner) {
07823 #ifdef HAVE_PRI
07824       /* Trust PRI */
07825       if (p->pri) {
07826          if (p->resetting || p->call)
07827             return 0;
07828          else
07829             return 1;
07830       }
07831 #endif
07832       if (!(p->radio || (p->oprmode < 0)))
07833       {
07834          if (!p->sig || (p->sig == SIG_FXSLS))
07835             return 1;
07836          /* Check hook state */
07837          if (p->subs[SUB_REAL].dfd > -1)
07838             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
07839          else {
07840             /* Assume not off hook on CVRS */
07841             res = 0;
07842             par.rxisoffhook = 0;
07843          }
07844          if (res) {
07845             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
07846          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
07847             /* When "onhook" that means no battery on the line, and thus
07848               it is out of service..., if it's on a TDM card... If it's a channel
07849               bank, there is no telling... */
07850             if (par.rxbits > -1)
07851                return 1;
07852             if (par.rxisoffhook)
07853                return 1;
07854             else
07855 #ifdef DAHDI_CHECK_HOOKSTATE
07856                return 0;
07857 #else
07858                return 1;
07859 #endif
07860          } else if (par.rxisoffhook) {
07861             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
07862             /* Not available when the other end is off hook */
07863             return 0;
07864          }
07865       }
07866       return 1;
07867    }
07868 
07869    /* If it's not an FXO, forget about call wait */
07870    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
07871       return 0;
07872 
07873    if (!p->callwaiting) {
07874       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
07875       return 0;
07876    }
07877 
07878    if (p->subs[SUB_CALLWAIT].dfd > -1) {
07879       /* If there is already a call waiting call, then we can't take a second one */
07880       return 0;
07881    }
07882    
07883    if ((p->owner->_state != AST_STATE_UP) &&
07884        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
07885       /* If the current call is not up, then don't allow the call */
07886       return 0;
07887    }
07888    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
07889       /* Can't take a call wait when the three way calling hasn't been merged yet. */
07890       return 0;
07891    }
07892    /* We're cool */
07893    return 1;
07894 }
07895 
07896 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
07897 {
07898    struct dahdi_pvt *p;
07899    struct dahdi_bufferinfo bi;
07900    int res;
07901    
07902    if ((p = ast_malloc(sizeof(*p)))) {
07903       memcpy(p, src, sizeof(struct dahdi_pvt));
07904       ast_mutex_init(&p->lock);
07905 #ifdef HAVE_ZAPTEL
07906       p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
07907 #else
07908       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
07909 #endif
07910       /* Allocate a DAHDI structure */
07911       if (p->subs[SUB_REAL].dfd < 0) {
07912          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
07913          destroy_dahdi_pvt(&p);
07914          return NULL;
07915       }
07916       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07917       if (!res) {
07918          bi.txbufpolicy = p->buf_policy;
07919          bi.rxbufpolicy = p->buf_policy;
07920          bi.numbufs = p->buf_no;
07921          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07922          if (res < 0) {
07923             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
07924          }
07925       } else
07926          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
07927    }
07928    p->destroy = 1;
07929    p->next = iflist;
07930    p->prev = NULL;
07931    iflist = p;
07932    if (iflist->next)
07933       iflist->next->prev = p;
07934    return p;
07935 }
07936    
07937 
07938 #ifdef HAVE_PRI
07939 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
07940 {
07941    int x;
07942    if (backwards)
07943       x = pri->numchans;
07944    else
07945       x = 0;
07946    for (;;) {
07947       if (backwards && (x < 0))
07948          break;
07949       if (!backwards && (x >= pri->numchans))
07950          break;
07951       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
07952          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
07953             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
07954          return x;
07955       }
07956       if (backwards)
07957          x--;
07958       else
07959          x++;
07960    }
07961    return -1;
07962 }
07963 #endif
07964 
07965 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
07966 {
07967    ast_group_t groupmatch = 0;
07968    int channelmatch = -1;
07969    int roundrobin = 0;
07970    int callwait = 0;
07971    int busy = 0;
07972    struct dahdi_pvt *p;
07973    struct ast_channel *tmp = NULL;
07974    char *dest=NULL;
07975    int x;
07976    char *s;
07977    char opt=0;
07978    int res=0, y=0;
07979    int backwards = 0;
07980 #ifdef HAVE_PRI
07981    int crv;
07982    int bearer = -1;
07983    int trunkgroup;
07984    struct dahdi_pri *pri=NULL;
07985 #endif   
07986    struct dahdi_pvt *exit, *start, *end;
07987    ast_mutex_t *lock;
07988    int channelmatched = 0;
07989    int groupmatched = 0;
07990    
07991    /* Assume we're locking the iflock */
07992    lock = &iflock;
07993    start = iflist;
07994    end = ifend;
07995    if (data) {
07996       dest = ast_strdupa((char *)data);
07997    } else {
07998       ast_log(LOG_WARNING, "Channel requested with no data\n");
07999       return NULL;
08000    }
08001    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08002       /* Retrieve the group number */
08003       char *stringp=NULL;
08004       stringp=dest + 1;
08005       s = strsep(&stringp, "/");
08006       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08007          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08008          return NULL;
08009       }
08010       groupmatch = ((ast_group_t) 1 << x);
08011       if (toupper(dest[0]) == 'G') {
08012          if (dest[0] == 'G') {
08013             backwards = 1;
08014             p = ifend;
08015          } else
08016             p = iflist;
08017       } else {
08018          if (dest[0] == 'R') {
08019             backwards = 1;
08020             p = round_robin[x]?round_robin[x]->prev:ifend;
08021             if (!p)
08022                p = ifend;
08023          } else {
08024             p = round_robin[x]?round_robin[x]->next:iflist;
08025             if (!p)
08026                p = iflist;
08027          }
08028          roundrobin = 1;
08029       }
08030    } else {
08031       char *stringp=NULL;
08032       stringp=dest;
08033       s = strsep(&stringp, "/");
08034       p = iflist;
08035       if (!strcasecmp(s, "pseudo")) {
08036          /* Special case for pseudo */
08037          x = CHAN_PSEUDO;
08038          channelmatch = x;
08039       } 
08040 #ifdef HAVE_PRI
08041       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
08042          if ((trunkgroup < 1) || (crv < 1)) {
08043             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08044             return NULL;
08045          }
08046          res--;
08047          for (x = 0; x < NUM_SPANS; x++) {
08048             if (pris[x].trunkgroup == trunkgroup) {
08049                pri = pris + x;
08050                lock = &pri->lock;
08051                start = pri->crvs;
08052                end = pri->crvend;
08053                break;
08054             }
08055          }
08056          if (!pri) {
08057             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08058             return NULL;
08059          }
08060          channelmatch = crv;
08061          p = pris[x].crvs;
08062       }
08063 #endif   
08064       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
08065          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08066          return NULL;
08067       } else {
08068          channelmatch = x;
08069       }
08070    }
08071    /* Search for an unowned channel */
08072    ast_mutex_lock(lock);
08073    exit = p;
08074    while (p && !tmp) {
08075       if (roundrobin)
08076          round_robin[x] = p;
08077 #if 0
08078       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08079 #endif
08080 
08081       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08082          if (option_debug)
08083             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08084             if (p->inalarm) 
08085                goto next;
08086 
08087          callwait = (p->owner != NULL);
08088 #ifdef HAVE_PRI
08089          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08090             if (p->sig != SIG_FXSKS) {
08091                /* Gotta find an actual channel to use for this
08092                   CRV if this isn't a callwait */
08093                bearer = pri_find_empty_chan(pri, 0);
08094                if (bearer < 0) {
08095                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08096                   p = NULL;
08097                   break;
08098                }
08099                pri_assign_bearer(p, pri, pri->pvts[bearer]);
08100             } else {
08101                if (alloc_sub(p, 0)) {
08102                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08103                   p = NULL;
08104                   break;
08105                } else
08106                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08107                p->pri = pri;
08108             }
08109          }
08110 #endif         
08111          if (p->channel == CHAN_PSEUDO) {
08112             p = chandup(p);
08113             if (!p) {
08114                break;
08115             }
08116          }
08117          if (p->owner) {
08118             if (alloc_sub(p, SUB_CALLWAIT)) {
08119                p = NULL;
08120                break;
08121             }
08122          }
08123          p->outgoing = 1;
08124          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08125 #ifdef HAVE_PRI
08126          if (p->bearer) {
08127             /* Log owner to bearer channel, too */
08128             p->bearer->owner = tmp;
08129          }
08130 #endif         
08131          /* Make special notes */
08132          if (res > 1) {
08133             if (opt == 'c') {
08134                /* Confirm answer */
08135                p->confirmanswer = 1;
08136             } else if (opt == 'r') {
08137                /* Distinctive ring */
08138                if (res < 3)
08139                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08140                else
08141                   p->distinctivering = y;
08142             } else if (opt == 'd') {
08143                /* If this is an ISDN call, make it digital */
08144                p->digital = 1;
08145                if (tmp)
08146                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08147             } else {
08148                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08149             }
08150          }
08151          /* Note if the call is a call waiting call */
08152          if (tmp && callwait)
08153             tmp->cdrflags |= AST_CDR_CALLWAIT;
08154          break;
08155       }
08156 next:
08157       if (backwards) {
08158          p = p->prev;
08159          if (!p)
08160             p = end;
08161       } else {
08162          p = p->next;
08163          if (!p)
08164             p = start;
08165       }
08166       /* stop when you roll to the one that we started from */
08167       if (p == exit)
08168          break;
08169    }
08170    ast_mutex_unlock(lock);
08171    restart_monitor();
08172    if (callwait)
08173       *cause = AST_CAUSE_BUSY;
08174    else if (!tmp) {
08175       if (channelmatched) {
08176          if (busy)
08177             *cause = AST_CAUSE_BUSY;
08178       } else if (groupmatched) {
08179          *cause = AST_CAUSE_CONGESTION;
08180       }
08181    }
08182       
08183    return tmp;
08184 }
08185 
08186 
08187 #ifdef HAVE_PRI
08188 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
08189 {
08190    struct dahdi_pvt *p;
08191    p = pri->crvs;
08192    while (p) {
08193       if (p->channel == crv)
08194          return p;
08195       p = p->next;
08196    }
08197    return NULL;
08198 }
08199 
08200 
08201 static int pri_find_principle(struct dahdi_pri *pri, int channel)
08202 {
08203    int x;
08204    int span = PRI_SPAN(channel);
08205    int spanfd;
08206    struct dahdi_params param;
08207    int principle = -1;
08208    int explicit = PRI_EXPLICIT(channel);
08209    channel = PRI_CHANNEL(channel);
08210 
08211    if (!explicit) {
08212       spanfd = pri_active_dchan_fd(pri);
08213       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
08214          return -1;
08215       span = pris[param.spanno - 1].prilogicalspan;
08216    }
08217 
08218    for (x = 0; x < pri->numchans; x++) {
08219       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08220          principle = x;
08221          break;
08222       }
08223    }
08224    
08225    return principle;
08226 }
08227 
08228 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
08229 {
08230    int x;
08231    struct dahdi_pvt *crv;
08232    if (!c) {
08233       if (principle < 0)
08234          return -1;
08235       return principle;
08236    }
08237    if ((principle > -1) && 
08238       (principle < pri->numchans) && 
08239       (pri->pvts[principle]) && 
08240       (pri->pvts[principle]->call == c))
08241       return principle;
08242    /* First, check for other bearers */
08243    for (x = 0; x < pri->numchans; x++) {
08244       if (!pri->pvts[x])
08245          continue;
08246       if (pri->pvts[x]->call == c) {
08247          /* Found our call */
08248          if (principle != x) {
08249             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08250 
08251             if (option_verbose > 2)
08252                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08253                   old->channel, new->channel);
08254             if (new->owner) {
08255                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08256                   old->channel, new->channel, new->channel);
08257                return -1;
08258             }
08259             /* Fix it all up now */
08260             new->owner = old->owner;
08261             old->owner = NULL;
08262             if (new->owner) {
08263                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08264                new->owner->tech_pvt = new;
08265                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08266                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08267                old->subs[SUB_REAL].owner = NULL;
08268             } else
08269                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);
08270             new->call = old->call;
08271             old->call = NULL;
08272 
08273             /* Copy any DSP that may be present */
08274             new->dsp = old->dsp;
08275             new->dsp_features = old->dsp_features;
08276             old->dsp = NULL;
08277             old->dsp_features = 0;
08278          }
08279          return principle;
08280       }
08281    }
08282    /* Now check for a CRV with no bearer */
08283    crv = pri->crvs;
08284    while (crv) {
08285       if (crv->call == c) {
08286          /* This is our match...  Perform some basic checks */
08287          if (crv->bearer)
08288             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08289          else if (pri->pvts[principle]->owner) 
08290             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08291          else {
08292             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
08293                wakeup the potential sleeper */
08294             dahdi_close_sub(crv, SUB_REAL);
08295             pri->pvts[principle]->call = crv->call;
08296             pri_assign_bearer(crv, pri, pri->pvts[principle]);
08297             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08298                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08299                            pri->trunkgroup, crv->channel);
08300             wakeup_sub(crv, SUB_REAL, pri);
08301          }
08302          return principle;
08303       }
08304       crv = crv->next;
08305    }
08306    ast_log(LOG_WARNING, "Call specified, but not found?\n");
08307    return -1;
08308 }
08309 
08310 static void *do_idle_thread(void *vchan)
08311 {
08312    struct ast_channel *chan = vchan;
08313    struct dahdi_pvt *pvt = chan->tech_pvt;
08314    struct ast_frame *f;
08315    char ex[80];
08316    /* Wait up to 30 seconds for an answer */
08317    int newms, ms = 30000;
08318    if (option_verbose > 2) 
08319       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08320    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08321    if (ast_call(chan, ex, 0)) {
08322       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08323       ast_hangup(chan);
08324       return NULL;
08325    }
08326    while ((newms = ast_waitfor(chan, ms)) > 0) {
08327       f = ast_read(chan);
08328       if (!f) {
08329          /* Got hangup */
08330          break;
08331       }
08332       if (f->frametype == AST_FRAME_CONTROL) {
08333          switch (f->subclass) {
08334          case AST_CONTROL_ANSWER:
08335             /* Launch the PBX */
08336             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08337             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08338             chan->priority = 1;
08339             if (option_verbose > 3) 
08340                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08341             ast_pbx_run(chan);
08342             /* It's already hungup, return immediately */
08343             return NULL;
08344          case AST_CONTROL_BUSY:
08345             if (option_verbose > 3) 
08346                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08347             break;
08348          case AST_CONTROL_CONGESTION:
08349             if (option_verbose > 3) 
08350                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08351             break;
08352          };
08353       }
08354       ast_frfree(f);
08355       ms = newms;
08356    }
08357    /* Hangup the channel since nothing happend */
08358    ast_hangup(chan);
08359    return NULL;
08360 }
08361 
08362 #ifndef PRI_RESTART
08363 #error "Upgrade your libpri"
08364 #endif
08365 static void dahdi_pri_message(struct pri *pri, char *s)
08366 {
08367    int x, y;
08368    int dchan = -1, span = -1;
08369    int dchancount = 0;
08370 
08371    if (pri) {
08372       for (x = 0; x < NUM_SPANS; x++) {
08373          for (y = 0; y < NUM_DCHANS; y++) {
08374             if (pris[x].dchans[y])
08375                dchancount++;
08376 
08377             if (pris[x].dchans[y] == pri)
08378                dchan = y;
08379          }
08380          if (dchan >= 0) {
08381             span = x;
08382             break;
08383          }
08384          dchancount = 0;
08385       }
08386       if ((dchan >= 0) && (span >= 0)) {
08387          if (dchancount > 1)
08388             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08389          else
08390             ast_verbose("%s", s);
08391       } else
08392          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08393    } else
08394       ast_verbose("%s", s);
08395 
08396    ast_mutex_lock(&pridebugfdlock);
08397 
08398    if (pridebugfd >= 0)
08399       write(pridebugfd, s, strlen(s));
08400 
08401    ast_mutex_unlock(&pridebugfdlock);
08402 }
08403 
08404 static void dahdi_pri_error(struct pri *pri, char *s)
08405 {
08406    int x, y;
08407    int dchan = -1, span = -1;
08408    int dchancount = 0;
08409 
08410    if (pri) {
08411       for (x = 0; x < NUM_SPANS; x++) {
08412          for (y = 0; y < NUM_DCHANS; y++) {
08413             if (pris[x].dchans[y])
08414                dchancount++;
08415 
08416             if (pris[x].dchans[y] == pri)
08417                dchan = y;
08418          }
08419          if (dchan >= 0) {
08420             span = x;
08421             break;
08422          }
08423          dchancount = 0;
08424       }
08425       if ((dchan >= 0) && (span >= 0)) {
08426          if (dchancount > 1)
08427             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08428          else
08429             ast_log(LOG_ERROR, "%s", s);
08430       } else
08431          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08432    } else
08433       ast_log(LOG_ERROR, "%s", s);
08434 
08435    ast_mutex_lock(&pridebugfdlock);
08436 
08437    if (pridebugfd >= 0)
08438       write(pridebugfd, s, strlen(s));
08439 
08440    ast_mutex_unlock(&pridebugfdlock);
08441 }
08442 
08443 static int pri_check_restart(struct dahdi_pri *pri)
08444 {
08445    do {
08446       pri->resetpos++;
08447    } while ((pri->resetpos < pri->numchans) &&
08448        (!pri->pvts[pri->resetpos] ||
08449         pri->pvts[pri->resetpos]->call ||
08450         pri->pvts[pri->resetpos]->resetting));
08451    if (pri->resetpos < pri->numchans) {
08452       /* Mark the channel as resetting and restart it */
08453       pri->pvts[pri->resetpos]->resetting = 1;
08454       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08455    } else {
08456       pri->resetting = 0;
08457       time(&pri->lastreset);
08458    }
08459    return 0;
08460 }
08461 
08462 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
08463 {
08464    int x;
08465    int redo;
08466    ast_mutex_unlock(&pri->lock);
08467    ast_mutex_lock(&p->lock);
08468    do {
08469       redo = 0;
08470       for (x = 0; x < 3; x++) {
08471          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08472             redo++;
08473             DEADLOCK_AVOIDANCE(&p->lock);
08474          }
08475          if (p->subs[x].owner) {
08476             ast_queue_hangup(p->subs[x].owner);
08477             ast_mutex_unlock(&p->subs[x].owner->lock);
08478          }
08479       }
08480    } while (redo);
08481    ast_mutex_unlock(&p->lock);
08482    ast_mutex_lock(&pri->lock);
08483    return 0;
08484 }
08485 
08486 static char * redirectingreason2str(int redirectingreason)
08487 {
08488    switch (redirectingreason) {
08489    case 0:
08490       return "UNKNOWN";
08491    case 1:
08492       return "BUSY";
08493    case 2:
08494       return "NO_REPLY";
08495    case 0xF:
08496       return "UNCONDITIONAL";
08497    default:
08498       return "NOREDIRECT";
08499    }
08500 }
08501 
08502 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
08503 {
08504    switch (plan) {
08505    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
08506       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08507       break;
08508    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
08509       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08510       break;
08511    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
08512       snprintf(buf, size, "%s%s", pri->localprefix, number);
08513       break;
08514    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
08515       snprintf(buf, size, "%s%s", pri->privateprefix, number);
08516       break;
08517    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
08518       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08519       break;
08520    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
08521       snprintf(buf, size, "%s", number);
08522       break;
08523    }
08524 }
08525 
08526 static int dahdi_setlaw(int dfd, int law)
08527 {
08528    int res;
08529    res = ioctl(dfd, DAHDI_SETLAW, &law);
08530    if (res)
08531       return res;
08532    return 0;
08533 }
08534 
08535 static void *pri_dchannel(void *vpri)
08536 {
08537    struct dahdi_pri *pri = vpri;
08538    pri_event *e;
08539    struct pollfd fds[NUM_DCHANS];
08540    int res;
08541    int chanpos = 0;
08542    int x;
08543    int haveidles;
08544    int activeidles;
08545    int nextidle = -1;
08546    struct ast_channel *c;
08547    struct timeval tv, lowest, *next;
08548    struct timeval lastidle = { 0, 0 };
08549    int doidling=0;
08550    char *cc;
08551    char idlen[80];
08552    struct ast_channel *idle;
08553    pthread_t p;
08554    time_t t;
08555    int i, which=-1;
08556    int numdchans;
08557    int cause=0;
08558    struct dahdi_pvt *crv;
08559    pthread_t threadid;
08560    pthread_attr_t attr;
08561    char ani2str[6];
08562    char plancallingnum[256];
08563    char plancallingani[256];
08564    char calledtonstr[10];
08565    
08566    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08567 
08568    gettimeofday(&lastidle, NULL);
08569    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08570       /* Need to do idle dialing, check to be sure though */
08571       cc = strchr(pri->idleext, '@');
08572       if (cc) {
08573          *cc = '\0';
08574          cc++;
08575          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08576 #if 0
08577          /* Extensions may not be loaded yet */
08578          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08579             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08580          else
08581 #endif
08582             doidling = 1;
08583       } else
08584          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08585    }
08586    for (;;) {
08587       for (i = 0; i < NUM_DCHANS; i++) {
08588          if (!pri->dchannels[i])
08589             break;
08590          fds[i].fd = pri->fds[i];
08591          fds[i].events = POLLIN | POLLPRI;
08592          fds[i].revents = 0;
08593       }
08594       numdchans = i;
08595       time(&t);
08596       ast_mutex_lock(&pri->lock);
08597       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08598          if (pri->resetting && pri_is_up(pri)) {
08599             if (pri->resetpos < 0)
08600                pri_check_restart(pri);
08601          } else {
08602             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
08603                pri->resetting = 1;
08604                pri->resetpos = -1;
08605             }
08606          }
08607       }
08608       /* Look for any idle channels if appropriate */
08609       if (doidling && pri_is_up(pri)) {
08610          nextidle = -1;
08611          haveidles = 0;
08612          activeidles = 0;
08613          for (x = pri->numchans; x >= 0; x--) {
08614             if (pri->pvts[x] && !pri->pvts[x]->owner && 
08615                 !pri->pvts[x]->call) {
08616                if (haveidles < pri->minunused) {
08617                   haveidles++;
08618                } else if (!pri->pvts[x]->resetting) {
08619                   nextidle = x;
08620                   break;
08621                }
08622             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08623                activeidles++;
08624          }
08625          if (nextidle > -1) {
08626             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08627                /* Don't create a new idle call more than once per second */
08628                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08629                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08630                if (idle) {
08631                   pri->pvts[nextidle]->isidlecall = 1;
08632                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08633                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08634                      dahdi_hangup(idle);
08635                   }
08636                } else
08637                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08638                gettimeofday(&lastidle, NULL);
08639             }
08640          } else if ((haveidles < pri->minunused) &&
08641                (activeidles > pri->minidle)) {
08642             /* Mark something for hangup if there is something 
08643                that can be hungup */
08644             for (x = pri->numchans; x >= 0; x--) {
08645                /* find a candidate channel */
08646                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08647                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08648                   haveidles++;
08649                   /* Stop if we have enough idle channels or
08650                     can't spare any more active idle ones */
08651                   if ((haveidles >= pri->minunused) ||
08652                       (activeidles <= pri->minidle))
08653                      break;
08654                } 
08655             }
08656          }
08657       }
08658       /* Start with reasonable max */
08659       lowest = ast_tv(60, 0);
08660       for (i = 0; i < NUM_DCHANS; i++) {
08661          /* Find lowest available d-channel */
08662          if (!pri->dchannels[i])
08663             break;
08664          if ((next = pri_schedule_next(pri->dchans[i]))) {
08665             /* We need relative time here */
08666             tv = ast_tvsub(*next, ast_tvnow());
08667             if (tv.tv_sec < 0) {
08668                tv = ast_tv(0,0);
08669             }
08670             if (doidling || pri->resetting) {
08671                if (tv.tv_sec > 1) {
08672                   tv = ast_tv(1, 0);
08673                }
08674             } else {
08675                if (tv.tv_sec > 60) {
08676                   tv = ast_tv(60, 0);
08677                }
08678             }
08679          } else if (doidling || pri->resetting) {
08680             /* Make sure we stop at least once per second if we're
08681                monitoring idle channels */
08682             tv = ast_tv(1,0);
08683          } else {
08684             /* Don't poll for more than 60 seconds */
08685             tv = ast_tv(60, 0);
08686          }
08687          if (!i || ast_tvcmp(tv, lowest) < 0) {
08688             lowest = tv;
08689          }
08690       }
08691       ast_mutex_unlock(&pri->lock);
08692 
08693       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08694       pthread_testcancel();
08695       e = NULL;
08696       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
08697       pthread_testcancel();
08698       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08699 
08700       ast_mutex_lock(&pri->lock);
08701       if (!res) {
08702          for (which = 0; which < NUM_DCHANS; which++) {
08703             if (!pri->dchans[which])
08704                break;
08705             /* Just a timeout, run the scheduler */
08706             e = pri_schedule_run(pri->dchans[which]);
08707             if (e)
08708                break;
08709          }
08710       } else if (res > -1) {
08711          for (which = 0; which < NUM_DCHANS; which++) {
08712             if (!pri->dchans[which])
08713                break;
08714             if (fds[which].revents & POLLPRI) {
08715                /* Check for an event */
08716                x = 0;
08717                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
08718                if (x) 
08719                   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);
08720                /* Keep track of alarm state */  
08721                if (x == DAHDI_EVENT_ALARM) {
08722                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
08723                   pri_find_dchan(pri);
08724                } else if (x == DAHDI_EVENT_NOALARM) {
08725                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
08726                   pri_restart(pri->dchans[which]);
08727                }
08728             
08729                if (option_debug)
08730                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
08731             } else if (fds[which].revents & POLLIN) {
08732                e = pri_check_event(pri->dchans[which]);
08733             }
08734             if (e)
08735                break;
08736          }
08737       } else if (errno != EINTR)
08738          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
08739 
08740       if (e) {
08741          if (pri->debug)
08742             pri_dump_event(pri->dchans[which], e);
08743 
08744          if (e->e != PRI_EVENT_DCHAN_DOWN) {
08745             if (!(pri->dchanavail[which] & DCHAN_UP)) {
08746                if (option_verbose > 1) 
08747                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
08748             }
08749             pri->dchanavail[which] |= DCHAN_UP;
08750          } else {
08751             if (pri->dchanavail[which] & DCHAN_UP) {
08752                if (option_verbose > 1) 
08753                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
08754             }
08755             pri->dchanavail[which] &= ~DCHAN_UP;
08756          }
08757 
08758          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
08759             /* Must be an NFAS group that has the secondary dchan active */
08760             pri->pri = pri->dchans[which];
08761 
08762          switch (e->e) {
08763          case PRI_EVENT_DCHAN_UP:
08764             if (!pri->pri) pri_find_dchan(pri);
08765 
08766             /* Note presense of D-channel */
08767             time(&pri->lastreset);
08768 
08769             /* Restart in 5 seconds */
08770             if (pri->resetinterval > -1) {
08771                pri->lastreset -= pri->resetinterval;
08772                pri->lastreset += 5;
08773             }
08774             pri->resetting = 0;
08775             /* Take the channels from inalarm condition */
08776             for (i = 0; i < pri->numchans; i++)
08777                if (pri->pvts[i]) {
08778                   pri->pvts[i]->inalarm = 0;
08779                }
08780             break;
08781          case PRI_EVENT_DCHAN_DOWN:
08782             pri_find_dchan(pri);
08783             if (!pri_is_up(pri)) {
08784                pri->resetting = 0;
08785                /* Hangup active channels and put them in alarm mode */
08786                for (i = 0; i < pri->numchans; i++) {
08787                   struct dahdi_pvt *p = pri->pvts[i];
08788                   if (p) {
08789                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08790                         /* T309 is not enabled : hangup calls when alarm occurs */
08791                         if (p->call) {
08792                            if (p->pri && p->pri->pri) {
08793                               pri_hangup(p->pri->pri, p->call, -1);
08794                               pri_destroycall(p->pri->pri, p->call);
08795                               p->call = NULL;
08796                            } else
08797                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
08798                         }
08799                         if (p->realcall) {
08800                            pri_hangup_all(p->realcall, pri);
08801                         } else if (p->owner)
08802                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08803                      }
08804                      p->inalarm = 1;
08805                   }
08806                }
08807             }
08808             break;
08809          case PRI_EVENT_RESTART:
08810             if (e->restart.channel > -1) {
08811                chanpos = pri_find_principle(pri, e->restart.channel);
08812                if (chanpos < 0)
08813                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
08814                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08815                else {
08816                   if (option_verbose > 2)
08817                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
08818                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
08819                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
08820                   if (pri->pvts[chanpos]->call) {
08821                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
08822                      pri->pvts[chanpos]->call = NULL;
08823                   }
08824                   /* Force soft hangup if appropriate */
08825                   if (pri->pvts[chanpos]->realcall) 
08826                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08827                   else if (pri->pvts[chanpos]->owner)
08828                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08829                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08830                }
08831             } else {
08832                if (option_verbose > 2)
08833                   ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
08834                for (x = 0; x < pri->numchans; x++)
08835                   if (pri->pvts[x]) {
08836                      ast_mutex_lock(&pri->pvts[x]->lock);
08837                      if (pri->pvts[x]->call) {
08838                         pri_destroycall(pri->pri, pri->pvts[x]->call);
08839                         pri->pvts[x]->call = NULL;
08840                      }
08841                      if (pri->pvts[chanpos]->realcall) 
08842                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
08843                      else if (pri->pvts[x]->owner)
08844                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08845                      ast_mutex_unlock(&pri->pvts[x]->lock);
08846                   }
08847             }
08848             break;
08849          case PRI_EVENT_KEYPAD_DIGIT:
08850             chanpos = pri_find_principle(pri, e->digit.channel);
08851             if (chanpos < 0) {
08852                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
08853                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
08854             } else {
08855                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
08856                if (chanpos > -1) {
08857                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
08858                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
08859                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
08860                      /* how to do that */
08861                      int digitlen = strlen(e->digit.digits);
08862                      char digit;
08863                      int i;               
08864                      for (i = 0; i < digitlen; i++) { 
08865                         digit = e->digit.digits[i];
08866                         {
08867                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
08868                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08869                         }
08870                      }
08871                   }
08872                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08873                }
08874             }
08875             break;
08876             
08877          case PRI_EVENT_INFO_RECEIVED:
08878             chanpos = pri_find_principle(pri, e->ring.channel);
08879             if (chanpos < 0) {
08880                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
08881                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08882             } else {
08883                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
08884                if (chanpos > -1) {
08885                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
08886                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
08887                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
08888                      /* how to do that */
08889                      int digitlen = strlen(e->ring.callednum);
08890                      char digit;
08891                      int i;               
08892                      for (i = 0; i < digitlen; i++) { 
08893                         digit = e->ring.callednum[i];
08894                         {
08895                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
08896                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
08897                         }
08898                      }
08899                   }
08900                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08901                }
08902             }
08903             break;
08904          case PRI_EVENT_RING:
08905             crv = NULL;
08906             if (e->ring.channel == -1)
08907                chanpos = pri_find_empty_chan(pri, 1);
08908             else
08909                chanpos = pri_find_principle(pri, e->ring.channel);
08910             /* if no channel specified find one empty */
08911             if (chanpos < 0) {
08912                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
08913                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08914             } else {
08915                ast_mutex_lock(&pri->pvts[chanpos]->lock);
08916                if (pri->pvts[chanpos]->owner) {
08917                   if (pri->pvts[chanpos]->call == e->ring.call) {
08918                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
08919                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08920                      break;
08921                   } else {
08922                      /* This is where we handle initial glare */
08923                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
08924                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
08925                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08926                      chanpos = -1;
08927                   }
08928                }
08929                if (chanpos > -1)
08930                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08931             }
08932             if ((chanpos < 0) && (e->ring.flexible))
08933                chanpos = pri_find_empty_chan(pri, 1);
08934             if (chanpos > -1) {
08935                ast_mutex_lock(&pri->pvts[chanpos]->lock);
08936                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
08937                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
08938                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
08939                   if (crv)
08940                      ast_mutex_lock(&crv->lock);
08941                   if (!crv || crv->owner) {
08942                      pri->pvts[chanpos]->call = NULL;
08943                      if (crv) {
08944                         if (crv->owner)
08945                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08946                         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);
08947                      } else
08948                         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);
08949                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
08950                      if (crv)
08951                         ast_mutex_unlock(&crv->lock);
08952                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
08953                      break;
08954                   }
08955                }
08956                pri->pvts[chanpos]->call = e->ring.call;
08957                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
08958                if (pri->pvts[chanpos]->use_callerid) {
08959                   ast_shrink_phone_number(plancallingnum);
08960                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
08961 #ifdef PRI_ANI
08962                   if (!ast_strlen_zero(e->ring.callingani)) {
08963                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
08964                      ast_shrink_phone_number(plancallingani);
08965                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
08966                   } else {
08967                      pri->pvts[chanpos]->cid_ani[0] = '\0';
08968                   }
08969 #endif
08970                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
08971                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
08972                } else {
08973                   pri->pvts[chanpos]->cid_num[0] = '\0';
08974                   pri->pvts[chanpos]->cid_ani[0] = '\0';
08975                   pri->pvts[chanpos]->cid_name[0] = '\0';
08976                   pri->pvts[chanpos]->cid_ton = 0;
08977                }
08978                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
08979                           e->ring.redirectingnum, e->ring.callingplanrdnis);
08980                /* If immediate=yes go to s|1 */
08981                if (pri->pvts[chanpos]->immediate) {
08982                   if (option_verbose > 2)
08983                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
08984                   pri->pvts[chanpos]->exten[0] = 's';
08985                   pri->pvts[chanpos]->exten[1] = '\0';
08986                }
08987                /* Get called number */
08988                else if (!ast_strlen_zero(e->ring.callednum)) {
08989                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
08990                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
08991                } else if (pri->overlapdial)
08992                   pri->pvts[chanpos]->exten[0] = '\0';
08993                else {
08994                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
08995                   pri->pvts[chanpos]->exten[0] = 's';
08996                   pri->pvts[chanpos]->exten[1] = '\0';
08997                }
08998                /* Set DNID on all incoming calls -- even immediate */
08999                if (!ast_strlen_zero(e->ring.callednum))
09000                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09001                /* No number yet, but received "sending complete"? */
09002                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09003                   if (option_verbose > 2)
09004                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09005                   pri->pvts[chanpos]->exten[0] = 's';
09006                   pri->pvts[chanpos]->exten[1] = '\0';
09007                }
09008                /* Make sure extension exists (or in overlap dial mode, can exist) */
09009                if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09010                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09011                   /* Setup law */
09012                   int law;
09013                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09014                      /* Set to audio mode at this point */
09015                      law = 1;
09016                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09017                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09018                   }
09019                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09020                      law = DAHDI_LAW_ALAW;
09021                   else
09022                      law = DAHDI_LAW_MULAW;
09023                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09024                   if (res < 0) 
09025                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09026                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09027                   if (res < 0)
09028                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09029                   if (e->ring.complete || !pri->overlapdial) {
09030                      /* Just announce proceeding */
09031                      pri->pvts[chanpos]->proceeding = 1;
09032                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09033                   } else {
09034                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
09035                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09036                      else
09037                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09038                   }
09039                   /* Get the use_callingpres state */
09040                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09041                
09042                   /* Start PBX */
09043                   if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09044                      /* Release the PRI lock while we create the channel */
09045                      ast_mutex_unlock(&pri->lock);
09046                      if (crv) {
09047                         /* Set bearer and such */
09048                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09049                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09050                         pri->pvts[chanpos]->owner = &inuse;
09051                         ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09052                      } else {
09053                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09054                      }
09055 
09056                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09057 
09058                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09059                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09060                      }
09061                      if (e->ring.ani2 >= 0) {
09062                         snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09063                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09064                      }
09065 
09066 #ifdef SUPPORT_USERUSER
09067                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
09068                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09069                      }
09070 #endif
09071 
09072                      snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09073                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09074                      if (e->ring.redirectingreason >= 0)
09075                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09076                   
09077                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09078                      ast_mutex_lock(&pri->lock);
09079 
09080                      pthread_attr_init(&attr);
09081                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09082                      if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09083                         if (option_verbose > 2)
09084                            ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09085                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09086                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09087                      } else {
09088                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09089                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09090                         if (c)
09091                            ast_hangup(c);
09092                         else {
09093                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09094                            pri->pvts[chanpos]->call = NULL;
09095                         }
09096                      }
09097                      pthread_attr_destroy(&attr);
09098                   } else  {
09099                      ast_mutex_unlock(&pri->lock);
09100                      /* Release PRI lock while we create the channel */
09101                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09102                      if (c) {
09103                         char calledtonstr[10];
09104 
09105                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09106 
09107                         if (e->ring.ani2 >= 0) {
09108                            snprintf(ani2str, 5, "%d", e->ring.ani2);
09109                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09110                         }
09111 
09112 #ifdef SUPPORT_USERUSER
09113                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
09114                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09115                         }
09116 #endif
09117 
09118                         if (e->ring.redirectingreason >= 0)
09119                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09120                      
09121                         snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09122                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09123 
09124                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
09125                         ast_mutex_lock(&pri->lock);
09126 
09127                         if (option_verbose > 2)
09128                            ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09129                               plancallingnum, pri->pvts[chanpos]->exten, 
09130                                  pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09131                         dahdi_enable_ec(pri->pvts[chanpos]);
09132                      } else {
09133 
09134                         ast_mutex_lock(&pri->lock);
09135 
09136                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09137                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09138                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09139                         pri->pvts[chanpos]->call = NULL;
09140                      }
09141                   }
09142                } else {
09143                   if (option_verbose > 2)
09144                      ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
09145                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
09146                            pri->pvts[chanpos]->prioffset, pri->span);
09147                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09148                   pri->pvts[chanpos]->call = NULL;
09149                   pri->pvts[chanpos]->exten[0] = '\0';
09150                }
09151                if (crv)
09152                   ast_mutex_unlock(&crv->lock);
09153                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09154             } else {
09155                if (e->ring.flexible)
09156                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09157                else
09158                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09159             }
09160             break;
09161          case PRI_EVENT_RINGING:
09162             chanpos = pri_find_principle(pri, e->ringing.channel);
09163             if (chanpos < 0) {
09164                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
09165                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09166             } else {
09167                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09168                if (chanpos < 0) {
09169                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
09170                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09171                } else {
09172                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09173                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09174                      dahdi_enable_ec(pri->pvts[chanpos]);
09175                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09176                      pri->pvts[chanpos]->alerting = 1;
09177                   } else
09178                      ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09179 #ifdef PRI_PROGRESS_MASK
09180                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09181 #else
09182                   if (e->ringing.progress == 8) {
09183 #endif
09184                      /* Now we can do call progress detection */
09185                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09186                         /* RINGING detection isn't required because we got ALERTING signal */
09187                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09188                         pri->pvts[chanpos]->dsp_features = 0;
09189                      }
09190                   }
09191 
09192 #ifdef SUPPORT_USERUSER
09193                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09194                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09195                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09196                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09197                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09198                   }
09199 #endif
09200 
09201                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09202                }
09203             }
09204             break;
09205          case PRI_EVENT_PROGRESS:
09206             /* Get chan value if e->e is not PRI_EVNT_RINGING */
09207             chanpos = pri_find_principle(pri, e->proceeding.channel);
09208             if (chanpos > -1) {
09209 #ifdef PRI_PROGRESS_MASK
09210                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09211 #else
09212                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09213 #endif
09214                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09215 
09216                   if (e->proceeding.cause > -1) {
09217                      if (option_verbose > 2)
09218                         ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09219 
09220                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
09221                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09222                         if (pri->pvts[chanpos]->owner) {
09223                            if (option_verbose > 2)
09224                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09225 
09226                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09227                            f.subclass = AST_CONTROL_BUSY;
09228                         }
09229                      }
09230                   }
09231                   
09232                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09233                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09234                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09235                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09236 #ifdef PRI_PROGRESS_MASK
09237                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09238 #else
09239                   if (e->proceeding.progress == 8) {
09240 #endif
09241                      /* Now we can do call progress detection */
09242                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09243                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09244                         pri->pvts[chanpos]->dsp_features = 0;
09245                      }
09246                   }
09247                   pri->pvts[chanpos]->progress = 1;
09248                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09249                }
09250             }
09251             break;
09252          case PRI_EVENT_PROCEEDING:
09253             chanpos = pri_find_principle(pri, e->proceeding.channel);
09254             if (chanpos > -1) {
09255                if (!pri->pvts[chanpos]->proceeding) {
09256                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09257                   
09258                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09259                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09260                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09261                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09262 #ifdef PRI_PROGRESS_MASK
09263                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09264 #else
09265                   if (e->proceeding.progress == 8) {
09266 #endif
09267                      /* Now we can do call progress detection */
09268                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09269                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09270                         pri->pvts[chanpos]->dsp_features = 0;
09271                      }
09272                      /* Bring voice path up */
09273                      f.subclass = AST_CONTROL_PROGRESS;
09274                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09275                   }
09276                   pri->pvts[chanpos]->proceeding = 1;
09277                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09278                }
09279             }
09280             break;
09281          case PRI_EVENT_FACNAME:
09282             chanpos = pri_find_principle(pri, e->facname.channel);
09283             if (chanpos < 0) {
09284                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
09285                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09286             } else {
09287                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09288                if (chanpos < 0) {
09289                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
09290                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09291                } else {
09292                   /* Re-use *69 field for PRI */
09293                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09294                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09295                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09296                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09297                   dahdi_enable_ec(pri->pvts[chanpos]);
09298                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09299                }
09300             }
09301             break;            
09302          case PRI_EVENT_ANSWER:
09303             chanpos = pri_find_principle(pri, e->answer.channel);
09304             if (chanpos < 0) {
09305                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
09306                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09307             } else {
09308                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09309                if (chanpos < 0) {
09310                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
09311                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09312                } else {
09313                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09314                   /* Now we can do call progress detection */
09315 
09316                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
09317                    * By this time, we need DTMF detection and other features that were previously disabled
09318                    * -- Matt F */
09319                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09320                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09321                      pri->pvts[chanpos]->dsp_features = 0;
09322                   }
09323                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09324                      ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09325                      x = DAHDI_START;
09326                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09327                      if (res < 0) {
09328                         if (errno != EINPROGRESS) {
09329                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09330                         }
09331                      }
09332                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09333                      pri->pvts[chanpos]->dialing = 1;
09334                      /* Send any "w" waited stuff */
09335                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09336                      if (res < 0) {
09337                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09338                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09339                      } else 
09340                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09341                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09342                   } else if (pri->pvts[chanpos]->confirmanswer) {
09343                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09344                   } else {
09345                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09346                      /* Enable echo cancellation if it's not on already */
09347                      dahdi_enable_ec(pri->pvts[chanpos]);
09348                   }
09349 
09350 #ifdef SUPPORT_USERUSER
09351                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
09352                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09353                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09354                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09355                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09356                   }
09357 #endif
09358 
09359                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09360                }
09361             }
09362             break;            
09363          case PRI_EVENT_HANGUP:
09364             chanpos = pri_find_principle(pri, e->hangup.channel);
09365             if (chanpos < 0) {
09366                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
09367                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09368             } else {
09369                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09370                if (chanpos > -1) {
09371                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09372                   if (!pri->pvts[chanpos]->alreadyhungup) {
09373                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
09374                      pri->pvts[chanpos]->alreadyhungup = 1;
09375                      if (pri->pvts[chanpos]->realcall) 
09376                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09377                      else if (pri->pvts[chanpos]->owner) {
09378                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
09379                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09380                         if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09381                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09382                         else {
09383                            switch (e->hangup.cause) {
09384                               case PRI_CAUSE_USER_BUSY:
09385                                  pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09386                                  break;
09387                               case PRI_CAUSE_CALL_REJECTED:
09388                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09389                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09390                               case PRI_CAUSE_SWITCH_CONGESTION:
09391                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09392                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09393                                  pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09394                                  break;
09395                               default:
09396                                  pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09397                            }
09398                         }
09399                      }
09400                      if (option_verbose > 2) 
09401                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
09402                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09403                   } else {
09404                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09405                      pri->pvts[chanpos]->call = NULL;
09406                   }
09407                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09408                      if (option_verbose > 2)
09409                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
09410                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09411                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09412                      pri->pvts[chanpos]->resetting = 1;
09413                   }
09414                   if (e->hangup.aoc_units > -1)
09415                      if (option_verbose > 2)
09416                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09417                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09418 
09419 #ifdef SUPPORT_USERUSER
09420                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09421                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09422                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09423                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09424                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09425                   }
09426 #endif
09427 
09428                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09429                } else {
09430                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
09431                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09432                }
09433             } 
09434             break;
09435 #ifndef PRI_EVENT_HANGUP_REQ
09436 #error please update libpri
09437 #endif
09438          case PRI_EVENT_HANGUP_REQ:
09439             chanpos = pri_find_principle(pri, e->hangup.channel);
09440             if (chanpos < 0) {
09441                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
09442                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09443             } else {
09444                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09445                if (chanpos > -1) {
09446                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09447                   if (pri->pvts[chanpos]->realcall) 
09448                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09449                   else if (pri->pvts[chanpos]->owner) {
09450                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09451                      if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09452                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09453                      else {
09454                         switch (e->hangup.cause) {
09455                            case PRI_CAUSE_USER_BUSY:
09456                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09457                               break;
09458                            case PRI_CAUSE_CALL_REJECTED:
09459                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09460                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09461                            case PRI_CAUSE_SWITCH_CONGESTION:
09462                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09463                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09464                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09465                               break;
09466                            default:
09467                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09468                         }
09469                      }
09470                      if (option_verbose > 2) 
09471                         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);
09472                      if (e->hangup.aoc_units > -1)
09473                         if (option_verbose > 2)
09474                            ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09475                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09476                   } else {
09477                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09478                      pri->pvts[chanpos]->call = NULL;
09479                   }
09480                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09481                      if (option_verbose > 2)
09482                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
09483                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09484                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09485                      pri->pvts[chanpos]->resetting = 1;
09486                   }
09487 
09488 #ifdef SUPPORT_USERUSER
09489                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09490                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09491                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09492                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09493                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09494                   }
09495 #endif
09496 
09497                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09498                } else {
09499                   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);
09500                }
09501             } 
09502             break;
09503          case PRI_EVENT_HANGUP_ACK:
09504             chanpos = pri_find_principle(pri, e->hangup.channel);
09505             if (chanpos < 0) {
09506                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
09507                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09508             } else {
09509                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09510                if (chanpos > -1) {
09511                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09512                   pri->pvts[chanpos]->call = NULL;
09513                   pri->pvts[chanpos]->resetting = 0;
09514                   if (pri->pvts[chanpos]->owner) {
09515                      if (option_verbose > 2) 
09516                         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);
09517                   }
09518 
09519 #ifdef SUPPORT_USERUSER
09520                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09521                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09522                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09523                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09524                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09525                   }
09526 #endif
09527 
09528                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09529                }
09530             }
09531             break;
09532          case PRI_EVENT_CONFIG_ERR:
09533             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09534             break;
09535          case PRI_EVENT_RESTART_ACK:
09536             chanpos = pri_find_principle(pri, e->restartack.channel);
09537             if (chanpos < 0) {
09538                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
09539                   channel number, so we have to figure it out...  This must be why
09540                   everybody resets exactly a channel at a time. */
09541                for (x = 0; x < pri->numchans; x++) {
09542                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
09543                      chanpos = x;
09544                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09545                      ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
09546                            pri->pvts[chanpos]->prioffset, pri->span);
09547                      if (pri->pvts[chanpos]->realcall) 
09548                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09549                      else if (pri->pvts[chanpos]->owner) {
09550                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
09551                            pri->pvts[chanpos]->prioffset, pri->span);
09552                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09553                      }
09554                      pri->pvts[chanpos]->resetting = 0;
09555                      if (option_verbose > 2)
09556                         ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09557                            pri->pvts[chanpos]->prioffset, pri->span);
09558                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09559                      if (pri->resetting)
09560                         pri_check_restart(pri);
09561                      break;
09562                   }
09563                }
09564                if (chanpos < 0) {
09565                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
09566                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09567                }
09568             } else {
09569                if (pri->pvts[chanpos]) {
09570                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09571                   if (pri->pvts[chanpos]->realcall) 
09572                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09573                   else if (pri->pvts[chanpos]->owner) {
09574                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09575                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09576                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09577                   }
09578                   pri->pvts[chanpos]->resetting = 0;
09579                   if (option_verbose > 2)
09580                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09581                            pri->pvts[chanpos]->prioffset, pri->span);
09582                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09583                   if (pri->resetting)
09584                      pri_check_restart(pri);
09585                }
09586             }
09587             break;
09588          case PRI_EVENT_SETUP_ACK:
09589             chanpos = pri_find_principle(pri, e->setup_ack.channel);
09590             if (chanpos < 0) {
09591                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
09592                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09593             } else {
09594                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09595                if (chanpos > -1) {
09596                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09597                   pri->pvts[chanpos]->setup_ack = 1;
09598                   /* Send any queued digits */
09599                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09600                      ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09601                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
09602                         pri->pvts[chanpos]->dialdest[x]);
09603                   }
09604                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09605                } else
09606                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09607             }
09608             break;
09609          case PRI_EVENT_NOTIFY:
09610             chanpos = pri_find_principle(pri, e->notify.channel);
09611             if (chanpos < 0) {
09612                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09613                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09614             } else {
09615                struct ast_frame f = { AST_FRAME_CONTROL, };
09616                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09617                switch (e->notify.info) {
09618                case PRI_NOTIFY_REMOTE_HOLD:
09619                   f.subclass = AST_CONTROL_HOLD;
09620                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09621                   break;
09622                case PRI_NOTIFY_REMOTE_RETRIEVAL:
09623                   f.subclass = AST_CONTROL_UNHOLD;
09624                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09625                   break;
09626                }
09627                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09628             }
09629             break;
09630          default:
09631             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09632          }
09633       }  
09634       ast_mutex_unlock(&pri->lock);
09635    }
09636    /* Never reached */
09637    return NULL;
09638 }
09639 
09640 static int start_pri(struct dahdi_pri *pri)
09641 {
09642    int res, x;
09643    struct dahdi_params p;
09644    struct dahdi_bufferinfo bi;
09645    struct dahdi_spaninfo si;
09646    int i;
09647    
09648    for (i = 0; i < NUM_DCHANS; i++) {
09649       if (!pri->dchannels[i])
09650          break;
09651 #ifdef HAVE_ZAPTEL
09652       pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
09653 #else
09654       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
09655 #endif
09656       x = pri->dchannels[i];
09657       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
09658          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
09659          return -1;
09660       }
09661       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
09662       if (res) {
09663          dahdi_close_pri_fd(pri, i);
09664          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
09665          return -1;
09666       }
09667       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
09668          dahdi_close_pri_fd(pri, i);
09669          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
09670          return -1;
09671       }
09672       memset(&si, 0, sizeof(si));
09673       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
09674       if (res) {
09675          dahdi_close_pri_fd(pri, i);
09676          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
09677       }
09678       if (!si.alarms)
09679          pri->dchanavail[i] |= DCHAN_NOTINALARM;
09680       else
09681          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
09682       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
09683       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
09684       bi.numbufs = 32;
09685       bi.bufsize = 1024;
09686       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
09687          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
09688          dahdi_close_pri_fd(pri, i);
09689          return -1;
09690       }
09691       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
09692       /* Force overlap dial if we're doing GR-303! */
09693       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
09694          pri->overlapdial = 1;
09695       pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
09696 #ifdef HAVE_PRI_INBANDDISCONNECT
09697       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
09698 #endif
09699       /* Enslave to master if appropriate */
09700       if (i)
09701          pri_enslave(pri->dchans[0], pri->dchans[i]);
09702       if (!pri->dchans[i]) {
09703          dahdi_close_pri_fd(pri, i);
09704          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
09705          return -1;
09706       }
09707       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
09708       pri_set_nsf(pri->dchans[i], pri->nsf);
09709 #ifdef PRI_GETSET_TIMERS
09710       for (x = 0; x < PRI_MAX_TIMERS; x++) {
09711          if (pritimers[x] != 0)
09712             pri_set_timer(pri->dchans[i], x, pritimers[x]);
09713       }
09714 #endif
09715    }
09716    /* Assume primary is the one we use */
09717    pri->pri = pri->dchans[0];
09718    pri->resetpos = -1;
09719    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
09720       for (i = 0; i < NUM_DCHANS; i++) {
09721          if (!pri->dchannels[i])
09722             break;
09723          dahdi_close_pri_fd(pri, i);
09724       }
09725       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
09726       return -1;
09727    }
09728    return 0;
09729 }
09730 
09731 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
09732 {
09733    int which, span;
09734    char *ret = NULL;
09735 
09736    if (pos != rpos)
09737       return ret;
09738 
09739    for (which = span = 0; span < NUM_SPANS; span++) {
09740       if (pris[span].pri && ++which > state) {
09741          asprintf(&ret, "%d", span + 1);  /* user indexes start from 1 */
09742          break;
09743       }
09744    }
09745    return ret;
09746 }
09747 
09748 static char *complete_span_4(const char *line, const char *word, int pos, int state)
09749 {
09750    return complete_span_helper(line,word,pos,state,3);
09751 }
09752 
09753 static char *complete_span_5(const char *line, const char *word, int pos, int state)
09754 {
09755    return complete_span_helper(line,word,pos,state,4);
09756 }
09757 
09758 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
09759 {
09760    int myfd;
09761 
09762    if (!strncasecmp(argv[1], "set", 3)) {
09763       if (argc < 5) 
09764          return RESULT_SHOWUSAGE;
09765 
09766       if (ast_strlen_zero(argv[4]))
09767          return RESULT_SHOWUSAGE;
09768 
09769       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
09770       if (myfd < 0) {
09771          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
09772          return RESULT_SUCCESS;
09773       }
09774 
09775       ast_mutex_lock(&pridebugfdlock);
09776 
09777       if (pridebugfd >= 0)
09778          close(pridebugfd);
09779 
09780       pridebugfd = myfd;
09781       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
09782       
09783       ast_mutex_unlock(&pridebugfdlock);
09784 
09785       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
09786    } else {
09787       /* Assume it is unset */
09788       ast_mutex_lock(&pridebugfdlock);
09789       close(pridebugfd);
09790       pridebugfd = -1;
09791       ast_cli(fd, "PRI debug output to file disabled\n");
09792       ast_mutex_unlock(&pridebugfdlock);
09793    }
09794 
09795    return RESULT_SUCCESS;
09796 }
09797 
09798 #ifdef HAVE_PRI_VERSION
09799 static int handle_pri_version(int fd, int agc, char *argv[]) {
09800    ast_cli(fd, "libpri version: %s\n", pri_get_version());
09801    return RESULT_SUCCESS;
09802 }
09803 #endif
09804 
09805 static int handle_pri_debug(int fd, int argc, char *argv[])
09806 {
09807    int span;
09808    int x;
09809    if (argc < 4) {
09810       return RESULT_SHOWUSAGE;
09811    }
09812    span = atoi(argv[3]);
09813    if ((span < 1) || (span > NUM_SPANS)) {
09814       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
09815       return RESULT_SUCCESS;
09816    }
09817    if (!pris[span-1].pri) {
09818       ast_cli(fd, "No PRI running on span %d\n", span);
09819       return RESULT_SUCCESS;
09820    }
09821    for (x = 0; x < NUM_DCHANS; x++) {
09822       if (pris[span-1].dchans[x])
09823          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09824                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09825                                                PRI_DEBUG_Q921_STATE);
09826    }
09827    ast_cli(fd, "Enabled debugging on span %d\n", span);
09828    return RESULT_SUCCESS;
09829 }
09830 
09831 
09832 
09833 static int handle_pri_no_debug(int fd, int argc, char *argv[])
09834 {
09835    int span;
09836    int x;
09837    if (argc < 5)
09838       return RESULT_SHOWUSAGE;
09839    span = atoi(argv[4]);
09840    if ((span < 1) || (span > NUM_SPANS)) {
09841       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09842       return RESULT_SUCCESS;
09843    }
09844    if (!pris[span-1].pri) {
09845       ast_cli(fd, "No PRI running on span %d\n", span);
09846       return RESULT_SUCCESS;
09847    }
09848    for (x = 0; x < NUM_DCHANS; x++) {
09849       if (pris[span-1].dchans[x])
09850          pri_set_debug(pris[span-1].dchans[x], 0);
09851    }
09852    ast_cli(fd, "Disabled debugging on span %d\n", span);
09853    return RESULT_SUCCESS;
09854 }
09855 
09856 static int handle_pri_really_debug(int fd, int argc, char *argv[])
09857 {
09858    int span;
09859    int x;
09860    if (argc < 5)
09861       return RESULT_SHOWUSAGE;
09862    span = atoi(argv[4]);
09863    if ((span < 1) || (span > NUM_SPANS)) {
09864       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
09865       return RESULT_SUCCESS;
09866    }
09867    if (!pris[span-1].pri) {
09868       ast_cli(fd, "No PRI running on span %d\n", span);
09869       return RESULT_SUCCESS;
09870    }
09871    for (x = 0; x < NUM_DCHANS; x++) {
09872       if (pris[span-1].dchans[x])
09873          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
09874                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
09875                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
09876    }
09877    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
09878    return RESULT_SUCCESS;
09879 }
09880 
09881 static void build_status(char *s, size_t len, int status, int active)
09882 {
09883    if (!s || len < 1) {
09884       return;
09885    }
09886    s[0] = '\0';
09887    if (status & DCHAN_PROVISIONED)
09888       strncat(s, "Provisioned, ", len - strlen(s) - 1);
09889    if (!(status & DCHAN_NOTINALARM))
09890       strncat(s, "In Alarm, ", len - strlen(s) - 1);
09891    if (status & DCHAN_UP)
09892       strncat(s, "Up", len - strlen(s) - 1);
09893    else
09894       strncat(s, "Down", len - strlen(s) - 1);
09895    if (active)
09896       strncat(s, ", Active", len - strlen(s) - 1);
09897    else
09898       strncat(s, ", Standby", len - strlen(s) - 1);
09899    s[len - 1] = '\0';
09900 }
09901 
09902 static int handle_pri_show_spans(int fd, int argc, char *argv[])
09903 {
09904    int span;
09905    int x;
09906    char status[256];
09907    if (argc != 3)
09908       return RESULT_SHOWUSAGE;
09909 
09910    for (span = 0; span < NUM_SPANS; span++) {
09911       if (pris[span].pri) {
09912          for (x = 0; x < NUM_DCHANS; x++) {
09913             if (pris[span].dchannels[x]) {
09914                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
09915                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
09916             }
09917          }
09918       }
09919    }
09920    return RESULT_SUCCESS;
09921 }
09922 
09923 static int handle_pri_show_span(int fd, int argc, char *argv[])
09924 {
09925    int span;
09926    int x;
09927    char status[256];
09928    if (argc < 4)
09929       return RESULT_SHOWUSAGE;
09930    span = atoi(argv[3]);
09931    if ((span < 1) || (span > NUM_SPANS)) {
09932       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
09933       return RESULT_SUCCESS;
09934    }
09935    if (!pris[span-1].pri) {
09936       ast_cli(fd, "No PRI running on span %d\n", span);
09937       return RESULT_SUCCESS;
09938    }
09939    for (x = 0; x < NUM_DCHANS; x++) {
09940       if (pris[span-1].dchannels[x]) {
09941 #ifdef PRI_DUMP_INFO_STR
09942          char *info_str = NULL;
09943 #endif
09944          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
09945          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
09946          ast_cli(fd, "Status: %s\n", status);
09947 #ifdef PRI_DUMP_INFO_STR
09948          info_str = pri_dump_info_str(pris[span-1].pri);
09949          if (info_str) {
09950             ast_cli(fd, "%s", info_str);
09951             free(info_str);
09952          }
09953 #else
09954          pri_dump_info(pris[span-1].pri);
09955 #endif
09956          ast_cli(fd, "\n");
09957       }
09958    }
09959    return RESULT_SUCCESS;
09960 }
09961 
09962 static int handle_pri_show_debug(int fd, int argc, char *argv[])
09963 {
09964    int x;
09965    int span;
09966    int count=0;
09967    int debug=0;
09968 
09969    for (span = 0; span < NUM_SPANS; span++) {
09970            if (pris[span].pri) {
09971          for (x = 0; x < NUM_DCHANS; x++) {
09972             debug = 0;
09973                if (pris[span].dchans[x]) {
09974                   debug = pri_get_debug(pris[span].dchans[x]);
09975                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" );
09976                count++;
09977             }
09978          }
09979       }
09980 
09981    }
09982    ast_mutex_lock(&pridebugfdlock);
09983    if (pridebugfd >= 0) 
09984       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
09985    ast_mutex_unlock(&pridebugfdlock);
09986        
09987    if (!count) 
09988       ast_cli(fd, "No debug set or no PRI running\n");
09989    return RESULT_SUCCESS;
09990 }
09991 
09992 static const char pri_debug_help[] = 
09993    "Usage: pri debug span <span>\n"
09994    "       Enables debugging on a given PRI span\n";
09995    
09996 static const char pri_no_debug_help[] = 
09997    "Usage: pri no debug span <span>\n"
09998    "       Disables debugging on a given PRI span\n";
09999 
10000 static const char pri_really_debug_help[] = 
10001    "Usage: pri intensive debug span <span>\n"
10002    "       Enables debugging down to the Q.921 level\n";
10003 
10004 static const char pri_show_span_help[] = 
10005    "Usage: pri show span <span>\n"
10006    "       Displays PRI Information on a given PRI span\n";
10007 
10008 static const char pri_show_spans_help[] = 
10009    "Usage: pri show spans\n"
10010    "       Displays PRI Information\n";
10011 
10012 static struct ast_cli_entry dahdi_pri_cli[] = {
10013    { { "pri", "debug", "span", NULL },
10014    handle_pri_debug, "Enables PRI debugging on a span",
10015    pri_debug_help, complete_span_4 },
10016 
10017    { { "pri", "no", "debug", "span", NULL },
10018    handle_pri_no_debug, "Disables PRI debugging on a span",
10019    pri_no_debug_help, complete_span_5 },
10020 
10021    { { "pri", "intense", "debug", "span", NULL },
10022    handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10023    pri_really_debug_help, complete_span_5 },
10024 
10025    { { "pri", "show", "spans", NULL },
10026    handle_pri_show_spans, "Displays PRI Information",
10027    pri_show_spans_help },
10028 
10029    { { "pri", "show", "span", NULL },
10030    handle_pri_show_span, "Displays PRI Information",
10031    pri_show_span_help, complete_span_4 },
10032 
10033    { { "pri", "show", "debug", NULL },
10034    handle_pri_show_debug, "Displays current PRI debug settings" },
10035 
10036    { { "pri", "set", "debug", "file", NULL },
10037    handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10038 
10039    { { "pri", "unset", "debug", "file", NULL },
10040    handle_pri_set_debug_file, "Ends PRI debug output to file" },
10041 
10042 #ifdef HAVE_PRI_VERSION
10043    { { "pri", "show", "version", NULL },
10044    handle_pri_version, "Displays version of libpri" },
10045 #endif
10046 };
10047 
10048 #endif /* HAVE_PRI */
10049 
10050 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10051 {
10052    int channel;
10053    
10054    if (argc != 4)
10055       return RESULT_SHOWUSAGE;
10056    
10057    channel = atoi(argv[3]);
10058 
10059    return dahdi_destroy_channel_bynum(channel);
10060 }
10061 
10062 static void dahdi_softhangup_all(void)
10063 {
10064    struct dahdi_pvt *p;
10065 retry:
10066    ast_mutex_lock(&iflock);
10067     for (p = iflist; p; p = p->next) {
10068       ast_mutex_lock(&p->lock);
10069         if (p->owner && !p->restartpending) {
10070          if (ast_channel_trylock(p->owner)) {
10071             if (option_debug > 2)
10072                ast_verbose("Avoiding deadlock\n");
10073             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10074             ast_mutex_unlock(&p->lock);
10075             ast_mutex_unlock(&iflock);
10076             goto retry;
10077          }
10078          if (option_debug > 2)
10079             ast_verbose("Softhanging up on %s\n", p->owner->name);
10080          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10081          p->restartpending = 1;
10082          num_restart_pending++;
10083          ast_channel_unlock(p->owner);
10084       }
10085       ast_mutex_unlock(&p->lock);
10086     }
10087    ast_mutex_unlock(&iflock);
10088 }
10089 
10090 static int setup_dahdi(int reload);
10091 static int dahdi_restart(void)
10092 {
10093 #if defined(HAVE_PRI)
10094    int i, j;
10095 #endif
10096    int cancel_code;
10097    struct dahdi_pvt *p;
10098 
10099    ast_mutex_lock(&restart_lock);
10100  
10101    if (option_verbose)
10102       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10103    dahdi_softhangup_all();
10104    if (option_verbose > 3)
10105       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10106 
10107    #if defined(HAVE_PRI)
10108    for (i = 0; i < NUM_SPANS; i++) {
10109       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10110          cancel_code = pthread_cancel(pris[i].master);
10111          pthread_kill(pris[i].master, SIGURG);
10112          if (option_debug > 3)
10113             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10114             pthread_join(pris[i].master, NULL);
10115          if (option_debug > 3)
10116             ast_verbose("Joined thread of span %d\n", i);
10117       }
10118     }
10119    #endif
10120 
10121     ast_mutex_lock(&monlock);
10122     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10123       cancel_code = pthread_cancel(monitor_thread);
10124       pthread_kill(monitor_thread, SIGURG);
10125       if (option_debug > 3)
10126          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10127         pthread_join(monitor_thread, NULL);
10128       if (option_debug > 3)
10129          ast_verbose("Joined monitor thread\n");
10130     }
10131    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10132 
10133    ast_mutex_lock(&ss_thread_lock);
10134    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10135       int x = DAHDI_FLASH;
10136       if (option_debug > 2)
10137          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10138 
10139       for (p = iflist; p; p = p->next) {
10140          if (p->owner)
10141             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 */    
10142       }
10143       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10144    }
10145 
10146    /* ensure any created channels before monitor threads were stopped are hungup */
10147    dahdi_softhangup_all();
10148    if (option_verbose > 3)
10149       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10150    destroy_all_channels();
10151    if (option_debug)
10152       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10153 
10154     ast_mutex_unlock(&monlock);
10155 
10156    #ifdef HAVE_PRI
10157    for (i = 0; i < NUM_SPANS; i++) {
10158       for (j = 0; j < NUM_DCHANS; j++)
10159             dahdi_close_pri_fd(&(pris[i]), j);
10160    }
10161 
10162    memset(pris, 0, sizeof(pris));
10163    for (i = 0; i < NUM_SPANS; i++) {
10164       ast_mutex_init(&pris[i].lock);
10165       pris[i].offset = -1;
10166       pris[i].master = AST_PTHREADT_NULL;
10167       for (j = 0; j < NUM_DCHANS; j++)
10168          pris[i].fds[j] = -1;
10169    }
10170    pri_set_error(dahdi_pri_error);
10171    pri_set_message(dahdi_pri_message);
10172    #endif
10173 
10174    if (setup_dahdi(2) != 0) {
10175       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10176       ast_mutex_unlock(&ss_thread_lock);
10177       return 1;
10178    }
10179    ast_mutex_unlock(&ss_thread_lock);
10180    ast_mutex_unlock(&restart_lock);
10181    return 0;
10182 }
10183 
10184 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10185 {
10186    if (argc != 2) {
10187       return RESULT_SHOWUSAGE;
10188    }
10189 
10190    if (dahdi_restart() != 0)
10191       return RESULT_FAILURE;
10192    return RESULT_SUCCESS;
10193 }
10194 
10195 static int dahdi_show_channels(int fd, int argc, char **argv)
10196 {
10197 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10198 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10199    struct dahdi_pvt *tmp = NULL;
10200    char tmps[20] = "";
10201    ast_mutex_t *lock;
10202    struct dahdi_pvt *start;
10203 #ifdef HAVE_PRI
10204    int trunkgroup;
10205    struct dahdi_pri *pri = NULL;
10206    int x;
10207 #endif
10208 
10209    lock = &iflock;
10210    start = iflist;
10211 
10212 #ifdef HAVE_PRI
10213    if (argc == 4) {
10214       if ((trunkgroup = atoi(argv[3])) < 1)
10215          return RESULT_SHOWUSAGE;
10216       for (x = 0; x < NUM_SPANS; x++) {
10217          if (pris[x].trunkgroup == trunkgroup) {
10218             pri = pris + x;
10219             break;
10220          }
10221       }
10222       if (pri) {
10223          start = pri->crvs;
10224          lock = &pri->lock;
10225       } else {
10226          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10227          return RESULT_FAILURE;
10228       }
10229    } else
10230 #endif
10231    if (argc != 3)
10232       return RESULT_SHOWUSAGE;
10233 
10234    ast_mutex_lock(lock);
10235 #ifdef HAVE_PRI
10236    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10237 #else
10238    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10239 #endif   
10240    
10241    tmp = start;
10242    while (tmp) {
10243       if (tmp->channel > 0) {
10244          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10245       } else
10246          ast_copy_string(tmps, "pseudo", sizeof(tmps));
10247       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10248       tmp = tmp->next;
10249    }
10250    ast_mutex_unlock(lock);
10251    return RESULT_SUCCESS;
10252 #undef FORMAT
10253 #undef FORMAT2
10254 }
10255 
10256 static int dahdi_show_channel(int fd, int argc, char **argv)
10257 {
10258    int channel;
10259    struct dahdi_pvt *tmp = NULL;
10260    struct dahdi_confinfo ci;
10261    struct dahdi_params ps;
10262    int x;
10263    ast_mutex_t *lock;
10264    struct dahdi_pvt *start;
10265 #ifdef HAVE_PRI
10266    char *c;
10267    int trunkgroup;
10268    struct dahdi_pri *pri=NULL;
10269 #endif
10270 
10271    lock = &iflock;
10272    start = iflist;
10273 
10274    if (argc != 4)
10275       return RESULT_SHOWUSAGE;
10276 #ifdef HAVE_PRI
10277    if ((c = strchr(argv[3], ':'))) {
10278       if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10279          return RESULT_SHOWUSAGE;
10280       if ((trunkgroup < 1) || (channel < 1))
10281          return RESULT_SHOWUSAGE;
10282       for (x = 0; x < NUM_SPANS; x++) {
10283          if (pris[x].trunkgroup == trunkgroup) {
10284             pri = pris + x;
10285             break;
10286          }
10287       }
10288       if (pri) {
10289          start = pri->crvs;
10290          lock = &pri->lock;
10291       } else {
10292          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10293          return RESULT_FAILURE;
10294       }
10295    } else
10296 #endif
10297       channel = atoi(argv[3]);
10298 
10299    ast_mutex_lock(lock);
10300    tmp = start;
10301    while (tmp) {
10302       if (tmp->channel == channel) {
10303 #ifdef HAVE_PRI
10304          if (pri) 
10305             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10306          else
10307 #endif         
10308          ast_cli(fd, "Channel: %d\n", tmp->channel);
10309          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10310          ast_cli(fd, "Span: %d\n", tmp->span);
10311          ast_cli(fd, "Extension: %s\n", tmp->exten);
10312          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10313          ast_cli(fd, "Context: %s\n", tmp->context);
10314          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10315          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10316          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10317          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10318          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10319          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10320          ast_cli(fd, "Radio: %d\n", tmp->radio);
10321          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10322          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)" : "");
10323          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)" : "");
10324          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)" : "");
10325          ast_cli(fd, "Confno: %d\n", tmp->confno);
10326          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10327          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10328          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10329          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10330          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10331          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10332          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10333          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10334          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10335          if (tmp->master)
10336             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10337          for (x = 0; x < MAX_SLAVES; x++) {
10338             if (tmp->slaves[x])
10339                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10340          }
10341 #ifdef HAVE_PRI
10342          if (tmp->pri) {
10343             ast_cli(fd, "PRI Flags: ");
10344             if (tmp->resetting)
10345                ast_cli(fd, "Resetting ");
10346             if (tmp->call)
10347                ast_cli(fd, "Call ");
10348             if (tmp->bearer)
10349                ast_cli(fd, "Bearer ");
10350             ast_cli(fd, "\n");
10351             if (tmp->logicalspan) 
10352                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10353             else
10354                ast_cli(fd, "PRI Logical Span: Implicit\n");
10355          }
10356             
10357 #endif
10358          memset(&ci, 0, sizeof(ci));
10359          ps.channo = tmp->channel;
10360          if (tmp->subs[SUB_REAL].dfd > -1) {
10361             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10362                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10363             }
10364 #ifdef DAHDI_GETCONFMUTE
10365             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10366                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10367             }
10368 #endif
10369             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10370                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10371             } else {
10372                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10373             }
10374          }
10375          if (ISTRUNK(tmp)) {
10376             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
10377             if (!ast_strlen_zero(progzone))
10378                ast_cli(fd, "Progress Zone: %s\n", progzone);
10379             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
10380             if(tmp->busydetect) {
10381                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10382                if(tmp->busytonelength > 0) {
10383                   ast_cli(fd, "Busy Pattern:\n");
10384                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10385                   if (tmp->busyquietlength > 0) 
10386                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10387                   else 
10388                      ast_cli(fd, " -- Detect Tone Only\n");
10389                   if(tmp->busyfuzziness > 0)
10390                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10391                }
10392             }
10393          }
10394          ast_mutex_unlock(lock);
10395          return RESULT_SUCCESS;
10396       }
10397       tmp = tmp->next;
10398    }
10399    
10400    ast_cli(fd, "Unable to find given channel %d\n", channel);
10401    ast_mutex_unlock(lock);
10402    return RESULT_FAILURE;
10403 }
10404 
10405 static char dahdi_show_cadences_usage[] =
10406 "Usage: dahdi show cadences\n"
10407 "       Shows all cadences currently defined\n";
10408 
10409 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10410 {
10411    int i, j;
10412    for (i = 0; i < num_cadence; i++) {
10413       char output[1024];
10414       char tmp[16], tmp2[64];
10415       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10416       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10417 
10418       for (j = 0; j < 16; j++) {
10419          if (cadences[i].ringcadence[j] == 0)
10420             break;
10421          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10422          if (cidrings[i] * 2 - 1 == j)
10423             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10424          else
10425             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10426          if (j != 0)
10427             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10428          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10429       }
10430       ast_cli(fd,"%s\n",output);
10431    }
10432    return 0;
10433 }
10434 
10435 /* Based on irqmiss.c */
10436 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10437    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10438    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10439 
10440    int span;
10441    int res;
10442    char alarms[50];
10443 
10444    int ctl;
10445    struct dahdi_spaninfo s;
10446 
10447 #ifdef HAVE_ZAPTEL
10448    if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
10449       ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10450       ast_cli(fd, "No Zaptel interface found.\n");
10451       return RESULT_FAILURE;
10452    }
10453 #else
10454    if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
10455       ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10456       ast_cli(fd, "No DAHDI interface found.\n");
10457       return RESULT_FAILURE;
10458    }
10459 #endif
10460    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10461 
10462    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10463       s.spanno = span;
10464       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10465       if (res) {
10466          continue;
10467       }
10468       alarms[0] = '\0';
10469       if (s.alarms > 0) {
10470          if (s.alarms & DAHDI_ALARM_BLUE)
10471             strcat(alarms, "BLU/");
10472          if (s.alarms & DAHDI_ALARM_YELLOW)
10473             strcat(alarms, "YEL/");
10474          if (s.alarms & DAHDI_ALARM_RED)
10475             strcat(alarms, "RED/");
10476          if (s.alarms & DAHDI_ALARM_LOOPBACK)
10477             strcat(alarms, "LB/");
10478          if (s.alarms & DAHDI_ALARM_RECOVER)
10479             strcat(alarms, "REC/");
10480          if (s.alarms & DAHDI_ALARM_NOTOPEN)
10481             strcat(alarms, "NOP/");
10482          if (!strlen(alarms))
10483             strcat(alarms, "UUU/");
10484          if (strlen(alarms)) {
10485             /* Strip trailing / */
10486             alarms[strlen(alarms) - 1] = '\0';
10487          }
10488       } else {
10489          if (s.numchans)
10490             strcpy(alarms, "OK");
10491          else
10492             strcpy(alarms, "UNCONFIGURED");
10493       }
10494 
10495       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10496    }
10497    close(ctl);
10498 
10499    return RESULT_SUCCESS;
10500 #undef FORMAT
10501 #undef FORMAT2
10502 }
10503 
10504 static char show_channels_usage[] =
10505    "Usage: dahdi show channels\n"
10506    "  Shows a list of available channels\n";
10507 
10508 static char show_channel_usage[] =
10509    "Usage: dahdi show channel <chan num>\n"
10510    "  Detailed information about a given channel\n";
10511 
10512 static char dahdi_show_status_usage[] =
10513    "Usage: dahdi show status\n"
10514    "       Shows a list of DAHDI cards with status\n";
10515 
10516 static char destroy_channel_usage[] =
10517    "Usage: dahdi destroy channel <chan num>\n"
10518    "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
10519 
10520 static char dahdi_restart_usage[] =
10521    "Usage: dahdi restart\n"
10522    "  Restarts the DAHDI channels: destroys them all and then\n"
10523    "  re-reads them from chan_dahdi.conf.\n"
10524    "  Note that this will STOP any running CALL on DAHDI channels.\n"
10525    "";
10526 
10527 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10528    { "zap", "show", "cadences", NULL },
10529    handle_dahdi_show_cadences, NULL,
10530    NULL };
10531 
10532 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10533    { "zap", "show", "channels", NULL },
10534    dahdi_show_channels, NULL,
10535    NULL };
10536 
10537 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10538    { "zap", "show", "channel", NULL },
10539    dahdi_show_channel, NULL,
10540    NULL };
10541 
10542 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10543    { "zap", "destroy", "channel", NULL },
10544    dahdi_destroy_channel, NULL,
10545    NULL };
10546 
10547 static struct ast_cli_entry cli_zap_restart_deprecated = {
10548    { "zap", "restart", NULL },
10549    dahdi_restart_cmd, NULL,
10550    NULL };
10551 
10552 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10553    { "zap", "show", "status", NULL },
10554    dahdi_show_status, NULL,
10555    NULL };
10556 
10557 static struct ast_cli_entry dahdi_cli[] = {
10558    { { "dahdi", "show", "cadences", NULL },
10559    handle_dahdi_show_cadences, "List cadences",
10560    dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10561 
10562    { { "dahdi", "show", "channels", NULL},
10563    dahdi_show_channels, "Show active DAHDI channels",
10564    show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10565 
10566    { { "dahdi", "show", "channel", NULL},
10567    dahdi_show_channel, "Show information on a channel",
10568    show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10569 
10570    { { "dahdi", "destroy", "channel", NULL},
10571    dahdi_destroy_channel, "Destroy a channel",
10572    destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10573 
10574    { { "dahdi", "restart", NULL},
10575    dahdi_restart_cmd, "Fully restart DAHDI channels",
10576    dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10577 
10578    { { "dahdi", "show", "status", NULL},
10579    dahdi_show_status, "Show all DAHDI cards status",
10580    dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10581 };
10582 
10583 #define TRANSFER  0
10584 #define HANGUP    1
10585 
10586 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10587 {
10588    if (p) {
10589       switch (mode) {
10590          case TRANSFER:
10591             p->fake_event = DAHDI_EVENT_WINKFLASH;
10592             break;
10593          case HANGUP:
10594             p->fake_event = DAHDI_EVENT_ONHOOK;
10595             break;
10596          default:
10597             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10598       }
10599    }
10600    return 0;
10601 }
10602 static struct dahdi_pvt *find_channel(int channel)
10603 {
10604    struct dahdi_pvt *p = iflist;
10605    while (p) {
10606       if (p->channel == channel) {
10607          break;
10608       }
10609       p = p->next;
10610    }
10611    return p;
10612 }
10613 
10614 #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)
10615 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10616 
10617 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10618 {
10619    struct dahdi_pvt *p = NULL;
10620    const char *channel = local_astman_header(m, "Channel", zap_mode);
10621 
10622    if (ast_strlen_zero(channel)) {
10623       astman_send_error(s, m, "No channel specified");
10624       return 0;
10625    }
10626    if (!(p = find_channel(atoi(channel)))) {
10627       astman_send_error(s, m, "No such channel");
10628       return 0;
10629    }
10630    p->dnd = dnd;
10631    local_astman_ack(s, m, "DND", zap_mode);
10632 
10633    return 0;
10634 }
10635 
10636 static int zap_action_dndon(struct mansession *s, const struct message *m)
10637 {
10638    return __action_dnd(s, m, 1, 1);
10639 }
10640 
10641 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10642 {
10643    return __action_dnd(s, m, 0, 1);
10644 }
10645 
10646 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10647 {
10648    return __action_dnd(s, m, 1, 0);
10649 }
10650 
10651 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10652 {
10653    return __action_dnd(s, m, 0, 0);
10654 }
10655 
10656 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10657 {
10658    struct dahdi_pvt *p = NULL;
10659    const char *channel = local_astman_header(m, "Channel", zap_mode);
10660 
10661    if (ast_strlen_zero(channel)) {
10662       astman_send_error(s, m, "No channel specified");
10663       return 0;
10664    }
10665    if (!(p = find_channel(atoi(channel)))) {
10666       astman_send_error(s, m, "No such channel");
10667       return 0;
10668    }
10669    dahdi_fake_event(p,TRANSFER);
10670    local_astman_ack(s, m, "Transfer", zap_mode);
10671 
10672    return 0;
10673 }
10674 
10675 static int zap_action_transfer(struct mansession *s, const struct message *m)
10676 {
10677    return __action_transfer(s, m, 1);
10678 }
10679 
10680 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10681 {
10682    return __action_transfer(s, m, 0);
10683 }
10684 
10685 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
10686 {
10687    struct dahdi_pvt *p = NULL;
10688    const char *channel = local_astman_header(m, "Channel", zap_mode);
10689 
10690    if (ast_strlen_zero(channel)) {
10691       astman_send_error(s, m, "No channel specified");
10692       return 0;
10693    }
10694    if (!(p = find_channel(atoi(channel)))) {
10695       astman_send_error(s, m, "No such channel");
10696       return 0;
10697    }
10698    dahdi_fake_event(p, HANGUP);
10699    local_astman_ack(s, m, "Hangup", zap_mode);
10700    return 0;
10701 }
10702 
10703 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10704 {
10705    return __action_transferhangup(s, m, 1);
10706 }
10707 
10708 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10709 {
10710    return __action_transferhangup(s, m, 0);
10711 }
10712 
10713 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10714 {
10715    struct dahdi_pvt *p = NULL;
10716    const char *channel = local_astman_header(m, "Channel", zap_mode);
10717    const char *number = astman_get_header(m, "Number");
10718    int i;
10719 
10720    if (ast_strlen_zero(channel)) {
10721       astman_send_error(s, m, "No channel specified");
10722       return 0;
10723    }
10724    if (ast_strlen_zero(number)) {
10725       astman_send_error(s, m, "No number specified");
10726       return 0;
10727    }
10728    if (!(p = find_channel(atoi(channel)))) {
10729       astman_send_error(s, m, "No such channel");
10730       return 0;
10731    }
10732    if (!p->owner) {
10733       astman_send_error(s, m, "Channel does not have an owner");
10734       return 0;
10735    }
10736    for (i = 0; i < strlen(number); i++) {
10737       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10738 
10739       dahdi_queue_frame(p, &f, NULL); 
10740    }
10741    local_astman_ack(s, m, "DialOffHook", zap_mode);
10742 
10743    return 0;
10744 }
10745 
10746 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10747 {
10748    return __action_dialoffhook(s, m, 1);
10749 }
10750 
10751 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10752 {
10753    return __action_dialoffhook(s, m, 0);
10754 }
10755 
10756 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10757 {
10758    struct dahdi_pvt *tmp = NULL;
10759    const char *id = astman_get_header(m, "ActionID");
10760    char idText[256] = "";
10761 
10762    local_astman_ack(s, m, " channel status will follow", zap_mode);
10763    if (!ast_strlen_zero(id))
10764       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10765 
10766    ast_mutex_lock(&iflock);
10767    
10768    tmp = iflist;
10769    while (tmp) {
10770       if (tmp->channel > 0) {
10771          int alarm = get_alarms(tmp);
10772          astman_append(s,
10773                   "Event: %sShowChannels\r\n"
10774                   "Channel: %d\r\n"
10775                   "Signalling: %s\r\n"
10776                   "Context: %s\r\n"
10777                   "DND: %s\r\n"
10778                   "Alarm: %s\r\n"
10779                   "%s"
10780                   "\r\n",
10781                   dahdi_chan_name,
10782                   tmp->channel, sig2str(tmp->sig), tmp->context, 
10783                   tmp->dnd ? "Enabled" : "Disabled",
10784                   alarm2str(alarm), idText);
10785       } 
10786 
10787       tmp = tmp->next;
10788    }
10789 
10790    ast_mutex_unlock(&iflock);
10791    
10792    astman_append(s, 
10793             "Event: %sShowChannelsComplete\r\n"
10794             "%s"
10795             "\r\n",
10796             dahdi_chan_name,
10797             idText);
10798    return 0;
10799 }
10800 
10801 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10802 {
10803    return __action_showchannels(s, m, 1);
10804 }
10805 
10806 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10807 {
10808    return __action_showchannels(s, m, 0);
10809 }
10810 
10811 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10812 {
10813    if (dahdi_restart() != 0) {
10814       if (zap_mode) {
10815          astman_send_error(s, m, "Failed to restart Zap");
10816       } else {
10817          astman_send_error(s, m, "Failed to restart DAHDI");
10818       }
10819       return 1;
10820    }
10821    local_astman_ack(s, m, "Restart: Success", zap_mode);
10822    return 0;
10823 }
10824 
10825 static int zap_action_restart(struct mansession *s, const struct message *m)
10826 {
10827    return __action_restart(s, m, 1);
10828 }
10829 
10830 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10831 {
10832    return __action_restart(s, m, 0);
10833 }
10834 
10835 #define local_astman_unregister(a) do { \
10836                if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10837                   ast_manager_unregister("DAHDI" a); \
10838                } \
10839                ast_manager_unregister("Zap" a); \
10840                } while (0)
10841 
10842 static int __unload_module(void)
10843 {
10844    struct dahdi_pvt *p;
10845 
10846 #ifdef HAVE_PRI
10847    int i, j;
10848    for (i = 0; i < NUM_SPANS; i++) {
10849       if (pris[i].master != AST_PTHREADT_NULL) 
10850          pthread_cancel(pris[i].master);
10851    }
10852    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10853 
10854    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10855       ast_unregister_application(dahdi_send_keypad_facility_app);
10856    }
10857    ast_unregister_application(zap_send_keypad_facility_app);
10858 #endif
10859    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10860    local_astman_unregister("DialOffHook");
10861    local_astman_unregister("Hangup");
10862    local_astman_unregister("Transfer");
10863    local_astman_unregister("DNDoff");
10864    local_astman_unregister("DNDon");
10865    local_astman_unregister("ShowChannels");
10866    local_astman_unregister("Restart");
10867    ast_channel_unregister(chan_tech);
10868    ast_mutex_lock(&iflock);
10869    /* Hangup all interfaces if they have an owner */
10870    p = iflist;
10871    while (p) {
10872       if (p->owner)
10873          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10874       p = p->next;
10875    }
10876    ast_mutex_unlock(&iflock);
10877    ast_mutex_lock(&monlock);
10878    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10879       pthread_cancel(monitor_thread);
10880       pthread_kill(monitor_thread, SIGURG);
10881       pthread_join(monitor_thread, NULL);
10882    }
10883    monitor_thread = AST_PTHREADT_STOP;
10884    ast_mutex_unlock(&monlock);
10885 
10886    destroy_all_channels();
10887 #ifdef HAVE_PRI      
10888    for (i = 0; i < NUM_SPANS; i++) {
10889       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10890          pthread_join(pris[i].master, NULL);
10891       for (j = 0; j < NUM_DCHANS; j++) {
10892          dahdi_close_pri_fd(&(pris[i]), j);
10893       }
10894    }
10895 #endif
10896    ast_cond_destroy(&ss_thread_complete);
10897    return 0;
10898 }
10899 
10900 static int unload_module(void)
10901 {
10902 #ifdef HAVE_PRI      
10903    int y;
10904    for (y = 0; y < NUM_SPANS; y++)
10905       ast_mutex_destroy(&pris[y].lock);
10906 #endif
10907    return __unload_module();
10908 }
10909 
10910 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10911 {
10912    char *c, *chan;
10913    int x, start, finish;
10914    struct dahdi_pvt *tmp;
10915 #ifdef HAVE_PRI
10916    struct dahdi_pri *pri;
10917    int trunkgroup, y;
10918 #endif
10919    
10920    if ((reload == 0) && (conf->chan.sig < 0)) {
10921       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10922       return -1;
10923    }
10924 
10925    c = ast_strdupa(value);
10926 
10927 #ifdef HAVE_PRI
10928    pri = NULL;
10929    if (iscrv) {
10930       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10931          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10932          return -1;
10933       }
10934       if (trunkgroup < 1) {
10935          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10936          return -1;
10937       }
10938       c += y;
10939       for (y = 0; y < NUM_SPANS; y++) {
10940          if (pris[y].trunkgroup == trunkgroup) {
10941             pri = pris + y;
10942             break;
10943          }
10944       }
10945       if (!pri) {
10946          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10947          return -1;
10948       }
10949    }
10950 #endif         
10951 
10952    while ((chan = strsep(&c, ","))) {
10953       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10954          /* Range */
10955       } else if (sscanf(chan, "%d", &start)) {
10956          /* Just one */
10957          finish = start;
10958       } else if (!strcasecmp(chan, "pseudo")) {
10959          finish = start = CHAN_PSEUDO;
10960          if (found_pseudo)
10961             *found_pseudo = 1;
10962       } else {
10963          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10964          return -1;
10965       }
10966       if (finish < start) {
10967          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10968          x = finish;
10969          finish = start;
10970          start = x;
10971       }
10972 
10973       for (x = start; x <= finish; x++) {
10974 #ifdef HAVE_PRI
10975          tmp = mkintf(x, conf, pri, reload);
10976 #else       
10977          tmp = mkintf(x, conf, NULL, reload);
10978 #endif         
10979 
10980          if (tmp) {
10981             if (option_verbose > 2) {
10982 #ifdef HAVE_PRI
10983                if (pri)
10984                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10985                else
10986 #endif
10987                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10988             }
10989          } else {
10990             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10991                (reload == 1) ? "reconfigure" : "register", value);
10992             return -1;
10993          }
10994       }
10995    }
10996 
10997    return 0;
10998 }
10999 
11000 /** The length of the parameters list of 'dahdichan'. 
11001  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
11002 #define MAX_CHANLIST_LEN 80
11003 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
11004 {
11005    struct dahdi_pvt *tmp;
11006    int y;
11007    int found_pseudo = 0;
11008         char dahdichan[MAX_CHANLIST_LEN] = {};
11009 
11010    for (; v; v = v->next) {
11011       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11012          continue;
11013 
11014       /* Create the interface list */
11015       if (!strcasecmp(v->name, "channel")
11016 #ifdef HAVE_PRI
11017           || !strcasecmp(v->name, "crv")
11018 #endif         
11019          ) {
11020          int iscrv;
11021          if (skipchannels)
11022             continue;
11023          iscrv = !strcasecmp(v->name, "crv");
11024          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11025                return -1;
11026       } else if (!strcasecmp(v->name, "buffers")) {
11027          int res;
11028          char policy[8] = "";
11029          res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
11030          if (res != 2) {
11031             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11032             confp->chan.buf_no = numbufs;
11033             continue;
11034          }
11035          if (confp->chan.buf_no < 0)
11036             confp->chan.buf_no = numbufs;
11037          if (!strcasecmp(policy, "full")) {
11038             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11039          } else if (!strcasecmp(policy, "half")) {
11040             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /* TODO: change to HALF_FULL */;
11041          } else if (!strcasecmp(policy, "immediate")) {
11042             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11043          } else {
11044             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11045          }
11046       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11047          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11048          if (v->name[0] == 'z' || v->name[0] == 'Z') {
11049             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11050          }
11051       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11052          if (ast_true(v->value))
11053             confp->chan.usedistinctiveringdetection = 1;
11054       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11055          if (ast_true(v->value))
11056             distinctiveringaftercid = 1;
11057       } else if (!strcasecmp(v->name, "dring1context")) {
11058          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11059       } else if (!strcasecmp(v->name, "dring2context")) {
11060          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11061       } else if (!strcasecmp(v->name, "dring3context")) {
11062          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11063       } else if (!strcasecmp(v->name, "dring1")) {
11064          sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11065       } else if (!strcasecmp(v->name, "dring2")) {
11066          sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11067       } else if (!strcasecmp(v->name, "dring3")) {
11068          sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11069       } else if (!strcasecmp(v->name, "usecallerid")) {
11070          confp->chan.use_callerid = ast_true(v->value);
11071       } else if (!strcasecmp(v->name, "cidsignalling")) {
11072          if (!strcasecmp(v->value, "bell"))
11073             confp->chan.cid_signalling = CID_SIG_BELL;
11074          else if (!strcasecmp(v->value, "v23"))
11075             confp->chan.cid_signalling = CID_SIG_V23;
11076          else if (!strcasecmp(v->value, "dtmf"))
11077             confp->chan.cid_signalling = CID_SIG_DTMF;
11078          else if (!strcasecmp(v->value, "smdi"))
11079             confp->chan.cid_signalling = CID_SIG_SMDI;
11080          else if (!strcasecmp(v->value, "v23_jp"))
11081             confp->chan.cid_signalling = CID_SIG_V23_JP;
11082          else if (ast_true(v->value))
11083             confp->chan.cid_signalling = CID_SIG_BELL;
11084       } else if (!strcasecmp(v->name, "cidstart")) {
11085          if (!strcasecmp(v->value, "ring"))
11086             confp->chan.cid_start = CID_START_RING;
11087          else if (!strcasecmp(v->value, "polarity"))
11088             confp->chan.cid_start = CID_START_POLARITY;
11089          else if (ast_true(v->value))
11090             confp->chan.cid_start = CID_START_RING;
11091       } else if (!strcasecmp(v->name, "threewaycalling")) {
11092          confp->chan.threewaycalling = ast_true(v->value);
11093       } else if (!strcasecmp(v->name, "cancallforward")) {
11094          confp->chan.cancallforward = ast_true(v->value);
11095       } else if (!strcasecmp(v->name, "relaxdtmf")) {
11096          if (ast_true(v->value)) 
11097             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11098          else
11099             confp->chan.dtmfrelax = 0;
11100       } else if (!strcasecmp(v->name, "mailbox")) {
11101          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11102       } else if (!strcasecmp(v->name, "hasvoicemail")) {
11103          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11104             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11105          }
11106       } else if (!strcasecmp(v->name, "adsi")) {
11107          confp->chan.adsi = ast_true(v->value);
11108       } else if (!strcasecmp(v->name, "usesmdi")) {
11109          confp->chan.use_smdi = ast_true(v->value);
11110       } else if (!strcasecmp(v->name, "smdiport")) {
11111          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11112       } else if (!strcasecmp(v->name, "transfer")) {
11113          confp->chan.transfer = ast_true(v->value);
11114       } else if (!strcasecmp(v->name, "canpark")) {
11115          confp->chan.canpark = ast_true(v->value);
11116       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11117          confp->chan.echocanbridged = ast_true(v->value);
11118       } else if (!strcasecmp(v->name, "busydetect")) {
11119          confp->chan.busydetect = ast_true(v->value);
11120       } else if (!strcasecmp(v->name, "busycount")) {
11121          confp->chan.busycount = atoi(v->value);
11122       } else if (!strcasecmp(v->name, "silencethreshold")) {
11123          confp->chan.silencethreshold = atoi(v->value);
11124       } else if (!strcasecmp(v->name, "busycompare")) {
11125          confp->chan.busycompare = ast_true(v->value);
11126       } else if (!strcasecmp(v->name, "busypattern")) {
11127          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11128          if (count == 1)
11129             confp->chan.busyquietlength = 0;
11130          else if (count < 1)
11131             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11132       } else if (!strcasecmp(v->name, "busyfuzziness")) {
11133          confp->chan.busyfuzziness = atoi(v->value);
11134       } else if (!strcasecmp(v->name, "callprogress")) {
11135          if (ast_true(v->value))
11136             confp->chan.callprogress |= 1;
11137          else
11138             confp->chan.callprogress &= ~1;
11139       } else if (!strcasecmp(v->name, "faxdetect")) {
11140          if (!strcasecmp(v->value, "incoming")) {
11141             confp->chan.callprogress |= 4;
11142             confp->chan.callprogress &= ~2;
11143          } else if (!strcasecmp(v->value, "outgoing")) {
11144             confp->chan.callprogress &= ~4;
11145             confp->chan.callprogress |= 2;
11146          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11147             confp->chan.callprogress |= 6;
11148          else
11149             confp->chan.callprogress &= ~6;
11150       } else if (!strcasecmp(v->name, "echocancel")) {
11151          if (!ast_strlen_zero(v->value)) {
11152             y = atoi(v->value);
11153          } else
11154             y = 0;
11155          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11156             confp->chan.echocancel = y;
11157          else {
11158             confp->chan.echocancel = ast_true(v->value);
11159             if (confp->chan.echocancel)
11160                confp->chan.echocancel=128;
11161          }
11162       } else if (!strcasecmp(v->name, "echotraining")) {
11163          if (sscanf(v->value, "%d", &y) == 1) {
11164             if ((y < 10) || (y > 4000)) {
11165                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
11166             } else {
11167                confp->chan.echotraining = y;
11168             }
11169          } else if (ast_true(v->value)) {
11170             confp->chan.echotraining = 400;
11171          } else
11172             confp->chan.echotraining = 0;
11173       } else if (!strcasecmp(v->name, "hidecallerid")) {
11174          confp->chan.hidecallerid = ast_true(v->value);
11175       } else if (!strcasecmp(v->name, "hidecalleridname")) {
11176          confp->chan.hidecalleridname = ast_true(v->value);
11177       } else if (!strcasecmp(v->name, "pulsedial")) {
11178          confp->chan.pulse = ast_true(v->value);
11179       } else if (!strcasecmp(v->name, "callreturn")) {
11180          confp->chan.callreturn = ast_true(v->value);
11181       } else if (!strcasecmp(v->name, "callwaiting")) {
11182          confp->chan.callwaiting = ast_true(v->value);
11183       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11184          confp->chan.callwaitingcallerid = ast_true(v->value);
11185       } else if (!strcasecmp(v->name, "context")) {
11186          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11187       } else if (!strcasecmp(v->name, "language")) {
11188          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11189       } else if (!strcasecmp(v->name, "progzone")) {
11190          ast_copy_string(progzone, v->value, sizeof(progzone));
11191       } else if (!strcasecmp(v->name, "mohinterpret") 
11192          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11193          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11194       } else if (!strcasecmp(v->name, "mohsuggest")) {
11195          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11196       } else if (!strcasecmp(v->name, "stripmsd")) {
11197          confp->chan.stripmsd = atoi(v->value);
11198       } else if (!strcasecmp(v->name, "jitterbuffers")) {
11199          numbufs = atoi(v->value);
11200       } else if (!strcasecmp(v->name, "group")) {
11201          confp->chan.group = ast_get_group(v->value);
11202       } else if (!strcasecmp(v->name, "callgroup")) {
11203          confp->chan.callgroup = ast_get_group(v->value);
11204       } else if (!strcasecmp(v->name, "pickupgroup")) {
11205          confp->chan.pickupgroup = ast_get_group(v->value);
11206       } else if (!strcasecmp(v->name, "immediate")) {
11207          confp->chan.immediate = ast_true(v->value);
11208       } else if (!strcasecmp(v->name, "transfertobusy")) {
11209          confp->chan.transfertobusy = ast_true(v->value);
11210       } else if (!strcasecmp(v->name, "rxgain")) {
11211          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11212             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11213          }
11214       } else if (!strcasecmp(v->name, "txgain")) {
11215          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11216             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11217          }
11218       } else if (!strcasecmp(v->name, "tonezone")) {
11219          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11220             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11221          }
11222       } else if (!strcasecmp(v->name, "callerid")) {
11223          if (!strcasecmp(v->value, "asreceived")) {
11224             confp->chan.cid_num[0] = '\0';
11225             confp->chan.cid_name[0] = '\0';
11226          } else {
11227             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11228          } 
11229       } else if (!strcasecmp(v->name, "fullname")) {
11230          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11231       } else if (!strcasecmp(v->name, "cid_number")) {
11232          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11233       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11234          confp->chan.dahditrcallerid = ast_true(v->value);
11235          if (strstr(v->name, "zap")) {
11236             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11237          }
11238       } else if (!strcasecmp(v->name, "restrictcid")) {
11239          confp->chan.restrictcid = ast_true(v->value);
11240       } else if (!strcasecmp(v->name, "usecallingpres")) {
11241          confp->chan.use_callingpres = ast_true(v->value);
11242       } else if (!strcasecmp(v->name, "accountcode")) {
11243          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11244       } else if (!strcasecmp(v->name, "amaflags")) {
11245          y = ast_cdr_amaflags2int(v->value);
11246          if (y < 0) 
11247             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11248          else
11249             confp->chan.amaflags = y;
11250       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11251          confp->chan.polarityonanswerdelay = atoi(v->value);
11252       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11253          confp->chan.answeronpolarityswitch = ast_true(v->value);
11254       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11255          confp->chan.hanguponpolarityswitch = ast_true(v->value);
11256       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11257          confp->chan.sendcalleridafter = atoi(v->value);
11258       } else if (reload != 1){ 
11259           if (!strcasecmp(v->name, "signalling")) {
11260             confp->chan.outsigmod = -1;
11261             if (!strcasecmp(v->value, "em")) {
11262                confp->chan.sig = SIG_EM;
11263             } else if (!strcasecmp(v->value, "em_e1")) {
11264                confp->chan.sig = SIG_EM_E1;
11265             } else if (!strcasecmp(v->value, "em_w")) {
11266                confp->chan.sig = SIG_EMWINK;
11267                confp->chan.radio = 0;
11268             } else if (!strcasecmp(v->value, "fxs_ls")) {
11269                confp->chan.sig = SIG_FXSLS;
11270                confp->chan.radio = 0;
11271             } else if (!strcasecmp(v->value, "fxs_gs")) {
11272                confp->chan.sig = SIG_FXSGS;
11273                confp->chan.radio = 0;
11274             } else if (!strcasecmp(v->value, "fxs_ks")) {
11275                confp->chan.sig = SIG_FXSKS;
11276                confp->chan.radio = 0;
11277             } else if (!strcasecmp(v->value, "fxo_ls")) {
11278                confp->chan.sig = SIG_FXOLS;
11279                confp->chan.radio = 0;
11280             } else if (!strcasecmp(v->value, "fxo_gs")) {
11281                confp->chan.sig = SIG_FXOGS;
11282                confp->chan.radio = 0;
11283             } else if (!strcasecmp(v->value, "fxo_ks")) {
11284                confp->chan.sig = SIG_FXOKS;
11285                confp->chan.radio = 0;
11286             } else if (!strcasecmp(v->value, "fxs_rx")) {
11287                confp->chan.sig = SIG_FXSKS;
11288                confp->chan.radio = 1;
11289             } else if (!strcasecmp(v->value, "fxo_rx")) {
11290                confp->chan.sig = SIG_FXOLS;
11291                confp->chan.radio = 1;
11292             } else if (!strcasecmp(v->value, "fxs_tx")) {
11293                confp->chan.sig = SIG_FXSLS;
11294                confp->chan.radio = 1;
11295             } else if (!strcasecmp(v->value, "fxo_tx")) {
11296                confp->chan.sig = SIG_FXOGS;
11297                confp->chan.radio = 1;
11298             } else if (!strcasecmp(v->value, "em_rx")) {
11299                confp->chan.sig = SIG_EM;
11300                confp->chan.radio = 1;
11301             } else if (!strcasecmp(v->value, "em_tx")) {
11302                confp->chan.sig = SIG_EM;
11303                confp->chan.radio = 1;
11304             } else if (!strcasecmp(v->value, "em_rxtx")) {
11305                confp->chan.sig = SIG_EM;
11306                confp->chan.radio = 2;
11307             } else if (!strcasecmp(v->value, "em_txrx")) {
11308                confp->chan.sig = SIG_EM;
11309                confp->chan.radio = 2;
11310             } else if (!strcasecmp(v->value, "sf")) {
11311                confp->chan.sig = SIG_SF;
11312                confp->chan.radio = 0;
11313             } else if (!strcasecmp(v->value, "sf_w")) {
11314                confp->chan.sig = SIG_SFWINK;
11315                confp->chan.radio = 0;
11316             } else if (!strcasecmp(v->value, "sf_featd")) {
11317                confp->chan.sig = SIG_FEATD;
11318                confp->chan.radio = 0;
11319             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11320                confp->chan.sig = SIG_FEATDMF;
11321                confp->chan.radio = 0;
11322             } else if (!strcasecmp(v->value, "sf_featb")) {
11323                confp->chan.sig = SIG_SF_FEATB;
11324                confp->chan.radio = 0;
11325             } else if (!strcasecmp(v->value, "sf")) {
11326                confp->chan.sig = SIG_SF;
11327                confp->chan.radio = 0;
11328             } else if (!strcasecmp(v->value, "sf_rx")) {
11329                confp->chan.sig = SIG_SF;
11330                confp->chan.radio = 1;
11331             } else if (!strcasecmp(v->value, "sf_tx")) {
11332                confp->chan.sig = SIG_SF;
11333                confp->chan.radio = 1;
11334             } else if (!strcasecmp(v->value, "sf_rxtx")) {
11335                confp->chan.sig = SIG_SF;
11336                confp->chan.radio = 2;
11337             } else if (!strcasecmp(v->value, "sf_txrx")) {
11338                confp->chan.sig = SIG_SF;
11339                confp->chan.radio = 2;
11340             } else if (!strcasecmp(v->value, "featd")) {
11341                confp->chan.sig = SIG_FEATD;
11342                confp->chan.radio = 0;
11343             } else if (!strcasecmp(v->value, "featdmf")) {
11344                confp->chan.sig = SIG_FEATDMF;
11345                confp->chan.radio = 0;
11346             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11347                confp->chan.sig = SIG_FEATDMF_TA;
11348                confp->chan.radio = 0;
11349             } else if (!strcasecmp(v->value, "e911")) {
11350                confp->chan.sig = SIG_E911;
11351                confp->chan.radio = 0;
11352             } else if (!strcasecmp(v->value, "fgccama")) {
11353                confp->chan.sig = SIG_FGC_CAMA;
11354                confp->chan.radio = 0;
11355             } else if (!strcasecmp(v->value, "fgccamamf")) {
11356                confp->chan.sig = SIG_FGC_CAMAMF;
11357                confp->chan.radio = 0;
11358             } else if (!strcasecmp(v->value, "featb")) {
11359                confp->chan.sig = SIG_FEATB;
11360                confp->chan.radio = 0;
11361 #ifdef HAVE_PRI
11362             } else if (!strcasecmp(v->value, "pri_net")) {
11363                confp->chan.radio = 0;
11364                confp->chan.sig = SIG_PRI;
11365                confp->pri.nodetype = PRI_NETWORK;
11366             } else if (!strcasecmp(v->value, "pri_cpe")) {
11367                confp->chan.sig = SIG_PRI;
11368                confp->chan.radio = 0;
11369                confp->pri.nodetype = PRI_CPE;
11370             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11371                confp->chan.sig = SIG_GR303FXOKS;
11372                confp->chan.radio = 0;
11373                confp->pri.nodetype = PRI_NETWORK;
11374             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11375                confp->chan.sig = SIG_GR303FXSKS;
11376                confp->chan.radio = 0;
11377                confp->pri.nodetype = PRI_CPE;
11378 #endif
11379             } else {
11380                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11381             }
11382           } else if (!strcasecmp(v->name, "outsignalling")) {
11383             if (!strcasecmp(v->value, "em")) {
11384                confp->chan.outsigmod = SIG_EM;
11385             } else if (!strcasecmp(v->value, "em_e1")) {
11386                confp->chan.outsigmod = SIG_EM_E1;
11387             } else if (!strcasecmp(v->value, "em_w")) {
11388                confp->chan.outsigmod = SIG_EMWINK;
11389             } else if (!strcasecmp(v->value, "sf")) {
11390                confp->chan.outsigmod = SIG_SF;
11391             } else if (!strcasecmp(v->value, "sf_w")) {
11392                confp->chan.outsigmod = SIG_SFWINK;
11393             } else if (!strcasecmp(v->value, "sf_featd")) {
11394                confp->chan.outsigmod = SIG_FEATD;
11395             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11396                confp->chan.outsigmod = SIG_FEATDMF;
11397             } else if (!strcasecmp(v->value, "sf_featb")) {
11398                confp->chan.outsigmod = SIG_SF_FEATB;
11399             } else if (!strcasecmp(v->value, "sf")) {
11400                confp->chan.outsigmod = SIG_SF;
11401             } else if (!strcasecmp(v->value, "featd")) {
11402                confp->chan.outsigmod = SIG_FEATD;
11403             } else if (!strcasecmp(v->value, "featdmf")) {
11404                confp->chan.outsigmod = SIG_FEATDMF;
11405             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11406                confp->chan.outsigmod = SIG_FEATDMF_TA;
11407             } else if (!strcasecmp(v->value, "e911")) {
11408                confp->chan.outsigmod = SIG_E911;
11409             } else if (!strcasecmp(v->value, "fgccama")) {
11410                confp->chan.outsigmod = SIG_FGC_CAMA;
11411             } else if (!strcasecmp(v->value, "fgccamamf")) {
11412                confp->chan.outsigmod = SIG_FGC_CAMAMF;
11413             } else if (!strcasecmp(v->value, "featb")) {
11414                confp->chan.outsigmod = SIG_FEATB;
11415             } else {
11416                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11417             }
11418 #ifdef HAVE_PRI
11419          } else if (!strcasecmp(v->name, "pridialplan")) {
11420             if (!strcasecmp(v->value, "national")) {
11421                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11422             } else if (!strcasecmp(v->value, "unknown")) {
11423                confp->pri.dialplan = PRI_UNKNOWN + 1;
11424             } else if (!strcasecmp(v->value, "private")) {
11425                confp->pri.dialplan = PRI_PRIVATE + 1;
11426             } else if (!strcasecmp(v->value, "international")) {
11427                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11428             } else if (!strcasecmp(v->value, "local")) {
11429                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11430             } else if (!strcasecmp(v->value, "dynamic")) {
11431                confp->pri.dialplan = -1;
11432             } else {
11433                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11434             }
11435          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11436             if (!strcasecmp(v->value, "national")) {
11437                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11438             } else if (!strcasecmp(v->value, "unknown")) {
11439                confp->pri.localdialplan = PRI_UNKNOWN + 1;
11440             } else if (!strcasecmp(v->value, "private")) {
11441                confp->pri.localdialplan = PRI_PRIVATE + 1;
11442             } else if (!strcasecmp(v->value, "international")) {
11443                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11444             } else if (!strcasecmp(v->value, "local")) {
11445                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11446             } else if (!strcasecmp(v->value, "dynamic")) {
11447                confp->pri.localdialplan = -1;
11448             } else {
11449                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11450             }
11451          } else if (!strcasecmp(v->name, "switchtype")) {
11452             if (!strcasecmp(v->value, "national")) 
11453                confp->pri.switchtype = PRI_SWITCH_NI2;
11454             else if (!strcasecmp(v->value, "ni1"))
11455                confp->pri.switchtype = PRI_SWITCH_NI1;
11456             else if (!strcasecmp(v->value, "dms100"))
11457                confp->pri.switchtype = PRI_SWITCH_DMS100;
11458             else if (!strcasecmp(v->value, "4ess"))
11459                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11460             else if (!strcasecmp(v->value, "5ess"))
11461                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11462             else if (!strcasecmp(v->value, "euroisdn"))
11463                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11464             else if (!strcasecmp(v->value, "qsig"))
11465                confp->pri.switchtype = PRI_SWITCH_QSIG;
11466             else {
11467                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11468                return -1;
11469             }
11470          } else if (!strcasecmp(v->name, "nsf")) {
11471             if (!strcasecmp(v->value, "sdn"))
11472                confp->pri.nsf = PRI_NSF_SDN;
11473             else if (!strcasecmp(v->value, "megacom"))
11474                confp->pri.nsf = PRI_NSF_MEGACOM;
11475             else if (!strcasecmp(v->value, "tollfreemegacom"))
11476                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
11477             else if (!strcasecmp(v->value, "accunet"))
11478                confp->pri.nsf = PRI_NSF_ACCUNET;
11479             else if (!strcasecmp(v->value, "none"))
11480                confp->pri.nsf = PRI_NSF_NONE;
11481             else {
11482                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11483                confp->pri.nsf = PRI_NSF_NONE;
11484             }
11485          } else if (!strcasecmp(v->name, "priindication")) {
11486             if (!strcasecmp(v->value, "outofband"))
11487                confp->chan.priindication_oob = 1;
11488             else if (!strcasecmp(v->value, "inband"))
11489                confp->chan.priindication_oob = 0;
11490             else
11491                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11492                   v->value, v->lineno);
11493          } else if (!strcasecmp(v->name, "priexclusive")) {
11494             confp->chan.priexclusive = ast_true(v->value);
11495          } else if (!strcasecmp(v->name, "internationalprefix")) {
11496             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11497          } else if (!strcasecmp(v->name, "nationalprefix")) {
11498             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11499          } else if (!strcasecmp(v->name, "localprefix")) {
11500             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11501          } else if (!strcasecmp(v->name, "privateprefix")) {
11502             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11503          } else if (!strcasecmp(v->name, "unknownprefix")) {
11504             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11505          } else if (!strcasecmp(v->name, "resetinterval")) {
11506             if (!strcasecmp(v->value, "never"))
11507                confp->pri.resetinterval = -1;
11508             else if (atoi(v->value) >= 60)
11509                confp->pri.resetinterval = atoi(v->value);
11510             else
11511                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11512                   v->value, v->lineno);
11513          } else if (!strcasecmp(v->name, "minunused")) {
11514             confp->pri.minunused = atoi(v->value);
11515          } else if (!strcasecmp(v->name, "minidle")) {
11516             confp->pri.minidle = atoi(v->value); 
11517          } else if (!strcasecmp(v->name, "idleext")) {
11518             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11519          } else if (!strcasecmp(v->name, "idledial")) {
11520             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11521          } else if (!strcasecmp(v->name, "overlapdial")) {
11522             confp->pri.overlapdial = ast_true(v->value);
11523 #ifdef HAVE_PRI_INBANDDISCONNECT
11524          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11525             confp->pri.inbanddisconnect = ast_true(v->value);
11526 #endif
11527          } else if (!strcasecmp(v->name, "pritimer")) {
11528 #ifdef PRI_GETSET_TIMERS
11529             char *timerc, *c;
11530             int timer, timeridx;
11531             c = v->value;
11532             timerc = strsep(&c, ",");
11533             if (timerc) {
11534                timer = atoi(c);
11535                if (!timer)
11536                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11537                else {
11538                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
11539                      pritimers[timeridx] = timer;
11540                   else
11541                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11542                }
11543             } else
11544                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11545 
11546          } else if (!strcasecmp(v->name, "facilityenable")) {
11547             confp->pri.facilityenable = ast_true(v->value);
11548 #endif /* PRI_GETSET_TIMERS */
11549 #endif /* HAVE_PRI */
11550          } else if (!strcasecmp(v->name, "cadence")) {
11551             /* setup to scan our argument */
11552             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11553             int i;
11554             struct dahdi_ring_cadence new_cadence;
11555             int cid_location = -1;
11556             int firstcadencepos = 0;
11557             char original_args[80];
11558             int cadence_is_ok = 1;
11559 
11560             ast_copy_string(original_args, v->value, sizeof(original_args));
11561             /* 16 cadences allowed (8 pairs) */
11562             element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
11563    
11564             /* Cadence must be even (on/off) */
11565             if (element_count % 2 == 1) {
11566                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11567                cadence_is_ok = 0;
11568             }
11569    
11570             /* Ring cadences cannot be negative */
11571             for (i = 0; i < element_count; i++) {
11572                if (c[i] == 0) {
11573                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11574                   cadence_is_ok = 0;
11575                   break;
11576                } else if (c[i] < 0) {
11577                   if (i % 2 == 1) {
11578                      /* Silence duration, negative possibly okay */
11579                      if (cid_location == -1) {
11580                         cid_location = i;
11581                         c[i] *= -1;
11582                      } else {
11583                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11584                         cadence_is_ok = 0;
11585                         break;
11586                      }
11587                   } else {
11588                      if (firstcadencepos == 0) {
11589                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
11590                                  /* duration will be passed negative to the DAHDI driver */
11591                      } else {
11592                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11593                         cadence_is_ok = 0;
11594                         break;
11595                      }
11596                   }
11597                }
11598             }
11599    
11600             /* Substitute our scanned cadence */
11601             for (i = 0; i < 16; i++) {
11602                new_cadence.ringcadence[i] = c[i];
11603             }
11604    
11605             if (cadence_is_ok) {
11606                /* ---we scanned it without getting annoyed; now some sanity checks--- */
11607                if (element_count < 2) {
11608                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11609                } else {
11610                   if (cid_location == -1) {
11611                      /* user didn't say; default to first pause */
11612                      cid_location = 1;
11613                   } else {
11614                      /* convert element_index to cidrings value */
11615                      cid_location = (cid_location + 1) / 2;
11616                   }
11617                   /* ---we like their cadence; try to install it--- */
11618                   if (!user_has_defined_cadences++)
11619                      /* this is the first user-defined cadence; clear the default user cadences */
11620                      num_cadence = 0;
11621                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
11622                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11623                   else {
11624                      cadences[num_cadence] = new_cadence;
11625                      cidrings[num_cadence++] = cid_location;
11626                      if (option_verbose > 2)
11627                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11628                   }
11629                }
11630             }
11631          } else if (!strcasecmp(v->name, "ringtimeout")) {
11632             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11633          } else if (!strcasecmp(v->name, "prewink")) {
11634             confp->timing.prewinktime = atoi(v->value);
11635          } else if (!strcasecmp(v->name, "preflash")) {
11636             confp->timing.preflashtime = atoi(v->value);
11637          } else if (!strcasecmp(v->name, "wink")) {
11638             confp->timing.winktime = atoi(v->value);
11639          } else if (!strcasecmp(v->name, "flash")) {
11640             confp->timing.flashtime = atoi(v->value);
11641          } else if (!strcasecmp(v->name, "start")) {
11642             confp->timing.starttime = atoi(v->value);
11643          } else if (!strcasecmp(v->name, "rxwink")) {
11644             confp->timing.rxwinktime = atoi(v->value);
11645          } else if (!strcasecmp(v->name, "rxflash")) {
11646             confp->timing.rxflashtime = atoi(v->value);
11647          } else if (!strcasecmp(v->name, "debounce")) {
11648             confp->timing.debouncetime = atoi(v->value);
11649          } else if (!strcasecmp(v->name, "toneduration")) {
11650             int toneduration;
11651             int ctlfd;
11652             int res;
11653             struct dahdi_dialparams dps;
11654 
11655 #ifdef HAVE_ZAPTEL
11656             ctlfd = open("/dev/zap/ctl", O_RDWR);
11657 #else
11658             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11659 #endif
11660 
11661             if (ctlfd == -1) {
11662                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11663                return -1;
11664             }
11665 
11666             toneduration = atoi(v->value);
11667             if (toneduration > -1) {
11668                memset(&dps, 0, sizeof(dps));
11669 
11670                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11671                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11672                if (res < 0) {
11673                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11674                   return -1;
11675                }
11676             }
11677             close(ctlfd);
11678          } else if (!strcasecmp(v->name, "defaultcic")) {
11679             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11680          } else if (!strcasecmp(v->name, "defaultozz")) {
11681             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11682          } 
11683       } else if (!skipchannels)
11684          ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11685    }
11686    if (dahdichan[0]) { 
11687       /* The user has set 'dahdichan' */
11688       /*< \todo pass proper line number instead of 0 */
11689       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11690          return -1;
11691       }
11692    }
11693    /*< \todo why check for the pseudo in the per-channel section.
11694     * Any actual use for manual setup of the pseudo channel? */
11695    if (!found_pseudo && reload == 0) {
11696       /* Make sure pseudo isn't a member of any groups if
11697          we're automatically making it. */   
11698       
11699       confp->chan.group = 0;
11700       confp->chan.callgroup = 0;
11701       confp->chan.pickupgroup = 0;
11702 
11703       tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11704 
11705       if (tmp) {
11706          if (option_verbose > 2)
11707             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11708       } else {
11709          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11710       }
11711    }
11712    return 0;
11713 }
11714       
11715 static int setup_dahdi(int reload)
11716 {
11717    struct ast_config *cfg;
11718    struct ast_variable *v;
11719    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11720    int res;
11721 
11722 #ifdef HAVE_PRI
11723    char *c;
11724    int spanno;
11725    int i, x;
11726    int logicalspan;
11727    int trunkgroup;
11728    int dchannels[NUM_DCHANS];
11729 #endif
11730 
11731 #ifdef HAVE_ZAPTEL
11732    int load_from_zapata_conf = 1;
11733 #else
11734    int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11735 #endif
11736 
11737    if (load_from_zapata_conf) {
11738       if (!(cfg = ast_config_load("zapata.conf"))) {
11739          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11740          return 0;
11741       }
11742    } else {
11743       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11744          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11745          return 0;
11746       }
11747    }
11748 
11749    /* It's a little silly to lock it, but we mind as well just to be sure */
11750    ast_mutex_lock(&iflock);
11751 #ifdef HAVE_PRI
11752    if (reload != 1) {
11753       /* Process trunkgroups first */
11754       v = ast_variable_browse(cfg, "trunkgroups");
11755       while (v) {
11756          if (!strcasecmp(v->name, "trunkgroup")) {
11757             trunkgroup = atoi(v->value);
11758             if (trunkgroup > 0) {
11759                if ((c = strchr(v->value, ','))) {
11760                   i = 0;
11761                   memset(dchannels, 0, sizeof(dchannels));
11762                   while (c && (i < NUM_DCHANS)) {
11763                      dchannels[i] = atoi(c + 1);
11764                      if (dchannels[i] < 0) {
11765                         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);
11766                      } else
11767                         i++;
11768                      c = strchr(c + 1, ',');
11769                   }
11770                   if (i) {
11771                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11772                         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);
11773                      } else if (option_verbose > 1)
11774                         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");
11775                   } else
11776                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11777                } else
11778                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11779             } else
11780                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11781          } else if (!strcasecmp(v->name, "spanmap")) {
11782             spanno = atoi(v->value);
11783             if (spanno > 0) {
11784                if ((c = strchr(v->value, ','))) {
11785                   trunkgroup = atoi(c + 1);
11786                   if (trunkgroup > 0) {
11787                      if ((c = strchr(c + 1, ','))) 
11788                         logicalspan = atoi(c + 1);
11789                      else
11790                         logicalspan = 0;
11791                      if (logicalspan >= 0) {
11792                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11793                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11794                         } else if (option_verbose > 1) 
11795                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11796                      } else
11797                         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);
11798                   } else
11799                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11800                } else
11801                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11802             } else
11803                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11804          } else {
11805             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11806          }
11807          v = v->next;
11808       }
11809    }
11810 #endif
11811    
11812    /* Copy the default jb config over global_jbconf */
11813    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11814 
11815    v = ast_variable_browse(cfg, "channels");
11816    res = process_dahdi(&conf, "", v, reload, 0);
11817    ast_mutex_unlock(&iflock);
11818    ast_config_destroy(cfg);
11819    if (res)
11820       return res;
11821    cfg = ast_config_load("users.conf");
11822    if (cfg) {
11823       char *cat;
11824       const char *chans;
11825       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11826       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11827          if (!strcasecmp(cat, "general"))
11828             continue;
11829          chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11830          if (!ast_strlen_zero(chans)) {
11831             struct dahdi_chan_conf sect_conf;
11832             memcpy(&sect_conf, &conf, sizeof(sect_conf));
11833 
11834             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11835          }
11836       }
11837       ast_config_destroy(cfg);
11838    }
11839 #ifdef HAVE_PRI
11840    if (reload != 1) {
11841       for (x = 0; x < NUM_SPANS; x++) {
11842          if (pris[x].pvts[0]) {
11843             if (start_pri(pris + x)) {
11844                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11845                return -1;
11846             } else if (option_verbose > 1)
11847                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11848          }
11849       }
11850    }
11851 #endif
11852    /* And start the monitor for the first time */
11853    restart_monitor();
11854    return 0;
11855 }
11856 
11857 #define local_astman_register(a, b, c, d) do { \
11858                   if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11859                      ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11860                   } \
11861                   ast_manager_register("Zap" a, b, zap_ ## c, d); \
11862                  } while (0)
11863 
11864 static int load_module(void)
11865 {
11866    int res;
11867 
11868 #ifdef HAVE_PRI
11869    int y,i;
11870    memset(pris, 0, sizeof(pris));
11871    for (y = 0; y < NUM_SPANS; y++) {
11872       ast_mutex_init(&pris[y].lock);
11873       pris[y].offset = -1;
11874       pris[y].master = AST_PTHREADT_NULL;
11875       for (i = 0; i < NUM_DCHANS; i++)
11876          pris[y].fds[i] = -1;
11877    }
11878    pri_set_error(dahdi_pri_error);
11879    pri_set_message(dahdi_pri_message);
11880    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11881       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11882          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11883    }
11884    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11885       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11886 #endif
11887    if ((res = setup_dahdi(0))) {
11888       return AST_MODULE_LOAD_DECLINE;
11889    }
11890    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11891       chan_tech = &dahdi_tech;
11892    } else {
11893       chan_tech = &zap_tech;
11894    }
11895    if (ast_channel_register(chan_tech)) {
11896       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11897       __unload_module();
11898       return -1;
11899    }
11900 #ifdef HAVE_PRI
11901    ast_string_field_init(&inuse, 16);
11902    ast_string_field_set(&inuse, name, "GR-303InUse");
11903    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11904 #endif   
11905    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11906    
11907    memset(round_robin, 0, sizeof(round_robin));
11908    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11909    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11910    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11911    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11912    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11913    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11914    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11915 
11916    ast_cond_init(&ss_thread_complete, NULL);
11917 
11918    return res;
11919 }
11920 
11921 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11922 {
11923 #define  END_SILENCE_LEN 400
11924 #define  HEADER_MS 50
11925 #define  TRAILER_MS 5
11926 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11927 #define  ASCII_BYTES_PER_CHAR 80
11928 
11929    unsigned char *buf,*mybuf;
11930    struct dahdi_pvt *p = c->tech_pvt;
11931    struct pollfd fds[1];
11932    int size,res,fd,len,x;
11933    int bytes=0;
11934    /* Initial carrier (imaginary) */
11935    float cr = 1.0;
11936    float ci = 0.0;
11937    float scont = 0.0;
11938    int index;
11939 
11940    index = dahdi_get_index(c, p, 0);
11941    if (index < 0) {
11942       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
11943       return -1;
11944    }
11945    if (!text[0]) return(0); /* if nothing to send, dont */
11946    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
11947    if (p->mate) 
11948       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11949    else
11950       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11951    if (!buf)
11952       return -1;
11953    mybuf = buf;
11954    if (p->mate) {
11955       int codec = AST_LAW(p);
11956       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
11957          PUT_CLID_MARKMS;
11958       }
11959       /* Put actual message */
11960       for (x = 0; text[x]; x++) {
11961          PUT_CLID(text[x]);
11962       }
11963       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
11964          PUT_CLID_MARKMS;
11965       }
11966       len = bytes;
11967       buf = mybuf;
11968    } else {
11969       len = tdd_generate(p->tdd, buf, text);
11970       if (len < 1) {
11971          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11972          free(mybuf);
11973          return -1;
11974       }
11975    }
11976    memset(buf + len, 0x7f, END_SILENCE_LEN);
11977    len += END_SILENCE_LEN;
11978    fd = p->subs[index].dfd;
11979    while (len) {
11980       if (ast_check_hangup(c)) {
11981          free(mybuf);
11982          return -1;
11983       }
11984       size = len;
11985       if (size > READ_SIZE)
11986          size = READ_SIZE;
11987       fds[0].fd = fd;
11988       fds[0].events = POLLOUT | POLLPRI;
11989       fds[0].revents = 0;
11990       res = poll(fds, 1, -1);
11991       if (!res) {
11992          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11993          continue;
11994       }
11995         /* if got exception */
11996       if (fds[0].revents & POLLPRI) {
11997          ast_free(mybuf);
11998          return -1;
11999       }
12000       if (!(fds[0].revents & POLLOUT)) {
12001          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12002          continue;
12003       }
12004       res = write(fd, buf, size);
12005       if (res != size) {
12006          if (res == -1) {
12007             free(mybuf);
12008             return -1;
12009          }
12010          if (option_debug)
12011             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12012          break;
12013       }
12014       len -= size;
12015       buf += size;
12016    }
12017    free(mybuf);
12018    return(0);
12019 }
12020 
12021 
12022 static int reload(void)
12023 {
12024    int res = 0;
12025 
12026    res = setup_dahdi(1);
12027    if (res) {
12028       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12029       return -1;
12030    }
12031    return 0;
12032 }
12033 
12034 /* This is a workaround so that menuselect displays a proper description
12035  * AST_MODULE_INFO(, , "DAHDI Telephony"
12036  */
12037 
12038 #ifdef DAHDI_PRI
12039 #define tdesc "DAHDI Telephony w/PRI"
12040 #else
12041 #define tdesc "DAHDI Telephony"
12042 #endif
12043 
12044 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12045       .load = load_module,
12046       .unload = unload_module,
12047       .reload = reload,
12048           );
12049 
12050 

Generated on Mon Nov 24 15:34:14 2008 for Asterisk - the Open Source PBX by  doxygen 1.4.7