Wed Mar 3 22:36:05 2010

Asterisk developer's documentation


chan_dahdi.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief DAHDI for Pseudo TDM
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    <use>pri</use>
00045    <use>ss7</use>
00046  ***/
00047 
00048 #include "asterisk.h"
00049 
00050 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211569 $")
00051 
00052 #ifdef __NetBSD__
00053 #include <pthread.h>
00054 #include <signal.h>
00055 #else
00056 #include <sys/signal.h>
00057 #endif
00058 #include <sys/ioctl.h>
00059 #include <math.h>
00060 #include <ctype.h>
00061 
00062 #include <dahdi/user.h>
00063 #include <dahdi/tonezone.h>
00064 
00065 #ifdef HAVE_PRI
00066 #include <libpri.h>
00067 #endif
00068 
00069 #ifdef HAVE_SS7
00070 #include <libss7.h>
00071 #endif
00072 
00073 #include "asterisk/lock.h"
00074 #include "asterisk/channel.h"
00075 #include "asterisk/config.h"
00076 #include "asterisk/module.h"
00077 #include "asterisk/pbx.h"
00078 #include "asterisk/file.h"
00079 #include "asterisk/ulaw.h"
00080 #include "asterisk/alaw.h"
00081 #include "asterisk/callerid.h"
00082 #include "asterisk/adsi.h"
00083 #include "asterisk/cli.h"
00084 #include "asterisk/cdr.h"
00085 #include "asterisk/features.h"
00086 #include "asterisk/musiconhold.h"
00087 #include "asterisk/say.h"
00088 #include "asterisk/tdd.h"
00089 #include "asterisk/app.h"
00090 #include "asterisk/dsp.h"
00091 #include "asterisk/astdb.h"
00092 #include "asterisk/manager.h"
00093 #include "asterisk/causes.h"
00094 #include "asterisk/term.h"
00095 #include "asterisk/utils.h"
00096 #include "asterisk/transcap.h"
00097 #include "asterisk/stringfields.h"
00098 #include "asterisk/abstract_jb.h"
00099 #include "asterisk/smdi.h"
00100 #include "asterisk/astobj.h"
00101 #include "asterisk/event.h"
00102 #include "asterisk/devicestate.h"
00103 
00104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
00105 
00106 static const char *lbostr[] = {
00107 "0 db (CSU)/0-133 feet (DSX-1)",
00108 "133-266 feet (DSX-1)",
00109 "266-399 feet (DSX-1)",
00110 "399-533 feet (DSX-1)",
00111 "533-655 feet (DSX-1)",
00112 "-7.5db (CSU)",
00113 "-15db (CSU)",
00114 "-22.5db (CSU)"
00115 };
00116 
00117 /*! Global jitterbuffer configuration - by default, jb is disabled */
00118 static struct ast_jb_conf default_jbconf =
00119 {
00120    .flags = 0,
00121    .max_size = -1,
00122    .resync_threshold = -1,
00123    .impl = ""
00124 };
00125 static struct ast_jb_conf global_jbconf;
00126 
00127 /* define this to send PRI user-user information elements */
00128 #undef SUPPORT_USERUSER
00129 
00130 /*! 
00131  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
00132  * the user hangs up to reset the state machine so ring works properly.
00133  * This is used to be able to support kewlstart by putting the zhone in
00134  * groundstart mode since their forward disconnect supervision is entirely
00135  * broken even though their documentation says it isn't and their support
00136  * is entirely unwilling to provide any assistance with their channel banks
00137  * even though their web site says they support their products for life.
00138  */
00139 /* #define ZHONE_HACK */
00140 
00141 /*! \note
00142  * Define if you want to check the hook state for an FXO (FXS signalled) interface
00143  * before dialing on it.  Certain FXO interfaces always think they're out of
00144  * service with this method however.
00145  */
00146 /* #define DAHDI_CHECK_HOOKSTATE */
00147 
00148 /*! \brief Typically, how many rings before we should send Caller*ID */
00149 #define DEFAULT_CIDRINGS 1
00150 
00151 #define CHANNEL_PSEUDO -12
00152 
00153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00154 
00155 
00156 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
00157 #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)) 
00158 
00159 static const char tdesc[] = "DAHDI Telephony Driver"
00160 #ifdef HAVE_PRI
00161                " w/PRI"
00162 #endif
00163 #ifdef HAVE_SS7
00164           " w/SS7"
00165 #endif
00166 ;
00167 
00168 static const char config[] = "chan_dahdi.conf";
00169 
00170 #define SIG_EM    DAHDI_SIG_EM
00171 #define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
00172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00173 #define  SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00174 #define  SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
00175 #define  SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00176 #define  SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00177 #define  SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
00178 #define  SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00179 #define SIG_FXSLS DAHDI_SIG_FXSLS
00180 #define SIG_FXSGS DAHDI_SIG_FXSGS
00181 #define SIG_FXSKS DAHDI_SIG_FXSKS
00182 #define SIG_FXOLS DAHDI_SIG_FXOLS
00183 #define SIG_FXOGS DAHDI_SIG_FXOGS
00184 #define SIG_FXOKS DAHDI_SIG_FXOKS
00185 #define SIG_PRI      DAHDI_SIG_CLEAR
00186 #define SIG_BRI      (0x2000000 | DAHDI_SIG_CLEAR)
00187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00188 #define SIG_SS7      (0x1000000 | DAHDI_SIG_CLEAR)
00189 #define  SIG_SF      DAHDI_SIG_SF
00190 #define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
00191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00192 #define  SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00193 #define  SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
00194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00195 #define SIG_GR303FXOKS  (0x0100000 | DAHDI_SIG_FXOKS)
00196 #define SIG_GR303FXSKS  (0x0100000 | DAHDI_SIG_FXSKS)
00197 
00198 #ifdef LOTS_OF_SPANS
00199 #define NUM_SPANS DAHDI_MAX_SPANS
00200 #else
00201 #define NUM_SPANS       32
00202 #endif
00203 #define NUM_DCHANS      4  /*!< No more than 4 d-channels */
00204 #define MAX_CHANNELS 672      /*!< No more than a DS3 per trunk group */
00205 
00206 #define CHAN_PSEUDO  -2
00207 
00208 #define DCHAN_PROVISIONED (1 << 0)
00209 #define DCHAN_NOTINALARM  (1 << 1)
00210 #define DCHAN_UP          (1 << 2)
00211 
00212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
00213 
00214 /* Overlap dialing option types */
00215 #define DAHDI_OVERLAPDIAL_NONE 0
00216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
00217 #define DAHDI_OVERLAPDIAL_INCOMING 2
00218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
00219 
00220 
00221 #define CALLPROGRESS_PROGRESS    1
00222 #define CALLPROGRESS_FAX_OUTGOING   2
00223 #define CALLPROGRESS_FAX_INCOMING   4
00224 #define CALLPROGRESS_FAX      (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00225 
00226 static char defaultcic[64] = "";
00227 static char defaultozz[64] = "";
00228 
00229 static char parkinglot[AST_MAX_EXTENSION] = "";    /*!< Default parking lot for this channel */
00230 
00231 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
00232 static char mwimonitornotify[PATH_MAX] = "";
00233 static int  mwisend_rpas = 0;
00234 
00235 static char progzone[10] = "";
00236 
00237 static int usedistinctiveringdetection = 0;
00238 static int distinctiveringaftercid = 0;
00239 
00240 static int numbufs = 4;
00241 
00242 static int mwilevel = 512;
00243 
00244 #ifdef HAVE_PRI
00245 static struct ast_channel inuse;
00246 #ifdef PRI_GETSET_TIMERS
00247 static int pritimers[PRI_MAX_TIMERS];
00248 #endif
00249 static int pridebugfd = -1;
00250 static char pridebugfilename[1024] = "";
00251 #endif
00252 
00253 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
00254 static int firstdigittimeout = 16000;
00255 
00256 /*! \brief How long to wait for following digits (FXO logic) */
00257 static int gendigittimeout = 8000;
00258 
00259 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
00260 static int matchdigittimeout = 3000;
00261 
00262 /*! \brief Protect the interface list (of dahdi_pvt's) */
00263 AST_MUTEX_DEFINE_STATIC(iflock);
00264 
00265 
00266 static int ifcount = 0;
00267 
00268 #ifdef HAVE_PRI
00269 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00270 #endif
00271 
00272 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
00273    when it's doing something critical. */
00274 AST_MUTEX_DEFINE_STATIC(monlock);
00275 
00276 /*! \brief This is the thread for the monitor which checks for input on the channels
00277    which are not currently in use. */
00278 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00279 static ast_cond_t mwi_thread_complete;
00280 static ast_cond_t ss_thread_complete;
00281 AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
00282 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00283 AST_MUTEX_DEFINE_STATIC(restart_lock);
00284 static int mwi_thread_count = 0;
00285 static int ss_thread_count = 0;
00286 static int num_restart_pending = 0;
00287 
00288 static int restart_monitor(void);
00289 
00290 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);
00291 
00292 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00293 
00294 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00295 {
00296    /* This module does not handle MWI in an event-based manner.  However, it
00297     * subscribes to MWI for each mailbox that is configured so that the core
00298     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00299     * event cache instead of checking the mailbox directly. */
00300 }
00301 
00302 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
00303 static inline int dahdi_get_event(int fd)
00304 {
00305    int j;
00306    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00307       return -1;
00308    return j;
00309 }
00310 
00311 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
00312 static inline int dahdi_wait_event(int fd)
00313 {
00314    int i, j = 0;
00315    i = DAHDI_IOMUX_SIGEVENT;
00316    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00317       return -1;
00318    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00319       return -1;
00320    return j;
00321 }
00322 
00323 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
00324 #define READ_SIZE 160
00325 
00326 #define MASK_AVAIL      (1 << 0) /*!< Channel available for PRI use */
00327 #define MASK_INUSE      (1 << 1) /*!< Channel currently in use */
00328 
00329 #define CALLWAITING_SILENT_SAMPLES  ( (300 * 8) / READ_SIZE) /*!< 300 ms */
00330 #define CALLWAITING_REPEAT_SAMPLES  ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
00331 #define CIDCW_EXPIRE_SAMPLES     ( (500 * 8) / READ_SIZE) /*!< 500 ms */
00332 #define MIN_MS_SINCE_FLASH       ( (2000) )  /*!< 2000 ms */
00333 #define DEFAULT_RINGT            ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
00334 
00335 struct dahdi_pvt;
00336 
00337 /*!
00338  * \brief Configured ring timeout base.
00339  * \note Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.
00340  */
00341 static int ringt_base = DEFAULT_RINGT;
00342 
00343 #ifdef HAVE_SS7
00344 
00345 #define LINKSTATE_INALARM  (1 << 0)
00346 #define LINKSTATE_STARTING (1 << 1)
00347 #define LINKSTATE_UP    (1 << 2)
00348 #define LINKSTATE_DOWN     (1 << 3)
00349 
00350 #define SS7_NAI_DYNAMIC    -1
00351 
00352 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
00353 
00354 struct dahdi_ss7 {
00355    pthread_t master;                /*!< Thread of master */
00356    ast_mutex_t lock;
00357    int fds[NUM_DCHANS];
00358    int numsigchans;
00359    int linkstate[NUM_DCHANS];
00360    int numchans;
00361    int type;
00362    enum {
00363       LINKSET_STATE_DOWN = 0,
00364       LINKSET_STATE_UP
00365    } state;
00366    char called_nai;                 /*!< Called Nature of Address Indicator */
00367    char calling_nai;                /*!< Calling Nature of Address Indicator */
00368    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00369    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00370    char subscriberprefix[20];             /*!< area access code + area code ('0'+area code for european dialplans) */
00371    char unknownprefix[20];                /*!< for unknown dialplans */
00372    struct ss7 *ss7;
00373    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00374    int flags;                    /*!< Linkset flags */
00375 };
00376 
00377 static struct dahdi_ss7 linksets[NUM_SPANS];
00378 
00379 static int cur_ss7type = -1;
00380 static int cur_linkset = -1;
00381 static int cur_pointcode = -1;
00382 static int cur_cicbeginswith = -1;
00383 static int cur_adjpointcode = -1;
00384 static int cur_networkindicator = -1;
00385 static int cur_defaultdpc = -1;
00386 #endif /* HAVE_SS7 */
00387 
00388 #ifdef HAVE_PRI
00389 
00390 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
00391 #define PRI_CHANNEL(p) ((p) & 0xff)
00392 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
00393 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
00394 
00395 struct dahdi_pri {
00396    pthread_t master;                /*!< Thread of master */
00397    ast_mutex_t lock;                /*!< Mutex */
00398    char idleext[AST_MAX_EXTENSION];          /*!< Where to idle extra calls */
00399    char idlecontext[AST_MAX_CONTEXT];           /*!< What context to use for idle */
00400    char idledial[AST_MAX_EXTENSION];            /*!< What to dial before dumping */
00401    int minunused;                   /*!< Min # of channels to keep empty */
00402    int minidle;                     /*!< Min # of "idling" calls to keep active */
00403    int nodetype;                    /*!< Node type */
00404    int switchtype;                     /*!< Type of switch to emulate */
00405    int nsf;                   /*!< Network-Specific Facilities */
00406    int dialplan;                    /*!< Dialing plan */
00407    int localdialplan;                  /*!< Local dialing plan */
00408    char internationalprefix[10];             /*!< country access code ('00' for european dialplans) */
00409    char nationalprefix[10];               /*!< area access code ('0' for european dialplans) */
00410    char localprefix[20];                  /*!< area access code + area code ('0'+area code for european dialplans) */
00411    char privateprefix[20];                /*!< for private dialplans */
00412    char unknownprefix[20];                /*!< for unknown dialplans */
00413    int dchannels[NUM_DCHANS];             /*!< What channel are the dchannels on */
00414    int trunkgroup;                     /*!< What our trunkgroup is */
00415    int mastertrunkgroup;                  /*!< What trunk group is our master */
00416    int prilogicalspan;                 /*!< Logical span number within trunk group */
00417    int numchans;                    /*!< Num of channels we represent */
00418    int overlapdial;                 /*!< In overlap dialing mode */
00419    int facilityenable;                 /*!< Enable facility IEs */
00420    struct pri *dchans[NUM_DCHANS];              /*!< Actual d-channels */
00421    int dchanavail[NUM_DCHANS];               /*!< Whether each channel is available */
00422    struct pri *pri;                 /*!< Currently active D-channel */
00423    /*! \brief TRUE if to dump PRI event info (Tested but never set) */
00424    int debug;
00425    int fds[NUM_DCHANS];                /*!< FD's for d-channels */
00426    /*! \brief Value set but not used */
00427    int offset;
00428    /*! \brief Span number put into user output messages */
00429    int span;
00430    /*! \brief TRUE if span is being reset/restarted */
00431    int resetting;
00432    /*! \brief Current position during a reset (-1 if not started) */
00433    int resetpos;
00434 #ifdef HAVE_PRI_INBANDDISCONNECT
00435    unsigned int inbanddisconnect:1;          /*!< Should we support inband audio after receiving DISCONNECT? */
00436 #endif
00437    time_t lastreset;                /*!< time when unused channels were last reset */
00438    long resetinterval;                 /*!< Interval (in seconds) for resetting unused channels */
00439    /*! \brief ISDN signalling type (SIG_PRI, SIG_BRI, SIG_BRI_PTMP, etc...) */
00440    int sig;
00441    struct dahdi_pvt *pvts[MAX_CHANNELS];           /*!< Member channel pvt structs */
00442    struct dahdi_pvt *crvs;                /*!< Member CRV structs */
00443    struct dahdi_pvt *crvend;                 /*!< Pointer to end of CRV structs */
00444 };
00445 
00446 
00447 static struct dahdi_pri pris[NUM_SPANS];
00448 
00449 #if 0
00450 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
00451 #else
00452 #define DEFAULT_PRI_DEBUG 0
00453 #endif
00454 
00455 static inline void pri_rel(struct dahdi_pri *pri)
00456 {
00457    ast_mutex_unlock(&pri->lock);
00458 }
00459 
00460 #else
00461 /*! Shut up the compiler */
00462 struct dahdi_pri;
00463 #endif
00464 
00465 #define SUB_REAL  0        /*!< Active call */
00466 #define SUB_CALLWAIT 1        /*!< Call-Waiting call on hold */
00467 #define SUB_THREEWAY 2        /*!< Three-way call */
00468 
00469 /* Polarity states */
00470 #define POLARITY_IDLE   0
00471 #define POLARITY_REV    1
00472 
00473 
00474 struct distRingData {
00475    int ring[3];
00476    int range;
00477 };
00478 struct ringContextData {
00479    char contextData[AST_MAX_CONTEXT];
00480 };
00481 struct dahdi_distRings {
00482    struct distRingData ringnum[3];
00483    struct ringContextData ringContext[3];
00484 };
00485 
00486 static char *subnames[] = {
00487    "Real",
00488    "Callwait",
00489    "Threeway"
00490 };
00491 
00492 struct dahdi_subchannel {
00493    int dfd;
00494    struct ast_channel *owner;
00495    int chan;
00496    short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00497    struct ast_frame f;     /*!< One frame for each channel.  How did this ever work before? */
00498    unsigned int needringing:1;
00499    unsigned int needbusy:1;
00500    unsigned int needcongestion:1;
00501    unsigned int needcallerid:1;
00502    unsigned int needanswer:1;
00503    unsigned int needflash:1;
00504    unsigned int needhold:1;
00505    unsigned int needunhold:1;
00506    unsigned int linear:1;
00507    unsigned int inthreeway:1;
00508    struct dahdi_confinfo curconf;
00509 };
00510 
00511 #define CONF_USER_REAL     (1 << 0)
00512 #define CONF_USER_THIRDCALL   (1 << 1)
00513 
00514 #define MAX_SLAVES   4
00515 
00516 static struct dahdi_pvt {
00517    ast_mutex_t lock;
00518    struct ast_channel *owner;       /*!< Our current active owner (if applicable) */
00519                      /*!< Up to three channels can be associated with this call */
00520       
00521    struct dahdi_subchannel sub_unused;    /*!< Just a safety precaution */
00522    struct dahdi_subchannel subs[3];       /*!< Sub-channels */
00523    struct dahdi_confinfo saveconf;        /*!< Saved conference info */
00524 
00525    struct dahdi_pvt *slaves[MAX_SLAVES];     /*!< Slave to us (follows our conferencing) */
00526    struct dahdi_pvt *master;           /*!< Master to us (we follow their conferencing) */
00527    int inconference;          /*!< If our real should be in the conference */
00528    
00529    int buf_no;             /*!< Number of buffers */
00530    int buf_policy;            /*!< Buffer policy */
00531    int sig;             /*!< Signalling style */
00532    /*!
00533     * \brief Nonzero if the signaling type is sent over a radio.
00534     * \note Set to a couple of nonzero values but it is only tested like a boolean.
00535     */
00536    int radio;
00537    int outsigmod;             /*!< Outbound Signalling style (modifier) */
00538    int oprmode;               /*!< "Operator Services" mode */
00539    struct dahdi_pvt *oprpeer;          /*!< "Operator Services" peer tech_pvt ptr */
00540    /*! \brief Amount of gain to increase during caller id */
00541    float cid_rxgain;
00542    /*! \brief Rx gain set by chan_dahdi.conf */
00543    float rxgain;
00544    /*! \brief Tx gain set by chan_dahdi.conf */
00545    float txgain;
00546    int tonezone;              /*!< tone zone for this chan, or -1 for default */
00547    struct dahdi_pvt *next;          /*!< Next channel in list */
00548    struct dahdi_pvt *prev;          /*!< Prev channel in list */
00549 
00550    /* flags */
00551 
00552    /*!
00553     * \brief TRUE if ADSI (Analog Display Services Interface) available
00554     * \note Set from the "adsi" value read in from chan_dahdi.conf
00555     */
00556    unsigned int adsi:1;
00557    /*!
00558     * \brief TRUE if we can use a polarity reversal to mark when an outgoing
00559     * call is answered by the remote party.
00560     * \note Set from the "answeronpolarityswitch" value read in from chan_dahdi.conf
00561     */
00562    unsigned int answeronpolarityswitch:1;
00563    /*!
00564     * \brief TRUE if busy detection is enabled.
00565     * (Listens for the beep-beep busy pattern.)
00566     * \note Set from the "busydetect" value read in from chan_dahdi.conf
00567     */
00568    unsigned int busydetect:1;
00569    /*!
00570     * \brief TRUE if call return is enabled.
00571     * (*69, if your dialplan doesn't catch this first)
00572     * \note Set from the "callreturn" value read in from chan_dahdi.conf
00573     */
00574    unsigned int callreturn:1;
00575    /*!
00576     * \brief TRUE if busy extensions will hear the call-waiting tone
00577     * and can use hook-flash to switch between callers.
00578     * \note Can be disabled by dialing *70.
00579     * \note Initialized with the "callwaiting" value read in from chan_dahdi.conf
00580     */
00581    unsigned int callwaiting:1;
00582    /*!
00583     * \brief TRUE if send caller ID for Call Waiting
00584     * \note Set from the "callwaitingcallerid" value read in from chan_dahdi.conf
00585     */
00586    unsigned int callwaitingcallerid:1;
00587    /*!
00588     * \brief TRUE if support for call forwarding enabled.
00589     * Dial *72 to enable call forwarding.
00590     * Dial *73 to disable call forwarding.
00591     * \note Set from the "cancallforward" value read in from chan_dahdi.conf
00592     */
00593    unsigned int cancallforward:1;
00594    /*!
00595     * \brief TRUE if support for call parking is enabled.
00596     * \note Set from the "canpark" value read in from chan_dahdi.conf
00597     */
00598    unsigned int canpark:1;
00599    /*! \brief TRUE if to wait for a DTMF digit to confirm answer */
00600    unsigned int confirmanswer:1;
00601    /*!
00602     * \brief TRUE if the channel is to be destroyed on hangup.
00603     * (Used by pseudo channels.)
00604     */
00605    unsigned int destroy:1;
00606    unsigned int didtdd:1;           /*!< flag to say its done it once */
00607    /*! \brief TRUE if analog type line dialed no digits in Dial() */
00608    unsigned int dialednone:1;
00609    /*! \brief TRUE if in the process of dialing digits or sending something. */
00610    unsigned int dialing:1;
00611    /*! \brief TRUE if the transfer capability of the call is digital. */
00612    unsigned int digital:1;
00613    /*! \brief TRUE if Do-Not-Disturb is enabled. */
00614    unsigned int dnd:1;
00615    /*! \brief XXX BOOLEAN Purpose??? */
00616    unsigned int echobreak:1;
00617    /*!
00618     * \brief TRUE if echo cancellation enabled when bridged.
00619     * \note Initialized with the "echocancelwhenbridged" value read in from chan_dahdi.conf
00620     * \note Disabled if the echo canceller is not setup.
00621     */
00622    unsigned int echocanbridged:1;
00623    /*! \brief TRUE if echo cancellation is turned on. */
00624    unsigned int echocanon:1;
00625    /*! \brief TRUE if a fax tone has already been handled. */
00626    unsigned int faxhandled:1;
00627    /*! \brief TRUE if over a radio and dahdi_read() has been called. */
00628    unsigned int firstradio:1;
00629    /*!
00630     * \brief TRUE if the call will be considered "hung up" on a polarity reversal.
00631     * \note Set from the "hanguponpolarityswitch" value read in from chan_dahdi.conf
00632     */
00633    unsigned int hanguponpolarityswitch:1;
00634    /*! \brief TRUE if DTMF detection needs to be done by hardware. */
00635    unsigned int hardwaredtmf:1;
00636    /*!
00637     * \brief TRUE if the outgoing caller ID is blocked/hidden.
00638     * \note Caller ID can be disabled by dialing *67.
00639     * \note Caller ID can be enabled by dialing *82.
00640     * \note Initialized with the "hidecallerid" value read in from chan_dahdi.conf
00641     */
00642    unsigned int hidecallerid:1;
00643    /*!
00644     * \brief TRUE if hide just the name not the number for legacy PBX use.
00645     * \note Only applies to PRI channels.
00646     * \note Set from the "hidecalleridname" value read in from chan_dahdi.conf
00647     */
00648    unsigned int hidecalleridname:1;
00649    /*! \brief TRUE if DTMF detection is disabled. */
00650    unsigned int ignoredtmf:1;
00651    /*!
00652     * \brief TRUE if the channel should be answered immediately
00653     * without attempting to gather any digits.
00654     * \note Set from the "immediate" value read in from chan_dahdi.conf
00655     */
00656    unsigned int immediate:1;
00657    /*! \brief TRUE if in an alarm condition. */
00658    unsigned int inalarm:1;
00659    /*! \brief TRUE if TDD in MATE mode */
00660    unsigned int mate:1;
00661    /*! \brief TRUE if we originated the call leg. */
00662    unsigned int outgoing:1;
00663    /* unsigned int overlapdial:1;         unused and potentially confusing */
00664    /*!
00665     * \brief TRUE if busy extensions will hear the call-waiting tone
00666     * and can use hook-flash to switch between callers.
00667     * \note Set from the "callwaiting" value read in from chan_dahdi.conf
00668     */
00669    unsigned int permcallwaiting:1;
00670    /*!
00671     * \brief TRUE if the outgoing caller ID is blocked/restricted/hidden.
00672     * \note Set from the "hidecallerid" value read in from chan_dahdi.conf
00673     */
00674    unsigned int permhidecallerid:1;
00675    /*!
00676     * \brief TRUE if PRI congestion/busy indications are sent out-of-band.
00677     * \note Set from the "priindication" value read in from chan_dahdi.conf
00678     */
00679    unsigned int priindication_oob:1;
00680    /*!
00681     * \brief TRUE if PRI B channels are always exclusively selected.
00682     * \note Set from the "priexclusive" value read in from chan_dahdi.conf
00683     */
00684    unsigned int priexclusive:1;
00685    /*!
00686     * \brief TRUE if we will pulse dial.
00687     * \note Set from the "pulsedial" value read in from chan_dahdi.conf
00688     */
00689    unsigned int pulse:1;
00690    /*! \brief TRUE if a pulsed digit was detected. (Pulse dial phone detected) */
00691    unsigned int pulsedial:1;
00692    unsigned int restartpending:1;      /*!< flag to ensure counted only once for restart */
00693    /*!
00694     * \brief TRUE if caller ID is restricted.
00695     * \note Set but not used.  Should be deleted.  Redundant with permhidecallerid.
00696     * \note Set from the "restrictcid" value read in from chan_dahdi.conf
00697     */
00698    unsigned int restrictcid:1;
00699    /*!
00700     * \brief TRUE if three way calling is enabled
00701     * \note Set from the "threewaycalling" value read in from chan_dahdi.conf
00702     */
00703    unsigned int threewaycalling:1;
00704    /*!
00705     * \brief TRUE if call transfer is enabled
00706     * \note For FXS ports (either direct analog or over T1/E1):
00707     *   Support flash-hook call transfer
00708     * \note For digital ports using ISDN PRI protocols:
00709     *   Support switch-side transfer (called 2BCT, RLT or other names)
00710     * \note Set from the "transfer" value read in from chan_dahdi.conf
00711     */
00712    unsigned int transfer:1;
00713    /*!
00714     * \brief TRUE if caller ID is used on this channel.
00715     * \note PRI and SS7 spans will save caller ID from the networking peer.
00716     * \note FXS ports will generate the caller ID spill.
00717     * \note FXO ports will listen for the caller ID spill.
00718     * \note Set from the "usecallerid" value read in from chan_dahdi.conf
00719     */
00720    unsigned int use_callerid:1;
00721    /*!
00722     * \brief TRUE if we will use the calling presentation setting
00723     * from the Asterisk channel for outgoing calls.
00724     * \note Only applies to PRI and SS7 channels.
00725     * \note Set from the "usecallingpres" value read in from chan_dahdi.conf
00726     */
00727    unsigned int use_callingpres:1;
00728    /*!
00729     * \brief TRUE if distinctive rings are to be detected.
00730     * \note For FXO lines
00731     * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf
00732     */
00733    unsigned int usedistinctiveringdetection:1;
00734    /*!
00735     * \brief TRUE if we should use the callerid from incoming call on dahdi transfer.
00736     * \note Set from the "useincomingcalleridondahditransfer" value read in from chan_dahdi.conf
00737     */
00738    unsigned int dahditrcallerid:1;
00739    /*!
00740     * \brief TRUE if allowed to flash-transfer to busy channels.
00741     * \note Set from the "transfertobusy" value read in from chan_dahdi.conf
00742     */
00743    unsigned int transfertobusy:1;
00744    /*!
00745     * \brief TRUE if the FXO port monitors for neon type MWI indications from the other end.
00746     * \note Set if the "mwimonitor" value read in contains "neon" from chan_dahdi.conf
00747     */
00748    unsigned int mwimonitor_neon:1;
00749    /*!
00750     * \brief TRUE if the FXO port monitors for fsk type MWI indications from the other end.
00751     * \note Set if the "mwimonitor" value read in contains "fsk" from chan_dahdi.conf
00752     */
00753    unsigned int mwimonitor_fsk:1;
00754    /*!
00755     * \brief TRUE if the FXO port monitors for rpas precursor to fsk MWI indications from the other end.
00756     * \note RPAS - Ring Pulse Alert Signal
00757     * \note Set if the "mwimonitor" value read in contains "rpas" from chan_dahdi.conf
00758     */
00759    unsigned int mwimonitor_rpas:1;
00760    /*! \brief TRUE if an MWI monitor thread is currently active */
00761    unsigned int mwimonitoractive:1;
00762    /*! \brief TRUE if a MWI message sending thread is active */
00763    unsigned int mwisendactive:1;
00764    /*!
00765     * \brief TRUE if channel is out of reset and ready
00766     * \note Set but not used.
00767     */
00768    unsigned int inservice:1;
00769    /*!
00770     * \brief TRUE if the channel is locally blocked.
00771     * \note Applies to SS7 channels.
00772     */
00773    unsigned int locallyblocked:1;
00774    /*!
00775     * \brief TRUE if the channel is remotely blocked.
00776     * \note Applies to SS7 channels.
00777     */
00778    unsigned int remotelyblocked:1;
00779 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00780    /*!
00781     * \brief XXX BOOLEAN Purpose???
00782     * \note Applies to SS7 channels.
00783     */
00784    unsigned int rlt:1;
00785    /*! \brief TRUE if channel is alerting/ringing */
00786    unsigned int alerting:1;
00787    /*! \brief TRUE if the call has already gone/hungup */
00788    unsigned int alreadyhungup:1;
00789    /*!
00790     * \brief TRUE if this is an idle call
00791     * \note Applies to PRI channels.
00792     */
00793    unsigned int isidlecall:1;
00794    /*!
00795     * \brief TRUE if call is in a proceeding state.
00796     * The call has started working its way through the network.
00797     */
00798    unsigned int proceeding:1;
00799    /*! \brief TRUE if the call has seen progress through the network. */
00800    unsigned int progress:1;
00801    /*!
00802     * \brief TRUE if this channel is being reset/restarted
00803     * \note Applies to PRI channels.
00804     */
00805    unsigned int resetting:1;
00806    /*!
00807     * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
00808     * \note Applies to PRI channels.
00809     */
00810    unsigned int setup_ack:1;
00811 #endif
00812    /*!
00813     * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
00814     * \note Set from the "usesmdi" value read in from chan_dahdi.conf
00815     */
00816    unsigned int use_smdi:1;
00817    /*! \brief The serial port to listen for SMDI data on */
00818    struct ast_smdi_interface *smdi_iface;
00819 
00820    /*! \brief Distinctive Ring data */
00821    struct dahdi_distRings drings;
00822 
00823    /*!
00824     * \brief The configured context for incoming calls.
00825     * \note The "context" string read in from chan_dahdi.conf
00826     */
00827    char context[AST_MAX_CONTEXT];
00828    /*!
00829     * \brief Saved context string.
00830     */
00831    char defcontext[AST_MAX_CONTEXT];
00832    /*! \brief Extension to use in the dialplan. */
00833    char exten[AST_MAX_EXTENSION];
00834    /*!
00835     * \brief Language configured for calls.
00836     * \note The "language" string read in from chan_dahdi.conf
00837     */
00838    char language[MAX_LANGUAGE];
00839    /*!
00840     * \brief The configured music-on-hold class to use for calls.
00841     * \note The "musicclass" or "mohinterpret" or "musiconhold" string read in from chan_dahdi.conf
00842     */
00843    char mohinterpret[MAX_MUSICCLASS];
00844    /*!
00845     * \brief Suggested music-on-hold class for peer channel to use for calls.
00846     * \note The "mohsuggest" string read in from chan_dahdi.conf
00847     */
00848    char mohsuggest[MAX_MUSICCLASS];
00849    char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
00850 #if defined(PRI_ANI) || defined(HAVE_SS7)
00851    /*! \brief Automatic Number Identification number (Alternate PRI caller ID number) */
00852    char cid_ani[AST_MAX_EXTENSION];
00853 #endif
00854    /*! \brief Automatic Number Identification code from PRI */
00855    int cid_ani2;
00856    /*! \brief Caller ID number from an incoming call. */
00857    char cid_num[AST_MAX_EXTENSION];
00858    /*! \brief Caller ID Q.931 TON/NPI field values.  Set by PRI. Zero otherwise. */
00859    int cid_ton;
00860    /*! \brief Caller ID name from an incoming call. */
00861    char cid_name[AST_MAX_EXTENSION];
00862    /*! \brief Last Caller ID number from an incoming call. */
00863    char lastcid_num[AST_MAX_EXTENSION];
00864    /*! \brief Last Caller ID name from an incoming call. */
00865    char lastcid_name[AST_MAX_EXTENSION];
00866    char *origcid_num;            /*!< malloced original callerid */
00867    char *origcid_name;           /*!< malloced original callerid */
00868    /*! \brief Call waiting number. */
00869    char callwait_num[AST_MAX_EXTENSION];
00870    /*! \brief Call waiting name. */
00871    char callwait_name[AST_MAX_EXTENSION];
00872    /*! \brief Redirecting Directory Number Information Service (RDNIS) number */
00873    char rdnis[AST_MAX_EXTENSION];
00874    /*! \brief Dialed Number Identifier */
00875    char dnid[AST_MAX_EXTENSION];
00876    /*!
00877     * \brief Bitmapped groups this belongs to.
00878     * \note The "group" bitmapped group string read in from chan_dahdi.conf
00879     */
00880    ast_group_t group;
00881    /*! \brief Active PCM encoding format: DAHDI_LAW_ALAW or DAHDI_LAW_MULAW */
00882    int law;
00883    int confno;             /*!< Our conference */
00884    int confusers;             /*!< Who is using our conference */
00885    int propconfno;               /*!< Propagated conference number */
00886    /*!
00887     * \brief Bitmapped call groups this belongs to.
00888     * \note The "callgroup" bitmapped group string read in from chan_dahdi.conf
00889     */
00890    ast_group_t callgroup;
00891    /*!
00892     * \brief Bitmapped pickup groups this belongs to.
00893     * \note The "pickupgroup" bitmapped group string read in from chan_dahdi.conf
00894     */
00895    ast_group_t pickupgroup;
00896    /*!
00897     * \brief Channel variable list with associated values to set when a channel is created.
00898     * \note The "setvar" strings read in from chan_dahdi.conf
00899     */
00900    struct ast_variable *vars;
00901    int channel;               /*!< Channel Number or CRV */
00902    int span;               /*!< Span number */
00903    time_t guardtime;          /*!< Must wait this much time before using for new call */
00904    int cid_signalling;           /*!< CID signalling type bell202 or v23 */
00905    int cid_start;             /*!< CID start indicator, polarity or ring */
00906    int callingpres;           /*!< The value of callling presentation that we're going to use when placing a PRI call */
00907    int callwaitingrepeat;           /*!< How many samples to wait before repeating call waiting */
00908    int cidcwexpire;           /*!< When to expire our muting for CID/CW */
00909    /*! \brief Analog caller ID waveform sample buffer */
00910    unsigned char *cidspill;
00911    /*! \brief Position in the cidspill buffer to send out next. */
00912    int cidpos;
00913    /*! \brief Length of the cidspill buffer containing samples. */
00914    int cidlen;
00915    /*! \brief Ring timeout timer?? */
00916    int ringt;
00917    /*!
00918     * \brief Ring timeout base.
00919     * \note Value computed indirectly from "ringtimeout" read in from chan_dahdi.conf
00920     */
00921    int ringt_base;
00922    /*!
00923     * \brief Number of most significant digits/characters to strip from the dialed number.
00924     * \note Feature is deprecated.  Use dialplan logic.
00925     * \note The characters are stripped before the PRI TON/NPI prefix
00926     * characters are processed.
00927     */
00928    int stripmsd;
00929    /*! \brief BOOLEAN. XXX Meaning what?? */
00930    int callwaitcas;
00931    /*! \brief Number of call waiting rings. */
00932    int callwaitrings;
00933    /*! \brief Echo cancel parameters. */
00934    struct {
00935       struct dahdi_echocanparams head;
00936       struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
00937    } echocancel;
00938    /*!
00939     * \brief Echo training time. 0 = disabled
00940     * \note Set from the "echotraining" value read in from chan_dahdi.conf
00941     */
00942    int echotraining;
00943    /*! \brief Filled with 'w'.  XXX Purpose?? */
00944    char echorest[20];
00945    /*!
00946     * \brief Number of times to see "busy" tone before hanging up.
00947     * \note Set from the "busycount" value read in from chan_dahdi.conf
00948     */
00949    int busycount;
00950    /*!
00951     * \brief Length of "busy" tone on time.
00952     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00953     */
00954    int busy_tonelength;
00955    /*!
00956     * \brief Length of "busy" tone off time.
00957     * \note Set from the "busypattern" value read in from chan_dahdi.conf
00958     */
00959    int busy_quietlength;
00960    /*!
00961     * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
00962     * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
00963     */
00964    int callprogress;
00965    struct timeval flashtime;        /*!< Last flash-hook time */
00966    /*! \brief Opaque DSP configuration structure. */
00967    struct ast_dsp *dsp;
00968    //int cref;             /*!< Call reference number (Not used) */
00969    /*! \brief DAHDI dial operation command struct for ioctl() call. */
00970    struct dahdi_dialoperation dop;
00971    int whichwink;             /*!< SIG_FEATDMF_TA Which wink are we on? */
00972    /*! \brief Second part of SIG_FEATDMF_TA wink operation. */
00973    char finaldial[64];
00974    char accountcode[AST_MAX_ACCOUNT_CODE];      /*!< Account code */
00975    int amaflags;              /*!< AMA Flags */
00976    struct tdd_state *tdd;           /*!< TDD flag */
00977    /*! \brief Accumulated call forwarding number. */
00978    char call_forward[AST_MAX_EXTENSION];
00979    /*!
00980     * \brief Voice mailbox location.
00981     * \note Set from the "mailbox" string read in from chan_dahdi.conf
00982     */
00983    char mailbox[AST_MAX_EXTENSION];
00984    /*! \brief Opaque event subscription parameters for message waiting indication support. */
00985    struct ast_event_sub *mwi_event_sub;
00986    /*! \brief Delayed dialing for E911.  Overlap digits for ISDN. */
00987    char dialdest[256];
00988    /*! \brief Time the interface went on-hook. */
00989    int onhooktime;
00990    /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */
00991    int msgstate;
00992    int distinctivering;          /*!< Which distinctivering to use */
00993    int cidrings;              /*!< Which ring to deliver CID on */
00994    int dtmfrelax;             /*!< whether to run in relaxed DTMF mode */
00995    /*! \brief Holding place for event injected from outside normal operation. */
00996    int fake_event;
00997    /*!
00998     * \brief Minimal time period (ms) between the answer polarity
00999     * switch and hangup polarity switch.
01000     */
01001    int polarityonanswerdelay;
01002    /*! \brief Start delay time if polarityonanswerdelay is nonzero. */
01003    struct timeval polaritydelaytv;
01004    /*!
01005     * \brief Send caller ID after this many rings.
01006     * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
01007     */
01008    int sendcalleridafter;
01009 #ifdef HAVE_PRI
01010    /*! \brief DAHDI PRI control parameters */
01011    struct dahdi_pri *pri;
01012    /*! \brief XXX Purpose??? */
01013    struct dahdi_pvt *bearer;
01014    /*! \brief XXX Purpose??? */
01015    struct dahdi_pvt *realcall;
01016    /*! \brief Opaque libpri call control structure */
01017    q931_call *call;
01018    /*! \brief Channel number in span. */
01019    int prioffset;
01020    /*! \brief Logical span number within trunk group */
01021    int logicalspan;
01022 #endif   
01023    /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
01024    int polarity;
01025    /*! \brief DSP feature flags: DSP_FEATURE_xxx */
01026    int dsp_features;
01027 #ifdef HAVE_SS7
01028    /*! \brief SS7 control parameters */
01029    struct dahdi_ss7 *ss7;
01030    /*! \brief Opaque libss7 call control structure */
01031    struct isup_call *ss7call;
01032    char charge_number[50];
01033    char gen_add_number[50];
01034    char gen_dig_number[50];
01035    char orig_called_num[50];
01036    char redirecting_num[50];
01037    char generic_name[50];
01038    unsigned char gen_add_num_plan;
01039    unsigned char gen_add_nai;
01040    unsigned char gen_add_pres_ind;
01041    unsigned char gen_add_type;
01042    unsigned char gen_dig_type;
01043    unsigned char gen_dig_scheme;
01044    char jip_number[50];
01045    unsigned char lspi_type;
01046    unsigned char lspi_scheme;
01047    unsigned char lspi_context;
01048    char lspi_ident[50];
01049    unsigned int call_ref_ident;
01050    unsigned int call_ref_pc;
01051    unsigned char calling_party_cat;
01052    int transcap;
01053    int cic;                   /*!< CIC associated with channel */
01054    unsigned int dpc;                /*!< CIC's DPC */
01055    unsigned int loopedback:1;
01056 #endif
01057    /*! \brief DTMF digit in progress.  0 when no digit in progress. */
01058    char begindigit;
01059    /*! \brief TRUE if confrence is muted. */
01060    int muting;
01061 } *iflist = NULL, *ifend = NULL;
01062 
01063 /*! \brief Channel configuration from chan_dahdi.conf .
01064  * This struct is used for parsing the [channels] section of chan_dahdi.conf.
01065  * Generally there is a field here for every possible configuration item.
01066  *
01067  * The state of fields is saved along the parsing and whenever a 'channel'
01068  * statement is reached, the current dahdi_chan_conf is used to configure the 
01069  * channel (struct dahdi_pvt)
01070  *
01071  * \see dahdi_chan_init for the default values.
01072  */
01073 struct dahdi_chan_conf {
01074    struct dahdi_pvt chan;
01075 #ifdef HAVE_PRI
01076    struct dahdi_pri pri;
01077 #endif
01078 
01079 #ifdef HAVE_SS7
01080    struct dahdi_ss7 ss7;
01081 #endif
01082    struct dahdi_params timing;
01083    int is_sig_auto; /*!< Use channel signalling from DAHDI? */
01084 
01085    /*!
01086     * \brief The serial port to listen for SMDI data on
01087     * \note Set from the "smdiport" string read in from chan_dahdi.conf
01088     */
01089    char smdi_port[SMDI_MAX_FILENAME_LEN];
01090 };
01091 
01092 /*! returns a new dahdi_chan_conf with default values (by-value) */
01093 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
01094    /* recall that if a field is not included here it is initialized
01095     * to 0 or equivalent
01096     */
01097    struct dahdi_chan_conf conf = {
01098 #ifdef HAVE_PRI
01099       .pri = {
01100          .nsf = PRI_NSF_NONE,
01101          .switchtype = PRI_SWITCH_NI2,
01102          .dialplan = PRI_UNKNOWN + 1,
01103          .localdialplan = PRI_NATIONAL_ISDN + 1,
01104          .nodetype = PRI_CPE,
01105 
01106          .minunused = 2,
01107          .idleext = "",
01108          .idledial = "",
01109          .internationalprefix = "",
01110          .nationalprefix = "",
01111          .localprefix = "",
01112          .privateprefix = "",
01113          .unknownprefix = "",
01114          .resetinterval = -1,
01115       },
01116 #endif
01117 #ifdef HAVE_SS7
01118       .ss7 = {
01119          .called_nai = SS7_NAI_NATIONAL,
01120          .calling_nai = SS7_NAI_NATIONAL,
01121          .internationalprefix = "",
01122          .nationalprefix = "",
01123          .subscriberprefix = "",
01124          .unknownprefix = ""
01125       },
01126 #endif
01127       .chan = {
01128          .context = "default",
01129          .cid_num = "",
01130          .cid_name = "",
01131          .mohinterpret = "default",
01132          .mohsuggest = "",
01133          .parkinglot = "",
01134          .transfertobusy = 1,
01135 
01136          .cid_signalling = CID_SIG_BELL,
01137          .cid_start = CID_START_RING,
01138          .dahditrcallerid = 0,
01139          .use_callerid = 1,
01140          .sig = -1,
01141          .outsigmod = -1,
01142 
01143          .cid_rxgain = +5.0,
01144 
01145          .tonezone = -1,
01146 
01147          .echocancel.head.tap_length = 1,
01148 
01149          .busycount = 3,
01150 
01151          .accountcode = "",
01152 
01153          .mailbox = "",
01154 
01155 
01156          .polarityonanswerdelay = 600,
01157 
01158          .sendcalleridafter = DEFAULT_CIDRINGS,
01159       
01160          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01161          .buf_no = numbufs
01162       },
01163       .timing = {
01164          .prewinktime = -1,
01165          .preflashtime = -1,
01166          .winktime = -1,
01167          .flashtime = -1,
01168          .starttime = -1,
01169          .rxwinktime = -1,
01170          .rxflashtime = -1,
01171          .debouncetime = -1
01172       },
01173       .is_sig_auto = 1,
01174       .smdi_port = "/dev/ttyS0",
01175    };
01176 
01177    return conf;
01178 }
01179 
01180 
01181 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
01182 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01183 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01184 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01185 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01186 static int dahdi_hangup(struct ast_channel *ast);
01187 static int dahdi_answer(struct ast_channel *ast);
01188 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01189 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01190 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01191 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01192 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01193 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01194 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01195 static int handle_init_event(struct dahdi_pvt *i, int event);
01196 
01197 static const struct ast_channel_tech dahdi_tech = {
01198    .type = "DAHDI",
01199    .description = tdesc,
01200    .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01201    .requester = dahdi_request,
01202    .send_digit_begin = dahdi_digit_begin,
01203    .send_digit_end = dahdi_digit_end,
01204    .send_text = dahdi_sendtext,
01205    .call = dahdi_call,
01206    .hangup = dahdi_hangup,
01207    .answer = dahdi_answer,
01208    .read = dahdi_read,
01209    .write = dahdi_write,
01210    .bridge = dahdi_bridge,
01211    .exception = dahdi_exception,
01212    .indicate = dahdi_indicate,
01213    .fixup = dahdi_fixup,
01214    .setoption = dahdi_setoption,
01215    .func_channel_read = dahdi_func_read,
01216 };
01217 
01218 #ifdef HAVE_PRI
01219 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
01220 #else
01221 #define GET_CHANNEL(p) ((p)->channel)
01222 #endif
01223 
01224 struct dahdi_pvt *round_robin[32];
01225 
01226 #ifdef HAVE_PRI
01227 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
01228 {
01229    int res;
01230    /* Grab the lock first */
01231    do {
01232       res = ast_mutex_trylock(&pri->lock);
01233       if (res) {
01234          DEADLOCK_AVOIDANCE(&pvt->lock);
01235       }
01236    } while (res);
01237    /* Then break the poll */
01238    if (pri->master != AST_PTHREADT_NULL)
01239       pthread_kill(pri->master, SIGURG);
01240    return 0;
01241 }
01242 #endif
01243 
01244 #ifdef HAVE_SS7
01245 static inline void ss7_rel(struct dahdi_ss7 *ss7)
01246 {
01247    ast_mutex_unlock(&ss7->lock);
01248 }
01249 
01250 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
01251 {
01252    int res;
01253    /* Grab the lock first */
01254    do {
01255       res = ast_mutex_trylock(&pri->lock);
01256       if (res) {
01257          DEADLOCK_AVOIDANCE(&pvt->lock);
01258       }
01259    } while (res);
01260    /* Then break the poll */
01261    if (pri->master != AST_PTHREADT_NULL)
01262       pthread_kill(pri->master, SIGURG);
01263    return 0;
01264 }
01265 #endif
01266 #define NUM_CADENCE_MAX 25
01267 static int num_cadence = 4;
01268 static int user_has_defined_cadences = 0;
01269 
01270 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
01271    { { 125, 125, 2000, 4000 } },       /*!< Quick chirp followed by normal ring */
01272    { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
01273    { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
01274    { { 1000, 500, 2500, 5000 } },   /*!< Long ring */
01275 };
01276 
01277 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
01278  * is 1, the second pause is 2 and so on.
01279  */
01280 
01281 static int cidrings[NUM_CADENCE_MAX] = {
01282    2,                            /*!< Right after first long ring */
01283    4,                            /*!< Right after long part */
01284    3,                            /*!< After third chirp */
01285    2,                            /*!< Second spell */
01286 };
01287 
01288 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
01289 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
01290 
01291 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
01292          (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
01293 
01294 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01295 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
01296 
01297 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
01298 {
01299    int res;
01300    if (p->subs[SUB_REAL].owner == ast)
01301       res = 0;
01302    else if (p->subs[SUB_CALLWAIT].owner == ast)
01303       res = 1;
01304    else if (p->subs[SUB_THREEWAY].owner == ast)
01305       res = 2;
01306    else {
01307       res = -1;
01308       if (!nullok)
01309          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01310    }
01311    return res;
01312 }
01313 
01314 #ifdef HAVE_PRI
01315 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
01316 #else
01317 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
01318 #endif
01319 {
01320 #ifdef HAVE_PRI
01321    if (pri)
01322       ast_mutex_unlock(&pri->lock);
01323 #endif         
01324    for (;;) {
01325       if (p->subs[a].owner) {
01326          if (ast_channel_trylock(p->subs[a].owner)) {
01327             DEADLOCK_AVOIDANCE(&p->lock);
01328          } else {
01329             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01330             ast_channel_unlock(p->subs[a].owner);
01331             break;
01332          }
01333       } else
01334          break;
01335    }
01336 #ifdef HAVE_PRI
01337    if (pri)
01338       ast_mutex_lock(&pri->lock);
01339 #endif         
01340 }
01341 
01342 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
01343 {
01344 #ifdef HAVE_PRI
01345    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01346 #endif
01347 #ifdef HAVE_SS7
01348    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01349 #endif
01350    /* We must unlock the PRI to avoid the possibility of a deadlock */
01351 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01352    if (data) {
01353       switch (p->sig) {
01354 #ifdef HAVE_PRI
01355       case SIG_BRI:
01356       case SIG_BRI_PTMP:
01357       case SIG_PRI:
01358          ast_mutex_unlock(&pri->lock);
01359          break;
01360 #endif
01361 #ifdef HAVE_SS7
01362       case SIG_SS7:
01363          ast_mutex_unlock(&ss7->lock);
01364          break;
01365 #endif
01366       default:
01367          break;
01368       }
01369    }
01370 #endif      
01371    for (;;) {
01372       if (p->owner) {
01373          if (ast_channel_trylock(p->owner)) {
01374             DEADLOCK_AVOIDANCE(&p->lock);
01375          } else {
01376             ast_queue_frame(p->owner, f);
01377             ast_channel_unlock(p->owner);
01378             break;
01379          }
01380       } else
01381          break;
01382    }
01383 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01384    if (data) {
01385       switch (p->sig) {
01386 #ifdef HAVE_PRI
01387       case SIG_BRI:
01388       case SIG_BRI_PTMP:
01389       case SIG_PRI:
01390          ast_mutex_lock(&pri->lock);
01391          break;
01392 #endif
01393 #ifdef HAVE_SS7
01394       case SIG_SS7:
01395          ast_mutex_lock(&ss7->lock);
01396          break;
01397 #endif
01398       default:
01399          break;
01400       }
01401    }
01402 
01403 #endif      
01404 }
01405 
01406 static int restore_gains(struct dahdi_pvt *p);
01407 
01408 static void swap_subs(struct dahdi_pvt *p, int a, int b)
01409 {
01410    int tchan;
01411    int tinthreeway;
01412    struct ast_channel *towner;
01413 
01414    ast_debug(1, "Swapping %d and %d\n", a, b);
01415 
01416    tchan = p->subs[a].chan;
01417    towner = p->subs[a].owner;
01418    tinthreeway = p->subs[a].inthreeway;
01419 
01420    p->subs[a].chan = p->subs[b].chan;
01421    p->subs[a].owner = p->subs[b].owner;
01422    p->subs[a].inthreeway = p->subs[b].inthreeway;
01423 
01424    p->subs[b].chan = tchan;
01425    p->subs[b].owner = towner;
01426    p->subs[b].inthreeway = tinthreeway;
01427 
01428    if (p->subs[a].owner) 
01429       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01430    if (p->subs[b].owner) 
01431       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01432    wakeup_sub(p, a, NULL);
01433    wakeup_sub(p, b, NULL);
01434 }
01435 
01436 static int dahdi_open(char *fn)
01437 {
01438    int fd;
01439    int isnum;
01440    int chan = 0;
01441    int bs;
01442    int x;
01443    isnum = 1;
01444    for (x = 0; x < strlen(fn); x++) {
01445       if (!isdigit(fn[x])) {
01446          isnum = 0;
01447          break;
01448       }
01449    }
01450    if (isnum) {
01451       chan = atoi(fn);
01452       if (chan < 1) {
01453          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01454          return -1;
01455       }
01456       fn = "/dev/dahdi/channel";
01457    }
01458    fd = open(fn, O_RDWR | O_NONBLOCK);
01459    if (fd < 0) {
01460       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01461       return -1;
01462    }
01463    if (chan) {
01464       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01465          x = errno;
01466          close(fd);
01467          errno = x;
01468          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01469          return -1;
01470       }
01471    }
01472    bs = READ_SIZE;
01473    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01474       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01475       x = errno;
01476       close(fd);
01477       errno = x;
01478       return -1;
01479    }
01480    return fd;
01481 }
01482 
01483 static void dahdi_close(int fd)
01484 {
01485    if (fd > 0)
01486       close(fd);
01487 }
01488 
01489 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
01490 {
01491    dahdi_close(chan_pvt->subs[sub_num].dfd);
01492    chan_pvt->subs[sub_num].dfd = -1;
01493 }
01494 
01495 #ifdef HAVE_PRI
01496 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
01497 {
01498    dahdi_close(pri->fds[fd_num]);
01499    pri->fds[fd_num] = -1;
01500 }
01501 #endif
01502 
01503 #ifdef HAVE_SS7
01504 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
01505 {
01506    dahdi_close(ss7->fds[fd_num]);
01507    ss7->fds[fd_num] = -1;
01508 }
01509 #endif
01510 
01511 static int dahdi_setlinear(int dfd, int linear)
01512 {
01513    int res;
01514    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01515    if (res)
01516       return res;
01517    return 0;
01518 }
01519 
01520 
01521 static int alloc_sub(struct dahdi_pvt *p, int x)
01522 {
01523    struct dahdi_bufferinfo bi;
01524    int res;
01525    if (p->subs[x].dfd >= 0) {
01526       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01527       return -1;
01528    }
01529 
01530    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01531    if (p->subs[x].dfd <= -1) {
01532       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01533       return -1;
01534    }
01535 
01536    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01537    if (!res) {
01538       bi.txbufpolicy = p->buf_policy;
01539       bi.rxbufpolicy = p->buf_policy;
01540       bi.numbufs = p->buf_no;
01541       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01542       if (res < 0) {
01543          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01544       }
01545    } else 
01546       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01547 
01548    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01549       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01550       dahdi_close_sub(p, x);
01551       p->subs[x].dfd = -1;
01552       return -1;
01553    }
01554    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01555    return 0;
01556 }
01557 
01558 static int unalloc_sub(struct dahdi_pvt *p, int x)
01559 {
01560    if (!x) {
01561       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01562       return -1;
01563    }
01564    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01565    dahdi_close_sub(p, x);
01566    p->subs[x].linear = 0;
01567    p->subs[x].chan = 0;
01568    p->subs[x].owner = NULL;
01569    p->subs[x].inthreeway = 0;
01570    p->polarity = POLARITY_IDLE;
01571    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01572    return 0;
01573 }
01574 
01575 static int digit_to_dtmfindex(char digit)
01576 {
01577    if (isdigit(digit))
01578       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01579    else if (digit >= 'A' && digit <= 'D')
01580       return DAHDI_TONE_DTMF_A + (digit - 'A');
01581    else if (digit >= 'a' && digit <= 'd')
01582       return DAHDI_TONE_DTMF_A + (digit - 'a');
01583    else if (digit == '*')
01584       return DAHDI_TONE_DTMF_s;
01585    else if (digit == '#')
01586       return DAHDI_TONE_DTMF_p;
01587    else
01588       return -1;
01589 }
01590 
01591 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
01592 {
01593    struct dahdi_pvt *pvt;
01594    int idx;
01595    int dtmf = -1;
01596    
01597    pvt = chan->tech_pvt;
01598 
01599    ast_mutex_lock(&pvt->lock);
01600 
01601    idx = dahdi_get_index(chan, pvt, 0);
01602 
01603    if ((idx != SUB_REAL) || !pvt->owner)
01604       goto out;
01605 
01606 #ifdef HAVE_PRI
01607    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 
01608          && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01609       if (pvt->setup_ack) {
01610          if (!pri_grab(pvt, pvt->pri)) {
01611             pri_information(pvt->pri->pri, pvt->call, digit);
01612             pri_rel(pvt->pri);
01613          } else
01614             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01615       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01616          int res;
01617          ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01618          res = strlen(pvt->dialdest);
01619          pvt->dialdest[res++] = digit;
01620          pvt->dialdest[res] = '\0';
01621       }
01622       goto out;
01623    }
01624 #endif
01625    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01626       goto out;
01627 
01628    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01629       int res;
01630       struct dahdi_dialoperation zo = {
01631          .op = DAHDI_DIAL_OP_APPEND,
01632       };
01633 
01634       zo.dialstr[0] = 'T';
01635       zo.dialstr[1] = digit;
01636       zo.dialstr[2] = '\0';
01637       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01638          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01639       else
01640          pvt->dialing = 1;
01641    } else {
01642       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01643       pvt->dialing = 1;
01644       pvt->begindigit = digit;
01645    }
01646 
01647 out:
01648    ast_mutex_unlock(&pvt->lock);
01649 
01650    return 0;
01651 }
01652 
01653 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
01654 {
01655    struct dahdi_pvt *pvt;
01656    int res = 0;
01657    int idx;
01658    int x;
01659    
01660    pvt = chan->tech_pvt;
01661 
01662    ast_mutex_lock(&pvt->lock);
01663    
01664    idx = dahdi_get_index(chan, pvt, 0);
01665 
01666    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01667       goto out;
01668 
01669 #ifdef HAVE_PRI
01670    /* This means that the digit was already sent via PRI signalling */
01671    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01672          && !pvt->begindigit)
01673       goto out;
01674 #endif
01675 
01676    if (pvt->begindigit) {
01677       x = -1;
01678       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01679       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01680       pvt->dialing = 0;
01681       pvt->begindigit = 0;
01682    }
01683 
01684 out:
01685    ast_mutex_unlock(&pvt->lock);
01686 
01687    return res;
01688 }
01689 
01690 static char *events[] = {
01691    "No event",
01692    "On hook",
01693    "Ring/Answered",
01694    "Wink/Flash",
01695    "Alarm",
01696    "No more alarm",
01697    "HDLC Abort",
01698    "HDLC Overrun",
01699    "HDLC Bad FCS",
01700    "Dial Complete",
01701    "Ringer On",
01702    "Ringer Off",
01703    "Hook Transition Complete",
01704    "Bits Changed",
01705    "Pulse Start",
01706    "Timer Expired",
01707    "Timer Ping",
01708    "Polarity Reversal",
01709    "Ring Begin",
01710 };
01711 
01712 static struct {
01713    int alarm;
01714    char *name;
01715 } alarms[] = {
01716    { DAHDI_ALARM_RED, "Red Alarm" },
01717    { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
01718    { DAHDI_ALARM_BLUE, "Blue Alarm" },
01719    { DAHDI_ALARM_RECOVER, "Recovering" },
01720    { DAHDI_ALARM_LOOPBACK, "Loopback" },
01721    { DAHDI_ALARM_NOTOPEN, "Not Open" },
01722    { DAHDI_ALARM_NONE, "None" },
01723 };
01724 
01725 static char *alarm2str(int alm)
01726 {
01727    int x;
01728    for (x = 0; x < ARRAY_LEN(alarms); x++) {
01729       if (alarms[x].alarm & alm)
01730          return alarms[x].name;
01731    }
01732    return alm ? "Unknown Alarm" : "No Alarm";
01733 }
01734 
01735 static char *event2str(int event)
01736 {
01737    static char buf[256];
01738    if ((event < (ARRAY_LEN(events))) && (event > -1))
01739       return events[event];
01740    sprintf(buf, "Event %d", event); /* safe */
01741    return buf;
01742 }
01743 
01744 #ifdef HAVE_PRI
01745 static char *dialplan2str(int dialplan)
01746 {
01747    if (dialplan == -1 || dialplan == -2) {
01748       return("Dynamically set dialplan in ISDN");
01749    }
01750    return (pri_plan2str(dialplan));
01751 }
01752 #endif
01753 
01754 static char *dahdi_sig2str(int sig)
01755 {
01756    static char buf[256];
01757    switch (sig) {
01758    case SIG_EM:
01759       return "E & M Immediate";
01760    case SIG_EMWINK:
01761       return "E & M Wink";
01762    case SIG_EM_E1:
01763       return "E & M E1";
01764    case SIG_FEATD:
01765       return "Feature Group D (DTMF)";
01766    case SIG_FEATDMF:
01767       return "Feature Group D (MF)";
01768    case SIG_FEATDMF_TA:
01769       return "Feature Groud D (MF) Tandem Access";
01770    case SIG_FEATB:
01771       return "Feature Group B (MF)";
01772    case SIG_E911:
01773       return "E911 (MF)";
01774    case SIG_FGC_CAMA:
01775       return "FGC/CAMA (Dialpulse)";
01776    case SIG_FGC_CAMAMF:
01777       return "FGC/CAMA (MF)";
01778    case SIG_FXSLS:
01779       return "FXS Loopstart";
01780    case SIG_FXSGS:
01781       return "FXS Groundstart";
01782    case SIG_FXSKS:
01783       return "FXS Kewlstart";
01784    case SIG_FXOLS:
01785       return "FXO Loopstart";
01786    case SIG_FXOGS:
01787       return "FXO Groundstart";
01788    case SIG_FXOKS:
01789       return "FXO Kewlstart";
01790    case SIG_PRI:
01791       return "ISDN PRI";
01792    case SIG_BRI:
01793       return "ISDN BRI Point to Point";
01794    case SIG_BRI_PTMP:
01795       return "ISDN BRI Point to MultiPoint";
01796    case SIG_SS7:
01797       return "SS7";
01798    case SIG_SF:
01799       return "SF (Tone) Immediate";
01800    case SIG_SFWINK:
01801       return "SF (Tone) Wink";
01802    case SIG_SF_FEATD:
01803       return "SF (Tone) with Feature Group D (DTMF)";
01804    case SIG_SF_FEATDMF:
01805       return "SF (Tone) with Feature Group D (MF)";
01806    case SIG_SF_FEATB:
01807       return "SF (Tone) with Feature Group B (MF)";
01808    case SIG_GR303FXOKS:
01809       return "GR-303 with FXOKS";
01810    case SIG_GR303FXSKS:
01811       return "GR-303 with FXSKS";
01812    case 0:
01813       return "Pseudo";
01814    default:
01815       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01816       return buf;
01817    }
01818 }
01819 
01820 #define sig2str dahdi_sig2str
01821 
01822 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
01823 {
01824    /* If the conference already exists, and we're already in it
01825       don't bother doing anything */
01826    struct dahdi_confinfo zi;
01827    
01828    memset(&zi, 0, sizeof(zi));
01829    zi.chan = 0;
01830 
01831    if (slavechannel > 0) {
01832       /* If we have only one slave, do a digital mon */
01833       zi.confmode = DAHDI_CONF_DIGITALMON;
01834       zi.confno = slavechannel;
01835    } else {
01836       if (!idx) {
01837          /* Real-side and pseudo-side both participate in conference */
01838          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01839             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01840       } else
01841          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01842       zi.confno = p->confno;
01843    }
01844    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01845       return 0;
01846    if (c->dfd < 0)
01847       return 0;
01848    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01849       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01850       return -1;
01851    }
01852    if (slavechannel < 1) {
01853       p->confno = zi.confno;
01854    }
01855    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01856    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01857    return 0;
01858 }
01859 
01860 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
01861 {
01862    /* If they're listening to our channel, they're ours */  
01863    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01864       return 1;
01865    /* If they're a talker on our (allocated) conference, they're ours */
01866    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01867       return 1;
01868    return 0;
01869 }
01870 
01871 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
01872 {
01873    struct dahdi_confinfo zi;
01874    if (/* Can't delete if there's no dfd */
01875       (c->dfd < 0) ||
01876       /* Don't delete from the conference if it's not our conference */
01877       !isourconf(p, c)
01878       /* Don't delete if we don't think it's conferenced at all (implied) */
01879       ) return 0;
01880    memset(&zi, 0, sizeof(zi));
01881    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01882       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01883       return -1;
01884    }
01885    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01886    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01887    return 0;
01888 }
01889 
01890 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
01891 {
01892    int x;
01893    int useslavenative;
01894    struct dahdi_pvt *slave = NULL;
01895    /* Start out optimistic */
01896    useslavenative = 1;
01897    /* Update conference state in a stateless fashion */
01898    for (x = 0; x < 3; x++) {
01899       /* Any three-way calling makes slave native mode *definitely* out
01900          of the question */
01901       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01902          useslavenative = 0;
01903    }
01904    /* If we don't have any 3-way calls, check to see if we have
01905       precisely one slave */
01906    if (useslavenative) {
01907       for (x = 0; x < MAX_SLAVES; x++) {
01908          if (p->slaves[x]) {
01909             if (slave) {
01910                /* Whoops already have a slave!  No 
01911                   slave native and stop right away */
01912                slave = NULL;
01913                useslavenative = 0;
01914                break;
01915             } else {
01916                /* We have one slave so far */
01917                slave = p->slaves[x];
01918             }
01919          }
01920       }
01921    }
01922    /* If no slave, slave native definitely out */
01923    if (!slave)
01924       useslavenative = 0;
01925    else if (slave->law != p->law) {
01926       useslavenative = 0;
01927       slave = NULL;
01928    }
01929    if (out)
01930       *out = slave;
01931    return useslavenative;
01932 }
01933 
01934 static int reset_conf(struct dahdi_pvt *p)
01935 {
01936    p->confno = -1;
01937    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01938    if (p->subs[SUB_REAL].dfd > -1) {
01939       struct dahdi_confinfo zi;
01940 
01941       memset(&zi, 0, sizeof(zi));
01942       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01943          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01944    }
01945    return 0;
01946 }
01947 
01948 static int update_conf(struct dahdi_pvt *p)
01949 {
01950    int needconf = 0;
01951    int x;
01952    int useslavenative;
01953    struct dahdi_pvt *slave = NULL;
01954 
01955    useslavenative = isslavenative(p, &slave);
01956    /* Start with the obvious, general stuff */
01957    for (x = 0; x < 3; x++) {
01958       /* Look for three way calls */
01959       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01960          conf_add(p, &p->subs[x], x, 0);
01961          needconf++;
01962       } else {
01963          conf_del(p, &p->subs[x], x);
01964       }
01965    }
01966    /* If we have a slave, add him to our conference now. or DAX
01967       if this is slave native */
01968    for (x = 0; x < MAX_SLAVES; x++) {
01969       if (p->slaves[x]) {
01970          if (useslavenative)
01971             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01972          else {
01973             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01974             needconf++;
01975          }
01976       }
01977    }
01978    /* If we're supposed to be in there, do so now */
01979    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01980       if (useslavenative)
01981          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01982       else {
01983          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01984          needconf++;
01985       }
01986    }
01987    /* If we have a master, add ourselves to his conference */
01988    if (p->master) {
01989       if (isslavenative(p->master, NULL)) {
01990          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01991       } else {
01992          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01993       }
01994    }
01995    if (!needconf) {
01996       /* Nobody is left (or should be left) in our conference.
01997          Kill it. */
01998       p->confno = -1;
01999    }
02000    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02001    return 0;
02002 }
02003 
02004 static void dahdi_enable_ec(struct dahdi_pvt *p)
02005 {
02006    int x;
02007    int res;
02008    if (!p)
02009       return;
02010    if (p->echocanon) {
02011       ast_debug(1, "Echo cancellation already on\n");
02012       return;
02013    }
02014    if (p->digital) {
02015       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02016       return;
02017    }
02018    if (p->echocancel.head.tap_length) {
02019       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02020          x = 1;
02021          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02022          if (res)
02023             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02024       }
02025       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02026       if (res)  {
02027          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02028       } else {
02029          p->echocanon = 1;
02030          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02031       }
02032    } else
02033       ast_debug(1, "No echo cancellation requested\n");
02034 }
02035 
02036 static void dahdi_train_ec(struct dahdi_pvt *p)
02037 {
02038    int x;
02039    int res;
02040    
02041    if (p && p->echocanon && p->echotraining) {
02042       x = p->echotraining;
02043       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02044       if (res)
02045          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02046       else
02047          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02048    } else {
02049       ast_debug(1, "No echo training requested\n");
02050    }
02051 }
02052 
02053 static void dahdi_disable_ec(struct dahdi_pvt *p)
02054 {
02055    int res;
02056 
02057    if (p->echocanon) {
02058       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02059 
02060       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02061 
02062       if (res)
02063          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02064       else
02065          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02066    }
02067 
02068    p->echocanon = 0;
02069 }
02070 
02071 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
02072 {
02073    int j;
02074    int k;
02075    float linear_gain = pow(10.0, gain / 20.0);
02076 
02077    switch (law) {
02078    case DAHDI_LAW_ALAW:
02079       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02080          if (gain) {
02081             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02082             if (k > 32767) k = 32767;
02083             if (k < -32767) k = -32767;
02084             g->txgain[j] = AST_LIN2A(k);
02085          } else {
02086             g->txgain[j] = j;
02087          }
02088       }
02089       break;
02090    case DAHDI_LAW_MULAW:
02091       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02092          if (gain) {
02093             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02094             if (k > 32767) k = 32767;
02095             if (k < -32767) k = -32767;
02096             g->txgain[j] = AST_LIN2MU(k);
02097          } else {
02098             g->txgain[j] = j;
02099          }
02100       }
02101       break;
02102    }
02103 }
02104 
02105 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
02106 {
02107    int j;
02108    int k;
02109    float linear_gain = pow(10.0, gain / 20.0);
02110 
02111    switch (law) {
02112    case DAHDI_LAW_ALAW:
02113       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02114          if (gain) {
02115             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02116             if (k > 32767) k = 32767;
02117             if (k < -32767) k = -32767;
02118             g->rxgain[j] = AST_LIN2A(k);
02119          } else {
02120             g->rxgain[j] = j;
02121          }
02122       }
02123       break;
02124    case DAHDI_LAW_MULAW:
02125       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02126          if (gain) {
02127             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02128             if (k > 32767) k = 32767;
02129             if (k < -32767) k = -32767;
02130             g->rxgain[j] = AST_LIN2MU(k);
02131          } else {
02132             g->rxgain[j] = j;
02133          }
02134       }
02135       break;
02136    }
02137 }
02138 
02139 static int set_actual_txgain(int fd, int chan, float gain, int law)
02140 {
02141    struct dahdi_gains g;
02142    int res;
02143 
02144    memset(&g, 0, sizeof(g));
02145    g.chan = chan;
02146    res = ioctl(fd, DAHDI_GETGAINS, &g);
02147    if (res) {
02148       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02149       return res;
02150    }
02151 
02152    fill_txgain(&g, gain, law);
02153 
02154    return ioctl(fd, DAHDI_SETGAINS, &g);
02155 }
02156 
02157 static int set_actual_rxgain(int fd, int chan, float gain, int law)
02158 {
02159    struct dahdi_gains g;
02160    int res;
02161 
02162    memset(&g, 0, sizeof(g));
02163    g.chan = chan;
02164    res = ioctl(fd, DAHDI_GETGAINS, &g);
02165    if (res) {
02166       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02167       return res;
02168    }
02169 
02170    fill_rxgain(&g, gain, law);
02171 
02172    return ioctl(fd, DAHDI_SETGAINS, &g);
02173 }
02174 
02175 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
02176 {
02177    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02178 }
02179 
02180 static int bump_gains(struct dahdi_pvt *p)
02181 {
02182    int res;
02183 
02184    /* Bump receive gain by value stored in cid_rxgain */
02185    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02186    if (res) {
02187       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02188       return -1;
02189    }
02190 
02191    return 0;
02192 }
02193 
02194 static int restore_gains(struct dahdi_pvt *p)
02195 {
02196    int res;
02197 
02198    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02199    if (res) {
02200       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02201       return -1;
02202    }
02203 
02204    return 0;
02205 }
02206 
02207 static inline int dahdi_set_hook(int fd, int hs)
02208 {
02209    int x, res;
02210 
02211    x = hs;
02212    res = ioctl(fd, DAHDI_HOOK, &x);
02213 
02214    if (res < 0) {
02215       if (errno == EINPROGRESS)
02216          return 0;
02217       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02218       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02219    }
02220 
02221    return res;
02222 }
02223 
02224 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
02225 {
02226    int x, y, res;
02227    x = muted;
02228    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02229       y = 1;
02230       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02231       if (res)
02232          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02233    }
02234    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02235    if (res < 0)
02236       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02237    return res;
02238 }
02239 
02240 static int save_conference(struct dahdi_pvt *p)
02241 {
02242    struct dahdi_confinfo c;
02243    int res;
02244    if (p->saveconf.confmode) {
02245       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02246       return -1;
02247    }
02248    p->saveconf.chan = 0;
02249    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02250    if (res) {
02251       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02252       p->saveconf.confmode = 0;
02253       return -1;
02254    }
02255    memset(&c, 0, sizeof(c));
02256    c.confmode = DAHDI_CONF_NORMAL;
02257    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02258    if (res) {
02259       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02260       return -1;
02261    }
02262    ast_debug(1, "Disabled conferencing\n");
02263    return 0;
02264 }
02265 
02266 /*!
02267  * \brief Send MWI state change
02268  *
02269  * \arg mailbox_full This is the mailbox associated with the FXO line that the
02270  *      MWI state has changed on.
02271  * \arg thereornot This argument should simply be set to 1 or 0, to indicate
02272  *      whether there are messages waiting or not.
02273  *
02274  *  \return nothing
02275  *
02276  * This function does two things:
02277  *
02278  * 1) It generates an internal Asterisk event notifying any other module that
02279  *    cares about MWI that the state of a mailbox has changed.
02280  *
02281  * 2) It runs the script specified by the mwimonitornotify option to allow
02282  *    some custom handling of the state change.
02283  */
02284 static void notify_message(char *mailbox_full, int thereornot)
02285 {
02286    char s[sizeof(mwimonitornotify) + 80];
02287    struct ast_event *event;
02288    char *mailbox, *context;
02289 
02290    /* Strip off @default */
02291    context = mailbox = ast_strdupa(mailbox_full);
02292    strsep(&context, "@");
02293    if (ast_strlen_zero(context))
02294       context = "default";
02295 
02296    if (!(event = ast_event_new(AST_EVENT_MWI,
02297          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02298          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02299          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02300          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02301          AST_EVENT_IE_END))) {
02302       return;
02303    }
02304 
02305    ast_event_queue_and_cache(event);
02306 
02307    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02308       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02309       ast_safe_system(s);
02310    }
02311 }
02312 
02313 static int restore_conference(struct dahdi_pvt *p)
02314 {
02315    int res;
02316    if (p->saveconf.confmode) {
02317       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02318       p->saveconf.confmode = 0;
02319       if (res) {
02320          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02321          return -1;
02322       }
02323    }
02324    ast_debug(1, "Restored conferencing\n");
02325    return 0;
02326 }
02327 
02328 static int send_callerid(struct dahdi_pvt *p);
02329 
02330 static int send_cwcidspill(struct dahdi_pvt *p)
02331 {
02332    p->callwaitcas = 0;
02333    p->cidcwexpire = 0;
02334    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02335       return -1;
02336    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02337    /* Make sure we account for the end */
02338    p->cidlen += READ_SIZE * 4;
02339    p->cidpos = 0;
02340    send_callerid(p);
02341    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02342    return 0;
02343 }
02344 
02345 static int has_voicemail(struct dahdi_pvt *p)
02346 {
02347    int new_msgs;
02348    struct ast_event *event;
02349    char *mailbox, *context;
02350 
02351    mailbox = context = ast_strdupa(p->mailbox);
02352    strsep(&context, "@");
02353    if (ast_strlen_zero(context))
02354       context = "default";
02355 
02356    event = ast_event_get_cached(AST_EVENT_MWI,
02357       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02358       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02359       AST_EVENT_IE_END);
02360 
02361    if (event) {
02362       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02363       ast_event_destroy(event);
02364    } else
02365       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02366 
02367    return new_msgs;
02368 }
02369 
02370 static int send_callerid(struct dahdi_pvt *p)
02371 {
02372    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02373    int res;
02374    /* Take out of linear mode if necessary */
02375    if (p->subs[SUB_REAL].linear) {
02376       p->subs[SUB_REAL].linear = 0;
02377       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02378    }
02379    while (p->cidpos < p->cidlen) {
02380       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02381       if (res < 0) {
02382          if (errno == EAGAIN)
02383             return 0;
02384          else {
02385             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02386             return -1;
02387          }
02388       }
02389       if (!res)
02390          return 0;
02391       p->cidpos += res;
02392    }
02393    ast_free(p->cidspill);
02394    p->cidspill = NULL;
02395    if (p->callwaitcas) {
02396       /* Wait for CID/CW to expire */
02397       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02398    } else
02399       restore_conference(p);
02400    return 0;
02401 }
02402 
02403 static int dahdi_callwait(struct ast_channel *ast)
02404 {
02405    struct dahdi_pvt *p = ast->tech_pvt;
02406    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02407    if (p->cidspill) {
02408       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02409       ast_free(p->cidspill);
02410    }
02411    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02412       return -1;
02413    save_conference(p);
02414    /* Silence */
02415    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02416    if (!p->callwaitrings && p->callwaitingcallerid) {
02417       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02418       p->callwaitcas = 1;
02419       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02420    } else {
02421       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02422       p->callwaitcas = 0;
02423       p->cidlen = 2400 + READ_SIZE * 4;
02424    }
02425    p->cidpos = 0;
02426    send_callerid(p);
02427    
02428    return 0;
02429 }
02430 
02431 #ifdef HAVE_SS7
02432 static unsigned char cid_pres2ss7pres(int cid_pres)
02433 {
02434     return (cid_pres >> 5) & 0x03;
02435 }
02436 
02437 static unsigned char cid_pres2ss7screen(int cid_pres)
02438 {
02439    return cid_pres & 0x03;
02440 }
02441 #endif
02442 
02443 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
02444 {
02445    struct dahdi_pvt *p = ast->tech_pvt;
02446    int x, res, idx,mysig;
02447    char *c, *n, *l;
02448 #ifdef HAVE_PRI
02449    char *s = NULL;
02450 #endif
02451    char dest[256]; /* must be same length as p->dialdest */
02452    ast_mutex_lock(&p->lock);
02453    ast_copy_string(dest, rdest, sizeof(dest));
02454    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02455    if ((ast->_state == AST_STATE_BUSY)) {
02456       p->subs[SUB_REAL].needbusy = 1;
02457       ast_mutex_unlock(&p->lock);
02458       return 0;
02459    }
02460    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02461       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02462       ast_mutex_unlock(&p->lock);
02463       return -1;
02464    }
02465    p->dialednone = 0;
02466    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02467    {
02468       /* Special pseudo -- automatically up */
02469       ast_setstate(ast, AST_STATE_UP); 
02470       ast_mutex_unlock(&p->lock);
02471       return 0;
02472    }
02473    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02474    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02475    if (res)
02476       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02477    p->outgoing = 1;
02478 
02479    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02480 
02481    mysig = p->sig;
02482    if (p->outsigmod > -1)
02483       mysig = p->outsigmod;
02484 
02485    switch (mysig) {
02486    case SIG_FXOLS:
02487    case SIG_FXOGS:
02488    case SIG_FXOKS:
02489       if (p->owner == ast) {
02490          /* Normal ring, on hook */
02491          
02492          /* Don't send audio while on hook, until the call is answered */
02493          p->dialing = 1;
02494          if (p->use_callerid) {
02495             /* Generate the Caller-ID spill if desired */
02496             if (p->cidspill) {
02497                ast_log(LOG_WARNING, "cidspill already exists??\n");
02498                ast_free(p->cidspill);
02499             }
02500             p->callwaitcas = 0;
02501             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02502                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02503                p->cidpos = 0;
02504                send_callerid(p);
02505             }
02506          }
02507          /* Choose proper cadence */
02508          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02509             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02510                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02511             p->cidrings = cidrings[p->distinctivering - 1];
02512          } else {
02513             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02514                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02515             p->cidrings = p->sendcalleridafter;
02516          }
02517 
02518          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02519          c = strchr(dest, '/');
02520          if (c)
02521             c++;
02522          if (c && (strlen(c) < p->stripmsd)) {
02523             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02524             c = NULL;
02525          }
02526          if (c) {
02527             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02528             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02529             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02530          } else {
02531             p->dop.dialstr[0] = '\0';
02532          }
02533          x = DAHDI_RING;
02534          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02535             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02536             ast_mutex_unlock(&p->lock);
02537             return -1;
02538          }
02539          p->dialing = 1;
02540       } else {
02541          /* Call waiting call */
02542          p->callwaitrings = 0;
02543          if (ast->cid.cid_num)
02544             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02545          else
02546             p->callwait_num[0] = '\0';
02547          if (ast->cid.cid_name)
02548             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02549          else
02550             p->callwait_name[0] = '\0';
02551          /* Call waiting tone instead */
02552          if (dahdi_callwait(ast)) {
02553             ast_mutex_unlock(&p->lock);
02554             return -1;
02555          }
02556          /* Make ring-back */
02557          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02558             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02559             
02560       }
02561       n = ast->cid.cid_name;
02562       l = ast->cid.cid_num;
02563       if (l)
02564          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02565       else
02566          p->lastcid_num[0] = '\0';
02567       if (n)
02568          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02569       else
02570          p->lastcid_name[0] = '\0';
02571       ast_setstate(ast, AST_STATE_RINGING);
02572       idx = dahdi_get_index(ast, p, 0);
02573       if (idx > -1) {
02574          p->subs[idx].needringing = 1;
02575       }
02576       break;
02577    case SIG_FXSLS:
02578    case SIG_FXSGS:
02579    case SIG_FXSKS:
02580       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02581          ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
02582          p->polaritydelaytv = ast_tvnow();
02583       }
02584       /* fall through */
02585    case SIG_EMWINK:
02586    case SIG_EM:
02587    case SIG_EM_E1:
02588    case SIG_FEATD:
02589    case SIG_FEATDMF:
02590    case SIG_E911:
02591    case SIG_FGC_CAMA:
02592    case SIG_FGC_CAMAMF:
02593    case SIG_FEATB:
02594    case SIG_SFWINK:
02595    case SIG_SF:
02596    case SIG_SF_FEATD:
02597    case SIG_SF_FEATDMF:
02598    case SIG_FEATDMF_TA:
02599    case SIG_SF_FEATB:
02600       c = strchr(dest, '/');
02601       if (c)
02602          c++;
02603       else
02604          c = "";
02605       if (strlen(c) < p->stripmsd) {
02606          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02607          ast_mutex_unlock(&p->lock);
02608          return -1;
02609       }
02610 #ifdef HAVE_PRI
02611       /* Start the trunk, if not GR-303 */
02612       if (!p->pri) {
02613 #endif
02614          x = DAHDI_START;
02615          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02616          if (res < 0) {
02617             if (errno != EINPROGRESS) {
02618                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02619                ast_mutex_unlock(&p->lock);
02620                return -1;
02621             }
02622          }
02623 #ifdef HAVE_PRI
02624       }
02625 #endif
02626       ast_debug(1, "Dialing '%s'\n", c);
02627       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02628 
02629       c += p->stripmsd;
02630 
02631       switch (mysig) {
02632       case SIG_FEATD:
02633          l = ast->cid.cid_num;
02634          if (l) 
02635             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02636          else
02637             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02638          break;
02639       case SIG_FEATDMF:
02640          l = ast->cid.cid_num;
02641          if (l) 
02642             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02643          else
02644             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02645          break;
02646       case SIG_FEATDMF_TA:
02647       {
02648          const char *cic, *ozz;
02649 
02650          /* If you have to go through a Tandem Access point you need to use this */
02651          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02652          if (!ozz)
02653             ozz = defaultozz;
02654          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02655          if (!cic)
02656             cic = defaultcic;
02657          if (!ozz || !cic) {
02658             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02659             ast_mutex_unlock(&p->lock);
02660             return -1;
02661          }
02662          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02663          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02664          p->whichwink = 0;
02665       }
02666          break;
02667       case SIG_E911:
02668          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02669          break;
02670       case SIG_FGC_CAMA:
02671          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02672          break;
02673       case SIG_FGC_CAMAMF:
02674       case SIG_FEATB:
02675          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02676          break;
02677       default:
02678          if (p->pulse)
02679             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02680          else
02681             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02682          break;
02683       }
02684 
02685       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02686          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02687          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02688          p->echorest[sizeof(p->echorest) - 1] = '\0';
02689          p->echobreak = 1;
02690          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02691       } else
02692          p->echobreak = 0;
02693       if (!res) {
02694          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02695             int saveerr = errno;
02696 
02697             x = DAHDI_ONHOOK;
02698             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02699             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02700             ast_mutex_unlock(&p->lock);
02701             return -1;
02702          }
02703       } else
02704          ast_debug(1, "Deferring dialing...\n");
02705 
02706       p->dialing = 1;
02707       if (ast_strlen_zero(c))
02708          p->dialednone = 1;
02709       ast_setstate(ast, AST_STATE_DIALING);
02710       break;
02711    case 0:
02712       /* Special pseudo -- automatically up*/
02713       ast_setstate(ast, AST_STATE_UP);
02714       break;      
02715    case SIG_PRI:
02716    case SIG_BRI:
02717    case SIG_BRI_PTMP:
02718    case SIG_SS7:
02719       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02720       p->dialdest[0] = '\0';
02721       p->dialing = 1;
02722       break;
02723    default:
02724       ast_debug(1, "not yet implemented\n");
02725       ast_mutex_unlock(&p->lock);
02726       return -1;
02727    }
02728 #ifdef HAVE_SS7
02729    if (p->ss7) {
02730       char ss7_called_nai;
02731       int called_nai_strip;
02732       char ss7_calling_nai;
02733       int calling_nai_strip;
02734       const char *charge_str = NULL;
02735       const char *gen_address = NULL;
02736       const char *gen_digits = NULL;
02737       const char *gen_dig_type = NULL;
02738       const char *gen_dig_scheme = NULL;
02739       const char *gen_name = NULL;
02740       const char *jip_digits = NULL;
02741       const char *lspi_ident = NULL;
02742       const char *rlt_flag = NULL;
02743       const char *call_ref_id = NULL;
02744       const char *call_ref_pc = NULL;
02745       const char *send_far = NULL;
02746 
02747       c = strchr(dest, '/');
02748       if (c) {
02749          c++;
02750       } else {
02751          c = "";
02752       }
02753       if (strlen(c) < p->stripmsd) {
02754          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02755          ast_mutex_unlock(&p->lock);
02756          return -1;
02757       }
02758 
02759       if (!p->hidecallerid) {
02760          l = ast->cid.cid_num;
02761       } else {
02762          l = NULL;
02763       }
02764 
02765       if (ss7_grab(p, p->ss7)) {
02766          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02767          ast_mutex_unlock(&p->lock);
02768          return -1;
02769       }
02770       p->digital = IS_DIGITAL(ast->transfercapability);
02771       p->ss7call = isup_new_call(p->ss7->ss7);
02772 
02773       if (!p->ss7call) {
02774          ss7_rel(p->ss7);
02775          ast_mutex_unlock(&p->lock);
02776          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02777          return -1;
02778       }
02779 
02780       called_nai_strip = 0;
02781       ss7_called_nai = p->ss7->called_nai;
02782       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
02783          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02784             called_nai_strip = strlen(p->ss7->internationalprefix);
02785             ss7_called_nai = SS7_NAI_INTERNATIONAL;
02786          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02787             called_nai_strip = strlen(p->ss7->nationalprefix);
02788             ss7_called_nai = SS7_NAI_NATIONAL;
02789          } else {
02790             ss7_called_nai = SS7_NAI_SUBSCRIBER;
02791          }
02792       }
02793       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02794 
02795       calling_nai_strip = 0;
02796       ss7_calling_nai = p->ss7->calling_nai;
02797       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
02798          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02799             calling_nai_strip = strlen(p->ss7->internationalprefix);
02800             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02801          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02802             calling_nai_strip = strlen(p->ss7->nationalprefix);
02803             ss7_calling_nai = SS7_NAI_NATIONAL;
02804          } else {
02805             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02806          }
02807       }
02808       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02809          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02810          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02811 
02812       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02813       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02814 
02815       ast_channel_lock(ast);
02816       /* Set the charge number if it is set */
02817       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02818       if (charge_str)
02819          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02820       
02821       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02822       if (gen_address)
02823          isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
02824       
02825       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02826       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02827       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02828       if (gen_digits)
02829          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 
02830       
02831       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02832       if (gen_name)
02833          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02834 
02835       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02836       if (jip_digits)
02837          isup_set_jip_digits(p->ss7call, jip_digits);
02838       
02839       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02840       if (lspi_ident)
02841          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 
02842       
02843       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02844       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02845          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
02846       }
02847       
02848       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02849       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02850       if (call_ref_id && call_ref_pc) {
02851          isup_set_callref(p->ss7call, atoi(call_ref_id),
02852                 call_ref_pc ? atoi(call_ref_pc) : 0);
02853       }
02854       
02855       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02856       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02857          (isup_far(p->ss7->ss7, p->ss7call));
02858       
02859       ast_channel_unlock(ast);
02860 
02861       isup_iam(p->ss7->ss7, p->ss7call);
02862       ast_setstate(ast, AST_STATE_DIALING);
02863       ss7_rel(p->ss7);
02864    }
02865 #endif /* HAVE_SS7 */
02866 #ifdef HAVE_PRI
02867    if (p->pri) {
02868       struct pri_sr *sr;
02869 #ifdef SUPPORT_USERUSER
02870       const char *useruser;
02871 #endif
02872       int pridialplan;
02873       int dp_strip;
02874       int prilocaldialplan;
02875       int ldp_strip;
02876       int exclusive;
02877       const char *rr_str;
02878       int redirect_reason;
02879 
02880       c = strchr(dest, '/');
02881       if (c) {
02882          c++;
02883       } else {
02884          c = "";
02885       }
02886 
02887       l = NULL;
02888       n = NULL;
02889       if (!p->hidecallerid) {
02890          l = ast->cid.cid_num;
02891          if (!p->hidecalleridname) {
02892             n = ast->cid.cid_name;
02893          }
02894       }
02895 
02896       if (strlen(c) < p->stripmsd) {
02897          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02898          ast_mutex_unlock(&p->lock);
02899          return -1;
02900       }
02901       if (mysig != SIG_FXSKS) {
02902          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02903          s = strchr(c + p->stripmsd, 'w');
02904          if (s) {
02905             if (strlen(s) > 1)
02906                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02907             else
02908                p->dop.dialstr[0] = '\0';
02909             *s = '\0';
02910          } else {
02911             p->dop.dialstr[0] = '\0';
02912          }
02913       }
02914       if (pri_grab(p, p->pri)) {
02915          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02916          ast_mutex_unlock(&p->lock);
02917          return -1;
02918       }
02919       if (!(p->call = pri_new_call(p->pri->pri))) {
02920          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02921          pri_rel(p->pri);
02922          ast_mutex_unlock(&p->lock);
02923          return -1;
02924       }
02925       if (!(sr = pri_sr_new())) {
02926          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02927          pri_rel(p->pri);
02928          ast_mutex_unlock(&p->lock);
02929       }
02930       if (p->bearer || (mysig == SIG_FXSKS)) {
02931          if (p->bearer) {
02932             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02933             p->bearer->call = p->call;
02934          } else
02935             ast_debug(1, "I'm being setup with no bearer right now...\n");
02936 
02937          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02938       }
02939       p->digital = IS_DIGITAL(ast->transfercapability);
02940 
02941       /* Should the picked channel be used exclusively? */
02942       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02943          exclusive = 1;
02944       } else {
02945          exclusive = 0;
02946       }
02947       
02948       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02949       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02950                (p->digital ? -1 : 
02951                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02952       if (p->pri->facilityenable)
02953          pri_facility_enable(p->pri->pri);
02954 
02955       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02956       dp_strip = 0;
02957       pridialplan = p->pri->dialplan - 1;
02958       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
02959          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02960             if (pridialplan == -2) {
02961                dp_strip = strlen(p->pri->internationalprefix);
02962             }
02963             pridialplan = PRI_INTERNATIONAL_ISDN;
02964          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02965             if (pridialplan == -2) {
02966                dp_strip = strlen(p->pri->nationalprefix);
02967             }
02968             pridialplan = PRI_NATIONAL_ISDN;
02969          } else {
02970             pridialplan = PRI_LOCAL_ISDN;
02971          }
02972       }
02973       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02974          switch (c[p->stripmsd]) {
02975          case 'U':
02976             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02977             break;
02978          case 'I':
02979             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02980             break;
02981          case 'N':
02982             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
02983             break;
02984          case 'L':
02985             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
02986             break;
02987          case 'S':
02988             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
02989             break;
02990          case 'V':
02991             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
02992             break;
02993          case 'R':
02994             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
02995             break;
02996          case 'u':
02997             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
02998             break;
02999          case 'e':
03000             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03001             break;
03002          case 'x':
03003             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03004             break;
03005          case 'f':
03006             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03007             break;
03008          case 'n':
03009             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03010             break;
03011          case 'p':
03012             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03013             break;
03014          case 'r':
03015             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03016             break;
03017          default:
03018             if (isalpha(c[p->stripmsd])) {
03019                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03020                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03021             }
03022             break;
03023          }
03024          c++;
03025       }
03026       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03027 
03028       ldp_strip = 0;
03029       prilocaldialplan = p->pri->localdialplan - 1;
03030       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03031          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03032             if (prilocaldialplan == -2) {
03033                ldp_strip = strlen(p->pri->internationalprefix);
03034             }
03035             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03036          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03037             if (prilocaldialplan == -2) {
03038                ldp_strip = strlen(p->pri->nationalprefix);
03039             }
03040             prilocaldialplan = PRI_NATIONAL_ISDN;
03041          } else {
03042             prilocaldialplan = PRI_LOCAL_ISDN;
03043          }
03044       }
03045       if (l != NULL) {
03046          while (*l > '9' && *l != '*' && *l != '#') {
03047             switch (*l) {
03048             case 'U':
03049                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03050                break;
03051             case 'I':
03052                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03053                break;
03054             case 'N':
03055                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03056                break;
03057             case 'L':
03058                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03059                break;
03060             case 'S':
03061                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03062                break;
03063             case 'V':
03064                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03065                break;
03066             case 'R':
03067                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03068                break;
03069             case 'u':
03070                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03071                break;
03072             case 'e':
03073                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03074                break;
03075             case 'x':
03076                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03077                break;
03078             case 'f':
03079                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03080                break;
03081             case 'n':
03082                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03083                break;
03084             case 'p':
03085                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03086                break;
03087             case 'r':
03088                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03089                break;
03090             default:
03091                if (isalpha(*l)) {
03092                   ast_log(LOG_WARNING,
03093                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03094                      *l > 'Z' ? "NPI" : "TON", *l);
03095                }
03096                break;
03097             }
03098             l++;
03099          }
03100       }
03101       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03102          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03103       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03104          if (!strcasecmp(rr_str, "UNKNOWN"))
03105             redirect_reason = 0;
03106          else if (!strcasecmp(rr_str, "BUSY"))
03107             redirect_reason = 1;
03108          else if (!strcasecmp(rr_str, "NO_REPLY"))
03109             redirect_reason = 2;
03110          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03111             redirect_reason = 15;
03112          else
03113             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03114       } else
03115          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03116       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03117 
03118 #ifdef SUPPORT_USERUSER
03119       /* User-user info */
03120       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03121 
03122       if (useruser)
03123          pri_sr_set_useruser(sr, useruser);
03124 #endif
03125 
03126       if (pri_setup(p->pri->pri, p->call, sr)) {
03127          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
03128             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03129          pri_rel(p->pri);
03130          ast_mutex_unlock(&p->lock);
03131          pri_sr_free(sr);
03132          return -1;
03133       }
03134       pri_sr_free(sr);
03135       ast_setstate(ast, AST_STATE_DIALING);
03136       pri_rel(p->pri);
03137    }
03138 #endif      
03139    ast_mutex_unlock(&p->lock);
03140    return 0;
03141 }
03142 
03143 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
03144 {
03145    struct dahdi_pvt *p = *pvt;
03146    /* Remove channel from the list */
03147    if (p->prev)
03148       p->prev->next = p->next;
03149    if (p->next)
03150       p->next->prev = p->prev;
03151    if (p->use_smdi)
03152       ast_smdi_interface_unref(p->smdi_iface);
03153    if (p->mwi_event_sub)
03154       ast_event_unsubscribe(p->mwi_event_sub);
03155    if (p->vars)
03156       ast_variables_destroy(p->vars);
03157    ast_mutex_destroy(&p->lock);
03158    dahdi_close_sub(p, SUB_REAL);
03159    if (p->owner)
03160       p->owner->tech_pvt = NULL;
03161    free(p);
03162    *pvt = NULL;
03163 }
03164 
03165 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
03166 {
03167    int owned = 0;
03168    int i = 0;
03169 
03170    if (!now) {
03171       if (cur->owner) {
03172          owned = 1;
03173       }
03174 
03175       for (i = 0; i < 3; i++) {
03176          if (cur->subs[i].owner) {
03177             owned = 1;
03178          }
03179       }
03180       if (!owned) {
03181          if (prev) {
03182             prev->next = cur->next;
03183             if (prev->next)
03184                prev->next->prev = prev;
03185             else
03186                ifend = prev;
03187          } else {
03188             iflist = cur->next;
03189             if (iflist)
03190                iflist->prev = NULL;
03191             else
03192                ifend = NULL;
03193          }
03194          destroy_dahdi_pvt(&cur);
03195       }
03196    } else {
03197       if (prev) {
03198          prev->next = cur->next;
03199          if (prev->next)
03200             prev->next->prev = prev;
03201          else
03202             ifend = prev;
03203       } else {
03204          iflist = cur->next;
03205          if (iflist)
03206             iflist->prev = NULL;
03207          else
03208             ifend = NULL;
03209       }
03210       destroy_dahdi_pvt(&cur);
03211    }
03212    return 0;
03213 }
03214 
03215 static void destroy_all_channels(void)
03216 {
03217    int x;
03218    struct dahdi_pvt *p, *pl;
03219 
03220    while (num_restart_pending) {
03221       usleep(1);
03222    }
03223 
03224    ast_mutex_lock(&iflock);
03225    /* Destroy all the interfaces and free their memory */
03226    p = iflist;
03227    while (p) {
03228       /* Free any callerid */
03229       if (p->cidspill)
03230          ast_free(p->cidspill);
03231       pl = p;
03232       p = p->next;
03233       x = pl->channel;
03234       /* Free associated memory */
03235       if (pl)
03236          destroy_dahdi_pvt(&pl);
03237       if (option_verbose > 2) 
03238          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03239    }
03240    iflist = NULL;
03241    ifcount = 0;
03242    ast_mutex_unlock(&iflock);
03243 }
03244 
03245 #ifdef HAVE_PRI
03246 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
03247 
03248 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
03249 
03250 static char *dahdi_send_keypad_facility_descrip = 
03251 "  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
03252 "  IE over the current channel.\n";
03253 
03254 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
03255 {
03256    /* Data will be our digit string */
03257    struct dahdi_pvt *p;
03258    char *digits = (char *) data;
03259 
03260    if (ast_strlen_zero(digits)) {
03261       ast_debug(1, "No digit string sent to application!\n");
03262       return -1;
03263    }
03264 
03265    p = (struct dahdi_pvt *)chan->tech_pvt;
03266 
03267    if (!p) {
03268       ast_debug(1, "Unable to find technology private\n");
03269       return -1;
03270    }
03271 
03272    ast_mutex_lock(&p->lock);
03273 
03274    if (!p->pri || !p->call) {
03275       ast_debug(1, "Unable to find pri or call on channel!\n");
03276       ast_mutex_unlock(&p->lock);
03277       return -1;
03278    }
03279 
03280    if (!pri_grab(p, p->pri)) {
03281       pri_keypad_facility(p->pri->pri, p->call, digits);
03282       pri_rel(p->pri);
03283    } else {
03284       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03285       ast_mutex_unlock(&p->lock);
03286       return -1;
03287    }
03288 
03289    ast_mutex_unlock(&p->lock);
03290 
03291    return 0;
03292 }
03293 
03294 static int pri_is_up(struct dahdi_pri *pri)
03295 {
03296    int x;
03297    for (x = 0; x < NUM_DCHANS; x++) {
03298       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03299          return 1;
03300    }
03301    return 0;
03302 }
03303 
03304 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
03305 {
03306    bearer->owner = &inuse;
03307    bearer->realcall = crv;
03308    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03309    if (crv->subs[SUB_REAL].owner)
03310       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03311    crv->bearer = bearer;
03312    crv->call = bearer->call;
03313    crv->pri = pri;
03314    return 0;
03315 }
03316 
03317 static char *pri_order(int level)
03318 {
03319    switch (level) {
03320    case 0:
03321       return "Primary";
03322    case 1:
03323       return "Secondary";
03324    case 2:
03325       return "Tertiary";
03326    case 3:
03327       return "Quaternary";
03328    default:
03329       return "<Unknown>";
03330    }     
03331 }
03332 
03333 /* Returns fd of the active dchan */
03334 static int pri_active_dchan_fd(struct dahdi_pri *pri)
03335 {
03336    int x = -1;
03337 
03338    for (x = 0; x < NUM_DCHANS; x++) {
03339       if ((pri->dchans[x] == pri->pri))
03340          break;
03341    }
03342 
03343    return pri->fds[x];
03344 }
03345 
03346 static int pri_find_dchan(struct dahdi_pri *pri)
03347 {
03348    int oldslot = -1;
03349    struct pri *old;
03350    int newslot = -1;
03351    int x;
03352    old = pri->pri;
03353    for (x = 0; x < NUM_DCHANS; x++) {
03354       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03355          newslot = x;
03356       if (pri->dchans[x] == old) {
03357          oldslot = x;
03358       }
03359    }
03360    if (newslot < 0) {
03361       newslot = 0;
03362       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03363          pri->dchannels[newslot]);
03364    }
03365    if (old && (oldslot != newslot))
03366       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03367          pri->dchannels[oldslot], pri->dchannels[newslot]);
03368    pri->pri = pri->dchans[newslot];
03369    return 0;
03370 }
03371 #endif
03372 
03373 static int dahdi_hangup(struct ast_channel *ast)
03374 {
03375    int res;
03376    int idx,x, law;
03377    /*static int restore_gains(struct dahdi_pvt *p);*/
03378    struct dahdi_pvt *p = ast->tech_pvt;
03379    struct dahdi_pvt *tmp = NULL;
03380    struct dahdi_pvt *prev = NULL;
03381    struct dahdi_params par;
03382 
03383    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03384    if (!ast->tech_pvt) {
03385       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03386       return 0;
03387    }
03388    
03389    ast_mutex_lock(&p->lock);
03390    
03391    idx = dahdi_get_index(ast, p, 1);
03392 
03393    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03394       x = 1;
03395       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03396    }
03397 
03398    x = 0;
03399    dahdi_confmute(p, 0);
03400    p->muting = 0;
03401    restore_gains(p);
03402    if (p->origcid_num) {
03403       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03404       ast_free(p->origcid_num);
03405       p->origcid_num = NULL;
03406    }  
03407    if (p->origcid_name) {
03408       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03409       ast_free(p->origcid_name);
03410       p->origcid_name = NULL;
03411    }  
03412    if (p->dsp)
03413       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03414    p->exten[0] = '\0';
03415 
03416    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03417       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03418    p->ignoredtmf = 0;
03419    
03420    if (idx > -1) {
03421       /* Real channel, do some fixup */
03422       p->subs[idx].owner = NULL;
03423       p->subs[idx].needanswer = 0;
03424       p->subs[idx].needflash = 0;
03425       p->subs[idx].needringing = 0;
03426       p->subs[idx].needbusy = 0;
03427       p->subs[idx].needcongestion = 0;
03428       p->subs[idx].linear = 0;
03429       p->subs[idx].needcallerid = 0;
03430       p->polarity = POLARITY_IDLE;
03431       dahdi_setlinear(p->subs[idx].dfd, 0);
03432       if (idx == SUB_REAL) {
03433          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03434             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03435             if (p->subs[SUB_CALLWAIT].inthreeway) {
03436                /* We had flipped over to answer a callwait and now it's gone */
03437                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03438                /* Move to the call-wait, but un-own us until they flip back. */
03439                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03440                unalloc_sub(p, SUB_CALLWAIT);
03441                p->owner = NULL;
03442             } else {
03443                /* The three way hung up, but we still have a call wait */
03444                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
03445                swap_subs(p, SUB_THREEWAY, SUB_REAL);
03446                unalloc_sub(p, SUB_THREEWAY);
03447                if (p->subs[SUB_REAL].inthreeway) {
03448                   /* This was part of a three way call.  Immediately make way for
03449                      another call */
03450                   ast_debug(1, "Call was complete, setting owner to former third call\n");
03451                   p->owner = p->subs[SUB_REAL].owner;
03452                } else {
03453                   /* This call hasn't been completed yet...  Set owner to NULL */
03454                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03455                   p->owner = NULL;
03456                }
03457                p->subs[SUB_REAL].inthreeway = 0;
03458             }
03459          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03460             /* Move to the call-wait and switch back to them. */
03461             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03462             unalloc_sub(p, SUB_CALLWAIT);
03463             p->owner = p->subs[SUB_REAL].owner;
03464             if (p->owner->_state != AST_STATE_UP)
03465                p->subs[SUB_REAL].needanswer = 1;
03466             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03467                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03468          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03469             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03470             unalloc_sub(p, SUB_THREEWAY);
03471             if (p->subs[SUB_REAL].inthreeway) {
03472                /* This was part of a three way call.  Immediately make way for
03473                   another call */
03474                ast_debug(1, "Call was complete, setting owner to former third call\n");
03475                p->owner = p->subs[SUB_REAL].owner;
03476             } else {
03477                /* This call hasn't been completed yet...  Set owner to NULL */
03478                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03479                p->owner = NULL;
03480             }
03481             p->subs[SUB_REAL].inthreeway = 0;
03482          }
03483       } else if (idx == SUB_CALLWAIT) {
03484          /* Ditch the holding callwait call, and immediately make it availabe */
03485          if (p->subs[SUB_CALLWAIT].inthreeway) {
03486             /* This is actually part of a three way, placed on hold.  Place the third part
03487                on music on hold now */
03488             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03489                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
03490                   S_OR(p->mohsuggest, NULL),
03491                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03492             }
03493             p->subs[SUB_THREEWAY].inthreeway = 0;
03494             /* Make it the call wait now */
03495             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03496             unalloc_sub(p, SUB_THREEWAY);
03497          } else
03498             unalloc_sub(p, SUB_CALLWAIT);
03499       } else if (idx == SUB_THREEWAY) {
03500          if (p->subs[SUB_CALLWAIT].inthreeway) {
03501             /* The other party of the three way call is currently in a call-wait state.
03502                Start music on hold for them, and take the main guy out of the third call */
03503             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03504                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
03505                   S_OR(p->mohsuggest, NULL),
03506                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03507             }
03508             p->subs[SUB_CALLWAIT].inthreeway = 0;
03509          }
03510          p->subs[SUB_REAL].inthreeway = 0;
03511          /* If this was part of a three way call index, let us make
03512             another three way call */
03513          unalloc_sub(p, SUB_THREEWAY);
03514       } else {
03515          /* This wasn't any sort of call, but how are we an index? */
03516          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03517       }
03518    }
03519 
03520    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03521       p->owner = NULL;
03522       p->ringt = 0;
03523       p->distinctivering = 0;
03524       p->confirmanswer = 0;
03525       p->cidrings = 1;
03526       p->outgoing = 0;
03527       p->digital = 0;
03528       p->faxhandled = 0;
03529       p->pulsedial = 0;
03530       p->onhooktime = time(NULL);
03531 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03532       p->proceeding = 0;
03533       p->dialing = 0;
03534       p->progress = 0;
03535       p->alerting = 0;
03536       p->setup_ack = 0;
03537       p->rlt = 0;
03538 #endif      
03539       if (p->dsp) {
03540          ast_dsp_free(p->dsp);
03541          p->dsp = NULL;
03542       }
03543 
03544       law = DAHDI_LAW_DEFAULT;
03545       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03546       if (res < 0) 
03547          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03548       /* Perform low level hangup if no owner left */
03549 #ifdef HAVE_SS7
03550       if (p->ss7) {
03551          if (p->ss7call) {
03552             if (!ss7_grab(p, p->ss7)) {
03553                if (!p->alreadyhungup) {
03554                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03555                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03556 
03557                   if (cause) {
03558                      if (atoi(cause))
03559                         icause = atoi(cause);
03560                   }
03561                   isup_rel(p->ss7->ss7, p->ss7call, icause);
03562                   ss7_rel(p->ss7);
03563                   p->alreadyhungup = 1;
03564                } else
03565                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03566             } else {
03567                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03568                res = -1;
03569             }
03570          }
03571       }
03572 #endif
03573 #ifdef HAVE_PRI
03574       if (p->pri) {
03575 #ifdef SUPPORT_USERUSER
03576          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03577 #endif
03578 
03579          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03580          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03581             if (!pri_grab(p, p->pri)) {
03582                if (p->alreadyhungup) {
03583                   ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
03584 
03585 #ifdef SUPPORT_USERUSER
03586                   pri_call_set_useruser(p->call, useruser);
03587 #endif
03588 
03589                   pri_hangup(p->pri->pri, p->call, -1);
03590                   p->call = NULL;
03591                   if (p->bearer) 
03592                      p->bearer->call = NULL;
03593                } else {
03594                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03595                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03596                   ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03597 
03598 #ifdef SUPPORT_USERUSER
03599                   pri_call_set_useruser(p->call, useruser);
03600 #endif
03601 
03602                   p->alreadyhungup = 1;
03603                   if (p->bearer)
03604                      p->bearer->alreadyhungup = 1;
03605                   if (cause) {
03606                      if (atoi(cause))
03607                         icause = atoi(cause);
03608                   }
03609                   pri_hangup(p->pri->pri, p->call, icause);
03610                }
03611                if (res < 0) 
03612                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03613                pri_rel(p->pri);        
03614             } else {
03615                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03616                res = -1;
03617             }
03618          } else {
03619             if (p->bearer)
03620                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03621             p->call = NULL;
03622             res = 0;
03623          }
03624       }
03625 #endif
03626       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03627          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03628       if (res < 0) {
03629          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03630       }
03631       switch (p->sig) {
03632       case SIG_FXOGS:
03633       case SIG_FXOLS:
03634       case SIG_FXOKS:
03635          memset(&par, 0, sizeof(par));
03636          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03637          if (!res) {
03638 #if 0
03639             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03640 #endif
03641             /* If they're off hook, try playing congestion */
03642             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03643                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03644             else
03645                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03646          }
03647          break;
03648       case SIG_FXSGS:
03649       case SIG_FXSLS:
03650       case SIG_FXSKS:
03651          /* Make sure we're not made available for at least two seconds assuming
03652             we were actually used for an inbound or outbound call. */
03653          if (ast->_state != AST_STATE_RESERVED) {
03654             time(&p->guardtime);
03655             p->guardtime += 2;
03656          }
03657          break;
03658       default:
03659          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03660       }
03661       if (p->cidspill)
03662          ast_free(p->cidspill);
03663       if (p->sig)
03664          dahdi_disable_ec(p);
03665       x = 0;
03666       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03667       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03668       p->didtdd = 0;
03669       p->cidspill = NULL;
03670       p->callwaitcas = 0;
03671       p->callwaiting = p->permcallwaiting;
03672       p->hidecallerid = p->permhidecallerid;
03673       p->dialing = 0;
03674       p->rdnis[0] = '\0';
03675       update_conf(p);
03676       reset_conf(p);
03677       /* Restore data mode */
03678       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03679          x = 0;
03680          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03681       }
03682 #ifdef HAVE_PRI
03683       if (p->bearer) {
03684          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03685          /* Free up the bearer channel as well, and
03686             don't use its file descriptor anymore */
03687          update_conf(p->bearer);
03688          reset_conf(p->bearer);
03689          p->bearer->owner = NULL;
03690          p->bearer->realcall = NULL;
03691          p->bearer = NULL;
03692          p->subs[SUB_REAL].dfd = -1;
03693          p->pri = NULL;
03694       }
03695 #endif
03696       if (num_restart_pending == 0)
03697          restart_monitor();
03698    }
03699 
03700    p->callwaitingrepeat = 0;
03701    p->cidcwexpire = 0;
03702    p->oprmode = 0;
03703    ast->tech_pvt = NULL;
03704    ast_mutex_unlock(&p->lock);
03705    ast_module_unref(ast_module_info->self);
03706    ast_verb(3, "Hungup '%s'\n", ast->name);
03707 
03708    ast_mutex_lock(&iflock);
03709 
03710    if (p->restartpending) {
03711       num_restart_pending--;
03712    }
03713 
03714    tmp = iflist;
03715    prev = NULL;
03716    if (p->destroy) {
03717       while (tmp) {
03718          if (tmp == p) {
03719             destroy_channel(prev, tmp, 0);
03720             break;
03721          } else {
03722             prev = tmp;
03723             tmp = tmp->next;
03724          }
03725       }
03726    }
03727    ast_mutex_unlock(&iflock);
03728    return 0;
03729 }
03730 
03731 static int dahdi_answer(struct ast_channel *ast)
03732 {
03733    struct dahdi_pvt *p = ast->tech_pvt;
03734    int res = 0;
03735    int idx;
03736    int oldstate = ast->_state;
03737    ast_setstate(ast, AST_STATE_UP);
03738    ast_mutex_lock(&p->lock);
03739    idx = dahdi_get_index(ast, p, 0);
03740    if (idx < 0)
03741       idx = SUB_REAL;
03742    /* nothing to do if a radio channel */
03743    if ((p->radio || (p->oprmode < 0))) {
03744       ast_mutex_unlock(&p->lock);
03745       return 0;
03746    }
03747    switch (p->sig) {
03748    case SIG_FXSLS:
03749    case SIG_FXSGS:
03750    case SIG_FXSKS:
03751       p->ringt = 0;
03752       /* Fall through */
03753    case SIG_EM:
03754    case SIG_EM_E1:
03755    case SIG_EMWINK:
03756    case SIG_FEATD:
03757    case SIG_FEATDMF:
03758    case SIG_FEATDMF_TA:
03759    case SIG_E911:
03760    case SIG_FGC_CAMA:
03761    case SIG_FGC_CAMAMF:
03762    case SIG_FEATB:
03763    case SIG_SF:
03764    case SIG_SFWINK:
03765    case SIG_SF_FEATD:
03766    case SIG_SF_FEATDMF:
03767    case SIG_SF_FEATB:
03768    case SIG_FXOLS:
03769    case SIG_FXOGS:
03770    case SIG_FXOKS:
03771       /* Pick up the line */
03772       ast_debug(1, "Took %s off hook\n", ast->name);
03773       if (p->hanguponpolarityswitch) {
03774          p->polaritydelaytv = ast_tvnow();
03775       }
03776       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03777       tone_zone_play_tone(p->subs[idx].dfd, -1);
03778       p->dialing = 0;
03779       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03780          if (oldstate == AST_STATE_RINGING) {
03781             ast_debug(1, "Finally swapping real and threeway\n");
03782             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03783             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03784             p->owner = p->subs[SUB_REAL].owner;
03785          }
03786       }
03787       if (p->sig & __DAHDI_SIG_FXS) {
03788          dahdi_enable_ec(p);
03789          dahdi_train_ec(p);
03790       }
03791       break;
03792 #ifdef HAVE_PRI
03793    case SIG_BRI:
03794    case SIG_BRI_PTMP:
03795    case SIG_PRI:
03796       /* Send a pri acknowledge */
03797       if (!pri_grab(p, p->pri)) {
03798          p->proceeding = 1;
03799          p->dialing = 0;
03800          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03801          pri_rel(p->pri);
03802       } else {
03803          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03804          res = -1;
03805       }
03806       break;
03807 #endif
03808 #ifdef HAVE_SS7
03809    case SIG_SS7:
03810       if (!ss7_grab(p, p->ss7)) {
03811          p->proceeding = 1;
03812          res = isup_anm(p->ss7->ss7, p->ss7call);
03813          ss7_rel(p->ss7);
03814       } else {
03815          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03816          res = -1;
03817       }
03818       break;
03819 #endif
03820    case 0:
03821       ast_mutex_unlock(&p->lock);
03822       return 0;
03823    default:
03824       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03825       res = -1;
03826    }
03827    ast_mutex_unlock(&p->lock);
03828    return res;
03829 }
03830 
03831 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
03832 {
03833    char *cp;
03834    signed char *scp;
03835    int x;
03836    int idx;
03837    struct dahdi_pvt *p = chan->tech_pvt, *pp;
03838    struct oprmode *oprmode;
03839    
03840 
03841    /* all supported options require data */
03842    if (!data || (datalen < 1)) {
03843       errno = EINVAL;
03844       return -1;
03845    }
03846 
03847    switch (option) {
03848    case AST_OPTION_TXGAIN:
03849       scp = (signed char *) data;
03850       idx = dahdi_get_index(chan, p, 0);
03851       if (idx < 0) {
03852          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03853          return -1;
03854       }
03855       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03856       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03857    case AST_OPTION_RXGAIN:
03858       scp = (signed char *) data;
03859       idx = dahdi_get_index(chan, p, 0);
03860       if (idx < 0) {
03861          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03862          return -1;
03863       }
03864       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03865       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03866    case AST_OPTION_TONE_VERIFY:
03867       if (!p->dsp)
03868          break;
03869       cp = (char *) data;
03870       switch (*cp) {
03871       case 1:
03872          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03873          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
03874          break;
03875       case 2:
03876          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03877          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
03878          break;
03879       default:
03880          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03881          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
03882          break;
03883       }
03884       break;
03885    case AST_OPTION_TDD:
03886       /* turn on or off TDD */
03887       cp = (char *) data;
03888       p->mate = 0;
03889       if (!*cp) { /* turn it off */
03890          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03891          if (p->tdd)
03892             tdd_free(p->tdd);
03893          p->tdd = 0;
03894          break;
03895       }
03896       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03897          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03898       dahdi_disable_ec(p);
03899       /* otherwise, turn it on */
03900       if (!p->didtdd) { /* if havent done it yet */
03901          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
03902          unsigned char *buf;
03903          int size, res, fd, len;
03904          struct pollfd fds[1];
03905 
03906          buf = mybuf;
03907          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03908          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03909          len = 40000;
03910          idx = dahdi_get_index(chan, p, 0);
03911          if (idx < 0) {
03912             ast_log(LOG_WARNING, "No index in TDD?\n");
03913             return -1;
03914          }
03915          fd = p->subs[idx].dfd;
03916          while (len) {
03917             if (ast_check_hangup(chan))
03918                return -1;
03919             size = len;
03920             if (size > READ_SIZE)
03921                size = READ_SIZE;
03922             fds[0].fd = fd;
03923             fds[0].events = POLLPRI | POLLOUT;
03924             fds[0].revents = 0;
03925             res = poll(fds, 1, -1);
03926             if (!res) {
03927                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03928                continue;
03929             }
03930             /* if got exception */
03931             if (fds[0].revents & POLLPRI)
03932                return -1;
03933             if (!(fds[0].revents & POLLOUT)) {
03934                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03935                continue;
03936             }
03937             res = write(fd, buf, size);
03938             if (res != size) {
03939                if (res == -1) return -1;
03940                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03941                break;
03942             }
03943             len -= size;
03944             buf += size;
03945          }
03946          p->didtdd = 1; /* set to have done it now */    
03947       }
03948       if (*cp == 2) { /* Mate mode */
03949          if (p->tdd)
03950             tdd_free(p->tdd);
03951          p->tdd = 0;
03952          p->mate = 1;
03953          break;
03954       }     
03955       if (!p->tdd) { /* if we dont have one yet */
03956          p->tdd = tdd_new(); /* allocate one */
03957       }     
03958       break;
03959    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03960       if (!p->dsp)
03961          break;
03962       cp = (char *) data;
03963       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03964          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03965       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03966       break;
03967    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03968       cp = (char *) data;
03969       if (!*cp) {    
03970          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03971          x = 0;
03972          dahdi_disable_ec(p);
03973       } else {    
03974          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03975          x = 1;
03976       }
03977       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03978          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03979       break;
03980    case AST_OPTION_OPRMODE:  /* Operator services mode */
03981       oprmode = (struct oprmode *) data;
03982       pp = oprmode->peer->tech_pvt;
03983       p->oprmode = pp->oprmode = 0;
03984       /* setup peers */
03985       p->oprpeer = pp;
03986       pp->oprpeer = p;
03987       /* setup modes, if any */
03988       if (oprmode->mode) 
03989       {
03990          pp->oprmode = oprmode->mode;
03991          p->oprmode = -oprmode->mode;
03992       }
03993       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
03994          oprmode->mode, chan->name,oprmode->peer->name);
03995       break;
03996    case AST_OPTION_ECHOCAN:
03997       cp = (char *) data;
03998       if (*cp) {
03999          ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04000          dahdi_enable_ec(p);
04001       } else {
04002          ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04003          dahdi_disable_ec(p);
04004       }
04005       break;
04006    }
04007    errno = 0;
04008 
04009    return 0;
04010 }
04011 
04012 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
04013 {
04014    struct dahdi_pvt *p = chan->tech_pvt;
04015    
04016    if (!strcasecmp(data, "rxgain")) {
04017       ast_mutex_lock(&p->lock);
04018       snprintf(buf, len, "%f", p->rxgain);
04019       ast_mutex_unlock(&p->lock);   
04020    } else if (!strcasecmp(data, "txgain")) {
04021       ast_mutex_lock(&p->lock);
04022       snprintf(buf, len, "%f", p->txgain);
04023       ast_mutex_unlock(&p->lock);   
04024    } else {
04025       ast_copy_string(buf, "", len);
04026    }
04027    return 0;
04028 }
04029 
04030 
04031 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
04032 {
04033    /* Unlink a specific slave or all slaves/masters from a given master */
04034    int x;
04035    int hasslaves;
04036    if (!master)
04037       return;
04038    if (needlock) {
04039       ast_mutex_lock(&master->lock);
04040       if (slave) {
04041          while (ast_mutex_trylock(&slave->lock)) {
04042             DEADLOCK_AVOIDANCE(&master->lock);
04043          }
04044       }
04045    }
04046    hasslaves = 0;
04047    for (x = 0; x < MAX_SLAVES; x++) {
04048       if (master->slaves[x]) {
04049          if (!slave || (master->slaves[x] == slave)) {
04050             /* Take slave out of the conference */
04051             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04052             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04053             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04054             master->slaves[x]->master = NULL;
04055             master->slaves[x] = NULL;
04056          } else
04057             hasslaves = 1;
04058       }
04059       if (!hasslaves)
04060          master->inconference = 0;
04061    }
04062    if (!slave) {
04063       if (master->master) {
04064          /* Take master out of the conference */
04065          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04066          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04067          hasslaves = 0;
04068          for (x = 0; x < MAX_SLAVES; x++) {
04069             if (master->master->slaves[x] == master)
04070                master->master->slaves[x] = NULL;
04071             else if (master->master->slaves[x])
04072                hasslaves = 1;
04073          }
04074          if (!hasslaves)
04075             master->master->inconference = 0;
04076       }
04077       master->master = NULL;
04078    }
04079    update_conf(master);
04080    if (needlock) {
04081       if (slave)
04082          ast_mutex_unlock(&slave->lock);
04083       ast_mutex_unlock(&master->lock);
04084    }
04085 }
04086 
04087 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
04088    int x;
04089    if (!slave || !master) {
04090       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04091       return;
04092    }
04093    for (x = 0; x < MAX_SLAVES; x++) {
04094       if (!master->slaves[x]) {
04095          master->slaves[x] = slave;
04096          break;
04097       }
04098    }
04099    if (x >= MAX_SLAVES) {
04100       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04101       master->slaves[MAX_SLAVES - 1] = slave;
04102    }
04103    if (slave->master) 
04104       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04105    slave->master = master;
04106    
04107    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04108 }
04109 
04110 static void disable_dtmf_detect(struct dahdi_pvt *p)
04111 {
04112    int val;
04113 
04114    p->ignoredtmf = 1;
04115 
04116    val = 0;
04117    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04118 
04119    if (!p->hardwaredtmf && p->dsp) {
04120       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04121       ast_dsp_set_features(p->dsp, p->dsp_features);
04122    }
04123 }
04124 
04125 static void enable_dtmf_detect(struct dahdi_pvt *p)
04126 {
04127    int val;
04128 
04129    if (p->channel == CHAN_PSEUDO)
04130       return;
04131 
04132    p->ignoredtmf = 0;
04133 
04134    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04135    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04136 
04137    if (!p->hardwaredtmf && p->dsp) {
04138       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04139       ast_dsp_set_features(p->dsp, p->dsp_features);
04140    }
04141 }
04142 
04143 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)
04144 {
04145    struct ast_channel *who;
04146    struct dahdi_pvt *p0, *p1, *op0, *op1;
04147    struct dahdi_pvt *master = NULL, *slave = NULL;
04148    struct ast_frame *f;
04149    int inconf = 0;
04150    int nothingok = 1;
04151    int ofd0, ofd1;
04152    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04153    int os0 = -1, os1 = -1;
04154    int priority = 0;
04155    struct ast_channel *oc0, *oc1;
04156    enum ast_bridge_result res;
04157 
04158 #ifdef PRI_2BCT
04159    int triedtopribridge = 0;
04160    q931_call *q931c0 = NULL, *q931c1 = NULL;
04161 #endif
04162 
04163    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
04164       There is code below to handle it properly until DTMF is actually seen,
04165       but due to currently unresolved issues it's ignored...
04166    */
04167 
04168    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04169       return AST_BRIDGE_FAILED_NOWARN;
04170 
04171    ast_channel_lock(c0);
04172    while (ast_channel_trylock(c1)) {
04173       CHANNEL_DEADLOCK_AVOIDANCE(c0);
04174    }
04175 
04176    p0 = c0->tech_pvt;
04177    p1 = c1->tech_pvt;
04178    /* cant do pseudo-channels here */
04179    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04180       ast_channel_unlock(c0);
04181       ast_channel_unlock(c1);
04182       return AST_BRIDGE_FAILED_NOWARN;
04183    }
04184 
04185    oi0 = dahdi_get_index(c0, p0, 0);
04186    oi1 = dahdi_get_index(c1, p1, 0);
04187    if ((oi0 < 0) || (oi1 < 0)) {
04188       ast_channel_unlock(c0);
04189       ast_channel_unlock(c1);
04190       return AST_BRIDGE_FAILED;
04191    }
04192 
04193    op0 = p0 = c0->tech_pvt;
04194    op1 = p1 = c1->tech_pvt;
04195    ofd0 = c0->fds[0];
04196    ofd1 = c1->fds[0];
04197    oc0 = p0->owner;
04198    oc1 = p1->owner;
04199 
04200    if (ast_mutex_trylock(&p0->lock)) {
04201       /* Don't block, due to potential for deadlock */
04202       ast_channel_unlock(c0);
04203       ast_channel_unlock(c1);
04204       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04205       return AST_BRIDGE_RETRY;
04206    }
04207    if (ast_mutex_trylock(&p1->lock)) {
04208       /* Don't block, due to potential for deadlock */
04209       ast_mutex_unlock(&p0->lock);
04210       ast_channel_unlock(c0);
04211       ast_channel_unlock(c1);
04212       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04213       return AST_BRIDGE_RETRY;
04214    }
04215 
04216    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04217       if (p0->owner && p1->owner) {
04218          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
04219          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04220             master = p0;
04221             slave = p1;
04222             inconf = 1;
04223          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04224             master = p1;
04225             slave = p0;
04226             inconf = 1;
04227          } else {
04228             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
04229             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04230                p0->channel,
04231                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04232                p0->subs[SUB_REAL].inthreeway, p0->channel,
04233                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04234                p1->subs[SUB_REAL].inthreeway);
04235          }
04236          nothingok = 0;
04237       }
04238    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04239       if (p1->subs[SUB_THREEWAY].inthreeway) {
04240          master = p1;
04241          slave = p0;
04242          nothingok = 0;
04243       }
04244    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04245       if (p0->subs[SUB_THREEWAY].inthreeway) {
04246          master = p0;
04247          slave = p1;
04248          nothingok = 0;
04249       }
04250    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04251       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
04252          don't put us in anything */
04253       if (p1->subs[SUB_CALLWAIT].inthreeway) {
04254          master = p1;
04255          slave = p0;
04256          nothingok = 0;
04257       }
04258    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04259       /* Same as previous */
04260       if (p0->subs[SUB_CALLWAIT].inthreeway) {
04261          master = p0;
04262          slave = p1;
04263          nothingok = 0;
04264       }
04265    }
04266    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04267       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04268    if (master && slave) {
04269       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
04270          in an active threeway call with a channel that is ringing, we should
04271          indicate ringing. */
04272       if ((oi1 == SUB_THREEWAY) && 
04273           p1->subs[SUB_THREEWAY].inthreeway && 
04274           p1->subs[SUB_REAL].owner && 
04275           p1->subs[SUB_REAL].inthreeway && 
04276           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04277          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04278          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04279          os1 = p1->subs[SUB_REAL].owner->_state;
04280       } else {
04281          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04282          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04283       }
04284       if ((oi0 == SUB_THREEWAY) && 
04285           p0->subs[SUB_THREEWAY].inthreeway && 
04286           p0->subs[SUB_REAL].owner && 
04287           p0->subs[SUB_REAL].inthreeway && 
04288           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04289          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04290          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04291          os0 = p0->subs[SUB_REAL].owner->_state;
04292       } else {
04293          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04294          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04295       }
04296       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04297          if (!p0->echocanbridged || !p1->echocanbridged) {
04298             /* Disable echo cancellation if appropriate */
04299             dahdi_disable_ec(p0);
04300             dahdi_disable_ec(p1);
04301          }
04302       }
04303       dahdi_link(slave, master);
04304       master->inconference = inconf;
04305    } else if (!nothingok)
04306       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04307 
04308    update_conf(p0);
04309    update_conf(p1);
04310    t0 = p0->subs[SUB_REAL].inthreeway;
04311    t1 = p1->subs[SUB_REAL].inthreeway;
04312 
04313    ast_mutex_unlock(&p0->lock);
04314    ast_mutex_unlock(&p1->lock);
04315 
04316    ast_channel_unlock(c0);
04317    ast_channel_unlock(c1);
04318 
04319    /* Native bridge failed */
04320    if ((!master || !slave) && !nothingok) {
04321       dahdi_enable_ec(p0);
04322       dahdi_enable_ec(p1);
04323       return AST_BRIDGE_FAILED;
04324    }
04325    
04326    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04327 
04328    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04329       disable_dtmf_detect(op0);
04330 
04331    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04332       disable_dtmf_detect(op1);
04333 
04334    for (;;) {
04335       struct ast_channel *c0_priority[2] = {c0, c1};
04336       struct ast_channel *c1_priority[2] = {c1, c0};
04337 
04338       /* Here's our main loop...  Start by locking things, looking for private parts, 
04339          and then balking if anything is wrong */
04340       
04341       ast_channel_lock(c0);
04342       while (ast_channel_trylock(c1)) {
04343          CHANNEL_DEADLOCK_AVOIDANCE(c0);
04344       }
04345 
04346       p0 = c0->tech_pvt;
04347       p1 = c1->tech_pvt;
04348 
04349       if (op0 == p0)
04350          i0 = dahdi_get_index(c0, p0, 1);
04351       if (op1 == p1)
04352          i1 = dahdi_get_index(c1, p1, 1);
04353 
04354       ast_channel_unlock(c0);
04355       ast_channel_unlock(c1);
04356 
04357       if (!timeoutms || 
04358           (op0 != p0) ||
04359           (op1 != p1) || 
04360           (ofd0 != c0->fds[0]) || 
04361           (ofd1 != c1->fds[0]) ||
04362           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
04363           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
04364           (oc0 != p0->owner) || 
04365           (oc1 != p1->owner) ||
04366           (t0 != p0->subs[SUB_REAL].inthreeway) ||
04367           (t1 != p1->subs[SUB_REAL].inthreeway) ||
04368           (oi0 != i0) ||
04369           (oi1 != i1)) {
04370          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04371             op0->channel, oi0, op1->channel, oi1);
04372          res = AST_BRIDGE_RETRY;
04373          goto return_from_bridge;
04374       }
04375 
04376 #ifdef PRI_2BCT
04377       q931c0 = p0->call;
04378       q931c1 = p1->call;
04379       if (p0->transfer && p1->transfer 
04380           && q931c0 && q931c1 
04381           && !triedtopribridge) {
04382          pri_channel_bridge(q931c0, q931c1);
04383          triedtopribridge = 1;
04384       }
04385 #endif
04386 
04387       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04388       if (!who) {
04389          ast_debug(1, "Ooh, empty read...\n");
04390          continue;
04391       }
04392       f = ast_read(who);
04393       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04394          *fo = f;
04395          *rc = who;
04396          res = AST_BRIDGE_COMPLETE;
04397          goto return_from_bridge;
04398       }
04399       if (f->frametype == AST_FRAME_DTMF) {
04400          if ((who == c0) && p0->pulsedial) {
04401             ast_write(c1, f);
04402          } else if ((who == c1) && p1->pulsedial) {
04403             ast_write(c0, f);
04404          } else {
04405             *fo = f;
04406             *rc = who;
04407             res = AST_BRIDGE_COMPLETE;
04408             goto return_from_bridge;
04409          }
04410       }
04411       ast_frfree(f);
04412       
04413       /* Swap who gets priority */
04414       priority = !priority;
04415    }
04416 
04417 return_from_bridge:
04418    if (op0 == p0)
04419       dahdi_enable_ec(p0);
04420 
04421    if (op1 == p1)
04422       dahdi_enable_ec(p1);
04423 
04424    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04425       enable_dtmf_detect(op0);
04426 
04427    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04428       enable_dtmf_detect(op1);
04429 
04430    dahdi_unlink(slave, master, 1);
04431 
04432    return res;
04433 }
04434 
04435 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04436 {
04437    struct dahdi_pvt *p = newchan->tech_pvt;
04438    int x;
04439    ast_mutex_lock(&p->lock);
04440    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04441    if (p->owner == oldchan) {
04442       p->owner = newchan;
04443    }
04444    for (x = 0; x < 3; x++)
04445       if (p->subs[x].owner == oldchan) {
04446          if (!x)
04447             dahdi_unlink(NULL, p, 0);
04448          p->subs[x].owner = newchan;
04449       }
04450    if (newchan->_state == AST_STATE_RINGING) 
04451       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04452    update_conf(p);
04453    ast_mutex_unlock(&p->lock);
04454    return 0;
04455 }
04456 
04457 static int dahdi_ring_phone(struct dahdi_pvt *p)
04458 {
04459    int x;
04460    int res;
04461    /* Make sure our transmit state is on hook */
04462    x = 0;
04463    x = DAHDI_ONHOOK;
04464    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04465    do {
04466       x = DAHDI_RING;
04467       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04468       if (res) {
04469          switch (errno) {
04470          case EBUSY:
04471          case EINTR:
04472             /* Wait just in case */
04473             usleep(10000);
04474             continue;
04475          case EINPROGRESS:
04476             res = 0;
04477             break;
04478          default:
04479             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04480             res = 0;
04481          }
04482       }
04483    } while (res);
04484    return res;
04485 }
04486 
04487 static void *ss_thread(void *data);
04488 
04489 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
04490 
04491 static int attempt_transfer(struct dahdi_pvt *p)
04492 {
04493    /* In order to transfer, we need at least one of the channels to
04494       actually be in a call bridge.  We can't conference two applications
04495       together (but then, why would we want to?) */
04496    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04497       /* The three-way person we're about to transfer to could still be in MOH, so
04498          stop if now if appropriate */
04499       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04500          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04501       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04502          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04503       }
04504       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04505          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04506       }
04507        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04508          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04509                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04510          return -1;
04511       }
04512       /* Orphan the channel after releasing the lock */
04513       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04514       unalloc_sub(p, SUB_THREEWAY);
04515    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04516       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04517       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04518          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04519       }
04520       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04521          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04522       }
04523       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04524          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04525                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04526          return -1;
04527       }
04528       /* Three-way is now the REAL */
04529       swap_subs(p, SUB_THREEWAY, SUB_REAL);
04530       ast_channel_unlock(p->subs[SUB_REAL].owner);
04531       unalloc_sub(p, SUB_THREEWAY);
04532       /* Tell the caller not to hangup */
04533       return 1;
04534    } else {
04535       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04536          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04537       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04538       return -1;
04539    }
04540    return 0;
04541 }
04542 
04543 static int check_for_conference(struct dahdi_pvt *p)
04544 {
04545    struct dahdi_confinfo ci;
04546    /* Fine if we already have a master, etc */
04547    if (p->master || (p->confno > -1))
04548       return 0;
04549    memset(&ci, 0, sizeof(ci));
04550    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04551       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04552       return 0;
04553    }
04554    /* If we have no master and don't have a confno, then 
04555       if we're in a conference, it's probably a MeetMe room or
04556       some such, so don't let us 3-way out! */
04557    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04558       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04559       return 1;
04560    }
04561    return 0;
04562 }
04563 
04564 /*! Checks channel for alarms
04565  * \param p a channel to check for alarms.
04566  * \returns the alarms on the span to which the channel belongs, or alarms on
04567  *          the channel if no span alarms.
04568  */
04569 static int get_alarms(struct dahdi_pvt *p)
04570 {
04571    int res;
04572    struct dahdi_spaninfo zi;
04573    struct dahdi_params params;
04574 
04575    memset(&zi, 0, sizeof(zi));
04576    zi.spanno = p->span;
04577 
04578    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04579       if (zi.alarms != DAHDI_ALARM_NONE)
04580          return zi.alarms;
04581    } else {
04582       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04583       return 0;
04584    }
04585 
04586    /* No alarms on the span. Check for channel alarms. */
04587    memset(&params, 0, sizeof(params));
04588    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04589       return params.chan_alarms;
04590 
04591    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04592 
04593    return DAHDI_ALARM_NONE;
04594 }
04595 
04596 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
04597 {
04598    struct dahdi_pvt *p = ast->tech_pvt;
04599    struct ast_frame *f = *dest;
04600 
04601    ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04602 
04603    if (p->confirmanswer) {
04604       ast_debug(1, "Confirm answer on %s!\n", ast->name);
04605       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04606          of a DTMF digit */
04607       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04608       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04609       *dest = &p->subs[idx].f;
04610       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04611       p->confirmanswer = 0;
04612    } else if (p->callwaitcas) {
04613       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04614          ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04615          if (p->cidspill)
04616             ast_free(p->cidspill);
04617          send_cwcidspill(p);
04618       }
04619       p->callwaitcas = 0;
04620       p->subs[idx].f.frametype = AST_FRAME_NULL;
04621       p->subs[idx].f.subclass = 0;
04622       *dest = &p->subs[idx].f;
04623    } else if (f->subclass == 'f') {
04624       /* Fax tone -- Handle and return NULL */
04625       if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04626          p->faxhandled = 1;
04627          if (strcmp(ast->exten, "fax")) {
04628             const char *target_context = S_OR(ast->macrocontext, ast->context);
04629 
04630             /* We need to unlock 'ast' here because ast_exists_extension has the
04631              * potential to start autoservice on the channel. Such action is prone
04632              * to deadlock.
04633              */
04634             ast_mutex_unlock(&p->lock);
04635             ast_channel_unlock(ast);
04636             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04637                ast_channel_lock(ast);
04638                ast_mutex_lock(&p->lock);
04639                ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04640                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04641                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04642                if (ast_async_goto(ast, target_context, "fax", 1))
04643                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04644             } else {
04645                ast_channel_lock(ast);
04646                ast_mutex_lock(&p->lock);
04647                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04648             }
04649          } else {
04650             ast_debug(1, "Already in a fax extension, not redirecting\n");
04651          }
04652       } else {
04653          ast_debug(1, "Fax already handled\n");
04654       }
04655       dahdi_confmute(p, 0);
04656       p->subs[idx].f.frametype = AST_FRAME_NULL;
04657       p->subs[idx].f.subclass = 0;
04658       *dest = &p->subs[idx].f;
04659    }
04660 }
04661          
04662 static void handle_alarms(struct dahdi_pvt *p, int alms)
04663 {
04664    const char *alarm_str = alarm2str(alms);
04665 
04666    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04667    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04668             "Alarm: %s\r\n"
04669             "Channel: %d\r\n",
04670             alarm_str, p->channel);
04671 }
04672 
04673 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
04674 {
04675    int res, x;
04676    int idx, mysig;
04677    char *c;
04678    struct dahdi_pvt *p = ast->tech_pvt;
04679    pthread_t threadid;
04680    struct ast_channel *chan;
04681    struct ast_frame *f;
04682 
04683    idx = dahdi_get_index(ast, p, 0);
04684    mysig = p->sig;
04685    if (p->outsigmod > -1)
04686       mysig = p->outsigmod;
04687    p->subs[idx].f.frametype = AST_FRAME_NULL;
04688    p->subs[idx].f.subclass = 0;
04689    p->subs[idx].f.datalen = 0;
04690    p->subs[idx].f.samples = 0;
04691    p->subs[idx].f.mallocd = 0;
04692    p->subs[idx].f.offset = 0;
04693    p->subs[idx].f.src = "dahdi_handle_event";
04694    p->subs[idx].f.data.ptr = NULL;
04695    f = &p->subs[idx].f;
04696 
04697    if (idx < 0)
04698       return &p->subs[idx].f;
04699    if (p->fake_event) {
04700       res = p->fake_event;
04701       p->fake_event = 0;
04702    } else
04703       res = dahdi_get_event(p->subs[idx].dfd);
04704 
04705    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04706 
04707    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04708       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04709       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04710 #ifdef HAVE_PRI
04711       if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04712          /* absorb event */
04713       } else {
04714 #endif
04715          dahdi_confmute(p, 0);
04716          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04717          p->subs[idx].f.subclass = res & 0xff;
04718 #ifdef HAVE_PRI
04719       }
04720 #endif
04721       dahdi_handle_dtmfup(ast, idx, &f);
04722       return f;
04723    }
04724 
04725    if (res & DAHDI_EVENT_DTMFDOWN) {
04726       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04727       /* Mute conference */
04728       dahdi_confmute(p, 1);
04729       p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04730       p->subs[idx].f.subclass = res & 0xff;
04731       return &p->subs[idx].f;
04732    }
04733 
04734    switch (res) {
04735       case DAHDI_EVENT_EC_DISABLED:
04736          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04737          p->echocanon = 0;
04738          break;
04739       case DAHDI_EVENT_BITSCHANGED:
04740          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
04741       case DAHDI_EVENT_PULSE_START:
04742          /* Stop tone if there's a pulse start and the PBX isn't started */
04743          if (!ast->pbx)
04744             tone_zone_play_tone(p->subs[idx].dfd, -1);
04745          break;   
04746       case DAHDI_EVENT_DIALCOMPLETE:
04747          if (p->inalarm) break;
04748          if ((p->radio || (p->oprmode < 0))) break;
04749          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04750             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04751             return NULL;
04752          }
04753          if (!x) { /* if not still dialing in driver */
04754             dahdi_enable_ec(p);
04755             if (p->echobreak) {
04756                dahdi_train_ec(p);
04757                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04758                p->dop.op = DAHDI_DIAL_OP_REPLACE;
04759                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04760                p->echobreak = 0;
04761             } else {
04762                p->dialing = 0;
04763                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04764                   /* if thru with dialing after offhook */
04765                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04766                      ast_setstate(ast, AST_STATE_UP);
04767                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04768                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04769                      break;
04770                   } else { /* if to state wait for offhook to dial rest */
04771                      /* we now wait for off hook */
04772                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04773                   }
04774                }
04775                if (ast->_state == AST_STATE_DIALING) {
04776                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04777                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04778                   } 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)))) {
04779                      ast_setstate(ast, AST_STATE_RINGING);
04780                   } else if (!p->answeronpolarityswitch) {
04781                      ast_setstate(ast, AST_STATE_UP);
04782                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04783                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04784                      /* If aops=0 and hops=1, this is necessary */
04785                      p->polarity = POLARITY_REV;
04786                   } else {
04787                      /* Start clean, so we can catch the change to REV polarity when party answers */
04788                      p->polarity = POLARITY_IDLE;
04789                   }
04790                }
04791             }
04792          }
04793          break;
04794       case DAHDI_EVENT_ALARM:
04795 #ifdef HAVE_PRI
04796          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04797             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04798                /* T309 is not enabled : hangup calls when alarm occurs */
04799                if (p->call) {
04800                   if (p->pri && p->pri->pri) {
04801                      if (!pri_grab(p, p->pri)) {
04802                         pri_hangup(p->pri->pri, p->call, -1);
04803                         pri_destroycall(p->pri->pri, p->call);
04804                         p->call = NULL;
04805                         pri_rel(p->pri);
04806                      } else
04807                         ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04808                   } else
04809                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04810                }
04811                if (p->owner)
04812                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04813             }
04814          }
04815          if (p->bearer)
04816             p->bearer->inalarm = 1;
04817          else
04818 #endif
04819          p->inalarm = 1;
04820          res = get_alarms(p);
04821          handle_alarms(p, res);
04822 #ifdef HAVE_PRI
04823          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04824             /* fall through intentionally */
04825          } else {
04826             break;
04827          }
04828 #endif
04829 #ifdef HAVE_SS7
04830          if (p->sig == SIG_SS7)
04831             break;
04832 #endif
04833       case DAHDI_EVENT_ONHOOK:
04834          if (p->radio) {
04835             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04836             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04837             break;
04838          }
04839          if (p->oprmode < 0)
04840          {
04841             if (p->oprmode != -1) break;
04842             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04843             {
04844                /* Make sure it starts ringing */
04845                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04846                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04847                save_conference(p->oprpeer);
04848                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04849             }
04850             break;
04851          }
04852          switch (p->sig) {
04853          case SIG_FXOLS:
04854          case SIG_FXOGS:
04855          case SIG_FXOKS:
04856             p->onhooktime = time(NULL);
04857             p->msgstate = -1;
04858             /* Check for some special conditions regarding call waiting */
04859             if (idx == SUB_REAL) {
04860                /* The normal line was hung up */
04861                if (p->subs[SUB_CALLWAIT].owner) {
04862                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
04863                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04864                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04865                   unalloc_sub(p, SUB_CALLWAIT); 
04866 #if 0
04867                   p->subs[idx].needanswer = 0;
04868                   p->subs[idx].needringing = 0;
04869 #endif                  
04870                   p->callwaitingrepeat = 0;
04871                   p->cidcwexpire = 0;
04872                   p->owner = NULL;
04873                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04874                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04875                      p->dialing = 1;
04876                   dahdi_ring_phone(p);
04877                } else if (p->subs[SUB_THREEWAY].owner) {
04878                   unsigned int mssinceflash;
04879                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04880                      the private structure -- not especially easy or clean */
04881                   while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04882                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04883                      DLA_UNLOCK(&p->lock);
04884                      CHANNEL_DEADLOCK_AVOIDANCE(ast);
04885                      /* We can grab ast and p in that order, without worry.  We should make sure
04886                         nothing seriously bad has happened though like some sort of bizarre double
04887                         masquerade! */
04888                      DLA_LOCK(&p->lock);
04889                      if (p->owner != ast) {
04890                         ast_log(LOG_WARNING, "This isn't good...\n");
04891                         return NULL;
04892                      }
04893                   }
04894                   if (!p->subs[SUB_THREEWAY].owner) {
04895                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04896                      return NULL;
04897                   }
04898                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04899                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04900                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04901                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04902                         hanging up.  Hangup both channels now */
04903                      if (p->subs[SUB_THREEWAY].owner)
04904                         ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04905                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04906                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04907                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04908                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04909                      if (p->transfer) {
04910                         /* In any case this isn't a threeway call anymore */
04911                         p->subs[SUB_REAL].inthreeway = 0;
04912                         p->subs[SUB_THREEWAY].inthreeway = 0;
04913                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04914                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04915                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04916                            /* Swap subs and dis-own channel */
04917                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04918                            p->owner = NULL;
04919                            /* Ring the phone */
04920                            dahdi_ring_phone(p);
04921                         } else {
04922                            if ((res = attempt_transfer(p)) < 0) {
04923                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04924                               if (p->subs[SUB_THREEWAY].owner)
04925                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04926                            } else if (res) {
04927                               /* Don't actually hang up at this point */
04928                               if (p->subs[SUB_THREEWAY].owner)
04929                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04930                               break;
04931                            }
04932                         }
04933                      } else {
04934                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04935                         if (p->subs[SUB_THREEWAY].owner)
04936                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04937                      }
04938                   } else {
04939                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04940                      /* Swap subs and dis-own channel */
04941                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04942                      p->owner = NULL;
04943                      /* Ring the phone */
04944                      dahdi_ring_phone(p);
04945                   }
04946                }
04947             } else {
04948                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04949             }
04950             /* Fall through */
04951          default:
04952             dahdi_disable_ec(p);
04953             return NULL;
04954          }
04955          break;
04956       case DAHDI_EVENT_RINGOFFHOOK:
04957          if (p->inalarm) break;
04958          if (p->oprmode < 0)
04959          {
04960             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04961             {
04962                /* Make sure it stops ringing */
04963                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04964                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04965                restore_conference(p->oprpeer);
04966             }
04967             break;
04968          }
04969          if (p->radio)
04970          {
04971             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04972             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04973             break;
04974          }
04975          /* for E911, its supposed to wait for offhook then dial
04976             the second half of the dial string */
04977          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04978             c = strchr(p->dialdest, '/');
04979             if (c)
04980                c++;
04981             else
04982                c = p->dialdest;
04983             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04984             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04985             if (strlen(p->dop.dialstr) > 4) {
04986                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04987                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04988                p->echorest[sizeof(p->echorest) - 1] = '\0';
04989                p->echobreak = 1;
04990                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04991             } else
04992                p->echobreak = 0;
04993             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04994                int saveerr = errno;
04995 
04996                x = DAHDI_ONHOOK;
04997                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04998                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04999                return NULL;
05000                }
05001             p->dialing = 1;
05002             return &p->subs[idx].f;
05003          }
05004          switch (p->sig) {
05005          case SIG_FXOLS:
05006          case SIG_FXOGS:
05007          case SIG_FXOKS:
05008             switch (ast->_state) {
05009             case AST_STATE_RINGING:
05010                dahdi_enable_ec(p);
05011                dahdi_train_ec(p);
05012                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05013                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05014                /* Make sure it stops ringing */
05015                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05016                ast_debug(1, "channel %d answered\n", p->channel);
05017                if (p->cidspill) {
05018                   /* Cancel any running CallerID spill */
05019                   ast_free(p->cidspill);
05020                   p->cidspill = NULL;
05021                }
05022                p->dialing = 0;
05023                p->callwaitcas = 0;
05024                if (p->confirmanswer) {
05025                   /* Ignore answer if "confirm answer" is enabled */
05026                   p->subs[idx].f.frametype = AST_FRAME_NULL;
05027                   p->subs[idx].f.subclass = 0;
05028                } else if (!ast_strlen_zero(p->dop.dialstr)) {
05029                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
05030                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05031                   if (res < 0) {
05032                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05033                      p->dop.dialstr[0] = '\0';
05034                      return NULL;
05035                   } else {
05036                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05037                      p->subs[idx].f.frametype = AST_FRAME_NULL;
05038                      p->subs[idx].f.subclass = 0;
05039                      p->dialing = 1;
05040                   }
05041                   p->dop.dialstr[0] = '\0';
05042                   ast_setstate(ast, AST_STATE_DIALING);
05043                } else
05044                   ast_setstate(ast, AST_STATE_UP);
05045                return &p->subs[idx].f;
05046             case AST_STATE_DOWN:
05047                ast_setstate(ast, AST_STATE_RING);
05048                ast->rings = 1;
05049                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05050                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05051                ast_debug(1, "channel %d picked up\n", p->channel);
05052                return &p->subs[idx].f;
05053             case AST_STATE_UP:
05054                /* Make sure it stops ringing */
05055                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05056                /* Okay -- probably call waiting*/
05057                if (ast_bridged_channel(p->owner))
05058                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05059                p->subs[idx].needunhold = 1;
05060                break;
05061             case AST_STATE_RESERVED:
05062                /* Start up dialtone */
05063                if (has_voicemail(p))
05064                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05065                else
05066                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05067                break;
05068             default:
05069                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05070             }
05071             break;
05072          case SIG_FXSLS:
05073          case SIG_FXSGS:
05074          case SIG_FXSKS:
05075             if (ast->_state == AST_STATE_RING) {
05076                p->ringt = p->ringt_base;
05077             }
05078 
05079             /* If we get a ring then we cannot be in 
05080              * reversed polarity. So we reset to idle */
05081             ast_debug(1, "Setting IDLE polarity due "
05082                "to ring. Old polarity was %d\n", 
05083                p->polarity);
05084             p->polarity = POLARITY_IDLE;
05085 
05086             /* Fall through */
05087          case SIG_EM:
05088          case SIG_EM_E1:
05089          case SIG_EMWINK:
05090          case SIG_FEATD:
05091          case SIG_FEATDMF:
05092          case SIG_FEATDMF_TA:
05093          case SIG_E911:
05094          case SIG_FGC_CAMA:
05095          case SIG_FGC_CAMAMF:
05096          case SIG_FEATB:
05097          case SIG_SF:
05098          case SIG_SFWINK:
05099          case SIG_SF_FEATD:
05100          case SIG_SF_FEATDMF:
05101          case SIG_SF_FEATB:
05102             if (ast->_state == AST_STATE_PRERING)
05103                ast_setstate(ast, AST_STATE_RING);
05104             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05105                ast_debug(1, "Ring detected\n");
05106                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05107                p->subs[idx].f.subclass = AST_CONTROL_RING;
05108             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05109                ast_debug(1, "Line answered\n");
05110                if (p->confirmanswer) {
05111                   p->subs[idx].f.frametype = AST_FRAME_NULL;
05112                   p->subs[idx].f.subclass = 0;
05113                } else {
05114                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05115                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05116                   ast_setstate(ast, AST_STATE_UP);
05117                }
05118             } else if (ast->_state != AST_STATE_RING)
05119                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05120             break;
05121          default:
05122             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05123          }
05124          break;
05125       case DAHDI_EVENT_RINGBEGIN:
05126          switch (p->sig) {
05127          case SIG_FXSLS:
05128          case SIG_FXSGS:
05129          case SIG_FXSKS:
05130             if (ast->_state == AST_STATE_RING) {
05131                p->ringt = p->ringt_base;
05132             }
05133             break;
05134          }
05135          break;
05136       case DAHDI_EVENT_RINGEROFF:
05137          if (p->inalarm) break;
05138          if ((p->radio || (p->oprmode < 0))) break;
05139          ast->rings++;
05140          if ((ast->rings > p->cidrings) && (p->cidspill)) {
05141             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
05142             ast_free(p->cidspill);
05143             p->cidspill = NULL;
05144             p->callwaitcas = 0;
05145          }
05146          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05147          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05148          break;
05149       case DAHDI_EVENT_RINGERON:
05150          break;
05151       case DAHDI_EVENT_NOALARM:
05152          p->inalarm = 0;
05153 #ifdef HAVE_PRI
05154          /* Extremely unlikely but just in case */
05155          if (p->bearer)
05156             p->bearer->inalarm = 0;
05157 #endif            
05158          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05159          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05160                         "Channel: %d\r\n", p->channel);
05161          break;
05162       case DAHDI_EVENT_WINKFLASH:
05163          if (p->inalarm) break;
05164          if (p->radio) break;
05165          if (p->oprmode < 0) break;
05166          if (p->oprmode > 1)
05167          {
05168             struct dahdi_params par;
05169 
05170             memset(&par, 0, sizeof(par));
05171             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05172             {
05173                if (!par.rxisoffhook)
05174                {
05175                   /* Make sure it stops ringing */
05176                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05177                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05178                   save_conference(p);
05179                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05180                }
05181             }
05182             break;
05183          }
05184          /* Remember last time we got a flash-hook */
05185          p->flashtime = ast_tvnow();
05186          switch (mysig) {
05187          case SIG_FXOLS:
05188          case SIG_FXOGS:
05189          case SIG_FXOKS:
05190             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05191                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05192             p->callwaitcas = 0;
05193 
05194             if (idx != SUB_REAL) {
05195                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05196                goto winkflashdone;
05197             }
05198             
05199             if (p->subs[SUB_CALLWAIT].owner) {
05200                /* Swap to call-wait */
05201                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05202                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05203                p->owner = p->subs[SUB_REAL].owner;
05204                ast_debug(1, "Making %s the new owner\n", p->owner->name);
05205                if (p->owner->_state == AST_STATE_RINGING) {
05206                   ast_setstate(p->owner, AST_STATE_UP);
05207                   p->subs[SUB_REAL].needanswer = 1;
05208                }
05209                p->callwaitingrepeat = 0;
05210                p->cidcwexpire = 0;
05211                /* Start music on hold if appropriate */
05212                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05213                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05214                      S_OR(p->mohsuggest, NULL),
05215                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05216                }
05217                p->subs[SUB_CALLWAIT].needhold = 1;
05218                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05219                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05220                      S_OR(p->mohsuggest, NULL),
05221                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05222                }
05223                p->subs[SUB_REAL].needunhold = 1;
05224             } else if (!p->subs[SUB_THREEWAY].owner) {
05225                if (!p->threewaycalling) {
05226                   /* Just send a flash if no 3-way calling */
05227                   p->subs[SUB_REAL].needflash = 1;
05228                   goto winkflashdone;
05229                } else if (!check_for_conference(p)) {
05230                   char cid_num[256];
05231                   char cid_name[256];
05232 
05233                   cid_num[0] = 0;
05234                   cid_name[0] = 0;
05235                   if (p->dahditrcallerid && p->owner) {
05236                      if (p->owner->cid.cid_num)
05237                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05238                      if (p->owner->cid.cid_name)
05239                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05240                   }
05241                   /* XXX This section needs much more error checking!!! XXX */
05242                   /* Start a 3-way call if feasible */
05243                   if (!((ast->pbx) ||
05244                         (ast->_state == AST_STATE_UP) ||
05245                         (ast->_state == AST_STATE_RING))) {
05246                      ast_debug(1, "Flash when call not up or ringing\n");
05247                      goto winkflashdone;
05248                   }
05249                   if (alloc_sub(p, SUB_THREEWAY)) {
05250                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05251                      goto winkflashdone;
05252                   }
05253                   /* Make new channel */
05254                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05255                   if (p->dahditrcallerid) {
05256                      if (!p->origcid_num)
05257                         p->origcid_num = ast_strdup(p->cid_num);
05258                      if (!p->origcid_name)
05259                         p->origcid_name = ast_strdup(p->cid_name);
05260                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05261                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05262                   }
05263                   /* Swap things around between the three-way and real call */
05264                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
05265                   /* Disable echo canceller for better dialing */
05266                   dahdi_disable_ec(p);
05267                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05268                   if (res)
05269                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05270                   p->owner = chan;
05271                   if (!chan) {
05272                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05273                   } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05274                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05275                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05276                      dahdi_enable_ec(p);
05277                      ast_hangup(chan);
05278                   } else {
05279                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05280                      int way3bridge = 0, cdr3way = 0;
05281                      
05282                      if (!other) {
05283                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05284                      } else
05285                         way3bridge = 1;
05286                      
05287                      if (p->subs[SUB_THREEWAY].owner->cdr)
05288                         cdr3way = 1;
05289                      
05290                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
05291 
05292                      /* Start music on hold if appropriate */
05293                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05294                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05295                            S_OR(p->mohsuggest, NULL),
05296                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05297                      }
05298                      p->subs[SUB_THREEWAY].needhold = 1;
05299                   }
05300                }
05301             } else {
05302                /* Already have a 3 way call */
05303                if (p->subs[SUB_THREEWAY].inthreeway) {
05304                   /* Call is already up, drop the last person */
05305                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05306                   /* If the primary call isn't answered yet, use it */
05307                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05308                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
05309                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05310                      p->owner = p->subs[SUB_REAL].owner;
05311                   }
05312                   /* Drop the last call and stop the conference */
05313                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05314                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05315                   p->subs[SUB_REAL].inthreeway = 0;
05316                   p->subs[SUB_THREEWAY].inthreeway = 0;
05317                } else {
05318                   /* Lets see what we're up to */
05319                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
05320                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05321                      int otherindex = SUB_THREEWAY;
05322                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05323                      int way3bridge = 0, cdr3way = 0;
05324                      
05325                      if (!other) {
05326                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05327                      } else
05328                         way3bridge = 1;
05329                      
05330                      if (p->subs[SUB_THREEWAY].owner->cdr)
05331                         cdr3way = 1;
05332 
05333                      ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05334                      /* Put them in the threeway, and flip */
05335                      p->subs[SUB_THREEWAY].inthreeway = 1;
05336                      p->subs[SUB_REAL].inthreeway = 1;
05337                      if (ast->_state == AST_STATE_UP) {
05338                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
05339                         otherindex = SUB_REAL;
05340                      }
05341                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05342                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05343                      p->subs[otherindex].needunhold = 1;
05344                      p->owner = p->subs[SUB_REAL].owner;
05345                      if (ast->_state == AST_STATE_RINGING) {
05346                         ast_debug(1, "Enabling ringtone on real and threeway\n");
05347                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05348                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05349                      }
05350                   } else {
05351                      ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05352                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05353                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05354                      p->owner = p->subs[SUB_REAL].owner;
05355                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05356                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05357                      p->subs[SUB_REAL].needunhold = 1;
05358                      dahdi_enable_ec(p);
05359                   }
05360                      
05361                }
05362             }
05363          winkflashdone:              
05364             update_conf(p);
05365             break;
05366          case SIG_EM:
05367          case SIG_EM_E1:
05368          case SIG_FEATD:
05369          case SIG_SF:
05370          case SIG_SFWINK:
05371          case SIG_SF_FEATD:
05372          case SIG_FXSLS:
05373          case SIG_FXSGS:
05374             if (option_debug) {
05375                if (p->dialing)
05376                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05377                else
05378                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05379             }
05380             break;
05381          case SIG_FEATDMF_TA:
05382             switch (p->whichwink) {
05383             case 0:
05384                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05385                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05386                break;
05387             case 1:
05388                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05389                break;
05390             case 2:
05391                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05392                return NULL;
05393             }
05394             p->whichwink++;
05395             /* Fall through */
05396          case SIG_FEATDMF:
05397          case SIG_E911:
05398          case SIG_FGC_CAMAMF:
05399          case SIG_FGC_CAMA:
05400          case SIG_FEATB:
05401          case SIG_SF_FEATDMF:
05402          case SIG_SF_FEATB:
05403          case SIG_EMWINK:
05404             /* FGD MF and EMWINK *Must* wait for wink */
05405             if (!ast_strlen_zero(p->dop.dialstr)) {
05406                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05407                if (res < 0) {
05408                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05409                   p->dop.dialstr[0] = '\0';
05410                   return NULL;
05411                } else 
05412                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05413             }
05414             p->dop.dialstr[0] = '\0';
05415             break;
05416          default:
05417             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05418          }
05419          break;
05420       case DAHDI_EVENT_HOOKCOMPLETE:
05421          if (p->inalarm) break;
05422          if ((p->radio || (p->oprmode < 0))) break;
05423          switch (mysig) {
05424          case SIG_FXSLS:  /* only interesting for FXS */
05425          case SIG_FXSGS:
05426          case SIG_FXSKS:
05427          case SIG_EM:
05428          case SIG_EM_E1:
05429          case SIG_EMWINK:
05430          case SIG_FEATD:
05431          case SIG_SF:
05432          case SIG_SFWINK:
05433          case SIG_SF_FEATD:
05434             if (!ast_strlen_zero(p->dop.dialstr)) {
05435                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05436                if (res < 0) {
05437                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05438                   p->dop.dialstr[0] = '\0';
05439                   return NULL;
05440                } else 
05441                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05442             }
05443             p->dop.dialstr[0] = '\0';
05444             p->dop.op = DAHDI_DIAL_OP_REPLACE;
05445             break;
05446          case SIG_FEATDMF:
05447          case SIG_FEATDMF_TA:
05448          case SIG_E911:
05449          case SIG_FGC_CAMA:
05450          case SIG_FGC_CAMAMF:
05451          case SIG_FEATB:
05452          case SIG_SF_FEATDMF:
05453          case SIG_SF_FEATB:
05454             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05455             break;
05456          default:
05457             break;
05458          }
05459          break;
05460       case DAHDI_EVENT_POLARITY:
05461          /*
05462           * If we get a Polarity Switch event, this could be
05463           * due to line seizure, remote end connect or remote end disconnect.
05464           *
05465           * Check to see if we should change the polarity state and
05466           * mark the channel as UP or if this is an indication
05467           * of remote end disconnect.
05468           */
05469 
05470          if (p->polarityonanswerdelay > 0) {
05471             /* check if event is not too soon after OffHook or Answer */
05472                if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05473                switch (ast->_state) {
05474                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
05475                case AST_STATE_RINGING:       /*!< Remote end is ringing */
05476                   if (p->answeronpolarityswitch) {
05477                      ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
05478                      ast_setstate(p->owner, AST_STATE_UP);
05479                      p->polarity = POLARITY_REV;
05480                      if (p->hanguponpolarityswitch) {
05481                         p->polaritydelaytv = ast_tvnow();
05482                      }
05483                   } else {
05484                      ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
05485                   }
05486                   break;
05487                case AST_STATE_UP:         /*!< Line is up */
05488                case AST_STATE_RING:       /*!< Line is ringing */
05489                   if (p->hanguponpolarityswitch) {
05490                      ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
05491                      ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05492                      p->polarity = POLARITY_IDLE;
05493                   } else {
05494                      ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
05495                   }
05496                   break;
05497 
05498                case AST_STATE_DOWN:       /*!< Channel is down and available */
05499                case AST_STATE_RESERVED:      /*!< Channel is down, but reserved */
05500                case AST_STATE_OFFHOOK:       /*!< Channel is off hook */
05501                case AST_STATE_BUSY:       /*!< Line is busy */
05502                case AST_STATE_DIALING_OFFHOOK:     /*!< Digits (or equivalent) have been dialed while offhook */
05503                case AST_STATE_PRERING:       /*!< Channel has detected an incoming call and is waiting for ring */
05504                default:
05505                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05506                      ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
05507                   }
05508 
05509                }
05510 
05511             } else {
05512                /* event is too soon after OffHook or Answer */
05513                switch (ast->_state) {
05514                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
05515                case AST_STATE_RINGING:       /*!< Remote end is ringing */
05516                   if (p->answeronpolarityswitch) {
05517                      ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
05518                   }
05519                   break;
05520 
05521                case AST_STATE_UP:         /*!< Line is up */
05522                case AST_STATE_RING:       /*!< Line is ringing */
05523                   if (p->hanguponpolarityswitch) {
05524                      ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
05525                   }
05526                   break;
05527 
05528                default: 
05529                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
05530                      ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
05531                   }
05532                }
05533             }
05534          }
05535                         /* Added more log_debug information below to provide a better indication of what is going on */
05536          ast_debug(1, "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) );
05537          break;
05538       default:
05539          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05540    }
05541    return &p->subs[idx].f;
05542 }
05543 
05544 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
05545 {
05546    struct dahdi_pvt *p = ast->tech_pvt;
05547    int res;
05548    int usedindex=-1;
05549    int idx;
05550    struct ast_frame *f;
05551 
05552 
05553    idx = dahdi_get_index(ast, p, 1);
05554    
05555    p->subs[idx].f.frametype = AST_FRAME_NULL;
05556    p->subs[idx].f.datalen = 0;
05557    p->subs[idx].f.samples = 0;
05558    p->subs[idx].f.mallocd = 0;
05559    p->subs[idx].f.offset = 0;
05560    p->subs[idx].f.subclass = 0;
05561    p->subs[idx].f.delivery = ast_tv(0,0);
05562    p->subs[idx].f.src = "dahdi_exception";
05563    p->subs[idx].f.data.ptr = NULL;
05564    
05565    
05566    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05567       /* If nobody owns us, absorb the event appropriately, otherwise
05568          we loop indefinitely.  This occurs when, during call waiting, the
05569          other end hangs up our channel so that it no longer exists, but we
05570          have neither FLASH'd nor ONHOOK'd to signify our desire to
05571          change to the other channel. */
05572       if (p->fake_event) {
05573          res = p->fake_event;
05574          p->fake_event = 0;
05575       } else
05576          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05577       /* Switch to real if there is one and this isn't something really silly... */
05578       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05579          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05580          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05581          p->owner = p->subs[SUB_REAL].owner;
05582          if (p->owner && ast_bridged_channel(p->owner))
05583             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05584          p->subs[SUB_REAL].needunhold = 1;
05585       }
05586       switch (res) {
05587       case DAHDI_EVENT_ONHOOK:
05588          dahdi_disable_ec(p);
05589          if (p->owner) {
05590             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05591             dahdi_ring_phone(p);
05592             p->callwaitingrepeat = 0;
05593             p->cidcwexpire = 0;
05594          } else
05595             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05596          update_conf(p);
05597          break;
05598       case DAHDI_EVENT_RINGOFFHOOK:
05599          dahdi_enable_ec(p);
05600          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05601          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05602             p->subs[SUB_REAL].needanswer = 1;
05603             p->dialing = 0;
05604          }
05605          break;
05606       case DAHDI_EVENT_HOOKCOMPLETE:
05607       case DAHDI_EVENT_RINGERON:
05608       case DAHDI_EVENT_RINGEROFF:
05609          /* Do nothing */
05610          break;
05611       case DAHDI_EVENT_WINKFLASH:
05612          p->flashtime = ast_tvnow();
05613          if (p->owner) {
05614             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05615             if (p->owner->_state != AST_STATE_UP) {
05616                /* Answer if necessary */
05617                usedindex = dahdi_get_index(p->owner, p, 0);
05618                if (usedindex > -1) {
05619                   p->subs[usedindex].needanswer = 1;
05620                }
05621                ast_setstate(p->owner, AST_STATE_UP);
05622             }
05623             p->callwaitingrepeat = 0;
05624             p->cidcwexpire = 0;
05625             if (ast_bridged_channel(p->owner))
05626                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05627             p->subs[SUB_REAL].needunhold = 1;
05628          } else
05629             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05630          update_conf(p);
05631          break;
05632       default:
05633          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05634       }
05635       f = &p->subs[idx].f;
05636       return f;
05637    }
05638    if (!(p->radio || (p->oprmode < 0))) 
05639       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05640    /* If it's not us, return NULL immediately */
05641    if (ast != p->owner) {
05642       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05643       f = &p->subs[idx].f;
05644       return f;
05645    }
05646    f = dahdi_handle_event(ast);
05647    return f;
05648 }
05649 
05650 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
05651 {
05652    struct dahdi_pvt *p = ast->tech_pvt;
05653    struct ast_frame *f;
05654    ast_mutex_lock(&p->lock);
05655    f = __dahdi_exception(ast);
05656    ast_mutex_unlock(&p->lock);
05657    return f;
05658 }
05659 
05660 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
05661 {
05662    struct dahdi_pvt *p = ast->tech_pvt;
05663    int res;
05664    int idx;
05665    void *readbuf;
05666    struct ast_frame *f;
05667 
05668    while (ast_mutex_trylock(&p->lock)) {
05669       CHANNEL_DEADLOCK_AVOIDANCE(ast);
05670    }
05671 
05672    idx = dahdi_get_index(ast, p, 0);
05673    
05674    /* Hang up if we don't really exist */
05675    if (idx < 0)   {
05676       ast_log(LOG_WARNING, "We dont exist?\n");
05677       ast_mutex_unlock(&p->lock);
05678       return NULL;
05679    }
05680    
05681    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05682 
05683    p->subs[idx].f.frametype = AST_FRAME_NULL;
05684    p->subs[idx].f.datalen = 0;
05685    p->subs[idx].f.samples = 0;
05686    p->subs[idx].f.mallocd = 0;
05687    p->subs[idx].f.offset = 0;
05688    p->subs[idx].f.subclass = 0;
05689    p->subs[idx].f.delivery = ast_tv(0,0);
05690    p->subs[idx].f.src = "dahdi_read";
05691    p->subs[idx].f.data.ptr = NULL;
05692    
05693    /* make sure it sends initial key state as first frame */
05694    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05695    {
05696       struct dahdi_params ps;
05697 
05698       memset(&ps, 0, sizeof(ps));
05699       ps.channo = p->channel;
05700       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05701          ast_mutex_unlock(&p->lock);
05702          return NULL;
05703       }
05704       p->firstradio = 1;
05705       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05706       if (ps.rxisoffhook)
05707       {
05708          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05709       }
05710       else
05711       {
05712          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05713       }
05714       ast_mutex_unlock(&p->lock);
05715       return &p->subs[idx].f;
05716    }
05717    if (p->ringt == 1) {
05718       ast_mutex_unlock(&p->lock);
05719       return NULL;
05720    }
05721    else if (p->ringt > 0) 
05722       p->ringt--;
05723 
05724    if (p->subs[idx].needringing) {
05725       /* Send ringing frame if requested */
05726       p->subs[idx].needringing = 0;
05727       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05728       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05729       ast_setstate(ast, AST_STATE_RINGING);
05730       ast_mutex_unlock(&p->lock);
05731       return &p->subs[idx].f;
05732    }
05733 
05734    if (p->subs[idx].needbusy) {
05735       /* Send busy frame if requested */
05736       p->subs[idx].needbusy = 0;
05737       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05738       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05739       ast_mutex_unlock(&p->lock);
05740       return &p->subs[idx].f;
05741    }
05742 
05743    if (p->subs[idx].needcongestion) {
05744       /* Send congestion frame if requested */
05745       p->subs[idx].needcongestion = 0;
05746       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05747       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05748       ast_mutex_unlock(&p->lock);
05749       return &p->subs[idx].f;
05750    }
05751 
05752    if (p->subs[idx].needcallerid) {
05753       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05754                      S_OR(p->lastcid_name, NULL),
05755                      S_OR(p->lastcid_num, NULL)
05756                      );
05757       p->subs[idx].needcallerid = 0;
05758    }
05759    
05760    if (p->subs[idx].needanswer) {
05761       /* Send answer frame if requested */
05762       p->subs[idx].needanswer = 0;
05763       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05764       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05765       ast_mutex_unlock(&p->lock);
05766       return &p->subs[idx].f;
05767    }  
05768    
05769    if (p->subs[idx].needflash) {
05770       /* Send answer frame if requested */
05771       p->subs[idx].needflash = 0;
05772       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05773       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05774       ast_mutex_unlock(&p->lock);
05775       return &p->subs[idx].f;
05776    }  
05777    
05778    if (p->subs[idx].needhold) {
05779       /* Send answer frame if requested */
05780       p->subs[idx].needhold = 0;
05781       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05782       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05783       ast_mutex_unlock(&p->lock);
05784       ast_debug(1, "Sending hold on '%s'\n", ast->name);
05785       return &p->subs[idx].f;
05786    }  
05787    
05788    if (p->subs[idx].needunhold) {
05789       /* Send answer frame if requested */
05790       p->subs[idx].needunhold = 0;
05791       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05792       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05793       ast_mutex_unlock(&p->lock);
05794       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05795       return &p->subs[idx].f;
05796    }  
05797    
05798    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05799       if (!p->subs[idx].linear) {
05800          p->subs[idx].linear = 1;
05801          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05802          if (res) 
05803             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05804       }
05805    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05806          (ast->rawreadformat == AST_FORMAT_ALAW)) {
05807       if (p->subs[idx].linear) {
05808          p->subs[idx].linear = 0;
05809          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05810          if (res) 
05811             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05812       }
05813    } else {
05814       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05815       ast_mutex_unlock(&p->lock);
05816       return NULL;
05817    }
05818    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05819    CHECK_BLOCKING(ast);
05820    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05821    ast_clear_flag(ast, AST_FLAG_BLOCKING);
05822    /* Check for hangup */
05823    if (res < 0) {
05824       f = NULL;
05825       if (res == -1)  {
05826          if (errno == EAGAIN) {
05827             /* Return "NULL" frame if there is nobody there */
05828             ast_mutex_unlock(&p->lock);
05829             return &p->subs[idx].f;
05830          } else if (errno == ELAST) {
05831             f = __dahdi_exception(ast);
05832          } else
05833             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05834       }
05835       ast_mutex_unlock(&p->lock);
05836       return f;
05837    }
05838    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05839       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05840       f = __dahdi_exception(ast);
05841       ast_mutex_unlock(&p->lock);
05842       return f;
05843    }
05844    if (p->tdd) { /* if in TDD mode, see if we receive that */
05845       int c;
05846 
05847       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05848       if (c < 0) {
05849          ast_debug(1,"tdd_feed failed\n");
05850          ast_mutex_unlock(&p->lock);
05851          return NULL;
05852       }
05853       if (c) { /* if a char to return */
05854          p->subs[idx].f.subclass = 0;
05855          p->subs[idx].f.frametype = AST_FRAME_TEXT;
05856          p->subs[idx].f.mallocd = 0;
05857          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05858          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05859          p->subs[idx].f.datalen = 1;
05860          *((char *) p->subs[idx].f.data.ptr) = c;
05861          ast_mutex_unlock(&p->lock);
05862          return &p->subs[idx].f;
05863       }
05864    }
05865    /* Ensure the CW timer decrements only on a single subchannel */
05866    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05867       p->callwaitingrepeat--;
05868    }
05869    if (p->cidcwexpire)
05870       p->cidcwexpire--;
05871    /* Repeat callwaiting */
05872    if (p->callwaitingrepeat == 1) {
05873       p->callwaitrings++;
05874       dahdi_callwait(ast);
05875    }
05876    /* Expire CID/CW */
05877    if (p->cidcwexpire == 1) {
05878       ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05879       restore_conference(p);
05880    }
05881    if (p->subs[idx].linear) {
05882       p->subs[idx].f.datalen = READ_SIZE * 2;
05883    } else 
05884       p->subs[idx].f.datalen = READ_SIZE;
05885 
05886    /* Handle CallerID Transmission */
05887    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05888       send_callerid(p);
05889    }
05890 
05891    p->subs[idx].f.frametype = AST_FRAME_VOICE;
05892    p->subs[idx].f.subclass = ast->rawreadformat;
05893    p->subs[idx].f.samples = READ_SIZE;
05894    p->subs[idx].f.mallocd = 0;
05895    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05896    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05897 #if 0
05898    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05899 #endif   
05900    if (p->dialing || /* Transmitting something */
05901       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05902       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05903       ) {
05904       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05905          don't send anything */
05906       p->subs[idx].f.frametype = AST_FRAME_NULL;
05907       p->subs[idx].f.subclass = 0;
05908       p->subs[idx].f.samples = 0;
05909       p->subs[idx].f.mallocd = 0;
05910       p->subs[idx].f.offset = 0;
05911       p->subs[idx].f.data.ptr = NULL;
05912       p->subs[idx].f.datalen= 0;
05913    }
05914    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !idx) {
05915       /* Perform busy detection. etc on the dahdi line */
05916       int mute;
05917 
05918       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05919 
05920       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
05921       mute = ast_dsp_was_muted(p->dsp);
05922       if (p->muting != mute) {
05923          p->muting = mute;
05924          dahdi_confmute(p, mute);
05925       }
05926 
05927       if (f) {
05928          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05929             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05930                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05931                   a busy  */
05932                f = NULL;
05933             }
05934          } else if (f->frametype == AST_FRAME_DTMF) {
05935 #ifdef HAVE_PRI
05936             if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 
05937                 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05938                  (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05939                /* Don't accept in-band DTMF when in overlap dial mode */
05940                f->frametype = AST_FRAME_NULL;
05941                f->subclass = 0;
05942             }
05943 #endif            
05944             /* DSP clears us of being pulse */
05945             p->pulsedial = 0;
05946          }
05947       }
05948    } else 
05949       f = &p->subs[idx].f; 
05950 
05951    if (f && (f->frametype == AST_FRAME_DTMF))
05952       dahdi_handle_dtmfup(ast, idx, &f);
05953 
05954    /* If we have a fake_event, trigger exception to handle it */
05955    if (p->fake_event)
05956       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05957 
05958    ast_mutex_unlock(&p->lock);
05959    return f;
05960 }
05961 
05962 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
05963 {
05964    int sent=0;
05965    int size;
05966    int res;
05967    int fd;
05968    fd = p->subs[idx].dfd;
05969    while (len) {
05970       size = len;
05971       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05972          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05973       res = write(fd, buf, size);
05974       if (res != size) {
05975          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05976          return sent;
05977       }
05978       len -= size;
05979       buf += size;
05980    }
05981    return sent;
05982 }
05983 
05984 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
05985 {
05986    struct dahdi_pvt *p = ast->tech_pvt;
05987    int res;
05988    int idx;
05989    idx = dahdi_get_index(ast, p, 0);
05990    if (idx < 0) {
05991       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05992       return -1;
05993    }
05994 
05995 #if 0
05996 #ifdef HAVE_PRI
05997    ast_mutex_lock(&p->lock);
05998    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05999       if (p->pri->pri) {      
06000          if (!pri_grab(p, p->pri)) {
06001                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06002                pri_rel(p->pri);
06003          } else
06004                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06005       }
06006       p->proceeding=1;
06007    }
06008    ast_mutex_unlock(&p->lock);
06009 #endif
06010 #endif
06011    /* Write a frame of (presumably voice) data */
06012    if (frame->frametype != AST_FRAME_VOICE) {
06013       if (frame->frametype != AST_FRAME_IMAGE)
06014          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06015       return 0;
06016    }
06017    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06018        (frame->subclass != AST_FORMAT_ULAW) &&
06019        (frame->subclass != AST_FORMAT_ALAW)) {
06020       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06021       return -1;
06022    }
06023    if (p->dialing) {
06024       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06025       return 0;
06026    }
06027    if (!p->owner) {
06028       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06029       return 0;
06030    }
06031    if (p->cidspill) {
06032       ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06033       return 0;
06034    }
06035    /* Return if it's not valid data */
06036    if (!frame->data.ptr || !frame->datalen)
06037       return 0;
06038 
06039    if (frame->subclass == AST_FORMAT_SLINEAR) {
06040       if (!p->subs[idx].linear) {
06041          p->subs[idx].linear = 1;
06042          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06043          if (res)
06044             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06045       }
06046       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06047    } else {
06048       /* x-law already */
06049       if (p->subs[idx].linear) {
06050          p->subs[idx].linear = 0;
06051          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06052          if (res)
06053             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06054       }
06055       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06056    }
06057    if (res < 0) {
06058       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06059       return -1;
06060    } 
06061    return 0;
06062 }
06063 
06064 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
06065 {
06066    struct dahdi_pvt *p = chan->tech_pvt;
06067    int res=-1;
06068    int idx;
06069    int func = DAHDI_FLASH;
06070    ast_mutex_lock(&p->lock);
06071    idx = dahdi_get_index(chan, p, 0);
06072    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06073    if (idx == SUB_REAL) {
06074       switch (condition) {
06075       case AST_CONTROL_BUSY:
06076 #ifdef HAVE_PRI
06077          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06078             chan->hangupcause = AST_CAUSE_USER_BUSY;
06079             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06080             res = 0;
06081          } else if (!p->progress && 
06082                ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06083                && p->pri && !p->outgoing) {
06084             if (p->pri->pri) {      
06085                if (!pri_grab(p, p->pri)) {
06086                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06087                   pri_rel(p->pri);
06088                }
06089                else
06090                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06091             }
06092             p->progress = 1;
06093             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06094          } else
06095 #endif
06096             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06097          break;
06098       case AST_CONTROL_RINGING:
06099 #ifdef HAVE_PRI
06100          if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 
06101                && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06102             if (p->pri->pri) {      
06103                if (!pri_grab(p, p->pri)) {
06104                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06105                   pri_rel(p->pri);
06106                }
06107                else
06108                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06109             }
06110             p->alerting = 1;
06111          }
06112 
06113 #endif
06114 #ifdef HAVE_SS7
06115          if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06116             if (p->ss7->ss7) {
06117                ss7_grab(p, p->ss7);
06118                
06119                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06120                   p->rlt = 1;
06121                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
06122                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06123                p->alerting = 1;
06124                ss7_rel(p->ss7);
06125             }
06126          }
06127 #endif
06128             
06129          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06130          
06131          if (chan->_state != AST_STATE_UP) {
06132             if ((chan->_state != AST_STATE_RING) ||
06133                ((p->sig != SIG_FXSKS) &&
06134              (p->sig != SIG_FXSLS) &&
06135              (p->sig != SIG_FXSGS)))
06136             ast_setstate(chan, AST_STATE_RINGING);
06137          }
06138          break;
06139       case AST_CONTROL_PROCEEDING:
06140          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06141 #ifdef HAVE_PRI
06142          if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06143                && p->pri && !p->outgoing) {
06144             if (p->pri->pri) {      
06145                if (!pri_grab(p, p->pri)) {
06146                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06147                   pri_rel(p->pri);
06148                }
06149                else
06150                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06151             }
06152             p->proceeding = 1;
06153             p->dialing = 0;
06154          }
06155 #endif
06156 #ifdef HAVE_SS7
06157          /* This IF sends the FAR for an answered ALEG call */
06158          if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06159             if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06160                p->rlt = 1; 
06161          }
06162             
06163          if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06164             if (p->ss7->ss7) {
06165                ss7_grab(p, p->ss7);
06166                isup_acm(p->ss7->ss7, p->ss7call);
06167                p->proceeding = 1;
06168                ss7_rel(p->ss7);
06169 
06170             }
06171          }
06172 #endif
06173          /* don't continue in ast_indicate */
06174          res = 0;
06175          break;
06176       case AST_CONTROL_PROGRESS:
06177          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06178 #ifdef HAVE_PRI
06179          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
06180          if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06181                && p->pri && !p->outgoing) {
06182             if (p->pri->pri) {      
06183                if (!pri_grab(p, p->pri)) {
06184                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06185                   pri_rel(p->pri);
06186                }
06187                else
06188                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06189             }
06190             p->progress = 1;
06191          }
06192 #endif
06193 #ifdef HAVE_SS7
06194          if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06195             if (p->ss7->ss7) {
06196                ss7_grab(p, p->ss7);
06197                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06198                p->progress = 1;
06199                ss7_rel(p->ss7);
06200                /* enable echo canceler here on SS7 calls */
06201                dahdi_enable_ec(p);
06202 
06203             }
06204          }
06205 #endif
06206          /* don't continue in ast_indicate */
06207          res = 0;
06208          break;
06209       case AST_CONTROL_CONGESTION:
06210          chan->hangupcause = AST_CAUSE_CONGESTION;
06211 #ifdef HAVE_PRI
06212          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06213             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06214             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06215             res = 0;
06216          } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 
06217                && p->pri && !p->outgoing) {
06218             if (p->pri) {     
06219                if (!pri_grab(p, p->pri)) {
06220                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06221                   pri_rel(p->pri);
06222                } else
06223                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06224             }
06225             p->progress = 1;
06226             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06227          } else
06228 #endif
06229             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06230          break;
06231       case AST_CONTROL_HOLD:
06232 #ifdef HAVE_PRI
06233          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06234             if (!pri_grab(p, p->pri)) {
06235                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06236                pri_rel(p->pri);
06237             } else
06238                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06239          } else
06240 #endif
06241             ast_moh_start(chan, data, p->mohinterpret);
06242          break;
06243       case AST_CONTROL_UNHOLD:
06244 #ifdef HAVE_PRI
06245          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06246             if (!pri_grab(p, p->pri)) {
06247                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06248                pri_rel(p->pri);
06249             } else
06250                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06251          } else
06252 #endif
06253             ast_moh_stop(chan);
06254          break;
06255       case AST_CONTROL_RADIO_KEY:
06256          if (p->radio) 
06257              res =  dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06258          res = 0;
06259          break;
06260       case AST_CONTROL_RADIO_UNKEY:
06261          if (p->radio)
06262              res =  dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06263          res = 0;
06264          break;
06265       case AST_CONTROL_FLASH:
06266          /* flash hookswitch */
06267          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06268             /* Clear out the dial buffer */
06269             p->dop.dialstr[0] = '\0';
06270             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06271                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06272                   chan->name, strerror(errno));
06273             } else
06274                res = 0;
06275          } else
06276             res = 0;
06277          break;
06278       case AST_CONTROL_SRCUPDATE:
06279          res = 0;
06280          break;
06281       case -1:
06282          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06283          break;
06284       }
06285    } else
06286       res = 0;
06287    ast_mutex_unlock(&p->lock);
06288    return res;
06289 }
06290 
06291 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, int transfercapability)
06292 {
06293    struct ast_channel *tmp;
06294    int deflaw;
06295    int res;
06296    int x,y;
06297    int features;
06298    struct ast_str *chan_name;
06299    struct ast_variable *v;
06300    struct dahdi_params ps;
06301    if (i->subs[idx].owner) {
06302       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06303       return NULL;
06304    }
06305    y = 1;
06306    chan_name = ast_str_alloca(32);
06307    do {
06308 #ifdef HAVE_PRI
06309       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06310          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06311       else
06312 #endif
06313       if (i->channel == CHAN_PSEUDO)
06314          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06315       else  
06316          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06317       for (x = 0; x < 3; x++) {
06318          if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06319             break;
06320       }
06321       y++;
06322    } while (x < 3);
06323    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str);
06324    if (!tmp)
06325       return NULL;
06326    tmp->tech = &dahdi_tech;
06327    memset(&ps, 0, sizeof(ps));
06328    ps.channo = i->channel;
06329    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06330    if (res) {
06331       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06332       ps.curlaw = DAHDI_LAW_MULAW;
06333    }
06334    if (ps.curlaw == DAHDI_LAW_ALAW)
06335       deflaw = AST_FORMAT_ALAW;
06336    else
06337       deflaw = AST_FORMAT_ULAW;
06338    if (law) {
06339       if (law == DAHDI_LAW_ALAW)
06340          deflaw = AST_FORMAT_ALAW;
06341       else
06342          deflaw = AST_FORMAT_ULAW;
06343    }
06344    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06345    tmp->nativeformats = deflaw;
06346    /* Start out assuming ulaw since it's smaller :) */
06347    tmp->rawreadformat = deflaw;
06348    tmp->readformat = deflaw;
06349    tmp->rawwriteformat = deflaw;
06350    tmp->writeformat = deflaw;
06351    i->subs[idx].linear = 0;
06352    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06353    features = 0;
06354    if (idx == SUB_REAL) {
06355       if (i->busydetect && CANBUSYDETECT(i))
06356          features |= DSP_FEATURE_BUSY_DETECT;
06357       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06358          features |= DSP_FEATURE_CALL_PROGRESS;
06359       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 
06360           (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06361          features |= DSP_FEATURE_FAX_DETECT;
06362       }
06363       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06364       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06365          i->hardwaredtmf = 0;
06366          features |= DSP_FEATURE_DIGIT_DETECT;
06367       } else if (NEED_MFDETECT(i)) {
06368          i->hardwaredtmf = 1;
06369          features |= DSP_FEATURE_DIGIT_DETECT;
06370       }
06371    }
06372    if (features) {
06373       if (i->dsp) {
06374          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06375       } else {
06376          if (i->channel != CHAN_PSEUDO)
06377             i->dsp = ast_dsp_new();
06378          else
06379             i->dsp = NULL;
06380          if (i->dsp) {
06381             i->dsp_features = features;
06382 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06383             /* We cannot do progress detection until receives PROGRESS message */
06384             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06385                /* Remember requested DSP features, don't treat
06386                   talking as ANSWER */
06387                i->dsp_features = features & ~DSP_PROGRESS_TALK;
06388                features = 0;
06389             }
06390 #endif
06391             ast_dsp_set_features(i->dsp, features);
06392             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06393             if (!ast_strlen_zero(progzone))
06394                ast_dsp_set_call_progress_zone(i->dsp, progzone);
06395             if (i->busydetect && CANBUSYDETECT(i)) {
06396                ast_dsp_set_busy_count(i->dsp, i->busycount);
06397                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
06398             }
06399          }
06400       }
06401    }
06402       
06403    if (state == AST_STATE_RING)
06404       tmp->rings = 1;
06405    tmp->tech_pvt = i;
06406    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06407       /* Only FXO signalled stuff can be picked up */
06408       tmp->callgroup = i->callgroup;
06409       tmp->pickupgroup = i->pickupgroup;
06410    }
06411    if (!ast_strlen_zero(i->parkinglot))
06412       ast_string_field_set(tmp, parkinglot, i->parkinglot);
06413    if (!ast_strlen_zero(i->language))
06414       ast_string_field_set(tmp, language, i->language);
06415    if (!i->owner)
06416       i->owner = tmp;
06417    if (!ast_strlen_zero(i->accountcode))
06418       ast_string_field_set(tmp, accountcode, i->accountcode);
06419    if (i->amaflags)
06420       tmp->amaflags = i->amaflags;
06421    i->subs[idx].owner = tmp;
06422    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06423    ast_string_field_set(tmp, call_forward, i->call_forward);
06424    /* If we've been told "no ADSI" then enforce it */
06425    if (!i->adsi)
06426       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06427    if (!ast_strlen_zero(i->exten))
06428       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06429    if (!ast_strlen_zero(i->rdnis))
06430       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06431    if (!ast_strlen_zero(i->dnid))
06432       tmp->cid.cid_dnid = ast_strdup(i->dnid);
06433 
06434    /* Don't use ast_set_callerid() here because it will
06435     * generate a needless NewCallerID event */
06436 #ifdef PRI_ANI
06437    if (!ast_strlen_zero(i->cid_ani))
06438       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06439    else  
06440       tmp->cid.cid_ani = ast_strdup(i->cid_num);
06441 #else
06442    tmp->cid.cid_ani = ast_strdup(i->cid_num);
06443 #endif
06444    tmp->cid.cid_pres = i->callingpres;
06445    tmp->cid.cid_ton = i->cid_ton;
06446    tmp->cid.cid_ani2 = i->cid_ani2;
06447 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06448    tmp->transfercapability = transfercapability;
06449    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06450    if (transfercapability & AST_TRANS_CAP_DIGITAL)
06451       i->digital = 1;
06452    /* Assume calls are not idle calls unless we're told differently */
06453    i->isidlecall = 0;
06454    i->alreadyhungup = 0;
06455 #endif
06456    /* clear the fake event in case we posted one before we had ast_channel */
06457    i->fake_event = 0;
06458    /* Assure there is no confmute on this channel */
06459    dahdi_confmute(i, 0);
06460    i->muting = 0;
06461    /* Configure the new channel jb */
06462    ast_jb_configure(tmp, &global_jbconf);
06463 
06464    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06465 
06466    for (v = i->vars ; v ; v = v->next)
06467                 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06468 
06469    if (startpbx) {
06470       if (ast_pbx_start(tmp)) {
06471          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06472          ast_hangup(tmp);
06473          i->owner = NULL;
06474          return NULL;
06475       }
06476    }
06477 
06478    ast_module_ref(ast_module_info->self);
06479    return tmp;
06480 }
06481 
06482 
06483 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
06484 {
06485    char c;
06486 
06487    *str = 0; /* start with empty output buffer */
06488    for (;;)
06489    {
06490       /* Wait for the first digit (up to specified ms). */
06491       c = ast_waitfordigit(chan, ms);
06492       /* if timeout, hangup or error, return as such */
06493       if (c < 1)
06494          return c;
06495       *str++ = c;
06496       *str = 0;
06497       if (strchr(term, c))
06498          return 1;
06499    }
06500 }
06501 
06502 static int dahdi_wink(struct dahdi_pvt *p, int idx)
06503 {
06504    int j;
06505    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06506    for (;;)
06507    {
06508          /* set bits of interest */
06509       j = DAHDI_IOMUX_SIGEVENT;
06510           /* wait for some happening */
06511       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06512          /* exit loop if we have it */
06513       if (j & DAHDI_IOMUX_SIGEVENT) break;
06514    }
06515      /* get the event info */
06516    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06517    return 0;
06518 }
06519 
06520 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
06521  * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
06522  * \param on 1 to enable, 0 to disable
06523  *
06524  * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical 
06525  * DAHDI channel). Use this to enable or disable it.
06526  *
06527  * \bug the use of the word "channel" for those dahdichans is really confusing.
06528  */
06529 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
06530 {
06531    /* Do not disturb */
06532    dahdichan->dnd = on;
06533    ast_verb(3, "%s DND on channel %d\n", 
06534          on? "Enabled" : "Disabled",
06535          dahdichan->channel);
06536    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06537          "Channel: DAHDI/%d\r\n"
06538          "Status: %s\r\n", dahdichan->channel,
06539          on? "enabled" : "disabled");
06540 }
06541 
06542 static void *ss_thread(void *data)
06543 {
06544    struct ast_channel *chan = data;
06545    struct dahdi_pvt *p = chan->tech_pvt;
06546    char exten[AST_MAX_EXTENSION] = "";
06547    char exten2[AST_MAX_EXTENSION] = "";
06548    unsigned char buf[256];
06549    char dtmfcid[300];
06550    char dtmfbuf[300];
06551    struct callerid_state *cs = NULL;
06552    char *name = NULL, *number = NULL;
06553    int distMatches;
06554    int curRingData[3];
06555    int receivedRingT;
06556    int counter1;
06557    int counter;
06558    int samples = 0;
06559    struct ast_smdi_md_message *smdi_msg = NULL;
06560    int flags;
06561    int i;
06562    int timeout;
06563    int getforward = 0;
06564    char *s1, *s2;
06565    int len = 0;
06566    int res;
06567    int idx;
06568 
06569    ast_mutex_lock(&ss_thread_lock);
06570    ss_thread_count++;
06571    ast_mutex_unlock(&ss_thread_lock);
06572    /* in the bizarre case where the channel has become a zombie before we
06573       even get started here, abort safely
06574    */
06575    if (!p) {
06576       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06577       ast_hangup(chan);
06578       goto quit;
06579    }
06580    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06581    idx = dahdi_get_index(chan, p, 1);
06582    if (idx < 0) {
06583       ast_log(LOG_WARNING, "Huh?\n");
06584       ast_hangup(chan);
06585       goto quit;
06586    }
06587    if (p->dsp)
06588       ast_dsp_digitreset(p->dsp);
06589    switch (p->sig) {
06590 #ifdef HAVE_PRI
06591    case SIG_PRI:
06592    case SIG_BRI:
06593    case SIG_BRI_PTMP:
06594       /* Now loop looking for an extension */
06595       ast_copy_string(exten, p->exten, sizeof(exten));
06596       len = strlen(exten);
06597       res = 0;
06598       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06599          if (len && !ast_ignore_pattern(chan->context, exten))
06600             tone_zone_play_tone(p->subs[idx].dfd, -1);
06601          else
06602             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06603          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06604             timeout = matchdigittimeout;
06605          else
06606             timeout = gendigittimeout;
06607          res = ast_waitfordigit(chan, timeout);
06608          if (res < 0) {
06609             ast_debug(1, "waitfordigit returned < 0...\n");
06610             ast_hangup(chan);
06611             goto quit;
06612          } else if (res) {
06613             exten[len++] = res;
06614             exten[len] = '\0';
06615          } else
06616             break;
06617       }
06618       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
06619       if (ast_strlen_zero(exten)) {
06620          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06621          exten[0] = 's';
06622          exten[1] = '\0';
06623       }
06624       tone_zone_play_tone(p->subs[idx].dfd, -1);
06625       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06626          /* Start the real PBX */
06627          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06628          if (p->dsp) ast_dsp_digitreset(p->dsp);
06629          dahdi_enable_ec(p);
06630          ast_setstate(chan, AST_STATE_RING);
06631          res = ast_pbx_run(chan);
06632          if (res) {
06633             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06634          }
06635       } else {
06636          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06637          chan->hangupcause = AST_CAUSE_UNALLOCATED;
06638          ast_hangup(chan);
06639          p->exten[0] = '\0';
06640          /* Since we send release complete here, we won't get one */
06641          p->call = NULL;
06642       }
06643       goto quit;
06644       break;
06645 #endif
06646    case SIG_FEATD:
06647    case SIG_FEATDMF:
06648    case SIG_FEATDMF_TA:
06649    case SIG_E911:
06650    case SIG_FGC_CAMAMF:
06651    case SIG_FEATB:
06652    case SIG_EMWINK:
06653    case SIG_SF_FEATD:
06654    case SIG_SF_FEATDMF:
06655    case SIG_SF_FEATB:
06656    case SIG_SFWINK:
06657       if (dahdi_wink(p, idx)) 
06658          goto quit;
06659       /* Fall through */
06660    case SIG_EM:
06661    case SIG_EM_E1:
06662    case SIG_SF:
06663    case SIG_FGC_CAMA:
06664       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06665       if (p->dsp)
06666          ast_dsp_digitreset(p->dsp);
06667       /* set digit mode appropriately */
06668       if (p->dsp) {
06669          if (NEED_MFDETECT(p))
06670             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 
06671          else 
06672             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06673       }
06674       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06675       /* Wait for the first digit only if immediate=no */
06676       if (!p->immediate)
06677          /* Wait for the first digit (up to 5 seconds). */
06678          res = ast_waitfordigit(chan, 5000);
06679       else
06680          res = 0;
06681       if (res > 0) {
06682          /* save first char */
06683          dtmfbuf[0] = res;
06684          switch (p->sig) {
06685          case SIG_FEATD:
06686          case SIG_SF_FEATD:
06687             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06688             if (res > 0)
06689                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06690             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06691             break;
06692          case SIG_FEATDMF_TA:
06693             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06694             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06695             if (dahdi_wink(p, idx)) goto quit;
06696             dtmfbuf[0] = 0;
06697             /* Wait for the first digit (up to 5 seconds). */
06698             res = ast_waitfordigit(chan, 5000);
06699             if (res <= 0) break;
06700             dtmfbuf[0] = res;
06701             /* fall through intentionally */
06702          case SIG_FEATDMF:
06703          case SIG_E911:
06704          case SIG_FGC_CAMAMF:
06705          case SIG_SF_FEATDMF:
06706             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06707             /* if international caca, do it again to get real ANO */
06708             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06709             {
06710                if (dahdi_wink(p, idx)) goto quit;
06711                dtmfbuf[0] = 0;
06712                /* Wait for the first digit (up to 5 seconds). */
06713                res = ast_waitfordigit(chan, 5000);
06714                if (res <= 0) break;
06715                dtmfbuf[0] = res;
06716                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06717             }
06718             if (res > 0) {
06719                /* if E911, take off hook */
06720                if (p->sig == SIG_E911)
06721                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06722                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06723             }
06724             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06725             break;
06726          case SIG_FEATB:
06727          case SIG_SF_FEATB:
06728             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06729             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06730             break;
06731          case SIG_EMWINK:
06732             /* if we received a '*', we are actually receiving Feature Group D
06733                dial syntax, so use that mode; otherwise, fall through to normal
06734                mode
06735             */
06736             if (res == '*') {
06737                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06738                if (res > 0)
06739                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06740                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06741                break;
06742             }
06743          default:
06744             /* If we got the first digit, get the rest */
06745             len = 1;
06746             dtmfbuf[len] = '\0';
06747             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06748                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06749                   timeout = matchdigittimeout;
06750                } else {
06751                   timeout = gendigittimeout;
06752                }
06753                res = ast_waitfordigit(chan, timeout);
06754                if (res < 0) {
06755                   ast_debug(1, "waitfordigit returned < 0...\n");
06756                   ast_hangup(chan);
06757                   goto quit;
06758                } else if (res) {
06759                   dtmfbuf[len++] = res;
06760                   dtmfbuf[len] = '\0';
06761                } else {
06762                   break;
06763                }
06764             }
06765             break;
06766          }
06767       }
06768       if (res == -1) {
06769          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06770          ast_hangup(chan);
06771          goto quit;
06772       } else if (res < 0) {
06773          ast_debug(1, "Got hung up before digits finished\n");
06774          ast_hangup(chan);
06775          goto quit;
06776       }
06777 
06778       if (p->sig == SIG_FGC_CAMA) {
06779          char anibuf[100];
06780 
06781          if (ast_safe_sleep(chan,1000) == -1) {
06782                            ast_hangup(chan);
06783                            goto quit;
06784          }
06785                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06786                         ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06787                         res = my_getsigstr(chan, anibuf, "#", 10000);
06788                         if ((res > 0) && (strlen(anibuf) > 2)) {
06789             if (anibuf[strlen(anibuf) - 1] == '#')
06790                anibuf[strlen(anibuf) - 1] = 0;
06791             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06792          }
06793                         ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06794       }
06795 
06796       ast_copy_string(exten, dtmfbuf, sizeof(exten));
06797       if (ast_strlen_zero(exten))
06798          ast_copy_string(exten, "s", sizeof(exten));
06799       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06800          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
06801          if (exten[0] == '*') {
06802             char *stringp=NULL;
06803             ast_copy_string(exten2, exten, sizeof(exten2));
06804             /* Parse out extension and callerid */
06805             stringp=exten2 +1;
06806             s1 = strsep(&stringp, "*");
06807             s2 = strsep(&stringp, "*");
06808             if (s2) {
06809                if (!ast_strlen_zero(p->cid_num))
06810                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06811                else
06812                   ast_set_callerid(chan, s1, NULL, s1);
06813                ast_copy_string(exten, s2, sizeof(exten));
06814             } else
06815                ast_copy_string(exten, s1, sizeof(exten));
06816          } else if (p->sig == SIG_FEATD)
06817             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06818       }
06819       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06820          if (exten[0] == '*') {
06821             char *stringp=NULL;
06822             ast_copy_string(exten2, exten, sizeof(exten2));
06823             /* Parse out extension and callerid */
06824             stringp=exten2 +1;
06825             s1 = strsep(&stringp, "#");
06826             s2 = strsep(&stringp, "#");
06827             if (s2) {
06828                if (!ast_strlen_zero(p->cid_num))
06829                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06830                else
06831                   if (*(s1 + 2))
06832                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06833                ast_copy_string(exten, s2 + 1, sizeof(exten));
06834             } else
06835                ast_copy_string(exten, s1 + 2, sizeof(exten));
06836          } else
06837             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06838       }
06839       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06840          if (exten[0] == '*') {
06841             char *stringp=NULL;
06842             ast_copy_string(exten2, exten, sizeof(exten2));
06843             /* Parse out extension and callerid */
06844             stringp=exten2 +1;
06845             s1 = strsep(&stringp, "#");
06846             s2 = strsep(&stringp, "#");
06847             if (s2 && (*(s2 + 1) == '0')) {
06848                if (*(s2 + 2))
06849                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06850             }
06851             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
06852             else ast_copy_string(exten, "911", sizeof(exten));
06853          } else
06854             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06855       }
06856       if (p->sig == SIG_FEATB) {
06857          if (exten[0] == '*') {
06858             char *stringp=NULL;
06859             ast_copy_string(exten2, exten, sizeof(exten2));
06860             /* Parse out extension and callerid */
06861             stringp=exten2 +1;
06862             s1 = strsep(&stringp, "#");
06863             ast_copy_string(exten, exten2 + 1, sizeof(exten));
06864          } else
06865             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06866       }
06867       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06868          dahdi_wink(p, idx);
06869                         /* some switches require a minimum guard time between
06870                            the last FGD wink and something that answers
06871                            immediately. This ensures it */
06872                         if (ast_safe_sleep(chan,100)) goto quit;
06873       }
06874       dahdi_enable_ec(p);
06875       if (NEED_MFDETECT(p)) {
06876          if (p->dsp) {
06877             if (!p->hardwaredtmf)
06878                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 
06879             else {
06880                ast_dsp_free(p->dsp);
06881                p->dsp = NULL;
06882             }
06883          }
06884       }
06885 
06886       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06887          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06888          if (p->dsp) ast_dsp_digitreset(p->dsp);
06889          res = ast_pbx_run(chan);
06890          if (res) {
06891             ast_log(LOG_WARNING, "PBX exited non-zero\n");
06892             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06893          }
06894          goto quit;
06895       } else {
06896          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06897          sleep(2);
06898          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06899          if (res < 0)
06900             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06901          else
06902             sleep(1);
06903          res = ast_streamfile(chan, "ss-noservice", chan->language);
06904          if (res >= 0)
06905             ast_waitstream(chan, "");
06906          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06907          ast_hangup(chan);
06908          goto quit;
06909       }
06910       break;
06911    case SIG_FXOLS:
06912    case SIG_FXOGS:
06913    case SIG_FXOKS:
06914       /* Read the first digit */
06915       timeout = firstdigittimeout;
06916       /* If starting a threeway call, never timeout on the first digit so someone
06917          can use flash-hook as a "hold" feature */
06918       if (p->subs[SUB_THREEWAY].owner) 
06919          timeout = 999999;
06920       while (len < AST_MAX_EXTENSION-1) {
06921          /* Read digit unless it's supposed to be immediate, in which case the
06922             only answer is 's' */
06923          if (p->immediate) 
06924             res = 's';
06925          else
06926             res = ast_waitfordigit(chan, timeout);
06927          timeout = 0;
06928          if (res < 0) {
06929             ast_debug(1, "waitfordigit returned < 0...\n");
06930             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06931             ast_hangup(chan);
06932             goto quit;
06933          } else if (res)  {
06934             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06935             exten[len++]=res;
06936             exten[len] = '\0';
06937          }
06938          if (!ast_ignore_pattern(chan->context, exten))
06939             tone_zone_play_tone(p->subs[idx].dfd, -1);
06940          else
06941             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06942          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06943             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06944                if (getforward) {
06945                   /* Record this as the forwarding extension */
06946                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
06947                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06948                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06949                   if (res)
06950                      break;
06951                   usleep(500000);
06952                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06953                   sleep(1);
06954                   memset(exten, 0, sizeof(exten));
06955                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06956                   len = 0;
06957                   getforward = 0;
06958                } else  {
06959                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06960                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06961                   if (!ast_strlen_zero(p->cid_num)) {
06962                      if (!p->hidecallerid)
06963                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
06964                      else
06965                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
06966                   }
06967                   if (!ast_strlen_zero(p->cid_name)) {
06968                      if (!p->hidecallerid)
06969                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
06970                   }
06971                   ast_setstate(chan, AST_STATE_RING);
06972                   dahdi_enable_ec(p);
06973                   res = ast_pbx_run(chan);
06974                   if (res) {
06975                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
06976                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06977                   }
06978                   goto quit;
06979                }
06980             } else {
06981                /* It's a match, but they just typed a digit, and there is an ambiguous match,
06982                   so just set the timeout to matchdigittimeout and wait some more */
06983                timeout = matchdigittimeout;
06984             }
06985          } else if (res == 0) {
06986             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
06987             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06988             dahdi_wait_event(p->subs[idx].dfd);
06989             ast_hangup(chan);
06990             goto quit;
06991          } else if (p->callwaiting && !strcmp(exten, "*70")) {
06992             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
06993             /* Disable call waiting if enabled */
06994             p->callwaiting = 0;
06995             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06996             if (res) {
06997                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06998                   chan->name, strerror(errno));
06999             }
07000             len = 0;
07001             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
07002             memset(exten, 0, sizeof(exten));
07003             timeout = firstdigittimeout;
07004                
07005          } else if (!strcmp(exten,ast_pickup_ext())) {
07006             /* Scan all channels and see if there are any
07007              * ringing channels that have call groups
07008              * that equal this channels pickup group  
07009              */
07010             if (idx == SUB_REAL) {
07011                /* Switch us from Third call to Call Wait */
07012                if (p->subs[SUB_THREEWAY].owner) {
07013                   /* If you make a threeway call and the *8# a call, it should actually 
07014                      look like a callwait */
07015                   alloc_sub(p, SUB_CALLWAIT);   
07016                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07017                   unalloc_sub(p, SUB_THREEWAY);
07018                }
07019                dahdi_enable_ec(p);
07020                if (ast_pickup_call(chan)) {
07021                   ast_debug(1, "No call pickup possible...\n");
07022                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07023                   dahdi_wait_event(p->subs[idx].dfd);
07024                }
07025                ast_hangup(chan);
07026                goto quit;
07027             } else {
07028                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
07029                ast_hangup(chan);
07030                goto quit;
07031             }
07032             
07033          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07034             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07035             /* Disable Caller*ID if enabled */
07036             p->hidecallerid = 1;
07037             if (chan->cid.cid_num)
07038                ast_free(chan->cid.cid_num);
07039             chan->cid.cid_num = NULL;
07040             if (chan->cid.cid_name)
07041                ast_free(chan->cid.cid_name);
07042             chan->cid.cid_name = NULL;
07043             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07044             if (res) {
07045                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07046                   chan->name, strerror(errno));
07047             }
07048             len = 0;
07049             memset(exten, 0, sizeof(exten));
07050             timeout = firstdigittimeout;
07051          } else if (p->callreturn && !strcmp(exten, "*69")) {
07052             res = 0;
07053             if (!ast_strlen_zero(p->lastcid_num)) {
07054                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07055             }
07056             if (!res)
07057                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07058             break;
07059          } else if (!strcmp(exten, "*78")) {
07060             dahdi_dnd(p, 1);
07061             /* Do not disturb */
07062             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07063             getforward = 0;
07064             memset(exten, 0, sizeof(exten));
07065             len = 0;
07066          } else if (!strcmp(exten, "*79")) {
07067             dahdi_dnd(p, 0);
07068             /* Do not disturb */
07069             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07070             getforward = 0;
07071             memset(exten, 0, sizeof(exten));
07072             len = 0;
07073          } else if (p->cancallforward && !strcmp(exten, "*72")) {
07074             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07075             getforward = 1;
07076             memset(exten, 0, sizeof(exten));
07077             len = 0;
07078          } else if (p->cancallforward && !strcmp(exten, "*73")) {
07079             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07080             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07081             memset(p->call_forward, 0, sizeof(p->call_forward));
07082             getforward = 0;
07083             memset(exten, 0, sizeof(exten));
07084             len = 0;
07085          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
07086                   p->subs[SUB_THREEWAY].owner &&
07087                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07088             /* This is a three way call, the main call being a real channel, 
07089                and we're parking the first call. */
07090             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07091             ast_verb(3, "Parking call to '%s'\n", chan->name);
07092             break;
07093          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07094             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07095             res = ast_db_put("blacklist", p->lastcid_num, "1");
07096             if (!res) {
07097                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07098                memset(exten, 0, sizeof(exten));
07099                len = 0;
07100             }
07101          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07102             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07103             /* Enable Caller*ID if enabled */
07104             p->hidecallerid = 0;
07105             if (chan->cid.cid_num)
07106                ast_free(chan->cid.cid_num);
07107             chan->cid.cid_num = NULL;
07108             if (chan->cid.cid_name)
07109                ast_free(chan->cid.cid_name);
07110             chan->cid.cid_name = NULL;
07111             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07112             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07113             if (res) {
07114                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07115                   chan->name, strerror(errno));
07116             }
07117             len = 0;
07118             memset(exten, 0, sizeof(exten));
07119             timeout = firstdigittimeout;
07120          } else if (!strcmp(exten, "*0")) {
07121             struct ast_channel *nbridge = 
07122                p->subs[SUB_THREEWAY].owner;
07123             struct dahdi_pvt *pbridge = NULL;
07124               /* set up the private struct of the bridged one, if any */
07125             if (nbridge && ast_bridged_channel(nbridge)) 
07126                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07127             if (nbridge && pbridge && 
07128                 (nbridge->tech == &dahdi_tech) && 
07129                 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07130                 ISTRUNK(pbridge)) {
07131                int func = DAHDI_FLASH;
07132                /* Clear out the dial buffer */
07133                p->dop.dialstr[0] = '\0';
07134                /* flash hookswitch */
07135                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07136                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
07137                      nbridge->name, strerror(errno));
07138                }
07139                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07140                unalloc_sub(p, SUB_THREEWAY);
07141                p->owner = p->subs[SUB_REAL].owner;
07142                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07143                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07144                ast_hangup(chan);
07145                goto quit;
07146             } else {
07147                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07148                dahdi_wait_event(p->subs[idx].dfd);
07149                tone_zone_play_tone(p->subs[idx].dfd, -1);
07150                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07151                unalloc_sub(p, SUB_THREEWAY);
07152                p->owner = p->subs[SUB_REAL].owner;
07153                ast_hangup(chan);
07154                goto quit;
07155             }              
07156          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07157                      ((exten[0] != '*') || (strlen(exten) > 2))) {
07158             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
07159             break;
07160          }
07161          if (!timeout)
07162             timeout = gendigittimeout;
07163          if (len && !ast_ignore_pattern(chan->context, exten))
07164             tone_zone_play_tone(p->subs[idx].dfd, -1);
07165       }
07166       break;
07167    case SIG_FXSLS:
07168    case SIG_FXSGS:
07169    case SIG_FXSKS:
07170 #ifdef HAVE_PRI
07171       if (p->pri) {
07172          /* This is a GR-303 trunk actually.  Wait for the first ring... */
07173          struct ast_frame *f;
07174          int res;
07175          time_t start;
07176 
07177          time(&start);
07178          ast_setstate(chan, AST_STATE_RING);
07179          while (time(NULL) < start + 3) {
07180             res = ast_waitfor(chan, 1000);
07181             if (res) {
07182                f = ast_read(chan);
07183                if (!f) {
07184                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07185                   ast_hangup(chan);
07186                   goto quit;
07187                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07188                   res = 1;
07189                } else
07190                   res = 0;
07191                ast_frfree(f);
07192                if (res) {
07193                   ast_debug(1, "Got ring!\n");
07194                   res = 0;
07195                   break;
07196                }
07197             }
07198          }
07199       }
07200 #endif
07201       /* check for SMDI messages */
07202       if (p->use_smdi && p->smdi_iface) {
07203          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07204 
07205          if (smdi_msg != NULL) {
07206             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07207 
07208             if (smdi_msg->type == 'B')
07209                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07210             else if (smdi_msg->type == 'N')
07211                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07212 
07213             ast_debug(1, "Received SMDI message on %s\n", chan->name);
07214          } else {
07215             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07216          }
07217       }
07218 
07219       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07220             number = smdi_msg->calling_st;
07221 
07222       /* If we want caller id, we're in a prering state due to a polarity reversal
07223        * and we're set to use a polarity reversal to trigger the start of caller id,
07224        * grab the caller id and wait for ringing to start... */
07225       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07226          /* If set to use DTMF CID signalling, listen for DTMF */
07227          if (p->cid_signalling == CID_SIG_DTMF) {
07228             int k = 0;
07229             cs = NULL;
07230             ast_debug(1, "Receiving DTMF cid on "
07231                "channel %s\n", chan->name);
07232             dahdi_setlinear(p->subs[idx].dfd, 0);
07233             res = 2000;
07234             for (;;) {
07235                struct ast_frame *f;
07236                res = ast_waitfor(chan, res);
07237                if (res <= 0) {
07238                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07239                      "Exiting simple switch\n");
07240                   ast_hangup(chan);
07241                   goto quit;
07242                } 
07243                f = ast_read(chan);
07244                if (!f)
07245                   break;
07246                if (f->frametype == AST_FRAME_DTMF) {
07247                   dtmfbuf[k++] = f->subclass;
07248                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
07249                   res = 2000;
07250                }
07251                ast_frfree(f);
07252                if (chan->_state == AST_STATE_RING ||
07253                    chan->_state == AST_STATE_RINGING) 
07254                   break; /* Got ring */
07255             }
07256             dtmfbuf[k] = '\0';
07257             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07258             /* Got cid and ring. */
07259             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07260             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07261             ast_debug(1, "CID is '%s', flags %d\n", 
07262                dtmfcid, flags);
07263             /* If first byte is NULL, we have no cid */
07264             if (!ast_strlen_zero(dtmfcid)) 
07265                number = dtmfcid;
07266             else
07267                number = NULL;
07268          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07269          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07270             cs = callerid_new(p->cid_signalling);
07271             if (cs) {
07272                samples = 0;
07273 #if 1
07274                bump_gains(p);
07275 #endif
07276                /* Take out of linear mode for Caller*ID processing */
07277                dahdi_setlinear(p->subs[idx].dfd, 0);
07278                
07279                /* First we wait and listen for the Caller*ID */
07280                for (;;) {  
07281                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07282                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07283                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07284                      callerid_free(cs);
07285                      ast_hangup(chan);
07286                      goto quit;
07287                   }
07288                   if (i & DAHDI_IOMUX_SIGEVENT) {
07289                      res = dahdi_get_event(p->subs[idx].dfd);
07290                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07291 
07292                      if (p->cid_signalling == CID_SIG_V23_JP) {
07293                         if (res == DAHDI_EVENT_RINGBEGIN) {
07294                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07295                            usleep(1);
07296                         }
07297                      } else {
07298                         res = 0;
07299                         break;
07300                      }
07301                   } else if (i & DAHDI_IOMUX_READ) {
07302                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
07303                      if (res < 0) {
07304                         if (errno != ELAST) {
07305                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07306                            callerid_free(cs);
07307                            ast_hangup(chan);
07308                            goto quit;
07309                         }
07310                         break;
07311                      }
07312                      samples += res;
07313 
07314                      if  (p->cid_signalling == CID_SIG_V23_JP) {
07315                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07316                      } else {
07317                         res = callerid_feed(cs, buf, res, AST_LAW(p));
07318                      }
07319 
07320                      if (res < 0) {
07321                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07322                         break;
07323                      } else if (res)
07324                         break;
07325                      else if (samples > (8000 * 10))
07326                         break;
07327                   }
07328                }
07329                if (res == 1) {
07330                   callerid_get(cs, &name, &number, &flags);
07331                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07332                }
07333 
07334                if (p->cid_signalling == CID_SIG_V23_JP) {
07335                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07336                   usleep(1);
07337                   res = 4000;
07338                } else {
07339 
07340                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
07341                   res = 2000;
07342                }
07343 
07344                for (;;) {
07345                   struct ast_frame *f;
07346                   res = ast_waitfor(chan, res);
07347                   if (res <= 0) {
07348                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07349                         "Exiting simple switch\n");
07350                      ast_hangup(chan);
07351                      goto quit;
07352                   } 
07353                   if (!(f = ast_read(chan))) {
07354                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07355                      ast_hangup(chan);
07356                      goto quit;
07357                   }
07358                   ast_frfree(f);
07359                   if (chan->_state == AST_STATE_RING ||
07360                       chan->_state == AST_STATE_RINGING) 
07361                      break; /* Got ring */
07362                }
07363    
07364                /* We must have a ring by now, so, if configured, lets try to listen for
07365                 * distinctive ringing */ 
07366                if (p->usedistinctiveringdetection) {
07367                   len = 0;
07368                   distMatches = 0;
07369                   /* Clear the current ring data array so we dont have old data in it. */
07370                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07371                      curRingData[receivedRingT] = 0;
07372                   receivedRingT = 0;
07373                   counter = 0;
07374                   counter1 = 0;
07375                   /* Check to see if context is what it should be, if not set to be. */
07376                   if (strcmp(p->context,p->defcontext) != 0) {
07377                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07378                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07379                   }
07380       
07381                   for (;;) {  
07382                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07383                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07384                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07385                         callerid_free(cs);
07386                         ast_hangup(chan);
07387                         goto quit;
07388                      }
07389                      if (i & DAHDI_IOMUX_SIGEVENT) {
07390                         res = dahdi_get_event(p->subs[idx].dfd);
07391                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07392                         res = 0;
07393                         /* Let us detect distinctive ring */
07394       
07395                         curRingData[receivedRingT] = p->ringt;
07396       
07397                         if (p->ringt < p->ringt_base/2)
07398                            break;
07399                         /* Increment the ringT counter so we can match it against
07400                            values in chan_dahdi.conf for distinctive ring */
07401                         if (++receivedRingT == ARRAY_LEN(curRingData))
07402                            break;
07403                      } else if (i & DAHDI_IOMUX_READ) {
07404                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
07405                         if (res < 0) {
07406                            if (errno != ELAST) {
07407                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07408                               callerid_free(cs);
07409                               ast_hangup(chan);
07410                               goto quit;
07411                            }
07412                            break;
07413                         }
07414                         if (p->ringt) 
07415                            p->ringt--;
07416                         if (p->ringt == 1) {
07417                            res = -1;
07418                            break;
07419                         }
07420                      }
07421                   }
07422                      /* this only shows up if you have n of the dring patterns filled in */
07423                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07424                   for (counter = 0; counter < 3; counter++) {
07425                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07426                      channel */
07427                      distMatches = 0;
07428                      for (counter1 = 0; counter1 < 3; counter1++) {
07429                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07430                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
07431                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07432                            curRingData[counter1]);
07433                            distMatches++;
07434                         }
07435                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07436                             curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07437                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07438                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07439                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07440                            distMatches++;
07441                         }
07442                      }
07443 
07444                      if (distMatches == 3) {
07445                         /* The ring matches, set the context to whatever is for distinctive ring.. */
07446                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07447                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07448                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07449                         break;
07450                      }
07451                   }
07452                }
07453                /* Restore linear mode (if appropriate) for Caller*ID processing */
07454                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07455 #if 1
07456                restore_gains(p);
07457 #endif            
07458             } else
07459                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
07460          } else {
07461             ast_log(LOG_WARNING, "Channel %s in prering "
07462                "state, but I have nothing to do. "
07463                "Terminating simple switch, should be "
07464                "restarted by the actual ring.\n", 
07465                chan->name);
07466             ast_hangup(chan);
07467             goto quit;
07468          }
07469       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07470                         if (p->cid_signalling == CID_SIG_DTMF) {
07471                                 int k = 0;
07472                                 cs = NULL;
07473                                 dahdi_setlinear(p->subs[idx].dfd, 0);
07474                                 res = 2000;
07475                                 for (;;) {
07476                                         struct ast_frame *f;
07477                                         res = ast_waitfor(chan, res);
07478                                         if (res <= 0) {
07479                                                 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07480                                                                 "Exiting simple switch\n");
07481                                                 ast_hangup(chan);
07482                                                 return NULL;
07483                                         }
07484                                         f = ast_read(chan);
07485                                         if (f->frametype == AST_FRAME_DTMF) {
07486                                                 dtmfbuf[k++] = f->subclass;
07487                                                 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07488                                                 res = 2000;
07489                                         }
07490                                         ast_frfree(f);
07491 
07492                                         if (p->ringt_base == p->ringt)
07493                                                 break;
07494 
07495                                 }
07496                                 dtmfbuf[k] = '\0';
07497                                 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07498                                 /* Got cid and ring. */
07499                                 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07500                                 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07501                                                 dtmfcid, flags);
07502                                 /* If first byte is NULL, we have no cid */
07503                                 if (!ast_strlen_zero(dtmfcid))
07504                                         number = dtmfcid;
07505                                 else
07506                                         number = NULL;
07507                                 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07508                         } else {
07509          /* FSK Bell202 callerID */
07510          cs = callerid_new(p->cid_signalling);
07511          if (cs) {
07512 #if 1
07513             bump_gains(p);
07514 #endif            
07515             samples = 0;
07516             len = 0;
07517             distMatches = 0;
07518             /* Clear the current ring data array so we dont have old data in it. */
07519             for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07520                curRingData[receivedRingT] = 0;
07521             receivedRingT = 0;
07522             counter = 0;
07523             counter1 = 0;
07524             /* Check to see if context is what it should be, if not set to be. */
07525             if (strcmp(p->context,p->defcontext) != 0) {
07526                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07527                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07528             }
07529 
07530             /* Take out of linear mode for Caller*ID processing */
07531             dahdi_setlinear(p->subs[idx].dfd, 0);
07532             for (;;) {  
07533                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07534                if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07535                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07536                   callerid_free(cs);
07537                   ast_hangup(chan);
07538                   goto quit;
07539                }
07540                if (i & DAHDI_IOMUX_SIGEVENT) {
07541                   res = dahdi_get_event(p->subs[idx].dfd);
07542                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07543                   /* If we get a PR event, they hung up while processing calerid */
07544                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07545                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07546                      p->polarity = POLARITY_IDLE;
07547                      callerid_free(cs);
07548                      ast_hangup(chan);
07549                      goto quit;
07550                   }
07551                   res = 0;
07552                   /* Let us detect callerid when the telco uses distinctive ring */
07553 
07554                   curRingData[receivedRingT] = p->ringt;
07555 
07556                   if (p->ringt < p->ringt_base/2)
07557                      break;
07558                   /* Increment the ringT counter so we can match it against
07559                      values in chan_dahdi.conf for distinctive ring */
07560                   if (++receivedRingT == ARRAY_LEN(curRingData))
07561                      break;
07562                } else if (i & DAHDI_IOMUX_READ) {
07563                   res = read(p->subs[idx].dfd, buf, sizeof(buf));
07564                   if (res < 0) {
07565                      if (errno != ELAST) {
07566                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07567                         callerid_free(cs);
07568                         ast_hangup(chan);
07569                         goto quit;
07570                      }
07571                      break;
07572                   }
07573                   if (p->ringt) 
07574                      p->ringt--;
07575                   if (p->ringt == 1) {
07576                      res = -1;
07577                      break;
07578                   }
07579                   samples += res;
07580                   res = callerid_feed(cs, buf, res, AST_LAW(p));
07581                   if (res < 0) {
07582                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07583                      break;
07584                   } else if (res)
07585                      break;
07586                   else if (samples > (8000 * 10))
07587                      break;
07588                }
07589             }
07590             if (res == 1) {
07591                callerid_get(cs, &name, &number, &flags);
07592                ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07593             }
07594             if (distinctiveringaftercid == 1) {
07595                /* Clear the current ring data array so we dont have old data in it. */
07596                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07597                   curRingData[receivedRingT] = 0;
07598                }
07599                receivedRingT = 0;
07600                ast_verb(3, "Detecting post-CID distinctive ring\n");
07601                for (;;) {
07602                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07603                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i)))    {
07604                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07605                      callerid_free(cs);
07606                      ast_hangup(chan);
07607                      goto quit;
07608                   }
07609                   if (i & DAHDI_IOMUX_SIGEVENT) {
07610                      res = dahdi_get_event(p->subs[idx].dfd);
07611                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07612                      res = 0;
07613                      /* Let us detect callerid when the telco uses distinctive ring */
07614 
07615                      curRingData[receivedRingT] = p->ringt;
07616 
07617                      if (p->ringt < p->ringt_base/2)
07618                         break;
07619                      /* Increment the ringT counter so we can match it against
07620                         values in chan_dahdi.conf for distinctive ring */
07621                      if (++receivedRingT == ARRAY_LEN(curRingData))
07622                         break;
07623                   } else if (i & DAHDI_IOMUX_READ) {
07624                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
07625                      if (res < 0) {
07626                         if (errno != ELAST) {
07627                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07628                            callerid_free(cs);
07629                            ast_hangup(chan);
07630                            goto quit;
07631                         }
07632                         break;
07633                      }
07634                   if (p->ringt)
07635                      p->ringt--;
07636                      if (p->ringt == 1) {
07637                         res = -1;
07638                         break;
07639                      }
07640                   }
07641                }
07642             }
07643             if (p->usedistinctiveringdetection) {
07644                   /* this only shows up if you have n of the dring patterns filled in */
07645                ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07646 
07647                for (counter = 0; counter < 3; counter++) {
07648                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07649                   channel */
07650                      /* this only shows up if you have n of the dring patterns filled in */
07651                   ast_verb(3, "Checking %d,%d,%d\n",
07652                         p->drings.ringnum[counter].ring[0],
07653                         p->drings.ringnum[counter].ring[1],
07654                         p->drings.ringnum[counter].ring[2]);
07655                   distMatches = 0;
07656                   for (counter1 = 0; counter1 < 3; counter1++) {
07657                      ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07658                      if (p->drings.ringnum[counter].ring[counter1] == -1) {
07659                         ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07660                         curRingData[counter1]);
07661                         distMatches++;
07662                      }
07663                      else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07664                          curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07665                         ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07666                         (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07667                         (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07668                         distMatches++;
07669                      }
07670                   }
07671                   if (distMatches == 3) {
07672                      /* The ring matches, set the context to whatever is for distinctive ring.. */
07673                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07674                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07675                      ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07676                      break;
07677                   }
07678                }
07679             }
07680             /* Restore linear mode (if appropriate) for Caller*ID processing */
07681             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07682 #if 1
07683             restore_gains(p);
07684 #endif            
07685             if (res < 0) {
07686                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07687             }
07688          } else
07689             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07690       }
07691       }
07692       else
07693          cs = NULL;
07694 
07695       if (number)
07696          ast_shrink_phone_number(number);
07697       ast_set_callerid(chan, number, name, number);
07698 
07699       if (smdi_msg)
07700          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07701 
07702       if (cs)
07703          callerid_free(cs);
07704       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
07705       if (flags & CID_MSGWAITING) {
07706          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07707          notify_message(p->mailbox, 1);
07708          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
07709          if (p->mwimonitor_rpas) {
07710             ast_hangup(chan);
07711             return NULL;
07712          }
07713       } else if (flags & CID_NOMSGWAITING) {
07714          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07715          notify_message(p->mailbox, 0);
07716          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
07717          if (p->mwimonitor_rpas) {
07718             ast_hangup(chan);
07719             return NULL;
07720          }
07721       }
07722 
07723       ast_setstate(chan, AST_STATE_RING);
07724       chan->rings = 1;
07725       p->ringt = p->ringt_base;
07726       res = ast_pbx_run(chan);
07727       if (res) {
07728          ast_hangup(chan);
07729          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07730       }
07731       goto quit;
07732    default:
07733       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07734       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07735       if (res < 0)
07736             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07737    }
07738    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07739    if (res < 0)
07740          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07741    ast_hangup(chan);
07742 quit:
07743    ast_mutex_lock(&ss_thread_lock);
07744    ss_thread_count--;
07745    ast_cond_signal(&ss_thread_complete);
07746    ast_mutex_unlock(&ss_thread_lock);
07747    return NULL;
07748 }
07749 
07750 struct mwi_thread_data {
07751    struct dahdi_pvt *pvt;
07752    unsigned char buf[READ_SIZE];
07753    size_t len;
07754 };
07755 
07756 static int calc_energy(const unsigned char *buf, int len, int law)
07757 {
07758    int x;
07759    int sum = 0;
07760 
07761    if (!len)
07762       return 0;
07763 
07764    for (x = 0; x < len; x++)
07765       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07766 
07767    return sum / len;
07768 }
07769 
07770 static void *mwi_thread(void *data)
07771 {
07772    struct mwi_thread_data *mtd = data;
07773    struct callerid_state *cs;
07774    pthread_t threadid;
07775    int samples = 0;
07776    char *name, *number;
07777    int flags;
07778    int i, res;
07779    unsigned int spill_done = 0;
07780    int spill_result = -1;
07781    
07782    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07783       mtd->pvt->mwimonitoractive = 0;
07784 
07785       return NULL;
07786    }
07787    
07788    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07789 
07790    bump_gains(mtd->pvt);
07791 
07792    for (;;) {  
07793       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07794       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07795          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07796          goto quit;
07797       }
07798 
07799       if (i & DAHDI_IOMUX_SIGEVENT) {
07800          struct ast_channel *chan;
07801 
07802          /* If we get an event, screen out events that we do not act on.
07803           * Otherwise, cancel and go to the simple switch to let it deal with it.
07804           */
07805          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07806 
07807          switch (res) {
07808          case DAHDI_EVENT_NEONMWI_ACTIVE:
07809          case DAHDI_EVENT_NEONMWI_INACTIVE:
07810          case DAHDI_EVENT_NONE:
07811          case DAHDI_EVENT_BITSCHANGED:
07812             break;
07813          case DAHDI_EVENT_NOALARM:
07814             mtd->pvt->inalarm = 0;
07815             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07816             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07817                "Channel: %d\r\n", mtd->pvt->channel);
07818             break;
07819          case DAHDI_EVENT_ALARM:
07820             mtd->pvt->inalarm = 1;
07821             res = get_alarms(mtd->pvt);
07822             handle_alarms(mtd->pvt, res);
07823             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
07824          default:
07825             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
07826             callerid_free(cs);
07827             
07828             restore_gains(mtd->pvt);
07829             mtd->pvt->ringt = mtd->pvt->ringt_base;
07830 
07831             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07832                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07833                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07834                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07835                   if (res < 0)
07836                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07837                   ast_hangup(chan);
07838                   goto quit;
07839                }
07840                goto quit_no_clean;
07841 
07842             } else {
07843                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07844             }
07845          }
07846       } else if (i & DAHDI_IOMUX_READ) {
07847          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07848             if (errno != ELAST) {
07849                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07850                goto quit;
07851             }
07852             break;
07853          }
07854          samples += res;
07855          if (!spill_done) {
07856             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07857                ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07858                break;
07859             } else if (spill_result) {
07860                spill_done = 1;
07861             }
07862          } else {
07863             /* keep reading data until the energy level drops below the threshold
07864                so we don't get another 'trigger' on the remaining carrier signal
07865             */
07866             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07867                break;
07868          }
07869          if (samples > (8000 * 4)) /*Termination case - time to give up*/
07870             break;
07871       }
07872    }
07873 
07874    if (spill_result == 1) {
07875       callerid_get(cs, &name, &number, &flags);
07876       if (flags & CID_MSGWAITING) {
07877          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07878          notify_message(mtd->pvt->mailbox, 1);
07879       } else if (flags & CID_NOMSGWAITING) {
07880          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07881          notify_message(mtd->pvt->mailbox, 0);
07882       } else {
07883          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07884       }
07885    }
07886 
07887 
07888 quit:
07889    callerid_free(cs);
07890 
07891    restore_gains(mtd->pvt);
07892 
07893 quit_no_clean:
07894    mtd->pvt->mwimonitoractive = 0;
07895 
07896    ast_free(mtd);
07897 
07898    return NULL;
07899 }
07900 
07901 /* States for sending MWI message
07902  * First three states are required for send Ring Pulse Alert Signal 
07903  */
07904 enum mwisend_states {
07905    MWI_SEND_SA,
07906  MWI_SEND_SA_WAIT,
07907  MWI_SEND_PAUSE,
07908  MWI_SEND_SPILL,
07909  MWI_SEND_CLEANUP,
07910  MWI_SEND_DONE
07911 };
07912 
07913 static void *mwi_send_thread(void *data)
07914 {
07915    struct mwi_thread_data *mtd = data;
07916    struct timeval timeout_basis, suspend, now;
07917    int x, i, res;
07918    int num_read;
07919    enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
07920 
07921    ast_mutex_lock(&mwi_thread_lock);
07922    mwi_thread_count++;
07923    ast_mutex_unlock(&mwi_thread_lock);
07924 
07925    /* Determine how this spill is to be sent */
07926    if(mwisend_rpas) {
07927       mwi_send_state = MWI_SEND_SA;
07928    }
07929 
07930    gettimeofday(&timeout_basis, NULL);
07931    
07932    mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
07933    if (!mtd->pvt->cidspill) {
07934       mtd->pvt->mwisendactive = 0;
07935       ast_free(mtd);
07936       return NULL;
07937    }
07938    x = DAHDI_FLUSH_BOTH;
07939    res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07940    x = 3000;
07941    ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07942    mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
07943                             AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
07944    mtd->pvt->cidpos = 0;
07945 
07946    while (MWI_SEND_DONE != mwi_send_state) {
07947       num_read = 0;
07948       gettimeofday(&now, NULL);
07949       if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
07950          ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
07951          goto quit;
07952       }
07953 
07954       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07955       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07956          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07957          goto quit;
07958       }
07959 
07960       if (i & DAHDI_IOMUX_SIGEVENT) {
07961          /* If we get an event, screen out events that we do not act on.
07962          * Otherwise, let handle_init_event determine what is needed
07963          */
07964          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07965          switch (res) {
07966             case DAHDI_EVENT_RINGEROFF:
07967                if(mwi_send_state == MWI_SEND_SA_WAIT) {
07968                   if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
07969                      ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
07970                      goto quit;
07971                   }
07972                   mwi_send_state = MWI_SEND_PAUSE;
07973                   gettimeofday(&suspend, NULL);
07974                }
07975                break;
07976             case DAHDI_EVENT_RINGERON:
07977             case DAHDI_EVENT_HOOKCOMPLETE:
07978                break;
07979             default:
07980                /* Got to the default init event handler */
07981                if (0 < handle_init_event(mtd->pvt, res)) {
07982                   /* I've spawned a thread, get out */
07983                   goto quit;
07984                }
07985                break;
07986          }
07987       } else if (i & DAHDI_IOMUX_READ) {
07988          if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07989             if (errno != ELAST) {
07990                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07991                goto quit;
07992             }
07993             break;
07994          }
07995       }
07996       /* Perform mwi send action */
07997       switch ( mwi_send_state) {
07998          case MWI_SEND_SA:
07999             /* Send the Ring Pulse Signal Alert */
08000             res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
08001             if (res) {
08002                ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
08003                goto quit;
08004             }
08005             dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
08006             mwi_send_state = MWI_SEND_SA_WAIT;
08007             break;
08008             case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
08009                break;
08010                case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
08011                   gettimeofday(&now, NULL);
08012                   if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08013                      mwi_send_state = MWI_SEND_SPILL;
08014                   }
08015                   break;
08016          case MWI_SEND_SPILL:
08017             /* We read some number of bytes.  Write an equal amount of data */
08018             if(0 < num_read) {
08019                if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08020                   num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08021                res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08022                if (res > 0) {
08023                   mtd->pvt->cidpos += res;
08024                   if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08025                      ast_free(mtd->pvt->cidspill);
08026                      mtd->pvt->cidspill = NULL;
08027                      mtd->pvt->cidpos = 0;
08028                      mtd->pvt->cidlen = 0;
08029                      mwi_send_state = MWI_SEND_CLEANUP;
08030                   }
08031                } else {
08032                   ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08033                   goto quit;
08034                }
08035             }
08036             break;
08037          case MWI_SEND_CLEANUP:
08038             /* For now, do nothing */
08039             mwi_send_state = MWI_SEND_DONE;
08040             break;
08041          default:
08042             /* Should not get here, punt*/
08043             goto quit;
08044             break;
08045       }
08046    }
08047 
08048 quit:
08049    if(mtd->pvt->cidspill) {
08050       ast_free(mtd->pvt->cidspill);
08051       mtd->pvt->cidspill = NULL;
08052    }
08053    mtd->pvt->mwisendactive = 0;
08054    ast_free(mtd);
08055 
08056    ast_mutex_lock(&mwi_thread_lock);
08057    mwi_thread_count--;
08058    ast_cond_signal(&mwi_thread_complete);
08059    ast_mutex_unlock(&mwi_thread_lock);
08060 
08061    return NULL;
08062 }
08063 
08064 
08065 /* destroy a DAHDI channel, identified by its number */
08066 static int dahdi_destroy_channel_bynum(int channel)
08067 {
08068    struct dahdi_pvt *tmp = NULL;
08069    struct dahdi_pvt *prev = NULL;
08070 
08071    tmp = iflist;
08072    while (tmp) {
08073       if (tmp->channel == channel) {
08074          int x = DAHDI_FLASH;
08075          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 */
08076          destroy_channel(prev, tmp, 1);
08077          ast_module_unref(ast_module_info->self);
08078          return RESULT_SUCCESS;
08079       }
08080       prev = tmp;
08081       tmp = tmp->next;
08082    }
08083    return RESULT_FAILURE;
08084 }
08085 
08086 /* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
08087 static int handle_init_event(struct dahdi_pvt *i, int event)
08088 {
08089    int res;
08090    int thread_spawned = 0;
08091    pthread_t threadid;
08092    struct ast_channel *chan;
08093 
08094    /* Handle an event on a given channel for the monitor thread. */
08095 
08096    switch (event) {
08097    case DAHDI_EVENT_NONE:
08098    case DAHDI_EVENT_BITSCHANGED:
08099       break;
08100    case DAHDI_EVENT_WINKFLASH:
08101    case DAHDI_EVENT_RINGOFFHOOK:
08102       if (i->inalarm) break;
08103       if (i->radio) break;
08104       /* Got a ring/answer.  What kind of channel are we? */
08105       switch (i->sig) {
08106       case SIG_FXOLS:
08107       case SIG_FXOGS:
08108       case SIG_FXOKS:
08109          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08110          if (res && (errno == EBUSY))
08111             break;
08112          if (i->cidspill) {
08113             /* Cancel VMWI spill */
08114             ast_free(i->cidspill);
08115             i->cidspill = NULL;
08116          }
08117          if (i->immediate) {
08118             dahdi_enable_ec(i);
08119             /* The channel is immediately up.  Start right away */
08120             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08121             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08122             if (!chan) {
08123                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08124                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08125                if (res < 0)
08126                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08127             }
08128          } else {
08129             /* Check for callerid, digits, etc */
08130             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08131             if (chan) {
08132                if (has_voicemail(i))
08133                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08134                else
08135                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08136                if (res < 0) 
08137                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08138                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08139                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08140                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08141                   if (res < 0)
08142                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08143                   ast_hangup(chan);
08144                } else {
08145                   thread_spawned = 1;
08146                }
08147             } else
08148                ast_log(LOG_WARNING, "Unable to create channel\n");
08149          }
08150          break;
08151       case SIG_FXSLS:
08152       case SIG_FXSGS:
08153       case SIG_FXSKS:
08154             i->ringt = i->ringt_base;
08155             /* Fall through */
08156       case SIG_EMWINK:
08157       case SIG_FEATD:
08158       case SIG_FEATDMF:
08159       case SIG_FEATDMF_TA:
08160       case SIG_E911:
08161       case SIG_FGC_CAMA:
08162       case SIG_FGC_CAMAMF:
08163       case SIG_FEATB:
08164       case SIG_EM:
08165       case SIG_EM_E1:
08166       case SIG_SFWINK:
08167       case SIG_SF_FEATD:
08168       case SIG_SF_FEATDMF:
08169       case SIG_SF_FEATB:
08170       case SIG_SF:
08171          /* Check for callerid, digits, etc */
08172          if (i->cid_start == CID_START_POLARITY_IN) {
08173             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08174          } else {
08175             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08176          }
08177 
08178          if (!chan) {
08179             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08180          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08181             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08182             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08183             if (res < 0) {
08184                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08185             }
08186             ast_hangup(chan);
08187          } else  {
08188             thread_spawned = 1;
08189          }
08190          break;
08191       default:
08192          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08193          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08194          if (res < 0)
08195                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08196          return -1;
08197       }
08198       break;
08199    case DAHDI_EVENT_NOALARM:
08200       i->inalarm = 0;
08201       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08202       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08203          "Channel: %d\r\n", i->channel);
08204       break;
08205    case DAHDI_EVENT_ALARM:
08206       i->inalarm = 1;
08207       res = get_alarms(i);
08208       handle_alarms(i, res);
08209       /* fall thru intentionally */
08210    case DAHDI_EVENT_ONHOOK:
08211       if (i->radio)
08212          break;
08213       /* Back on hook.  Hang up. */
08214       switch (i->sig) {
08215       case SIG_FXOLS:
08216       case SIG_FXOGS:
08217       case SIG_FEATD:
08218       case SIG_FEATDMF:
08219       case SIG_FEATDMF_TA:
08220       case SIG_E911:
08221       case SIG_FGC_CAMA:
08222       case SIG_FGC_CAMAMF:
08223       case SIG_FEATB:
08224       case SIG_EM:
08225       case SIG_EM_E1:
08226       case SIG_EMWINK:
08227       case SIG_SF_FEATD:
08228       case SIG_SF_FEATDMF:
08229       case SIG_SF_FEATB:
08230       case SIG_SF:
08231       case SIG_SFWINK:
08232       case SIG_FXSLS:
08233       case SIG_FXSGS:
08234       case SIG_FXSKS:
08235       case SIG_GR303FXSKS:
08236          dahdi_disable_ec(i);
08237          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08238          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08239          break;
08240       case SIG_GR303FXOKS:
08241       case SIG_FXOKS:
08242          dahdi_disable_ec(i);
08243          /* Diddle the battery for the zhone */
08244 #ifdef ZHONE_HACK
08245          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08246          usleep(1);
08247 #endif         
08248          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08249          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08250          break;
08251       case SIG_PRI:
08252       case SIG_SS7:
08253       case SIG_BRI:
08254       case SIG_BRI_PTMP:
08255          dahdi_disable_ec(i);
08256          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08257          break;
08258       default:
08259          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08260          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08261          return -1;
08262       }
08263       break;
08264    case DAHDI_EVENT_POLARITY:
08265       switch (i->sig) {
08266       case SIG_FXSLS:
08267       case SIG_FXSKS:
08268       case SIG_FXSGS:
08269          /* We have already got a PR before the channel was 
08270             created, but it wasn't handled. We need polarity 
08271             to be REV for remote hangup detection to work. 
08272             At least in Spain */
08273          if (i->hanguponpolarityswitch)
08274             i->polarity = POLARITY_REV;
08275          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08276             i->polarity = POLARITY_REV;
08277             ast_verb(2, "Starting post polarity "
08278                    "CID detection on channel %d\n",
08279                    i->channel);
08280             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08281             if (!chan) {
08282                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08283             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08284                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08285             } else {
08286                thread_spawned = 1;
08287             }
08288          }
08289          break;
08290       default:
08291          ast_log(LOG_WARNING, "handle_init_event detected "
08292             "polarity reversal on non-FXO (SIG_FXS) "
08293             "interface %d\n", i->channel);
08294       }
08295       break;
08296    case DAHDI_EVENT_REMOVED: /* destroy channel */
08297       ast_log(LOG_NOTICE, 
08298             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08299             i->channel);
08300       dahdi_destroy_channel_bynum(i->channel);
08301       break;
08302    case DAHDI_EVENT_NEONMWI_ACTIVE:
08303       if (i->mwimonitor_neon) {
08304          notify_message(i->mailbox, 1);
08305          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08306       }
08307       break;
08308    case DAHDI_EVENT_NEONMWI_INACTIVE:
08309       if (i->mwimonitor_neon) {
08310          notify_message(i->mailbox, 0);
08311          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08312       }
08313       break;
08314    }
08315    return thread_spawned;
08316 }
08317 
08318 static void *do_monitor(void *data)
08319 {
08320    int count, res, res2, spoint, pollres=0;
08321    struct dahdi_pvt *i;
08322    struct dahdi_pvt *last = NULL;
08323    time_t thispass = 0, lastpass = 0;
08324    int found;
08325    char buf[1024];
08326    struct pollfd *pfds=NULL;
08327    int lastalloc = -1;
08328    /* This thread monitors all the frame relay interfaces which are not yet in use
08329       (and thus do not have a separate thread) indefinitely */
08330    /* From here on out, we die whenever asked */
08331 #if 0
08332    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08333       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08334       return NULL;
08335    }
08336    ast_debug(1, "Monitor starting...\n");
08337 #endif
08338    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08339 
08340    for (;;) {
08341       /* Lock the interface list */
08342       ast_mutex_lock(&iflock);
08343       if (!pfds || (lastalloc != ifcount)) {
08344          if (pfds) {
08345             ast_free(pfds);
08346             pfds = NULL;
08347          }
08348          if (ifcount) {
08349             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08350                ast_mutex_unlock(&iflock);
08351                return NULL;
08352             }
08353          }
08354          lastalloc = ifcount;
08355       }
08356       /* Build the stuff we're going to poll on, that is the socket of every
08357          dahdi_pvt that does not have an associated owner channel */
08358       count = 0;
08359       i = iflist;
08360       while (i) {
08361          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08362             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08363                /* This needs to be watched, as it lacks an owner */
08364                pfds[count].fd = i->subs[SUB_REAL].dfd;
08365                pfds[count].events = POLLPRI;
08366                pfds[count].revents = 0;
08367                /* If we are monitoring for VMWI or sending CID, we need to
08368                   read from the channel as well */
08369                if (i->cidspill || i->mwimonitor_fsk)
08370                   pfds[count].events |= POLLIN;
08371                count++;
08372             }
08373          }
08374          i = i->next;
08375       }
08376       /* Okay, now that we know what to do, release the interface lock */
08377       ast_mutex_unlock(&iflock);
08378       
08379       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08380       pthread_testcancel();
08381       /* Wait at least a second for something to happen */
08382       res = poll(pfds, count, 1000);
08383       pthread_testcancel();
08384       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08385 
08386       /* Okay, poll has finished.  Let's see what happened.  */
08387       if (res < 0) {
08388          if ((errno != EAGAIN) && (errno != EINTR))
08389             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08390          continue;
08391       }
08392       /* Alright, lock the interface list again, and let's look and see what has
08393          happened */
08394       ast_mutex_lock(&iflock);
08395       found = 0;
08396       spoint = 0;
08397       lastpass = thispass;
08398       thispass = time(NULL);
08399       i = iflist;
08400       while (i) {
08401          if (thispass != lastpass) {
08402             if (!found && ((i == last) || ((i == iflist) && !last))) {
08403                last = i;
08404                if (last) {
08405                   if (!last->mwisendactive &&    last->sig & __DAHDI_SIG_FXO) {
08406                      res = has_voicemail(last);
08407                      if (last->msgstate != res) {
08408 
08409                         /* This channel has a new voicemail state,
08410                         * initiate a thread to send an MWI message
08411                         */
08412                         pthread_attr_t attr;
08413                         pthread_t threadid;
08414                         struct mwi_thread_data *mtd;
08415                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08416                         if (res2) {
08417                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
08418                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08419                         }
08420                         pthread_attr_init(&attr);
08421                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08422                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08423                            last->msgstate = res;
08424                            mtd->pvt = last;
08425                            last->mwisendactive = 1;
08426                            if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08427                               ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08428                               ast_free(mtd);
08429                               last->mwisendactive = 0;
08430                            }
08431                         }
08432                         found ++;
08433                      }
08434                   }
08435                   last = last->next;
08436                }
08437             }
08438          }
08439          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08440             if (i->radio && !i->owner)
08441             {
08442                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08443                if (res)
08444                {
08445                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08446                   /* Don't hold iflock while handling init events */
08447                   ast_mutex_unlock(&iflock);
08448                   handle_init_event(i, res);
08449                   ast_mutex_lock(&iflock);   
08450                }
08451                i = i->next;
08452                continue;
08453             }              
08454             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08455             if (pollres & POLLIN) {
08456                if (i->owner || i->subs[SUB_REAL].owner) {
08457 #ifdef HAVE_PRI
08458                   if (!i->pri)
08459 #endif                  
08460                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08461                   i = i->next;
08462                   continue;
08463                }
08464                if (!i->cidspill && !i->mwimonitor_fsk) {
08465                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08466                   i = i->next;
08467                   continue;
08468                }
08469                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08470                if (res > 0) {
08471                   if (i->mwimonitor_fsk) {
08472                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08473                         pthread_attr_t attr;
08474                         pthread_t threadid;
08475                         struct mwi_thread_data *mtd;
08476 
08477                         pthread_attr_init(&attr);
08478                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08479 
08480                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08481                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08482                            mtd->pvt = i;
08483                            memcpy(mtd->buf, buf, res);
08484                            mtd->len = res;
08485                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08486                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08487                               ast_free(mtd);
08488                            }
08489                            i->mwimonitoractive = 1;
08490                         }
08491                      }
08492                   }
08493                } else {
08494                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08495                }
08496             }
08497             if (pollres & POLLPRI) {
08498                if (i->owner || i->subs[SUB_REAL].owner) {
08499 #ifdef HAVE_PRI
08500                   if (!i->pri)
08501 #endif                  
08502                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08503                   i = i->next;
08504                   continue;
08505                }
08506                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08507                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08508                /* Don't hold iflock while handling init events */
08509                ast_mutex_unlock(&iflock);
08510                handle_init_event(i, res);
08511                ast_mutex_lock(&iflock);   
08512             }
08513          }
08514          i=i->next;
08515       }
08516       ast_mutex_unlock(&iflock);
08517    }
08518    /* Never reached */
08519    return NULL;
08520    
08521 }
08522 
08523 static int restart_monitor(void)
08524 {
08525    /* If we're supposed to be stopped -- stay stopped */
08526    if (monitor_thread == AST_PTHREADT_STOP)
08527       return 0;
08528    ast_mutex_lock(&monlock);
08529    if (monitor_thread == pthread_self()) {
08530       ast_mutex_unlock(&monlock);
08531       ast_log(LOG_WARNING, "Cannot kill myself\n");
08532       return -1;
08533    }
08534    if (monitor_thread != AST_PTHREADT_NULL) {
08535       /* Wake up the thread */
08536       pthread_kill(monitor_thread, SIGURG);
08537    } else {
08538       /* Start a new monitor */
08539       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08540          ast_mutex_unlock(&monlock);
08541          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08542          return -1;
08543       }
08544    }
08545    ast_mutex_unlock(&monlock);
08546    return 0;
08547 }
08548 
08549 #ifdef HAVE_PRI
08550 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
08551 {
08552    int x;
08553    int trunkgroup;
08554    /* Get appropriate trunk group if there is one */
08555    trunkgroup = pris[*span].mastertrunkgroup;
08556    if (trunkgroup) {
08557       /* Select a specific trunk group */
08558       for (x = 0; x < NUM_SPANS; x++) {
08559          if (pris[x].trunkgroup == trunkgroup) {
08560             *span = x;
08561             return 0;
08562          }
08563       }
08564       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08565       *span = -1;
08566    } else {
08567       if (pris[*span].trunkgroup) {
08568          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08569          *span = -1;
08570       } else if (pris[*span].mastertrunkgroup) {
08571          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08572          *span = -1;
08573       } else {
08574          if (si->totalchans == 31) {
08575             /* E1 */
08576             pris[*span].dchannels[0] = 16 + offset;
08577          } else if (si->totalchans == 24) {
08578             /* T1 or J1 */
08579             pris[*span].dchannels[0] = 24 + offset;
08580          } else if (si->totalchans == 3) {
08581             /* BRI */
08582             pris[*span].dchannels[0] = 3 + offset;
08583          } else {
08584             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);
08585             *span = -1;
08586             return 0;
08587          }
08588          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08589          pris[*span].offset = offset;
08590          pris[*span].span = *span + 1;
08591       }
08592    }
08593    return 0;
08594 }
08595 
08596 static int pri_create_trunkgroup(int trunkgroup, int *channels)
08597 {
08598    struct dahdi_spaninfo si;
08599    struct dahdi_params p;
08600    int fd;
08601    int span;
08602    int ospan=0;
08603    int x,y;
08604    for (x = 0; x < NUM_SPANS; x++) {
08605       if (pris[x].trunkgroup == trunkgroup) {
08606          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08607          return -1;
08608       }
08609    }
08610    for (y = 0; y < NUM_DCHANS; y++) {
08611       if (!channels[y]) 
08612          break;
08613       memset(&si, 0, sizeof(si));
08614       memset(&p, 0, sizeof(p));
08615       fd = open("/dev/dahdi/channel", O_RDWR);
08616       if (fd < 0) {
08617          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08618          return -1;
08619       }
08620       x = channels[y];
08621       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08622          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08623          close(fd);
08624          return -1;
08625       }
08626       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08627          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08628          return -1;
08629       }
08630       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08631          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08632          close(fd);
08633          return -1;
08634       }
08635       span = p.spanno - 1;
08636       if (pris[span].trunkgroup) {
08637          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08638          close(fd);
08639          return -1;
08640       }
08641       if (pris[span].pvts[0]) {
08642          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08643          close(fd);
08644          return -1;
08645       }
08646       if (!y) {
08647          pris[span].trunkgroup = trunkgroup;
08648          pris[span].offset = channels[y] - p.chanpos;
08649          ospan = span;
08650       }
08651       pris[ospan].dchannels[y] = channels[y];
08652       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08653       pris[span].span = span + 1;
08654       close(fd);
08655    }
08656    return 0;   
08657 }
08658 
08659 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
08660 {
08661    if (pris[span].mastertrunkgroup) {
08662       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);
08663       return -1;
08664    }
08665    pris[span].mastertrunkgroup = trunkgroup;
08666    pris[span].prilogicalspan = logicalspan;
08667    return 0;
08668 }
08669 
08670 #endif
08671 
08672 #ifdef HAVE_SS7
08673 
08674 static unsigned int parse_pointcode(const char *pcstring)
08675 {
08676    unsigned int code1, code2, code3;
08677    int numvals;
08678 
08679    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08680    if (numvals == 1)
08681       return code1;
08682    if (numvals == 3)
08683       return (code1 << 16) | (code2 << 8) | code3;
08684 
08685    return 0;
08686 }
08687 
08688 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
08689 {
08690    if ((linkset < 0) || (linkset >= NUM_SPANS))
08691       return NULL;
08692    else
08693       return &linksets[linkset - 1];
08694 }
08695 #endif /* HAVE_SS7 */
08696 
08697 /* converts a DAHDI sigtype to signalling as can be configured from
08698  * chan_dahdi.conf.
08699  * While both have basically the same values, this will later be the
08700  * place to add filters and sanity checks
08701  */
08702 static int sigtype_to_signalling(int sigtype)
08703 {
08704         return sigtype;
08705 }
08706 
08707 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
08708 {
08709    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
08710    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
08711    char fn[80];
08712    struct dahdi_bufferinfo bi;
08713 
08714    int res;
08715    int span = 0;
08716    int here = 0;
08717    int x;
08718    struct dahdi_pvt **wlist;
08719    struct dahdi_pvt **wend;
08720    struct dahdi_params p;
08721 
08722    wlist = &iflist;
08723    wend = &ifend;
08724 
08725 #ifdef HAVE_PRI
08726    if (pri) {
08727       wlist = &pri->crvs;
08728       wend = &pri->crvend;
08729    }
08730 #endif
08731 
08732    tmp2 = *wlist;
08733    prev = NULL;
08734 
08735    while (tmp2) {
08736       if (!tmp2->destroy) {
08737          if (tmp2->channel == channel) {
08738             tmp = tmp2;
08739             here = 1;
08740             break;
08741          }
08742          if (tmp2->channel > channel) {
08743             break;
08744          }
08745       }
08746       prev = tmp2;
08747       tmp2 = tmp2->next;
08748    }
08749 
08750    if (!here && reloading != 1) {
08751       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08752          if (tmp)
08753             free(tmp);
08754          return NULL;
08755       }
08756       ast_mutex_init(&tmp->lock);
08757       ifcount++;
08758       for (x = 0; x < 3; x++)
08759          tmp->subs[x].dfd = -1;
08760       tmp->channel = channel;
08761       tmp->priindication_oob = conf->chan.priindication_oob;
08762    }
08763 
08764    if (tmp) {
08765       int chan_sig = conf->chan.sig;
08766       if (!here) {
08767          if ((channel != CHAN_PSEUDO) && !pri) {
08768             int count = 0;
08769             snprintf(fn, sizeof(fn), "%d", channel);
08770             /* Open non-blocking */
08771             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08772             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 */
08773                usleep(1);
08774                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08775                count++;
08776             }
08777             /* Allocate a DAHDI structure */
08778             if (tmp->subs[SUB_REAL].dfd < 0) {
08779                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);
08780                destroy_dahdi_pvt(&tmp);
08781                return NULL;
08782             }
08783             memset(&p, 0, sizeof(p));
08784             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08785             if (res < 0) {
08786                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08787                destroy_dahdi_pvt(&tmp);
08788                return NULL;
08789             }
08790             if (conf->is_sig_auto)
08791                chan_sig = sigtype_to_signalling(p.sigtype);
08792             if (p.sigtype != (chan_sig & 0x3ffff)) {
08793                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
08794                destroy_dahdi_pvt(&tmp);
08795                return NULL;
08796             }
08797             tmp->law = p.curlaw;
08798             tmp->span = p.spanno;
08799             span = p.spanno - 1;
08800          } else {
08801             if (channel == CHAN_PSEUDO)
08802                chan_sig = 0;
08803             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08804                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08805                return NULL;
08806             }
08807          }
08808 #ifdef HAVE_SS7
08809          if (chan_sig == SIG_SS7) {
08810             struct dahdi_ss7 *ss7;
08811             int clear = 0;
08812             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08813                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08814                destroy_dahdi_pvt(&tmp);
08815                return NULL;
08816             }
08817 
08818             ss7 = ss7_resolve_linkset(cur_linkset);
08819             if (!ss7) {
08820                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08821                destroy_dahdi_pvt(&tmp);
08822                return NULL;
08823             }
08824             if (cur_cicbeginswith < 0) {
08825                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08826                destroy_dahdi_pvt(&tmp);
08827                return NULL;
08828             }
08829 
08830             tmp->cic = cur_cicbeginswith++;
08831 
08832             /* DB: Add CIC's DPC information */
08833             tmp->dpc = cur_defaultdpc;
08834 
08835             tmp->ss7 = ss7;
08836             tmp->ss7call = NULL;
08837             ss7->pvts[ss7->numchans++] = tmp;
08838 
08839             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08840             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08841             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08842             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08843 
08844             ss7->called_nai = conf->ss7.called_nai;
08845             ss7->calling_nai = conf->ss7.calling_nai;
08846          }
08847 #endif
08848 #ifdef HAVE_PRI
08849          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08850             int offset;
08851             int myswitchtype;
08852             int matchesdchan;
08853             int x,y;
08854             offset = 0;
08855             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 
08856                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08857                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08858                destroy_dahdi_pvt(&tmp);
08859                return NULL;
08860             }
08861             if (span >= NUM_SPANS) {
08862                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08863                destroy_dahdi_pvt(&tmp);
08864                return NULL;
08865             } else {
08866                struct dahdi_spaninfo si;
08867                si.spanno = 0;
08868                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08869                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08870                   destroy_dahdi_pvt(&tmp);
08871                   return NULL;
08872                }
08873                /* Store the logical span first based upon the real span */
08874                tmp->logicalspan = pris[span].prilogicalspan;
08875                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08876                if (span < 0) {
08877                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08878                   destroy_dahdi_pvt(&tmp);
08879                   return NULL;
08880                }
08881                if ((chan_sig == SIG_PRI) ||
08882                      (chan_sig == SIG_BRI) ||
08883                      (chan_sig == SIG_BRI_PTMP))
08884                   myswitchtype = conf->pri.switchtype;
08885                else
08886                   myswitchtype = PRI_SWITCH_GR303_TMC;
08887                /* Make sure this isn't a d-channel */
08888                matchesdchan=0;
08889                for (x = 0; x < NUM_SPANS; x++) {
08890                   for (y = 0; y < NUM_DCHANS; y++) {
08891                      if (pris[x].dchannels[y] == tmp->channel) {
08892                         matchesdchan = 1;
08893                         break;
08894                      }
08895                   }
08896                }
08897                offset = p.chanpos;
08898                if (!matchesdchan) {
08899                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08900                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08901                      destroy_dahdi_pvt(&tmp);
08902                      return NULL;
08903                   }
08904                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08905                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08906                      destroy_dahdi_pvt(&tmp);
08907                      return NULL;
08908                   }
08909                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08910                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08911                      destroy_dahdi_pvt(&tmp);
08912                      return NULL;
08913                   }
08914                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08915                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08916                      destroy_dahdi_pvt(&tmp);
08917                      return NULL;
08918                   }
08919                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08920                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08921                      destroy_dahdi_pvt(&tmp);
08922                      return NULL;
08923                   }
08924                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08925                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08926                      destroy_dahdi_pvt(&tmp);
08927                      return NULL;
08928                   }
08929                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08930                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08931                      destroy_dahdi_pvt(&tmp);
08932                      return NULL;
08933                   }
08934                   if (pris[span].numchans >= MAX_CHANNELS) {
08935                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08936                         pris[span].trunkgroup);
08937                      destroy_dahdi_pvt(&tmp);
08938                      return NULL;
08939                   }
08940 
08941                   pris[span].sig = chan_sig;
08942                   pris[span].nodetype = conf->pri.nodetype;
08943                   pris[span].switchtype = myswitchtype;
08944                   pris[span].nsf = conf->pri.nsf;
08945                   pris[span].dialplan = conf->pri.dialplan;
08946                   pris[span].localdialplan = conf->pri.localdialplan;
08947                   pris[span].pvts[pris[span].numchans++] = tmp;
08948                   pris[span].minunused = conf->pri.minunused;
08949                   pris[span].minidle = conf->pri.minidle;
08950                   pris[span].overlapdial = conf->pri.overlapdial;
08951 #ifdef HAVE_PRI_INBANDDISCONNECT
08952                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08953 #endif
08954                   pris[span].facilityenable = conf->pri.facilityenable;
08955                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08956                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08957                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08958                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08959                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08960                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08961                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08962                   pris[span].resetinterval = conf->pri.resetinterval;
08963                   
08964                   tmp->pri = &pris[span];
08965                   tmp->prioffset = offset;
08966                   tmp->call = NULL;
08967                } else {
08968                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08969                   destroy_dahdi_pvt(&tmp);
08970                   return NULL;
08971                }
08972             }
08973          } else {
08974             tmp->prioffset = 0;
08975          }
08976 #endif
08977       } else {
08978          chan_sig = tmp->sig;
08979          if (tmp->subs[SUB_REAL].dfd > -1) {
08980             memset(&p, 0, sizeof(p));
08981             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08982          }
08983       }
08984       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
08985       switch (chan_sig) {
08986       case SIG_FXSKS:
08987       case SIG_FXSLS:
08988       case SIG_EM:
08989       case SIG_EM_E1:
08990       case SIG_EMWINK:
08991       case SIG_FEATD:
08992       case SIG_FEATDMF:
08993       case SIG_FEATDMF_TA:
08994       case SIG_FEATB:
08995       case SIG_E911:
08996       case SIG_SF:
08997       case SIG_SFWINK:
08998       case SIG_FGC_CAMA:
08999       case SIG_FGC_CAMAMF:
09000       case SIG_SF_FEATD:
09001       case SIG_SF_FEATDMF:
09002       case SIG_SF_FEATB:
09003          p.starttime = 250;
09004          break;
09005       }
09006 
09007       if (tmp->radio) {
09008          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
09009          p.channo = channel;
09010          p.rxwinktime = 1;
09011          p.rxflashtime = 1;
09012          p.starttime = 1;
09013          p.debouncetime = 5;
09014       }
09015       if (!tmp->radio) {
09016          p.channo = channel;
09017          /* Override timing settings based on config file */
09018          if (conf->timing.prewinktime >= 0)
09019             p.prewinktime = conf->timing.prewinktime;
09020          if (conf->timing.preflashtime >= 0)
09021             p.preflashtime = conf->timing.preflashtime;
09022          if (conf->timing.winktime >= 0)
09023             p.winktime = conf->timing.winktime;
09024          if (conf->timing.flashtime >= 0)
09025             p.flashtime = conf->timing.flashtime;
09026          if (conf->timing.starttime >= 0)
09027             p.starttime = conf->timing.starttime;
09028          if (conf->timing.rxwinktime >= 0)
09029             p.rxwinktime = conf->timing.rxwinktime;
09030          if (conf->timing.rxflashtime >= 0)
09031             p.rxflashtime = conf->timing.rxflashtime;
09032          if (conf->timing.debouncetime >= 0)
09033             p.debouncetime = conf->timing.debouncetime;
09034       }
09035 
09036       /* dont set parms on a pseudo-channel (or CRV) */
09037       if (tmp->subs[SUB_REAL].dfd >= 0)
09038       {
09039          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09040          if (res < 0) {
09041             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09042             destroy_dahdi_pvt(&tmp);
09043             return NULL;
09044          }
09045       }
09046 #if 1
09047       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09048          memset(&bi, 0, sizeof(bi));
09049          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09050          if (!res) {
09051             bi.txbufpolicy = conf->chan.buf_policy;
09052             bi.rxbufpolicy = conf->chan.buf_policy;
09053             bi.numbufs = conf->chan.buf_no;
09054             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09055             if (res < 0) {
09056                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09057             }
09058          } else
09059             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09060       }
09061 #endif
09062       tmp->immediate = conf->chan.immediate;
09063       tmp->transfertobusy = conf->chan.transfertobusy;
09064       if (chan_sig & __DAHDI_SIG_FXS) {
09065          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09066          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09067          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09068       }
09069       tmp->sig = chan_sig;
09070       tmp->outsigmod = conf->chan.outsigmod;
09071       tmp->ringt_base = ringt_base;
09072       tmp->firstradio = 0;
09073       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09074          tmp->permcallwaiting = conf->chan.callwaiting;
09075       else
09076          tmp->permcallwaiting = 0;
09077       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
09078       tmp->destroy = 0;
09079       tmp->drings = conf->chan.drings;
09080 
09081       /* 10 is a nice default. */
09082       if (tmp->drings.ringnum[0].range == 0)
09083          tmp->drings.ringnum[0].range = 10;
09084       if (tmp->drings.ringnum[1].range == 0)
09085          tmp->drings.ringnum[1].range = 10;
09086       if (tmp->drings.ringnum[2].range == 0)
09087          tmp->drings.ringnum[2].range = 10;
09088 
09089       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09090       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09091       tmp->threewaycalling = conf->chan.threewaycalling;
09092       tmp->adsi = conf->chan.adsi;
09093       tmp->use_smdi = conf->chan.use_smdi;
09094       tmp->permhidecallerid = conf->chan.hidecallerid;
09095       tmp->callreturn = conf->chan.callreturn;
09096       tmp->echocancel = conf->chan.echocancel;
09097       tmp->echotraining = conf->chan.echotraining;
09098       tmp->pulse = conf->chan.pulse;
09099       if (tmp->echocancel.head.tap_length) {
09100          tmp->echocanbridged = conf->chan.echocanbridged;
09101       } else {
09102          if (conf->chan.echocanbridged)
09103             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09104          tmp->echocanbridged = 0;
09105       }
09106       tmp->busydetect = conf->chan.busydetect;
09107       tmp->busycount = conf->chan.busycount;
09108       tmp->busy_tonelength = conf->chan.busy_tonelength;
09109       tmp->busy_quietlength = conf->chan.busy_quietlength;
09110       tmp->callprogress = conf->chan.callprogress;
09111       tmp->cancallforward = conf->chan.cancallforward;
09112       tmp->dtmfrelax = conf->chan.dtmfrelax;
09113       tmp->callwaiting = tmp->permcallwaiting;
09114       tmp->hidecallerid = tmp->permhidecallerid;
09115       tmp->channel = channel;
09116       tmp->stripmsd = conf->chan.stripmsd;
09117       tmp->use_callerid = conf->chan.use_callerid;
09118       tmp->cid_signalling = conf->chan.cid_signalling;
09119       tmp->cid_start = conf->chan.cid_start;
09120       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09121       tmp->restrictcid = conf->chan.restrictcid;
09122       tmp->use_callingpres = conf->chan.use_callingpres;
09123       tmp->priexclusive = conf->chan.priexclusive;
09124       if (tmp->usedistinctiveringdetection) {
09125          if (!tmp->use_callerid) {
09126             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09127             tmp->use_callerid = 1;
09128          }
09129       }
09130 
09131       if (tmp->cid_signalling == CID_SIG_SMDI) {
09132          if (!tmp->use_smdi) {
09133             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09134             tmp->use_smdi = 1;
09135          }
09136       }
09137       if (tmp->use_smdi) {
09138          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09139          if (!(tmp->smdi_iface)) {
09140             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09141             tmp->use_smdi = 0;
09142          }
09143       }
09144 
09145       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09146       tmp->amaflags = conf->chan.amaflags;
09147       if (!here) {
09148          tmp->confno = -1;
09149          tmp->propconfno = -1;
09150       }
09151       tmp->canpark = conf->chan.canpark;
09152       tmp->transfer = conf->chan.transfer;
09153       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09154       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09155       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09156       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09157       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09158       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09159       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09160       tmp->cid_ton = 0;
09161       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09162       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09163       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09164          char *mailbox, *context;
09165          mailbox = context = ast_strdupa(tmp->mailbox);
09166          strsep(&context, "@");
09167          if (ast_strlen_zero(context))
09168             context = "default";
09169          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09170             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09171             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09172             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09173             AST_EVENT_IE_END);
09174       }
09175       tmp->msgstate = -1;
09176       tmp->group = conf->chan.group;
09177       tmp->callgroup = conf->chan.callgroup;
09178       tmp->pickupgroup= conf->chan.pickupgroup;
09179       if (conf->chan.vars) {
09180          tmp->vars = conf->chan.vars;
09181       }
09182       tmp->cid_rxgain = conf->chan.cid_rxgain;
09183       tmp->rxgain = conf->chan.rxgain;
09184       tmp->txgain = conf->chan.txgain;
09185       tmp->tonezone = conf->chan.tonezone;
09186       tmp->onhooktime = time(NULL);
09187       if (tmp->subs[SUB_REAL].dfd > -1) {
09188          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09189          if (tmp->dsp)
09190             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09191          update_conf(tmp);
09192          if (!here) {
09193             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09194                /* Hang it up to be sure it's good */
09195                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09196          }
09197          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09198 #ifdef HAVE_PRI
09199          /* the dchannel is down so put the channel in alarm */
09200          if (tmp->pri && !pri_is_up(tmp->pri))
09201             tmp->inalarm = 1;
09202 #endif            
09203          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09204             tmp->inalarm = 1;
09205             handle_alarms(tmp, res);
09206          }
09207       }
09208 
09209       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09210       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09211       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09212       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09213       if (!here) {
09214          tmp->locallyblocked = tmp->remotelyblocked = 0;
09215          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09216             tmp->inservice = 0;
09217          else /* We default to in service on protocols that don't have a reset */
09218             tmp->inservice = 1;
09219       }
09220    }
09221    if (tmp && !here) {
09222       /* nothing on the iflist */
09223       if (!*wlist) {
09224          *wlist = tmp;
09225          tmp->prev = NULL;
09226          tmp->next = NULL;
09227          *wend = tmp;
09228       } else {
09229          /* at least one member on the iflist */
09230          struct dahdi_pvt *working = *wlist;
09231 
09232          /* check if we maybe have to put it on the begining */
09233          if (working->channel > tmp->channel) {
09234             tmp->next = *wlist;
09235             tmp->prev = NULL;
09236             (*wlist)->prev = tmp;
09237             *wlist = tmp;
09238          } else {
09239          /* go through all the members and put the member in the right place */
09240             while (working) {
09241                /* in the middle */
09242                if (working->next) {
09243                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09244                      tmp->next = working->next;
09245                      tmp->prev = working;
09246                      working->next->prev = tmp;
09247                      working->next = tmp;
09248                      break;
09249                   }
09250                } else {
09251                /* the last */
09252                   if (working->channel < tmp->channel) {
09253                      working->next = tmp;
09254                      tmp->next = NULL;
09255                      tmp->prev = working;
09256                      *wend = tmp;
09257                      break;
09258                   }
09259                }
09260                working = working->next;
09261             }
09262          }
09263       }
09264    }
09265    return tmp;
09266 }
09267 
09268 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
09269 {
09270    int res;
09271    struct dahdi_params par;
09272 
09273    /* First, check group matching */
09274    if (groupmatch) {
09275       if ((p->group & groupmatch) != groupmatch)
09276          return 0;
09277       *groupmatched = 1;
09278    }
09279    /* Check to see if we have a channel match */
09280    if (channelmatch != -1) {
09281       if (p->channel != channelmatch)
09282          return 0;
09283       *channelmatched = 1;
09284    }
09285    /* We're at least busy at this point */
09286    if (busy) {
09287       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09288          *busy = 1;
09289    }
09290    /* If do not disturb, definitely not */
09291    if (p->dnd)
09292       return 0;
09293    /* If guard time, definitely not */
09294    if (p->guardtime && (time(NULL) < p->guardtime)) 
09295       return 0;
09296 
09297    if (p->locallyblocked || p->remotelyblocked)
09298       return 0;
09299       
09300    /* If no owner definitely available */
09301    if (!p->owner) {
09302 #ifdef HAVE_PRI
09303       /* Trust PRI */
09304       if (p->pri) {
09305          if (p->resetting || p->call)
09306             return 0;
09307          else
09308             return 1;
09309       }
09310 #endif
09311 #ifdef HAVE_SS7
09312       /* Trust SS7 */
09313       if (p->ss7) {
09314          if (p->ss7call)
09315             return 0;
09316          else
09317             return 1;
09318       }
09319 #endif
09320       if (!(p->radio || (p->oprmode < 0)))
09321       {
09322          if (!p->sig || (p->sig == SIG_FXSLS))
09323             return 1;
09324          /* Check hook state */
09325          if (p->subs[SUB_REAL].dfd > -1) {
09326             memset(&par, 0, sizeof(par));
09327             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09328          } else {
09329             /* Assume not off hook on CVRS */
09330             res = 0;
09331             par.rxisoffhook = 0;
09332          }
09333          if (res) {
09334             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09335          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09336             /* When "onhook" that means no battery on the line, and thus
09337               it is out of service..., if it's on a TDM card... If it's a channel
09338               bank, there is no telling... */
09339             if (par.rxbits > -1)
09340                return 1;
09341             if (par.rxisoffhook)
09342                return 1;
09343             else
09344                return 0;
09345          } else if (par.rxisoffhook) {
09346             ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09347             /* Not available when the other end is off hook */
09348 #ifdef DAHDI_CHECK_HOOKSTATE
09349             return 0;
09350 #else
09351             return 1;
09352 #endif
09353          }
09354       }
09355       return 1;
09356    }
09357 
09358    /* If it's not an FXO, forget about call wait */
09359    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09360       return 0;
09361 
09362    if (!p->callwaiting) {
09363       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09364       return 0;
09365    }
09366 
09367    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09368       /* If there is already a call waiting call, then we can't take a second one */
09369       return 0;
09370    }
09371    
09372    if ((p->owner->_state != AST_STATE_UP) &&
09373        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09374       /* If the current call is not up, then don't allow the call */
09375       return 0;
09376    }
09377    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09378       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09379       return 0;
09380    }
09381    /* We're cool */
09382    return 1;
09383 }
09384 
09385 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
09386 {
09387    struct dahdi_pvt *p;
09388    struct dahdi_bufferinfo bi;
09389    int res;
09390    
09391    if ((p = ast_malloc(sizeof(*p)))) {
09392       memcpy(p, src, sizeof(struct dahdi_pvt));
09393       ast_mutex_init(&p->lock);
09394       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09395       /* Allocate a dahdi structure */
09396       if (p->subs[SUB_REAL].dfd < 0) {
09397          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09398          destroy_dahdi_pvt(&p);
09399          return NULL;
09400       }
09401       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09402       if (!res) {
09403          bi.txbufpolicy = src->buf_policy;
09404          bi.rxbufpolicy = src->buf_policy;
09405          bi.numbufs = src->buf_no;
09406          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09407          if (res < 0) {
09408             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09409          }
09410       } else
09411          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09412    }
09413    p->destroy = 1;
09414    p->next = iflist;
09415    p->prev = NULL;
09416    iflist = p;
09417    if (iflist->next)
09418       iflist->next->prev = p;
09419    return p;
09420 }
09421    
09422 
09423 #ifdef HAVE_PRI
09424 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
09425 {
09426    int x;
09427    if (backwards)
09428       x = pri->numchans;
09429    else
09430       x = 0;
09431    for (;;) {
09432       if (backwards && (x < 0))
09433          break;
09434       if (!backwards && (x >= pri->numchans))
09435          break;
09436       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09437          ast_debug(1, "Found empty available channel %d/%d\n", 
09438             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09439          return x;
09440       }
09441       if (backwards)
09442          x--;
09443       else
09444          x++;
09445    }
09446    return -1;
09447 }
09448 #endif
09449 
09450 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
09451 {
09452    ast_group_t groupmatch = 0;
09453    int channelmatch = -1;
09454    int roundrobin = 0;
09455    int callwait = 0;
09456    int busy = 0;
09457    struct dahdi_pvt *p;
09458    struct ast_channel *tmp = NULL;
09459    char *dest=NULL;
09460    int x;
09461    char *s;
09462    char opt=0;
09463    int res=0, y=0;
09464    int backwards = 0;
09465 #ifdef HAVE_PRI
09466    int crv;
09467    int bearer = -1;
09468    int trunkgroup;
09469    struct dahdi_pri *pri=NULL;
09470 #endif   
09471    struct dahdi_pvt *exitpvt, *start, *end;
09472    ast_mutex_t *lock;
09473    int channelmatched = 0;
09474    int groupmatched = 0;
09475    
09476    /*
09477     * data is ---v
09478     * Dial(DAHDI/pseudo[/extension])
09479     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09480     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09481     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09482     *
09483     * g - channel group allocation search forward
09484     * G - channel group allocation search backward
09485     * r - channel group allocation round robin search forward
09486     * R - channel group allocation round robin search backward
09487     *
09488     * c - Wait for DTMF digit to confirm answer
09489     * r<cadance#> - Set distintive ring cadance number
09490     * d - Force bearer capability for ISDN/SS7 call to digital.
09491     */
09492 
09493    /* Assume we're locking the iflock */
09494    lock = &iflock;
09495    start = iflist;
09496    end = ifend;
09497    if (data) {
09498       dest = ast_strdupa((char *)data);
09499    } else {
09500       ast_log(LOG_WARNING, "Channel requested with no data\n");
09501       return NULL;
09502    }
09503    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09504       /* Retrieve the group number */
09505       char *stringp;
09506 
09507       stringp = dest + 1;
09508       s = strsep(&stringp, "/");
09509       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09510          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09511          return NULL;
09512       }
09513       groupmatch = ((ast_group_t) 1 << x);
09514       if (toupper(dest[0]) == 'G') {
09515          if (dest[0] == 'G') {
09516             backwards = 1;
09517             p = ifend;
09518          } else
09519             p = iflist;
09520       } else {
09521          if (dest[0] == 'R') {
09522             backwards = 1;
09523             p = round_robin[x]?round_robin[x]->prev:ifend;
09524             if (!p)
09525                p = ifend;
09526          } else {
09527             p = round_robin[x]?round_robin[x]->next:iflist;
09528             if (!p)
09529                p = iflist;
09530          }
09531          roundrobin = 1;
09532       }
09533    } else {
09534       char *stringp;
09535 
09536       stringp = dest;
09537       s = strsep(&stringp, "/");
09538       p = iflist;
09539       if (!strcasecmp(s, "pseudo")) {
09540          /* Special case for pseudo */
09541          x = CHAN_PSEUDO;
09542          channelmatch = x;
09543       } 
09544 #ifdef HAVE_PRI
09545       else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
09546          if ((trunkgroup < 1) || (crv < 1)) {
09547             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09548             return NULL;
09549          }
09550          res--;
09551          for (x = 0; x < NUM_SPANS; x++) {
09552             if (pris[x].trunkgroup == trunkgroup) {
09553                pri = pris + x;
09554                lock = &pri->lock;
09555                start = pri->crvs;
09556                end = pri->crvend;
09557                break;
09558             }
09559          }
09560          if (!pri) {
09561             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09562             return NULL;
09563          }
09564          channelmatch = crv;
09565          p = pris[x].crvs;
09566       }
09567 #endif
09568       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
09569          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09570          return NULL;
09571       } else {
09572          channelmatch = x;
09573       }
09574    }
09575    /* Search for an unowned channel */
09576    ast_mutex_lock(lock);
09577    exitpvt = p;
09578    while (p && !tmp) {
09579       if (roundrobin)
09580          round_robin[x] = p;
09581 #if 0
09582       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09583 #endif
09584 
09585       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09586          ast_debug(1, "Using channel %d\n", p->channel);
09587          if (p->inalarm) 
09588             goto next;
09589 
09590          callwait = (p->owner != NULL);
09591 #ifdef HAVE_PRI
09592          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09593             if (p->sig != SIG_FXSKS) {
09594                /* Gotta find an actual channel to use for this
09595                   CRV if this isn't a callwait */
09596                bearer = pri_find_empty_chan(pri, 0);
09597                if (bearer < 0) {
09598                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09599                   p = NULL;
09600                   break;
09601                }
09602                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09603             } else {
09604                if (alloc_sub(p, 0)) {
09605                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09606                   p = NULL;
09607                   break;
09608                } else
09609                   ast_debug(1, "Allocated placeholder pseudo channel\n");
09610 
09611                p->pri = pri;
09612             }
09613          }
09614 #endif         
09615          if (p->channel == CHAN_PSEUDO) {
09616             p = chandup(p);
09617             if (!p) {
09618                break;
09619             }
09620          }
09621          if (p->owner) {
09622             if (alloc_sub(p, SUB_CALLWAIT)) {
09623                p = NULL;
09624                break;
09625             }
09626          }
09627          p->outgoing = 1;
09628          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09629 #ifdef HAVE_PRI
09630          if (p->bearer) {
09631             /* Log owner to bearer channel, too */
09632             p->bearer->owner = tmp;
09633          }
09634 #endif         
09635          /* Make special notes */
09636          if (res > 1) {
09637             if (opt == 'c') {
09638                /* Confirm answer */
09639                p->confirmanswer = 1;
09640             } else if (opt == 'r') {
09641                /* Distinctive ring */
09642                if (res < 3)
09643                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09644                else
09645                   p->distinctivering = y;
09646             } else if (opt == 'd') {
09647                /* If this is an ISDN call, make it digital */
09648                p->digital = 1;
09649                if (tmp)
09650                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09651             } else {
09652                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09653             }
09654          }
09655          /* Note if the call is a call waiting call */
09656          if (tmp && callwait)
09657             tmp->cdrflags |= AST_CDR_CALLWAIT;
09658          break;
09659       }
09660 next:
09661       if (backwards) {
09662          p = p->prev;
09663          if (!p)
09664             p = end;
09665       } else {
09666          p = p->next;
09667          if (!p)
09668             p = start;
09669       }
09670       /* stop when you roll to the one that we started from */
09671       if (p == exitpvt)
09672          break;
09673    }
09674    ast_mutex_unlock(lock);
09675    restart_monitor();
09676    if (callwait)
09677       *cause = AST_CAUSE_BUSY;
09678    else if (!tmp) {
09679       if (channelmatched) {
09680          if (busy)
09681             *cause = AST_CAUSE_BUSY;
09682       } else if (groupmatched) {
09683          *cause = AST_CAUSE_CONGESTION;
09684       }
09685    }
09686       
09687    return tmp;
09688 }
09689 
09690 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09691 static int dahdi_setlaw(int dfd, int law)
09692 {
09693    return ioctl(dfd, DAHDI_SETLAW, &law);
09694 }
09695 #endif
09696 
09697 #ifdef HAVE_SS7
09698 
09699 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
09700 {
09701    int i;
09702    int winner = -1;
09703    for (i = 0; i < linkset->numchans; i++) {
09704       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09705          winner = i;
09706          break;
09707       }
09708    }
09709    return winner;
09710 }
09711 
09712 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09713 {
09714    unsigned char status[32];
09715    struct dahdi_pvt *p = NULL;
09716    int i, offset;
09717 
09718    for (i = 0; i < linkset->numchans; i++) {
09719       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09720          p = linkset->pvts[i];
09721          offset = p->cic - startcic;
09722          status[offset] = 0;
09723          if (p->locallyblocked)
09724             status[offset] |= (1 << 0) | (1 << 4);
09725          if (p->remotelyblocked)
09726             status[offset] |= (1 << 1) | (1 << 5);
09727          if (p->ss7call) {
09728             if (p->outgoing)
09729                status[offset] |= (1 << 3);
09730             else
09731                status[offset] |= (1 << 2);
09732          } else
09733             status[offset] |= 0x3 << 2;
09734       }
09735    }
09736 
09737    if (p)
09738       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09739    else
09740       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09741    
09742 }
09743 
09744 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
09745 {
09746    int i;
09747 
09748    for (i = 0; i < linkset->numchans; i++) {
09749       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09750          if (state) {
09751             if (state[i])
09752                linkset->pvts[i]->remotelyblocked = block;
09753          } else
09754             linkset->pvts[i]->remotelyblocked = block;
09755       }
09756    }
09757 }
09758 
09759 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
09760 {
09761    int i;
09762 
09763    for (i = 0; i < linkset->numchans; i++) {
09764       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09765          linkset->pvts[i]->inservice = 1;
09766    }
09767 }
09768 
09769 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
09770 {
09771    int i, startcic = -1, endcic, dpc;
09772 
09773    if (linkset->numchans <= 0)
09774       return;
09775 
09776    startcic = linkset->pvts[0]->cic;
09777    /* DB: CIC's DPC fix */
09778    dpc = linkset->pvts[0]->dpc;
09779 
09780    for (i = 0; i < linkset->numchans; i++) {
09781       if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
09782          continue;
09783       } else {
09784          endcic = linkset->pvts[i]->cic;
09785          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09786          isup_grs(linkset->ss7, startcic, endcic, dpc);
09787 
09788          /* DB: CIC's DPC fix */
09789          if (linkset->pvts[i+1]) {
09790             startcic = linkset->pvts[i+1]->cic;
09791             dpc = linkset->pvts[i+1]->dpc;
09792          }
09793       }
09794    }
09795 }
09796 
09797 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
09798 {
09799    if (p->loopedback != enable) {
09800       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09801          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09802          return;
09803       }
09804       p->loopedback = enable;
09805    }
09806 }
09807 
09808 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
09809 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
09810 {
09811    struct ss7 *ss7 = linkset->ss7;
09812    int res;
09813    int law = 1;
09814    struct ast_channel *c;
09815    char tmp[256];
09816 
09817    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09818       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09819    
09820    if (linkset->type == SS7_ITU)
09821       law = DAHDI_LAW_ALAW;
09822    else
09823       law = DAHDI_LAW_MULAW;
09824 
09825    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09826    if (res < 0) 
09827       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09828    
09829    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09830       p->proceeding = 1;
09831       isup_acm(ss7, p->ss7call);
09832    }
09833 
09834    ast_mutex_unlock(&linkset->lock);
09835    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09836 
09837    if (!c) {
09838       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09839       /* Holding this lock is assumed entering the function */
09840       ast_mutex_lock(&linkset->lock);
09841       return;
09842    } else
09843       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09844 
09845    dahdi_enable_ec(p);
09846 
09847    /* We only reference these variables in the context of the ss7_linkset function
09848     * when receiving either and IAM or a COT message.  Since they are only accessed
09849     * from this context, we should be safe to unlock around them */
09850 
09851    ast_mutex_unlock(&p->lock);
09852 
09853    if (!ast_strlen_zero(p->charge_number)) {
09854       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09855       /* Clear this after we set it */
09856       p->charge_number[0] = 0;
09857    }
09858    if (!ast_strlen_zero(p->gen_add_number)) {
09859       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09860       /* Clear this after we set it */
09861       p->gen_add_number[0] = 0;
09862    }
09863    if (!ast_strlen_zero(p->jip_number)) {
09864       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09865       /* Clear this after we set it */
09866       p->jip_number[0] = 0;
09867    }
09868    if (!ast_strlen_zero(p->gen_dig_number)) {
09869       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09870       /* Clear this after we set it */
09871       p->gen_dig_number[0] = 0;
09872    }
09873    if (!ast_strlen_zero(p->orig_called_num)) {
09874       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09875       /* Clear this after we set it */
09876       p->orig_called_num[0] = 0;
09877    }
09878 
09879    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09880    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09881    /* Clear this after we set it */
09882    p->gen_dig_type = 0;
09883 
09884    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09885    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09886    /* Clear this after we set it */
09887    p->gen_dig_scheme = 0;
09888 
09889    if (!ast_strlen_zero(p->lspi_ident)) {
09890       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09891       /* Clear this after we set it */
09892       p->lspi_ident[0] = 0;
09893    }
09894 
09895    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09896    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09897    /* Clear this after we set it */
09898    p->call_ref_ident = 0;
09899 
09900    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09901    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09902    /* Clear this after we set it */
09903    p->call_ref_pc = 0;
09904 
09905    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09906    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09907    /* Clear this after we set it */
09908    p->calling_party_cat = 0;
09909 
09910    if (!ast_strlen_zero(p->redirecting_num)) {
09911       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09912       /* Clear this after we set it */
09913       p->redirecting_num[0] = 0;
09914    }
09915    if (!ast_strlen_zero(p->generic_name)) {
09916       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09917       /* Clear this after we set it */
09918       p->generic_name[0] = 0;
09919    }
09920 
09921    ast_mutex_lock(&p->lock);
09922    ast_mutex_lock(&linkset->lock);
09923 }
09924 
09925 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
09926 {
09927    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
09928       if (size) {
09929          *buf = '\0';
09930       }
09931       return;
09932    }
09933    switch (nai) {
09934    case SS7_NAI_INTERNATIONAL:
09935       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09936       break;
09937    case SS7_NAI_NATIONAL:
09938       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09939       break;
09940    case SS7_NAI_SUBSCRIBER:
09941       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09942       break;
09943    case SS7_NAI_UNKNOWN:
09944       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09945       break;
09946    default:
09947       snprintf(buf, size, "%s", number);
09948       break;
09949    }
09950 }
09951 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
09952 {
09953     return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
09954 }
09955 
09956 static void *ss7_linkset(void *data)
09957 {
09958    int res, i;
09959    struct timeval *next = NULL, tv;
09960    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
09961    struct ss7 *ss7 = linkset->ss7;
09962    ss7_event *e = NULL;
09963    struct dahdi_pvt *p;
09964    int chanpos;
09965    struct pollfd pollers[NUM_DCHANS];
09966    int cic;
09967    unsigned int dpc;
09968    int nextms = 0;
09969 
09970    ss7_start(ss7);
09971 
09972    while(1) {
09973       ast_mutex_lock(&linkset->lock);
09974       if ((next = ss7_schedule_next(ss7))) {
09975          tv = ast_tvnow();
09976          tv.tv_sec = next->tv_sec - tv.tv_sec;
09977          tv.tv_usec = next->tv_usec - tv.tv_usec;
09978          if (tv.tv_usec < 0) {
09979             tv.tv_usec += 1000000;
09980             tv.tv_sec -= 1;
09981          }
09982          if (tv.tv_sec < 0) {
09983             tv.tv_sec = 0;
09984             tv.tv_usec = 0;
09985          }
09986          nextms = tv.tv_sec * 1000;
09987          nextms += tv.tv_usec / 1000;
09988       }
09989       ast_mutex_unlock(&linkset->lock);
09990 
09991       for (i = 0; i < linkset->numsigchans; i++) {
09992          pollers[i].fd = linkset->fds[i];
09993          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
09994          pollers[i].revents = 0;
09995       }
09996 
09997       res = poll(pollers, linkset->numsigchans, nextms);
09998       if ((res < 0) && (errno != EINTR)) {
09999          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
10000       } else if (!res) {
10001          ast_mutex_lock(&linkset->lock);
10002          ss7_schedule_run(ss7);
10003          ast_mutex_unlock(&linkset->lock);
10004          continue;
10005       }
10006 
10007       ast_mutex_lock(&linkset->lock);
10008       for (i = 0; i < linkset->numsigchans; i++) {
10009          if (pollers[i].revents & POLLPRI) {
10010             int x;
10011             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10012                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10013             }
10014             switch (x) {
10015             case DAHDI_EVENT_OVERRUN:
10016                ast_debug(1, "Overrun detected!\n");
10017                break;
10018             case DAHDI_EVENT_BADFCS:
10019                ast_debug(1, "Bad FCS\n");
10020                break;
10021             case DAHDI_EVENT_ABORT:
10022                ast_debug(1, "HDLC Abort\n");
10023                break;
10024             case DAHDI_EVENT_ALARM:
10025                ast_log(LOG_ERROR, "Alarm on link!\n");
10026                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10027                linkset->linkstate[i] &= ~LINKSTATE_UP;
10028                ss7_link_alarm(ss7, pollers[i].fd);
10029                break;
10030             case DAHDI_EVENT_NOALARM:
10031                ast_log(LOG_ERROR, "Alarm cleared on link\n");
10032                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10033                linkset->linkstate[i] |= LINKSTATE_STARTING;
10034                ss7_link_noalarm(ss7, pollers[i].fd);
10035                break;
10036             default:
10037                ast_log(LOG_ERROR, "Got exception %d!\n", x);
10038                break;
10039             }
10040          }
10041 
10042          if (pollers[i].revents & POLLIN) {
10043             ast_mutex_lock(&linkset->lock);
10044             res = ss7_read(ss7, pollers[i].fd);
10045             ast_mutex_unlock(&linkset->lock);
10046          }
10047 
10048          if (pollers[i].revents & POLLOUT) {
10049             ast_mutex_lock(&linkset->lock);
10050             res = ss7_write(ss7, pollers[i].fd);
10051             ast_mutex_unlock(&linkset->lock);
10052             if (res < 0) {
10053                ast_debug(1, "Error in write %s\n", strerror(errno));
10054             }
10055          }
10056       }
10057 
10058       while ((e = ss7_check_event(ss7))) {
10059          switch (e->e) {
10060          case SS7_EVENT_UP:
10061             if (linkset->state != LINKSET_STATE_UP) {
10062                ast_verbose("--- SS7 Up ---\n");
10063                ss7_reset_linkset(linkset);
10064             }
10065             linkset->state = LINKSET_STATE_UP;
10066             break;
10067          case SS7_EVENT_DOWN:
10068             ast_verbose("--- SS7 Down ---\n");
10069             linkset->state = LINKSET_STATE_DOWN;
10070             for (i = 0; i < linkset->numchans; i++) {
10071                struct dahdi_pvt *p = linkset->pvts[i];
10072                if (p)
10073                   p->inalarm = 1;
10074             }
10075             break;
10076          case MTP2_LINK_UP:
10077             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10078             break;
10079          case MTP2_LINK_DOWN:
10080             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10081             break;
10082          case ISUP_EVENT_CPG:
10083             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10084             if (chanpos < 0) {
10085                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10086                break;
10087             }
10088             p = linkset->pvts[chanpos];
10089             ast_mutex_lock(&p->lock);
10090             switch (e->cpg.event) {
10091             case CPG_EVENT_ALERTING:
10092                p->alerting = 1;
10093                p->subs[SUB_REAL].needringing = 1;
10094                break;
10095             case CPG_EVENT_PROGRESS:
10096             case CPG_EVENT_INBANDINFO:
10097                {
10098                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10099                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10100                   dahdi_queue_frame(p, &f, linkset);
10101                   p->progress = 1;
10102                   p->dialing = 0;
10103                   if (p->dsp && p->dsp_features) {
10104                           ast_dsp_set_features(p->dsp, p->dsp_features);
10105                           p->dsp_features = 0;
10106                   }
10107                }
10108                break;
10109             default:
10110                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10111             }
10112 
10113             ast_mutex_unlock(&p->lock);
10114             break;
10115          case ISUP_EVENT_RSC:
10116             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10117             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10118             if (chanpos < 0) {
10119                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10120                break;
10121             }
10122             p = linkset->pvts[chanpos];
10123             ast_mutex_lock(&p->lock);
10124             p->inservice = 1;
10125             p->remotelyblocked = 0;
10126             dpc = p->dpc;
10127             isup_set_call_dpc(e->rsc.call, dpc);
10128             if (p->ss7call)
10129                p->ss7call = NULL;
10130             if (p->owner)
10131                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10132             ast_mutex_unlock(&p->lock);
10133             isup_rlc(ss7, e->rsc.call);
10134             break;
10135          case ISUP_EVENT_GRS:
10136             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10137             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10138             if (chanpos < 0) {
10139                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10140                break;
10141             }
10142             p = linkset->pvts[chanpos];
10143             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10144             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10145             break;
10146          case ISUP_EVENT_CQM:
10147             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10148             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10149             break;
10150          case ISUP_EVENT_GRA:
10151             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10152             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10153             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10154             break;
10155          case ISUP_EVENT_IAM:
10156             ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
10157             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10158             if (chanpos < 0) {
10159                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10160                isup_rel(ss7, e->iam.call, -1);
10161                break;
10162             }
10163             p = linkset->pvts[chanpos];
10164             ast_mutex_lock(&p->lock);
10165             if (p->owner) {
10166                if (p->ss7call == e->iam.call) {
10167                   ast_mutex_unlock(&p->lock);
10168                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10169                   break;
10170                } else {
10171                   ast_mutex_unlock(&p->lock);
10172                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10173                   break;
10174                }
10175             }
10176 
10177             dpc = p->dpc;
10178             p->ss7call = e->iam.call;
10179             isup_set_call_dpc(p->ss7call, dpc);
10180 
10181             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10182                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10183                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10184             } else
10185                p->cid_num[0] = 0;
10186 
10187             if (p->immediate) {
10188                p->exten[0] = 's';
10189                p->exten[1] = '\0';
10190             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10191                char *st;
10192                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10193                st = strchr(p->exten, '#');
10194                if (st)
10195                   *st = '\0';
10196                } else
10197                   p->exten[0] = '\0';
10198 
10199             p->cid_ani[0] = '\0';
10200             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10201                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10202             else
10203                p->cid_name[0] = '\0';
10204             
10205             p->cid_ani2 = e->iam.oli_ani2;
10206             p->cid_ton = 0;
10207             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10208             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10209             p->gen_add_type = e->iam.gen_add_type;
10210             p->gen_add_nai = e->iam.gen_add_nai;
10211             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10212             p->gen_add_num_plan = e->iam.gen_add_num_plan;
10213             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10214             p->gen_dig_type = e->iam.gen_dig_type;
10215             p->gen_dig_scheme = e->iam.gen_dig_scheme;
10216             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10217             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10218             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10219             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10220             p->calling_party_cat = e->iam.calling_party_cat;
10221                
10222             /* Set DNID */
10223             if (!ast_strlen_zero(e->iam.called_party_num))
10224                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10225             
10226             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10227 
10228                if (e->iam.cot_check_required) {
10229                   dahdi_loopback(p, 1);
10230                } else
10231                   ss7_start_call(p, linkset);
10232             } else {
10233                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10234                p->alreadyhungup = 1;
10235                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10236             }
10237             ast_mutex_unlock(&p->lock);
10238             break;
10239          case ISUP_EVENT_COT:
10240             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10241             if (chanpos < 0) {
10242                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10243                isup_rel(ss7, e->cot.call, -1);
10244                break;
10245             }
10246             p = linkset->pvts[chanpos];
10247 
10248             ast_mutex_lock(&p->lock);
10249 
10250             if (p->loopedback) {
10251                dahdi_loopback(p, 0);
10252                ss7_start_call(p, linkset);
10253             }
10254 
10255             ast_mutex_unlock(&p->lock);
10256 
10257             break;
10258          case ISUP_EVENT_CCR:
10259             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10260             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10261             if (chanpos < 0) {
10262                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10263                break;
10264             }
10265 
10266             p = linkset->pvts[chanpos];
10267 
10268             ast_mutex_lock(&p->lock);
10269             dahdi_loopback(p, 1);
10270             ast_mutex_unlock(&p->lock);
10271 
10272             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10273             break;
10274          case ISUP_EVENT_CVT:
10275             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10276             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10277             if (chanpos < 0) {
10278                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10279                break;
10280             }
10281             
10282             p = linkset->pvts[chanpos];
10283             
10284             ast_mutex_lock(&p->lock);
10285             dahdi_loopback(p, 1);
10286             ast_mutex_unlock(&p->lock);
10287             
10288             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10289             break;
10290          case ISUP_EVENT_REL:
10291             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10292             if (chanpos < 0) {
10293                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10294                break;
10295             }
10296             p = linkset->pvts[chanpos];
10297             ast_mutex_lock(&p->lock);
10298             if (p->owner) {
10299                p->owner->hangupcause = e->rel.cause;
10300                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10301             } else if (!p->restartpending)
10302                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10303 
10304             /* End the loopback if we have one */
10305             dahdi_loopback(p, 0);
10306 
10307             isup_rlc(ss7, e->rel.call);
10308             p->ss7call = NULL;
10309 
10310             ast_mutex_unlock(&p->lock);
10311             break;
10312          case ISUP_EVENT_ACM:
10313             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10314             if (chanpos < 0) {
10315                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10316                isup_rel(ss7, e->acm.call, -1);
10317                break;
10318             } else {
10319                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10320 
10321                p = linkset->pvts[chanpos];
10322 
10323                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10324                
10325                if (e->acm.call_ref_ident > 0) {
10326                   p->rlt = 1; /* Setting it but not using it here*/
10327                }
10328 
10329                ast_mutex_lock(&p->lock);
10330                dahdi_queue_frame(p, &f, linkset);
10331                p->proceeding = 1;
10332                p->dialing = 0;
10333                /* Send alerting if subscriber is free */
10334                if (e->acm.called_party_status_ind == 1) {
10335                   p->alerting = 1;
10336                   p->subs[SUB_REAL].needringing = 1;
10337                }
10338                ast_mutex_unlock(&p->lock);
10339             }
10340             break;
10341          case ISUP_EVENT_CGB:
10342             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10343             if (chanpos < 0) {
10344                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10345                break;
10346             }
10347             p = linkset->pvts[chanpos];
10348             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10349             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10350             break;
10351          case ISUP_EVENT_CGU:
10352             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10353             if (chanpos < 0) {
10354                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10355                break;
10356             }
10357             p = linkset->pvts[chanpos];
10358             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10359             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10360             break;
10361          case ISUP_EVENT_UCIC:
10362             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10363             if (chanpos < 0) {
10364                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10365                break;
10366             }
10367             p = linkset->pvts[chanpos];
10368             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10369             ast_mutex_lock(&p->lock);
10370             p->remotelyblocked = 1;
10371             p->inservice = 0;
10372             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
10373             break;
10374          case ISUP_EVENT_BLO:
10375             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10376             if (chanpos < 0) {
10377                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10378                break;
10379             }
10380             p = linkset->pvts[chanpos];
10381             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10382             ast_mutex_lock(&p->lock);
10383             p->remotelyblocked = 1;
10384             ast_mutex_unlock(&p->lock);
10385             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10386             break;
10387          case ISUP_EVENT_BLA:
10388             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10389             if (chanpos < 0) {
10390                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10391                break;
10392             }
10393             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10394             p = linkset->pvts[chanpos];
10395             ast_mutex_lock(&p->lock);
10396             p->locallyblocked = 1;
10397             ast_mutex_unlock(&p->lock);
10398             break;
10399          case ISUP_EVENT_UBL:
10400             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10401             if (chanpos < 0) {
10402                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10403                break;
10404             }
10405             p = linkset->pvts[chanpos];
10406             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10407             ast_mutex_lock(&p->lock);
10408             p->remotelyblocked = 0;
10409             ast_mutex_unlock(&p->lock);
10410             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10411             break;
10412          case ISUP_EVENT_UBA:
10413             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10414             if (chanpos < 0) {
10415                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10416                break;
10417             }
10418             p = linkset->pvts[chanpos];
10419             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10420             ast_mutex_lock(&p->lock);
10421             p->locallyblocked = 0;
10422             ast_mutex_unlock(&p->lock);
10423             break;
10424          case ISUP_EVENT_CON:
10425          case ISUP_EVENT_ANM:
10426             if (e->e == ISUP_EVENT_CON)
10427                cic = e->con.cic;
10428             else
10429                cic = e->anm.cic;
10430 
10431             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10432             if (chanpos < 0) {
10433                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10434                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10435                break;
10436             } else {
10437                p = linkset->pvts[chanpos];
10438                ast_mutex_lock(&p->lock);
10439                p->subs[SUB_REAL].needanswer = 1;
10440                if (p->dsp && p->dsp_features) {
10441                        ast_dsp_set_features(p->dsp, p->dsp_features);
10442                        p->dsp_features = 0;
10443                }
10444                dahdi_enable_ec(p);
10445                ast_mutex_unlock(&p->lock);
10446             }
10447             break;
10448          case ISUP_EVENT_RLC:
10449             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10450             if (chanpos < 0) {
10451                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10452                break;
10453             } else {
10454                p = linkset->pvts[chanpos];
10455                ast_mutex_lock(&p->lock);
10456                if (p->alreadyhungup)
10457                   p->ss7call = NULL;
10458                else
10459                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
10460                ast_mutex_unlock(&p->lock);
10461                }
10462                break;
10463          case ISUP_EVENT_FAA:
10464             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10465             if (chanpos < 0) {
10466                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10467                break;
10468             } else {
10469                p = linkset->pvts[chanpos];
10470                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10471                ast_mutex_lock(&p->lock);
10472                if (p->alreadyhungup){
10473                   p->ss7call = NULL;
10474                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
10475                }
10476                ast_mutex_unlock(&p->lock);
10477             }
10478             break;
10479          default:
10480             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10481             break;
10482          }
10483       }
10484       ast_mutex_unlock(&linkset->lock);
10485    }
10486 
10487    return 0;
10488 }
10489 
10490 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
10491 {
10492 #if 0
10493    int i;
10494 
10495    for (i = 0; i < NUM_SPANS; i++)
10496       if (linksets[i].ss7 == ss7)
10497          break;
10498 
10499    ast_verbose("[%d] %s", i+1, s);
10500 #else
10501    ast_verbose("%s", s);
10502 #endif
10503 }
10504 
10505 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
10506 {
10507 #if 0
10508    int i;
10509 
10510    for (i = 0; i < NUM_SPANS; i++)
10511       if (linksets[i].ss7 == ss7)
10512          break;
10513 
10514 #else
10515    ast_log(LOG_ERROR, "%s", s);
10516 #endif
10517 }
10518 
10519 #endif /* HAVE_SS7 */
10520 
10521 #ifdef HAVE_PRI
10522 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10523 {
10524    struct dahdi_pvt *p;
10525    p = pri->crvs;
10526    while (p) {
10527       if (p->channel == crv)
10528          return p;
10529       p = p->next;
10530    }
10531    return NULL;
10532 }
10533 
10534 
10535 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10536 {
10537    int x;
10538    int span = PRI_SPAN(channel);
10539    int spanfd;
10540    struct dahdi_params param;
10541    int principle = -1;
10542    int explicit = PRI_EXPLICIT(channel);
10543    channel = PRI_CHANNEL(channel);
10544 
10545    if (!explicit) {
10546       spanfd = pri_active_dchan_fd(pri);
10547       memset(&param, 0, sizeof(param));
10548       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10549          return -1;
10550       span = pris[param.spanno - 1].prilogicalspan;
10551    }
10552 
10553    for (x = 0; x < pri->numchans; x++) {
10554       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10555          principle = x;
10556          break;
10557       }
10558    }
10559    
10560    return principle;
10561 }
10562 
10563 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10564 {
10565    int x;
10566    struct dahdi_pvt *crv;
10567    if (!c) {
10568       if (principle < 0)
10569          return -1;
10570       return principle;
10571    }
10572    if ((principle > -1) && 
10573       (principle < pri->numchans) && 
10574       (pri->pvts[principle]) && 
10575       (pri->pvts[principle]->call == c))
10576       return principle;
10577    /* First, check for other bearers */
10578    for (x = 0; x < pri->numchans; x++) {
10579       if (!pri->pvts[x])
10580          continue;
10581       if (pri->pvts[x]->call == c) {
10582          /* Found our call */
10583          if (principle != x) {
10584             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10585 
10586             ast_verb(3, "Moving call from channel %d to channel %d\n",
10587                 old->channel, new->channel);
10588             if (new->owner) {
10589                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10590                   old->channel, new->channel, new->channel);
10591                return -1;
10592             }
10593             /* Fix it all up now */
10594             new->owner = old->owner;
10595             old->owner = NULL;
10596             if (new->owner) {
10597                ast_string_field_build(new->owner, name, 
10598                             "DAHDI/%d:%d-%d", pri->trunkgroup,
10599                             new->channel, 1);
10600                new->owner->tech_pvt = new;
10601                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10602                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10603                old->subs[SUB_REAL].owner = NULL;
10604             } else
10605                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);
10606             new->call = old->call;
10607             old->call = NULL;
10608 
10609             /* Copy any DSP that may be present */
10610             new->dsp = old->dsp;
10611             new->dsp_features = old->dsp_features;
10612             old->dsp = NULL;
10613             old->dsp_features = 0;
10614          }
10615          return principle;
10616       }
10617    }
10618    /* Now check for a CRV with no bearer */
10619    crv = pri->crvs;
10620    while (crv) {
10621       if (crv->call == c) {
10622          /* This is our match...  Perform some basic checks */
10623          if (crv->bearer)
10624             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10625          else if (pri->pvts[principle]->owner) 
10626             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10627          else {
10628             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
10629                wakeup the potential sleeper */
10630             dahdi_close_sub(crv, SUB_REAL);
10631             pri->pvts[principle]->call = crv->call;
10632             pri_assign_bearer(crv, pri, pri->pvts[principle]);
10633             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10634                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10635                pri->trunkgroup, crv->channel);
10636             wakeup_sub(crv, SUB_REAL, pri);
10637          }
10638          return principle;
10639       }
10640       crv = crv->next;
10641    }
10642    ast_log(LOG_WARNING, "Call specified, but not found?\n");
10643    return -1;
10644 }
10645 
10646 static void *do_idle_thread(void *vchan)
10647 {
10648    struct ast_channel *chan = vchan;
10649    struct dahdi_pvt *pvt = chan->tech_pvt;
10650    struct ast_frame *f;
10651    char ex[80];
10652    /* Wait up to 30 seconds for an answer */
10653    int newms, ms = 30000;
10654    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10655    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10656    if (ast_call(chan, ex, 0)) {
10657       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10658       ast_hangup(chan);
10659       return NULL;
10660    }
10661    while ((newms = ast_waitfor(chan, ms)) > 0) {
10662       f = ast_read(chan);
10663       if (!f) {
10664          /* Got hangup */
10665          break;
10666       }
10667       if (f->frametype == AST_FRAME_CONTROL) {
10668          switch (f->subclass) {
10669          case AST_CONTROL_ANSWER:
10670             /* Launch the PBX */
10671             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10672             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10673             chan->priority = 1;
10674             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10675             ast_pbx_run(chan);
10676             /* It's already hungup, return immediately */
10677             return NULL;
10678          case AST_CONTROL_BUSY:
10679             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10680             break;
10681          case AST_CONTROL_CONGESTION:
10682             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10683             break;
10684          };
10685       }
10686       ast_frfree(f);
10687       ms = newms;
10688    }
10689    /* Hangup the channel since nothing happend */
10690    ast_hangup(chan);
10691    return NULL;
10692 }
10693 
10694 #ifndef PRI_RESTART
10695 #error "Upgrade your libpri"
10696 #endif
10697 static void dahdi_pri_message(struct pri *pri, char *s)
10698 {
10699    int x, y;
10700    int dchan = -1, span = -1;
10701    int dchancount = 0;
10702 
10703    if (pri) {
10704       for (x = 0; x < NUM_SPANS; x++) {
10705          for (y = 0; y < NUM_DCHANS; y++) {
10706             if (pris[x].dchans[y])
10707                dchancount++;
10708 
10709             if (pris[x].dchans[y] == pri)
10710                dchan = y;
10711          }
10712          if (dchan >= 0) {
10713             span = x;
10714             break;
10715          }
10716          dchancount = 0;
10717       }
10718       if (dchancount > 1 && (span > -1))
10719          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10720       else
10721          ast_verbose("%s", s);
10722    } else
10723       ast_verbose("%s", s);
10724 
10725    ast_mutex_lock(&pridebugfdlock);
10726 
10727    if (pridebugfd >= 0) {
10728       if (write(pridebugfd, s, strlen(s)) < 0) {
10729          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10730       }
10731    }
10732 
10733    ast_mutex_unlock(&pridebugfdlock);
10734 }
10735 
10736 static void dahdi_pri_error(struct pri *pri, char *s)
10737 {
10738    int x, y;
10739    int dchan = -1, span = -1;
10740    int dchancount = 0;
10741 
10742    if (pri) {
10743       for (x = 0; x < NUM_SPANS; x++) {
10744          for (y = 0; y < NUM_DCHANS; y++) {
10745             if (pris[x].dchans[y])
10746                dchancount++;
10747 
10748             if (pris[x].dchans[y] == pri)
10749                dchan = y;
10750          }
10751          if (dchan >= 0) {
10752             span = x;
10753             break;
10754          }
10755          dchancount = 0;
10756       }
10757       if ((dchancount > 1) && (span > -1))
10758          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10759       else
10760          ast_log(LOG_ERROR, "%s", s);
10761    } else
10762       ast_log(LOG_ERROR, "%s", s);
10763 
10764    ast_mutex_lock(&pridebugfdlock);
10765 
10766    if (pridebugfd >= 0) {
10767       if (write(pridebugfd, s, strlen(s)) < 0) {
10768          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10769       }
10770    }
10771 
10772    ast_mutex_unlock(&pridebugfdlock);
10773 }
10774 
10775 static int pri_check_restart(struct dahdi_pri *pri)
10776 {
10777    do {
10778       pri->resetpos++;
10779    } while ((pri->resetpos < pri->numchans) &&
10780        (!pri->pvts[pri->resetpos] ||
10781         pri->pvts[pri->resetpos]->call ||
10782         pri->pvts[pri->resetpos]->resetting));
10783    if (pri->resetpos < pri->numchans) {
10784       /* Mark the channel as resetting and restart it */
10785       pri->pvts[pri->resetpos]->resetting = 1;
10786       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10787    } else {
10788       pri->resetting = 0;
10789       time(&pri->lastreset);
10790    }
10791    return 0;
10792 }
10793 
10794 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10795 {
10796    int x;
10797    int redo;
10798    ast_mutex_unlock(&pri->lock);
10799    ast_mutex_lock(&p->lock);
10800    do {
10801       redo = 0;
10802       for (x = 0; x < 3; x++) {
10803          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10804             redo++;
10805             DEADLOCK_AVOIDANCE(&p->lock);
10806          }
10807          if (p->subs[x].owner) {
10808             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10809             ast_channel_unlock(p->subs[x].owner);
10810          }
10811       }
10812    } while (redo);
10813    ast_mutex_unlock(&p->lock);
10814    ast_mutex_lock(&pri->lock);
10815    return 0;
10816 }
10817 
10818 static char * redirectingreason2str(int redirectingreason)
10819 {
10820    switch (redirectingreason) {
10821    case 0:
10822       return "UNKNOWN";
10823    case 1:
10824       return "BUSY";
10825    case 2:
10826       return "NO_REPLY";
10827    case 0xF:
10828       return "UNCONDITIONAL";
10829    default:
10830       return "NOREDIRECT";
10831    }
10832 }
10833 
10834 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10835 {
10836    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10837       snprintf(buf, size, "%s", number);
10838       return;
10839    }
10840    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10841       if (size) {
10842          *buf = '\0';
10843       }
10844       return;
10845    }
10846    switch (plan) {
10847    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10848       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10849       break;
10850    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10851       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10852       break;
10853    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10854       snprintf(buf, size, "%s%s", pri->localprefix, number);
10855       break;
10856    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10857       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10858       break;
10859    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10860       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10861       break;
10862    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10863       snprintf(buf, size, "%s", number);
10864       break;
10865    }
10866 }
10867 
10868 
10869 static void *pri_dchannel(void *vpri)
10870 {
10871    struct dahdi_pri *pri = vpri;
10872    pri_event *e;
10873    struct pollfd fds[NUM_DCHANS];
10874    int res;
10875    int chanpos = 0;
10876    int x;
10877    int haveidles;
10878    int activeidles;
10879    int nextidle = -1;
10880    struct ast_channel *c;
10881    struct timeval tv, lowest, *next;
10882    struct timeval lastidle = ast_tvnow();
10883    int doidling=0;
10884    char *cc;
10885    char idlen[80];
10886    struct ast_channel *idle;
10887    pthread_t p;
10888    time_t t;
10889    int i, which=-1;
10890    int numdchans;
10891    int cause=0;
10892    struct dahdi_pvt *crv;
10893    pthread_t threadid;
10894    char ani2str[6];
10895    char plancallingnum[256];
10896    char plancallingani[256];
10897    char calledtonstr[10];
10898    
10899    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10900 
10901    gettimeofday(&lastidle, NULL);
10902    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10903       /* Need to do idle dialing, check to be sure though */
10904       cc = strchr(pri->idleext, '@');
10905       if (cc) {
10906          *cc = '\0';
10907          cc++;
10908          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10909 #if 0
10910          /* Extensions may not be loaded yet */
10911          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10912             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10913          else
10914 #endif
10915             doidling = 1;
10916       } else
10917          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10918    }
10919    for (;;) {
10920       for (i = 0; i < NUM_DCHANS; i++) {
10921          if (!pri->dchannels[i])
10922             break;
10923          fds[i].fd = pri->fds[i];
10924          fds[i].events = POLLIN | POLLPRI;
10925          fds[i].revents = 0;
10926       }
10927       numdchans = i;
10928       time(&t);
10929       ast_mutex_lock(&pri->lock);
10930       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10931          if (pri->resetting && pri_is_up(pri)) {
10932             if (pri->resetpos < 0)
10933                pri_check_restart(pri);
10934          } else {
10935             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
10936                pri->resetting = 1;
10937                pri->resetpos = -1;
10938             }
10939          }
10940       }
10941       /* Look for any idle channels if appropriate */
10942       if (doidling && pri_is_up(pri)) {
10943          nextidle = -1;
10944          haveidles = 0;
10945          activeidles = 0;
10946          for (x = pri->numchans; x >= 0; x--) {
10947             if (pri->pvts[x] && !pri->pvts[x]->owner && 
10948                 !pri->pvts[x]->call) {
10949                if (haveidles < pri->minunused) {
10950                   haveidles++;
10951                } else if (!pri->pvts[x]->resetting) {
10952                   nextidle = x;
10953                   break;
10954                }
10955             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10956                activeidles++;
10957          }
10958          if (nextidle > -1) {
10959             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10960                /* Don't create a new idle call more than once per second */
10961                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10962                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10963                if (idle) {
10964                   pri->pvts[nextidle]->isidlecall = 1;
10965                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10966                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10967                      dahdi_hangup(idle);
10968                   }
10969                } else
10970                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10971                lastidle = ast_tvnow();
10972             }
10973          } else if ((haveidles < pri->minunused) &&
10974                (activeidles > pri->minidle)) {
10975             /* Mark something for hangup if there is something 
10976                that can be hungup */
10977             for (x = pri->numchans; x >= 0; x--) {
10978                /* find a candidate channel */
10979                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10980                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10981                   haveidles++;
10982                   /* Stop if we have enough idle channels or
10983                     can't spare any more active idle ones */
10984                   if ((haveidles >= pri->minunused) ||
10985                       (activeidles <= pri->minidle))
10986                      break;
10987                } 
10988             }
10989          }
10990       }
10991       /* Start with reasonable max */
10992       lowest = ast_tv(60, 0);
10993       for (i = 0; i < NUM_DCHANS; i++) {
10994          /* Find lowest available d-channel */
10995          if (!pri->dchannels[i])
10996             break;
10997          if ((next = pri_schedule_next(pri->dchans[i]))) {
10998             /* We need relative time here */
10999             tv = ast_tvsub(*next, ast_tvnow());
11000             if (tv.tv_sec < 0) {
11001                tv = ast_tv(0,0);
11002             }
11003             if (doidling || pri->resetting) {
11004                if (tv.tv_sec > 1) {
11005                   tv = ast_tv(1, 0);
11006                }
11007             } else {
11008                if (tv.tv_sec > 60) {
11009                   tv = ast_tv(60, 0);
11010                }
11011             }
11012          } else if (doidling || pri->resetting) {
11013             /* Make sure we stop at least once per second if we're
11014                monitoring idle channels */
11015             tv = ast_tv(1,0);
11016          } else {
11017             /* Don't poll for more than 60 seconds */
11018             tv = ast_tv(60, 0);
11019          }
11020          if (!i || ast_tvcmp(tv, lowest) < 0) {
11021             lowest = tv;
11022          }
11023       }
11024       ast_mutex_unlock(&pri->lock);
11025 
11026       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11027       pthread_testcancel();
11028       e = NULL;
11029       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11030       pthread_testcancel();
11031       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11032 
11033       ast_mutex_lock(&pri->lock);
11034       if (!res) {
11035          for (which = 0; which < NUM_DCHANS; which++) {
11036             if (!pri->dchans[which])
11037                break;
11038             /* Just a timeout, run the scheduler */
11039             e = pri_schedule_run(pri->dchans[which]);
11040             if (e)
11041                break;
11042          }
11043       } else if (res > -1) {
11044          for (which = 0; which < NUM_DCHANS; which++) {
11045             if (!pri->dchans[which])
11046                break;
11047             if (fds[which].revents & POLLPRI) {
11048                /* Check for an event */
11049                x = 0;
11050                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11051                if (x) {
11052                   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);
11053                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11054                      "PRIEvent: %s\r\n"
11055                      "PRIEventCode: %d\r\n"
11056                      "D-channel: %s\r\n"
11057                      "Span: %d\r\n",
11058                      event2str(x),
11059                      x,
11060                      pri_order(which),
11061                      pri->span
11062                      );
11063                }
11064                /* Keep track of alarm state */  
11065                if (x == DAHDI_EVENT_ALARM) {
11066                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11067                   pri_find_dchan(pri);
11068                } else if (x == DAHDI_EVENT_NOALARM) {
11069                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
11070                   pri_restart(pri->dchans[which]);
11071                }
11072             
11073                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11074             } else if (fds[which].revents & POLLIN) {
11075                e = pri_check_event(pri->dchans[which]);
11076             }
11077             if (e)
11078                break;
11079          }
11080       } else if (errno != EINTR)
11081          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11082 
11083       if (e) {
11084          if (pri->debug)
11085             pri_dump_event(pri->dchans[which], e);
11086 
11087          if (e->e != PRI_EVENT_DCHAN_DOWN) {
11088             if (!(pri->dchanavail[which] & DCHAN_UP)) {
11089                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11090             }
11091             pri->dchanavail[which] |= DCHAN_UP;
11092          } else if (pri->sig != SIG_BRI_PTMP) {
11093             if (pri->dchanavail[which] & DCHAN_UP) {
11094                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11095             }
11096             pri->dchanavail[which] &= ~DCHAN_UP;
11097          }
11098 
11099          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11100             /* Must be an NFAS group that has the secondary dchan active */
11101             pri->pri = pri->dchans[which];
11102 
11103          switch (e->e) {
11104          case PRI_EVENT_DCHAN_UP:
11105             if (!pri->pri) pri_find_dchan(pri);
11106 
11107             /* Note presense of D-channel */
11108             time(&pri->lastreset);
11109 
11110             /* Restart in 5 seconds */
11111             if (pri->resetinterval > -1) {
11112                pri->lastreset -= pri->resetinterval;
11113                pri->lastreset += 5;
11114             }
11115             pri->resetting = 0;
11116             /* Take the channels from inalarm condition */
11117             for (i = 0; i < pri->numchans; i++)
11118                if (pri->pvts[i]) {
11119                   pri->pvts[i]->inalarm = 0;
11120                }
11121             break;
11122          case PRI_EVENT_DCHAN_DOWN:
11123             pri_find_dchan(pri);
11124             if (!pri_is_up(pri)) {
11125                pri->resetting = 0;
11126                /* Hangup active channels and put them in alarm mode */
11127                for (i = 0; i < pri->numchans; i++) {
11128                   struct dahdi_pvt *p = pri->pvts[i];
11129                   if (p) {
11130                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11131                         /* T309 is not enabled : hangup calls when alarm occurs */
11132                         if (p->call) {
11133                            if (p->pri && p->pri->pri) {
11134                               pri_hangup(p->pri->pri, p->call, -1);
11135                               pri_destroycall(p->pri->pri, p->call);
11136                               p->call = NULL;
11137                            } else
11138                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11139                         }
11140                         if (p->realcall) {
11141                            pri_hangup_all(p->realcall, pri);
11142                         } else if (p->owner)
11143                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11144                      }
11145                      p->inalarm = 1;
11146                   }
11147                }
11148             }
11149             break;
11150          case PRI_EVENT_RESTART:
11151             if (e->restart.channel > -1) {
11152                chanpos = pri_find_principle(pri, e->restart.channel);
11153                if (chanpos < 0)
11154                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
11155                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11156                else {
11157                   ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11158                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11159                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11160                   if (pri->pvts[chanpos]->call) {
11161                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11162                      pri->pvts[chanpos]->call = NULL;
11163                   }
11164                   /* Force soft hangup if appropriate */
11165                   if (pri->pvts[chanpos]->realcall) 
11166                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11167                   else if (pri->pvts[chanpos]->owner)
11168                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11169                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11170                }
11171             } else {
11172                ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11173                for (x = 0; x < pri->numchans; x++)
11174                   if (pri->pvts[x]) {
11175                      ast_mutex_lock(&pri->pvts[x]->lock);
11176                      if (pri->pvts[x]->call) {
11177                         pri_destroycall(pri->pri, pri->pvts[x]->call);
11178                         pri->pvts[x]->call = NULL;
11179                      }
11180                      if (pri->pvts[chanpos]->realcall) 
11181                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11182                      else if (pri->pvts[x]->owner)
11183                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11184                      ast_mutex_unlock(&pri->pvts[x]->lock);
11185                   }
11186             }
11187             break;
11188          case PRI_EVENT_KEYPAD_DIGIT:
11189             chanpos = pri_find_principle(pri, e->digit.channel);
11190             if (chanpos < 0) {
11191                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
11192                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11193             } else {
11194                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11195                if (chanpos > -1) {
11196                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11197                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
11198                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11199                      /* how to do that */
11200                      int digitlen = strlen(e->digit.digits);
11201                      char digit;
11202                      int i;               
11203                      for (i = 0; i < digitlen; i++) { 
11204                         digit = e->digit.digits[i];
11205                         {
11206                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
11207                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11208                         }
11209                      }
11210                   }
11211                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11212                }
11213             }
11214             break;
11215             
11216          case PRI_EVENT_INFO_RECEIVED:
11217             chanpos = pri_find_principle(pri, e->ring.channel);
11218             if (chanpos < 0) {
11219                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
11220                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11221             } else {
11222                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11223                if (chanpos > -1) {
11224                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11225                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
11226                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11227                      /* how to do that */
11228                      int digitlen = strlen(e->ring.callednum);
11229                      char digit;
11230                      int i;               
11231                      for (i = 0; i < digitlen; i++) { 
11232                         digit = e->ring.callednum[i];
11233                         {
11234                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
11235                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11236                         }
11237                      }
11238                   }
11239                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11240                }
11241             }
11242             break;
11243          case PRI_EVENT_RING:
11244             crv = NULL;
11245             if (e->ring.channel == -1)
11246                chanpos = pri_find_empty_chan(pri, 1);
11247             else
11248                chanpos = pri_find_principle(pri, e->ring.channel);
11249             /* if no channel specified find one empty */
11250             if (chanpos < 0) {
11251                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
11252                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11253             } else {
11254                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11255                if (pri->pvts[chanpos]->owner) {
11256                   if (pri->pvts[chanpos]->call == e->ring.call) {
11257                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
11258                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11259                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11260                      break;
11261                   } else {
11262                      /* This is where we handle initial glare */
11263                      ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n", 
11264                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11265                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11266                      chanpos = -1;
11267                   }
11268                }
11269                if (chanpos > -1)
11270                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11271             }
11272             if ((chanpos < 0) && (e->ring.flexible))
11273                chanpos = pri_find_empty_chan(pri, 1);
11274             if (chanpos > -1) {
11275                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11276                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11277                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
11278                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11279                   if (crv)
11280                      ast_mutex_lock(&crv->lock);
11281                   if (!crv || crv->owner) {
11282                      pri->pvts[chanpos]->call = NULL;
11283                      if (crv) {
11284                         if (crv->owner)
11285                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11286                         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);
11287                      } else
11288                         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);
11289                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11290                      if (crv)
11291                         ast_mutex_unlock(&crv->lock);
11292                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11293                      break;
11294                   }
11295                }
11296                pri->pvts[chanpos]->call = e->ring.call;
11297                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11298                if (pri->pvts[chanpos]->use_callerid) {
11299                   ast_shrink_phone_number(plancallingnum);
11300                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11301 #ifdef PRI_ANI
11302                   if (!ast_strlen_zero(e->ring.callingani)) {
11303                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11304                      ast_shrink_phone_number(plancallingani);
11305                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11306                   } else {
11307                      pri->pvts[chanpos]->cid_ani[0] = '\0';
11308                   }
11309 #endif
11310                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11311                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
11312                } else {
11313                   pri->pvts[chanpos]->cid_num[0] = '\0';
11314                   pri->pvts[chanpos]->cid_ani[0] = '\0';
11315                   pri->pvts[chanpos]->cid_name[0] = '\0';
11316                   pri->pvts[chanpos]->cid_ton = 0;
11317                }
11318                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11319                           e->ring.redirectingnum, e->ring.callingplanrdnis);
11320                /* If immediate=yes go to s|1 */
11321                if (pri->pvts[chanpos]->immediate) {
11322                   ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11323                   pri->pvts[chanpos]->exten[0] = 's';
11324                   pri->pvts[chanpos]->exten[1] = '\0';
11325                }
11326                /* Get called number */
11327                else if (!ast_strlen_zero(e->ring.callednum)) {
11328                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11329                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11330                } else if (pri->overlapdial)
11331                   pri->pvts[chanpos]->exten[0] = '\0';
11332                else {
11333                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
11334                   pri->pvts[chanpos]->exten[0] = 's';
11335                   pri->pvts[chanpos]->exten[1] = '\0';
11336                }
11337                /* Set DNID on all incoming calls -- even immediate */
11338                if (!ast_strlen_zero(e->ring.callednum))
11339                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11340                /* No number yet, but received "sending complete"? */
11341                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11342                   ast_verb(3, "Going to extension s|1 because of Complete received\n");
11343                   pri->pvts[chanpos]->exten[0] = 's';
11344                   pri->pvts[chanpos]->exten[1] = '\0';
11345                }
11346 
11347                /* Make sure extension exists (or in overlap dial mode, can exist) */
11348                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11349                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11350                   /* Setup law */
11351                   int law;
11352                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11353                      /* Set to audio mode at this point */
11354                      law = 1;
11355                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11356                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11357                   }
11358                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11359                      law = DAHDI_LAW_ALAW;
11360                   else
11361                      law = DAHDI_LAW_MULAW;
11362                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11363                   if (res < 0) 
11364                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11365                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11366                   if (res < 0)
11367                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11368                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11369                      /* Just announce proceeding */
11370                      pri->pvts[chanpos]->proceeding = 1;
11371                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11372                   } else {
11373                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
11374                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11375                      else
11376                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11377                   }
11378                   /* Get the use_callingpres state */
11379                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11380                
11381                   /* Start PBX */
11382                   if (!e->ring.complete
11383                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
11384                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11385                      /*
11386                       * Release the PRI lock while we create the channel
11387                       * so other threads can send D channel messages.
11388                       */
11389                      ast_mutex_unlock(&pri->lock);
11390                      if (crv) {
11391                         /* Set bearer and such */
11392                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11393                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11394                         pri->pvts[chanpos]->owner = &inuse;
11395                         ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11396                      } else {
11397                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11398                      }
11399                      ast_mutex_lock(&pri->lock);
11400                      if (c) {
11401                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11402                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11403                         }
11404                         if (e->ring.ani2 >= 0) {
11405                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11406                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11407                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11408                         }
11409 
11410 #ifdef SUPPORT_USERUSER
11411                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
11412                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11413                         }
11414 #endif
11415 
11416                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11417                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11418                         if (e->ring.redirectingreason >= 0)
11419                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11420                      }
11421                      if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11422                         ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11423                            plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11424                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11425                      } else {
11426                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11427                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11428                         if (c)
11429                            ast_hangup(c);
11430                         else {
11431                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11432                            pri->pvts[chanpos]->call = NULL;
11433                         }
11434                      }
11435                   } else {
11436                      /*
11437                       * Release the PRI lock while we create the channel
11438                       * so other threads can send D channel messages.
11439                       */
11440                      ast_mutex_unlock(&pri->lock);
11441                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
11442                      ast_mutex_lock(&pri->lock);
11443                      if (c) {
11444                         /*
11445                          * It is reasonably safe to set the following
11446                          * channel variables while the PRI and DAHDI private
11447                          * structures are locked.  The PBX has not been
11448                          * started yet and it is unlikely that any other task
11449                          * will do anything with the channel we have just
11450                          * created.
11451                          */
11452                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11453                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11454                         }
11455                         if (e->ring.ani2 >= 0) {
11456                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
11457                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11458                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11459                         }
11460 
11461 #ifdef SUPPORT_USERUSER
11462                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
11463                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11464                         }
11465 #endif
11466 
11467                         if (e->ring.redirectingreason >= 0)
11468                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11469 
11470                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11471                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11472                      }
11473                      if (c && !ast_pbx_start(c)) {
11474                         ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11475                            plancallingnum, pri->pvts[chanpos]->exten,
11476                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11477 
11478                         dahdi_enable_ec(pri->pvts[chanpos]);
11479                      } else {
11480                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
11481                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11482                         if (c) {
11483                            ast_hangup(c);
11484                         } else {
11485                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11486                            pri->pvts[chanpos]->call = NULL;
11487                         }
11488                      }
11489                   }
11490                } else {
11491                   ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
11492                      pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
11493                      pri->pvts[chanpos]->prioffset, pri->span);
11494                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11495                   pri->pvts[chanpos]->call = NULL;
11496                   pri->pvts[chanpos]->exten[0] = '\0';
11497                }
11498                if (crv)
11499                   ast_mutex_unlock(&crv->lock);
11500                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11501             } else {
11502                if (e->ring.flexible)
11503                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11504                else
11505                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11506             }
11507             break;
11508          case PRI_EVENT_RINGING:
11509             chanpos = pri_find_principle(pri, e->ringing.channel);
11510             if (chanpos < 0) {
11511                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
11512                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11513             } else {
11514                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11515                if (chanpos < 0) {
11516                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
11517                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11518                } else {
11519                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11520                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11521                      dahdi_enable_ec(pri->pvts[chanpos]);
11522                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11523                      pri->pvts[chanpos]->alerting = 1;
11524                   } else
11525                      ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11526 
11527 #ifdef PRI_PROGRESS_MASK
11528                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11529 #else
11530                   if (e->ringing.progress == 8) {
11531 #endif
11532                      /* Now we can do call progress detection */
11533                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11534                         /* RINGING detection isn't required because we got ALERTING signal */
11535                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11536                         pri->pvts[chanpos]->dsp_features = 0;
11537                      }
11538                   }
11539 
11540 #ifdef SUPPORT_USERUSER
11541                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11542                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11543                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11544                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11545                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11546                   }
11547 #endif
11548 
11549                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11550                }
11551             }
11552             break;
11553          case PRI_EVENT_PROGRESS:
11554             /* Get chan value if e->e is not PRI_EVNT_RINGING */
11555             chanpos = pri_find_principle(pri, e->proceeding.channel);
11556             if (chanpos > -1) {
11557 #ifdef PRI_PROGRESS_MASK
11558                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11559 #else
11560                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11561 #endif
11562                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11563 
11564                   if (e->proceeding.cause > -1) {
11565                      ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11566 
11567                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
11568                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11569                         if (pri->pvts[chanpos]->owner) {
11570                            ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11571 
11572                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11573                            f.subclass = AST_CONTROL_BUSY;
11574                         }
11575                      }
11576                   }
11577                   
11578                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11579                   ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11580                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11581                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11582 #ifdef PRI_PROGRESS_MASK
11583                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11584 #else
11585                   if (e->proceeding.progress == 8) {
11586 #endif
11587                      /* Now we can do call progress detection */
11588                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11589                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11590                         pri->pvts[chanpos]->dsp_features = 0;
11591                      }
11592                      /* Bring voice path up */
11593                      f.subclass = AST_CONTROL_PROGRESS;
11594                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11595                   }
11596                   pri->pvts[chanpos]->progress = 1;
11597                   pri->pvts[chanpos]->dialing = 0;
11598                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11599                }
11600             }
11601             break;
11602          case PRI_EVENT_PROCEEDING:
11603             chanpos = pri_find_principle(pri, e->proceeding.channel);
11604             if (chanpos > -1) {
11605                if (!pri->pvts[chanpos]->proceeding) {
11606                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11607                   
11608                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11609                   ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11610                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11611                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11612 #ifdef PRI_PROGRESS_MASK
11613                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11614 #else
11615                   if (e->proceeding.progress == 8) {
11616 #endif
11617                      /* Now we can do call progress detection */
11618                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11619                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11620                         pri->pvts[chanpos]->dsp_features = 0;
11621                      }
11622                      /* Bring voice path up */
11623                      f.subclass = AST_CONTROL_PROGRESS;
11624                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11625                   }
11626                   pri->pvts[chanpos]->proceeding = 1;
11627                   pri->pvts[chanpos]->dialing = 0;
11628                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11629                }
11630             }
11631             break;
11632          case PRI_EVENT_FACNAME:
11633             chanpos = pri_find_principle(pri, e->facname.channel);
11634             if (chanpos < 0) {
11635                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
11636                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11637             } else {
11638                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11639                if (chanpos < 0) {
11640                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
11641                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11642                } else {
11643                   /* Re-use *69 field for PRI */
11644                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11645                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11646                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11647                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11648                   dahdi_enable_ec(pri->pvts[chanpos]);
11649                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11650                }
11651             }
11652             break;            
11653          case PRI_EVENT_ANSWER:
11654             chanpos = pri_find_principle(pri, e->answer.channel);
11655             if (chanpos < 0) {
11656                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
11657                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11658             } else {
11659                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11660                if (chanpos < 0) {
11661                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
11662                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11663                } else {
11664                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11665                   /* Now we can do call progress detection */
11666 
11667                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
11668                    * By this time, we need DTMF detection and other features that were previously disabled
11669                    * -- Matt F */
11670                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11671                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11672                      pri->pvts[chanpos]->dsp_features = 0;
11673                   }
11674                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11675                      ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11676                      x = DAHDI_START;
11677                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11678                      if (res < 0) {
11679                         if (errno != EINPROGRESS) {
11680                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11681                         }
11682                      }
11683                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11684                      pri->pvts[chanpos]->dialing = 1;
11685                      /* Send any "w" waited stuff */
11686                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11687                      if (res < 0) {
11688                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11689                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11690                      } else
11691                         ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11692 
11693                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11694                   } else if (pri->pvts[chanpos]->confirmanswer) {
11695                      ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11696                   } else {
11697                      pri->pvts[chanpos]->dialing = 0;
11698                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11699                      /* Enable echo cancellation if it's not on already */
11700                      dahdi_enable_ec(pri->pvts[chanpos]);
11701                   }
11702 
11703 #ifdef SUPPORT_USERUSER
11704                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
11705                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11706                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11707                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11708                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11709                   }
11710 #endif
11711 
11712                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11713                }
11714             }
11715             break;            
11716          case PRI_EVENT_HANGUP:
11717             chanpos = pri_find_principle(pri, e->hangup.channel);
11718             if (chanpos < 0) {
11719                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
11720                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11721             } else {
11722                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11723                if (chanpos > -1) {
11724                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11725                   if (!pri->pvts[chanpos]->alreadyhungup) {
11726                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11727                      pri->pvts[chanpos]->alreadyhungup = 1;
11728                      if (pri->pvts[chanpos]->realcall) 
11729                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11730                      else if (pri->pvts[chanpos]->owner) {
11731                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
11732                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11733                         if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11734                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11735                         else {
11736                            switch (e->hangup.cause) {
11737                            case PRI_CAUSE_USER_BUSY:
11738                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11739                               break;
11740                            case PRI_CAUSE_CALL_REJECTED:
11741                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11742                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11743                            case PRI_CAUSE_SWITCH_CONGESTION:
11744                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11745                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11746                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11747                               break;
11748                            default:
11749                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11750                            }
11751                         }
11752                      }
11753                      ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11754                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11755                   } else {
11756                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11757                      pri->pvts[chanpos]->call = NULL;
11758                   }
11759                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11760                      ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11761                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11762                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11763                      pri->pvts[chanpos]->resetting = 1;
11764                   }
11765                   if (e->hangup.aoc_units > -1)
11766                      ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11767                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11768 
11769 #ifdef SUPPORT_USERUSER
11770                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11771                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11772                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11773                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11774                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11775                   }
11776 #endif
11777 
11778                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11779                } else {
11780                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
11781                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11782                }
11783             } 
11784             break;
11785 #ifndef PRI_EVENT_HANGUP_REQ
11786 #error please update libpri
11787 #endif
11788          case PRI_EVENT_HANGUP_REQ:
11789             chanpos = pri_find_principle(pri, e->hangup.channel);
11790             if (chanpos < 0) {
11791                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
11792                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11793             } else {
11794                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11795                if (chanpos > -1) {
11796                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11797                   if (pri->pvts[chanpos]->realcall) 
11798                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11799                   else if (pri->pvts[chanpos]->owner) {
11800                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11801                      if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11802                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11803                      else {
11804                         switch (e->hangup.cause) {
11805                            case PRI_CAUSE_USER_BUSY:
11806                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11807                               break;
11808                            case PRI_CAUSE_CALL_REJECTED:
11809                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11810                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11811                            case PRI_CAUSE_SWITCH_CONGESTION:
11812                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11813                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11814                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11815                               break;
11816                            default:
11817                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11818                         }
11819                      }
11820                      ast_verb(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);
11821                      if (e->hangup.aoc_units > -1)
11822                         ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11823                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11824                   } else {
11825                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11826                      pri->pvts[chanpos]->call = NULL;
11827                   }
11828                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11829                      ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11830                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11831                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11832                      pri->pvts[chanpos]->resetting = 1;
11833                   }
11834 
11835 #ifdef SUPPORT_USERUSER
11836                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11837                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11838                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11839                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11840                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11841                   }
11842 #endif
11843 
11844                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11845                } else {
11846                   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);
11847                }
11848             } 
11849             break;
11850          case PRI_EVENT_HANGUP_ACK:
11851             chanpos = pri_find_principle(pri, e->hangup.channel);
11852             if (chanpos < 0) {
11853                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
11854                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11855             } else {
11856                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11857                if (chanpos > -1) {
11858                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11859                   pri->pvts[chanpos]->call = NULL;
11860                   pri->pvts[chanpos]->resetting = 0;
11861                   if (pri->pvts[chanpos]->owner) {
11862                      ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11863                   }
11864 
11865 #ifdef SUPPORT_USERUSER
11866                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11867                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11868                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11869                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11870                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11871                   }
11872 #endif
11873 
11874                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11875                }
11876             }
11877             break;
11878          case PRI_EVENT_CONFIG_ERR:
11879             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11880             break;
11881          case PRI_EVENT_RESTART_ACK:
11882             chanpos = pri_find_principle(pri, e->restartack.channel);
11883             if (chanpos < 0) {
11884                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11885                   channel number, so we have to figure it out...  This must be why
11886                   everybody resets exactly a channel at a time. */
11887                for (x = 0; x < pri->numchans; x++) {
11888                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
11889                      chanpos = x;
11890                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11891                      ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
11892                         pri->pvts[chanpos]->prioffset, pri->span);
11893                      if (pri->pvts[chanpos]->realcall) 
11894                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11895                      else if (pri->pvts[chanpos]->owner) {
11896                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
11897                            pri->pvts[chanpos]->prioffset, pri->span);
11898                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11899                      }
11900                      pri->pvts[chanpos]->resetting = 0;
11901                      ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11902                            pri->pvts[chanpos]->prioffset, pri->span);
11903                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11904                      if (pri->resetting)
11905                         pri_check_restart(pri);
11906                      break;
11907                   }
11908                }
11909                if (chanpos < 0) {
11910                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
11911                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11912                }
11913             } else {
11914                if (pri->pvts[chanpos]) {
11915                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11916                   if (pri->pvts[chanpos]->realcall) 
11917                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11918                   else if (pri->pvts[chanpos]->owner) {
11919                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11920                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11921                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11922                   }
11923                   pri->pvts[chanpos]->resetting = 0;
11924                   pri->pvts[chanpos]->inservice = 1;
11925                   ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11926                            pri->pvts[chanpos]->prioffset, pri->span);
11927                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11928                   if (pri->resetting)
11929                      pri_check_restart(pri);
11930                }
11931             }
11932             break;
11933          case PRI_EVENT_SETUP_ACK:
11934             chanpos = pri_find_principle(pri, e->setup_ack.channel);
11935             if (chanpos < 0) {
11936                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
11937                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11938             } else {
11939                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11940                if (chanpos > -1) {
11941                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11942                   pri->pvts[chanpos]->setup_ack = 1;
11943                   /* Send any queued digits */
11944                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11945                      ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11946                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
11947                         pri->pvts[chanpos]->dialdest[x]);
11948                   }
11949                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11950                } else
11951                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11952             }
11953             break;
11954          case PRI_EVENT_NOTIFY:
11955             chanpos = pri_find_principle(pri, e->notify.channel);
11956             if (chanpos < 0) {
11957                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11958                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11959             } else {
11960                struct ast_frame f = { AST_FRAME_CONTROL, };
11961                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11962                switch (e->notify.info) {
11963                case PRI_NOTIFY_REMOTE_HOLD:
11964                   f.subclass = AST_CONTROL_HOLD;
11965                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11966                   break;
11967                case PRI_NOTIFY_REMOTE_RETRIEVAL:
11968                   f.subclass = AST_CONTROL_UNHOLD;
11969                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11970                   break;
11971                }
11972                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11973             }
11974             break;
11975          default:
11976             ast_debug(1, "Event: %d\n", e->e);
11977          }
11978       }  
11979       ast_mutex_unlock(&pri->lock);
11980    }
11981    /* Never reached */
11982    return NULL;
11983 }
11984 
11985 static int start_pri(struct dahdi_pri *pri)
11986 {
11987    int res, x;
11988    struct dahdi_params p;
11989    struct dahdi_bufferinfo bi;
11990    struct dahdi_spaninfo si;
11991    int i;
11992    
11993    for (i = 0; i < NUM_DCHANS; i++) {
11994       if (!pri->dchannels[i])
11995          break;
11996       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11997       x = pri->dchannels[i];
11998       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11999          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12000          return -1;
12001       }
12002       memset(&p, 0, sizeof(p));
12003       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12004       if (res) {
12005          dahdi_close_pri_fd(pri, i);
12006          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12007          return -1;
12008       }
12009       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12010          dahdi_close_pri_fd(pri, i);
12011          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12012          return -1;
12013       }
12014       memset(&si, 0, sizeof(si));
12015       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12016       if (res) {
12017          dahdi_close_pri_fd(pri, i);
12018          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12019       }
12020       if (!si.alarms)
12021          pri->dchanavail[i] |= DCHAN_NOTINALARM;
12022       else
12023          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12024       memset(&bi, 0, sizeof(bi));
12025       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12026       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12027       bi.numbufs = 32;
12028       bi.bufsize = 1024;
12029       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12030          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12031          dahdi_close_pri_fd(pri, i);
12032          return -1;
12033       }
12034       switch (pri->sig) {
12035          case SIG_BRI:
12036             pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12037             break;
12038          case SIG_BRI_PTMP:
12039             pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12040             break;
12041          default:
12042             pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12043       }
12044       /* Force overlap dial if we're doing GR-303! */
12045       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12046          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12047       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12048 #ifdef HAVE_PRI_INBANDDISCONNECT
12049       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12050 #endif
12051       /* Enslave to master if appropriate */
12052       if (i)
12053          pri_enslave(pri->dchans[0], pri->dchans[i]);
12054       if (!pri->dchans[i]) {
12055          dahdi_close_pri_fd(pri, i);
12056          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12057          return -1;
12058       }
12059       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12060       pri_set_nsf(pri->dchans[i], pri->nsf);
12061 #ifdef PRI_GETSET_TIMERS
12062       for (x = 0; x < PRI_MAX_TIMERS; x++) {
12063          if (pritimers[x] != 0)
12064             pri_set_timer(pri->dchans[i], x, pritimers[x]);
12065       }
12066 #endif
12067    }
12068    /* Assume primary is the one we use */
12069    pri->pri = pri->dchans[0];
12070    pri->resetpos = -1;
12071    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12072       for (i = 0; i < NUM_DCHANS; i++) {
12073          if (!pri->dchannels[i])
12074             break;
12075          dahdi_close_pri_fd(pri, i);
12076       }
12077       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12078       return -1;
12079    }
12080    return 0;
12081 }
12082 
12083 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
12084 {
12085    int which, span;
12086    char *ret = NULL;
12087 
12088    if (pos != rpos)
12089       return ret;
12090 
12091    for (which = span = 0; span < NUM_SPANS; span++) {
12092       if (pris[span].pri && ++which > state) {
12093          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
12094             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12095          }
12096          break;
12097       }
12098    }
12099    return ret;
12100 }
12101 
12102 static char *complete_span_4(const char *line, const char *word, int pos, int state)
12103 {
12104    return complete_span_helper(line,word,pos,state,3);
12105 }
12106 
12107 static char *complete_span_5(const char *line, const char *word, int pos, int state)
12108 {
12109    return complete_span_helper(line,word,pos,state,4);
12110 }
12111 
12112 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12113 {
12114    switch (cmd) {
12115    case CLI_INIT:
12116       e->command = "pri unset debug file";
12117       e->usage = "Usage: pri unset debug file\n"
12118             "       Stop sending debug output to the previously \n"
12119                  "       specified file\n";
12120       return NULL;
12121    case CLI_GENERATE:
12122       return NULL;   
12123    }
12124    /* Assume it is unset */
12125    ast_mutex_lock(&pridebugfdlock);
12126    close(pridebugfd);
12127    pridebugfd = -1;
12128    ast_cli(a->fd, "PRI debug output to file disabled\n");
12129    ast_mutex_unlock(&pridebugfdlock);
12130    return CLI_SUCCESS;
12131 }
12132 
12133 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12134 {
12135    int myfd;
12136    switch (cmd) {
12137    case CLI_INIT:
12138       e->command = "pri set debug file";
12139       e->usage = "Usage: pri set debug file [output-file]\n"
12140             "       Sends PRI debug output to the specified output file\n";
12141       return NULL;
12142    case CLI_GENERATE:
12143       return NULL;   
12144    }
12145    if (a->argc < 5)
12146       return CLI_SHOWUSAGE;
12147 
12148    if (ast_strlen_zero(a->argv[4]))
12149       return CLI_SHOWUSAGE;
12150 
12151    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12152    if (myfd < 0) {
12153       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12154       return CLI_SUCCESS;
12155    }
12156 
12157    ast_mutex_lock(&pridebugfdlock);
12158 
12159    if (pridebugfd >= 0)
12160       close(pridebugfd);
12161 
12162    pridebugfd = myfd;
12163    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12164    ast_mutex_unlock(&pridebugfdlock);
12165    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12166    return CLI_SUCCESS;
12167 }
12168 
12169 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12170 {
12171    int span;
12172    int x;
12173    switch (cmd) {
12174    case CLI_INIT: 
12175       e->command = "pri debug span";
12176       e->usage = 
12177          "Usage: pri debug span <span>\n"
12178          "       Enables debugging on a given PRI span\n";
12179       return NULL;
12180    case CLI_GENERATE:   
12181       return complete_span_4(a->line, a->word, a->pos, a->n);
12182    }
12183    if (a->argc < 4) {
12184       return CLI_SHOWUSAGE;
12185    }
12186    span = atoi(a->argv[3]);
12187    if ((span < 1) || (span > NUM_SPANS)) {
12188       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12189       return CLI_SUCCESS;
12190    }
12191    if (!pris[span-1].pri) {
12192       ast_cli(a->fd, "No PRI running on span %d\n", span);
12193       return CLI_SUCCESS;
12194    }
12195    for (x = 0; x < NUM_DCHANS; x++) {
12196       if (pris[span-1].dchans[x])
12197          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12198                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12199                                                PRI_DEBUG_Q921_STATE);
12200    }
12201    ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12202    return CLI_SUCCESS;
12203 }
12204 
12205 
12206 
12207 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12208 {
12209    int span;
12210    int x;
12211    switch (cmd) {
12212    case CLI_INIT:
12213       e->command = "pri no debug span";
12214       e->usage = 
12215          "Usage: pri no debug span <span>\n"
12216          "       Disables debugging on a given PRI span\n";
12217       return NULL;
12218    case CLI_GENERATE:
12219       return complete_span_5(a->line, a->word, a->pos, a->n);
12220    }
12221    if (a->argc < 5)
12222       return CLI_SHOWUSAGE;
12223 
12224    span = atoi(a->argv[4]);
12225    if ((span < 1) || (span > NUM_SPANS)) {
12226       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12227       return CLI_SUCCESS;
12228    }
12229    if (!pris[span-1].pri) {
12230       ast_cli(a->fd, "No PRI running on span %d\n", span);
12231       return CLI_SUCCESS;
12232    }
12233    for (x = 0; x < NUM_DCHANS; x++) {
12234       if (pris[span-1].dchans[x])
12235          pri_set_debug(pris[span-1].dchans[x], 0);
12236    }
12237    ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12238    return CLI_SUCCESS;
12239 }
12240 
12241 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12242 {
12243    int span;
12244    int x;
12245    switch (cmd) {
12246    case CLI_INIT:
12247       e->command = "pri intensive debug span";
12248       e->usage = 
12249          "Usage: pri intensive debug span <span>\n"
12250          "       Enables debugging down to the Q.921 level\n";
12251       return NULL;
12252    case CLI_GENERATE:
12253       return complete_span_5(a->line, a->word, a->pos, a->n);
12254    }
12255 
12256    if (a->argc < 5)
12257       return CLI_SHOWUSAGE;
12258    span = atoi(a->argv[4]);
12259    if ((span < 1) || (span > NUM_SPANS)) {
12260       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12261       return CLI_SUCCESS;
12262    }
12263    if (!pris[span-1].pri) {
12264       ast_cli(a->fd, "No PRI running on span %d\n", span);
12265       return CLI_SUCCESS;
12266    }
12267    for (x = 0; x < NUM_DCHANS; x++) {
12268       if (pris[span-1].dchans[x])
12269          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12270                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12271                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12272    }
12273    ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12274    return CLI_SUCCESS;
12275 }
12276 
12277 static void build_status(char *s, size_t len, int status, int active)
12278 {
12279    if (!s || len < 1) {
12280       return;
12281    }
12282    s[0] = '\0';
12283    if (status & DCHAN_PROVISIONED)
12284       strncat(s, "Provisioned, ", len - strlen(s) - 1);
12285    if (!(status & DCHAN_NOTINALARM))
12286       strncat(s, "In Alarm, ", len - strlen(s) - 1);
12287    if (status & DCHAN_UP)
12288       strncat(s, "Up", len - strlen(s) - 1);
12289    else
12290       strncat(s, "Down", len - strlen(s) - 1);
12291    if (active)
12292       strncat(s, ", Active", len - strlen(s) - 1);
12293    else
12294       strncat(s, ", Standby", len - strlen(s) - 1);
12295    s[len - 1] = '\0';
12296 }
12297 
12298 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12299 {
12300    int span;
12301    int x;
12302    char status[256];
12303 
12304    switch (cmd) {
12305    case CLI_INIT:
12306       e->command = "pri show spans";
12307       e->usage = 
12308          "Usage: pri show spans\n"
12309          "       Displays PRI Information\n";
12310       return NULL;
12311    case CLI_GENERATE:
12312       return NULL;   
12313    }
12314 
12315    if (a->argc != 3)
12316       return CLI_SHOWUSAGE;
12317 
12318    for (span = 0; span < NUM_SPANS; span++) {
12319       if (pris[span].pri) {
12320          for (x = 0; x < NUM_DCHANS; x++) {
12321             if (pris[span].dchannels[x]) {
12322                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12323                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12324             }
12325          }
12326       }
12327    }
12328    return CLI_SUCCESS;
12329 }
12330 
12331 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12332 {
12333    int span;
12334    int x;
12335    char status[256];
12336    switch (cmd) {
12337    case CLI_INIT: 
12338       e->command = "pri show span";
12339       e->usage = 
12340          "Usage: pri show span <span>\n"
12341          "       Displays PRI Information on a given PRI span\n";
12342       return NULL;
12343    case CLI_GENERATE:
12344       return complete_span_4(a->line, a->word, a->pos, a->n);
12345    }
12346 
12347    if (a->argc < 4)
12348       return CLI_SHOWUSAGE;
12349    span = atoi(a->argv[3]);
12350    if ((span < 1) || (span > NUM_SPANS)) {
12351       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12352       return CLI_SUCCESS;
12353    }
12354    if (!pris[span-1].pri) {
12355       ast_cli(a->fd, "No PRI running on span %d\n", span);
12356       return CLI_SUCCESS;
12357    }
12358    for (x = 0; x < NUM_DCHANS; x++) {
12359       if (pris[span-1].dchannels[x]) {
12360 #ifdef PRI_DUMP_INFO_STR
12361          char *info_str = NULL;
12362 #endif
12363          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12364          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12365          ast_cli(a->fd, "Status: %s\n", status);
12366 #ifdef PRI_DUMP_INFO_STR
12367          info_str = pri_dump_info_str(pris[span-1].pri);
12368          if (info_str) {
12369             ast_cli(a->fd, "%s", info_str);
12370             ast_free(info_str);
12371          }
12372 #else
12373          pri_dump_info(pris[span-1].pri);
12374 #endif
12375          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12376       }
12377    }
12378    return CLI_SUCCESS;
12379 }
12380 
12381 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12382 {
12383    int x;
12384    int span;
12385    int count=0;
12386    int debug=0;
12387 
12388    switch (cmd) {
12389    case CLI_INIT: 
12390       e->command = "pri show debug";
12391       e->usage = 
12392          "Usage: pri show debug\n"
12393          "  Show the debug state of pri spans\n";
12394       return NULL;
12395    case CLI_GENERATE:
12396       return NULL;   
12397    }
12398 
12399    for (span = 0; span < NUM_SPANS; span++) {
12400            if (pris[span].pri) {
12401          for (x = 0; x < NUM_DCHANS; x++) {
12402             debug = 0;
12403                if (pris[span].dchans[x]) {
12404                   debug = pri_get_debug(pris[span].dchans[x]);
12405                ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
12406                count++;
12407             }
12408          }
12409       }
12410 
12411    }
12412    ast_mutex_lock(&pridebugfdlock);
12413    if (pridebugfd >= 0) 
12414       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12415    ast_mutex_unlock(&pridebugfdlock);
12416        
12417    if (!count) 
12418       ast_cli(a->fd, "No debug set or no PRI running\n");
12419    return CLI_SUCCESS;
12420 }
12421 
12422 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12423 {
12424    switch (cmd) {
12425    case CLI_INIT:
12426       e->command = "pri show version";
12427       e->usage = 
12428          "Usage: pri show version\n"
12429          "Show libpri version information\n";
12430       return NULL;
12431    case CLI_GENERATE:
12432       return NULL;
12433    }
12434 
12435    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12436 
12437    return CLI_SUCCESS;
12438 }
12439 
12440 static struct ast_cli_entry dahdi_pri_cli[] = {
12441    AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
12442    AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
12443    AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
12444    AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
12445    AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
12446    AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
12447    AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
12448    AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
12449    AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
12450 };
12451 
12452 #endif /* HAVE_PRI */
12453 
12454 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12455 {
12456    int channel;
12457    int ret;
12458    switch (cmd) {
12459    case CLI_INIT:
12460       e->command = "dahdi destroy channel";
12461       e->usage = 
12462          "Usage: dahdi destroy channel <chan num>\n"
12463          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12464       return NULL;
12465    case CLI_GENERATE:
12466       return NULL;   
12467    }
12468    if (a->argc != 4)
12469       return CLI_SHOWUSAGE;
12470    
12471    channel = atoi(a->argv[3]);
12472    ret = dahdi_destroy_channel_bynum(channel);
12473    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12474 }
12475 
12476 static void dahdi_softhangup_all(void)
12477 {
12478    struct dahdi_pvt *p;
12479 retry:
12480    ast_mutex_lock(&iflock);
12481     for (p = iflist; p; p = p->next) {
12482       ast_mutex_lock(&p->lock);
12483         if (p->owner && !p->restartpending) {
12484          if (ast_channel_trylock(p->owner)) {
12485             if (option_debug > 2)
12486                ast_verbose("Avoiding deadlock\n");
12487             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
12488             ast_mutex_unlock(&p->lock);
12489             ast_mutex_unlock(&iflock);
12490             goto retry;
12491          }
12492          if (option_debug > 2)
12493             ast_verbose("Softhanging up on %s\n", p->owner->name);
12494          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12495          p->restartpending = 1;
12496          num_restart_pending++;
12497          ast_channel_unlock(p->owner);
12498       }
12499       ast_mutex_unlock(&p->lock);
12500     }
12501    ast_mutex_unlock(&iflock);
12502 }
12503 
12504 static int setup_dahdi(int reload);
12505 static int dahdi_restart(void)
12506 {
12507 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12508    int i, j;
12509 #endif
12510    int cancel_code;
12511    struct dahdi_pvt *p;
12512 
12513    ast_mutex_lock(&restart_lock);
12514 
12515    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12516    dahdi_softhangup_all();
12517    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12518 
12519 #if defined(HAVE_PRI)
12520    for (i = 0; i < NUM_SPANS; i++) {
12521       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12522          cancel_code = pthread_cancel(pris[i].master);
12523          pthread_kill(pris[i].master, SIGURG);
12524          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12525          pthread_join(pris[i].master, NULL);
12526          ast_debug(4, "Joined thread of span %d\n", i);
12527       }
12528    }
12529 #endif
12530 
12531 #if defined(HAVE_SS7)
12532    for (i = 0; i < NUM_SPANS; i++) {
12533       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12534          cancel_code = pthread_cancel(linksets[i].master);
12535          pthread_kill(linksets[i].master, SIGURG);
12536          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12537          pthread_join(linksets[i].master, NULL);
12538          ast_debug(4, "Joined thread of span %d\n", i);
12539       }
12540     }
12541 #endif
12542 
12543    ast_mutex_lock(&monlock);
12544    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12545       cancel_code = pthread_cancel(monitor_thread);
12546       pthread_kill(monitor_thread, SIGURG);
12547       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12548       pthread_join(monitor_thread, NULL);
12549       ast_debug(4, "Joined monitor thread\n");
12550    }
12551    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12552 
12553    ast_mutex_lock(&mwi_thread_lock);
12554    while (mwi_thread_count > 0) {
12555       ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12556       ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12557    }
12558    ast_mutex_unlock(&mwi_thread_lock);
12559    ast_mutex_lock(&ss_thread_lock);
12560    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12561       int x = DAHDI_FLASH;
12562       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12563 
12564       for (p = iflist; p; p = p->next) {
12565          if (p->owner)
12566             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 */      
12567          }
12568          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12569       }
12570 
12571    /* ensure any created channels before monitor threads were stopped are hungup */
12572    dahdi_softhangup_all();
12573    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12574    destroy_all_channels();
12575    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12576 
12577    ast_mutex_unlock(&monlock);
12578 
12579 #ifdef HAVE_PRI
12580    for (i = 0; i < NUM_SPANS; i++) {
12581       for (j = 0; j < NUM_DCHANS; j++)
12582          dahdi_close_pri_fd(&(pris[i]), j);
12583    }
12584 
12585    memset(pris, 0, sizeof(pris));
12586    for (i = 0; i < NUM_SPANS; i++) {
12587       ast_mutex_init(&pris[i].lock);
12588       pris[i].offset = -1;
12589       pris[i].master = AST_PTHREADT_NULL;
12590       for (j = 0; j < NUM_DCHANS; j++)
12591          pris[i].fds[j] = -1;
12592       }
12593    pri_set_error(dahdi_pri_error);
12594    pri_set_message(dahdi_pri_message);
12595 #endif
12596 #ifdef HAVE_SS7
12597    for (i = 0; i < NUM_SPANS; i++) {
12598       for (j = 0; j < NUM_DCHANS; j++)
12599          dahdi_close_ss7_fd(&(linksets[i]), j);
12600    }
12601 
12602    memset(linksets, 0, sizeof(linksets));
12603    for (i = 0; i < NUM_SPANS; i++) {
12604       ast_mutex_init(&linksets[i].lock);
12605       linksets[i].master = AST_PTHREADT_NULL;
12606       for (j = 0; j < NUM_DCHANS; j++)
12607          linksets[i].fds[j] = -1;
12608    }
12609    ss7_set_error(dahdi_ss7_error);
12610    ss7_set_message(dahdi_ss7_message);
12611 #endif
12612 
12613    if (setup_dahdi(2) != 0) {
12614       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12615       ast_mutex_unlock(&ss_thread_lock);
12616       return 1;
12617    }
12618    ast_mutex_unlock(&ss_thread_lock);
12619    ast_mutex_unlock(&restart_lock);
12620    return 0;
12621 }
12622 
12623 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12624 {
12625    switch (cmd) {
12626    case CLI_INIT:
12627       e->command = "dahdi restart";
12628       e->usage = 
12629          "Usage: dahdi restart\n"
12630          "  Restarts the DAHDI channels: destroys them all and then\n"
12631          "  re-reads them from chan_dahdi.conf.\n"
12632          "  Note that this will STOP any running CALL on DAHDI channels.\n"
12633          "";
12634       return NULL;
12635    case CLI_GENERATE:
12636       return NULL;
12637    }
12638    if (a->argc != 2)
12639       return CLI_SHOWUSAGE;
12640 
12641    if (dahdi_restart() != 0)
12642       return CLI_FAILURE;
12643    return CLI_SUCCESS;
12644 }
12645 
12646 static int action_dahdirestart(struct mansession *s, const struct message *m)
12647 {
12648    if (dahdi_restart() != 0) {
12649       astman_send_error(s, m, "Failed rereading DAHDI configuration");
12650       return 1;
12651    }
12652    astman_send_ack(s, m, "DAHDIRestart: Success");
12653    return 0;
12654 }
12655 
12656 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12657 {
12658 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12659 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12660    unsigned int targetnum = 0;
12661    int filtertype = 0;
12662    struct dahdi_pvt *tmp = NULL;
12663    char tmps[20] = "";
12664    char statestr[20] = "";
12665    char blockstr[20] = "";
12666    ast_mutex_t *lock;
12667    struct dahdi_pvt *start;
12668 #ifdef HAVE_PRI
12669    int trunkgroup;
12670    struct dahdi_pri *pri = NULL;
12671    int x;
12672 #endif
12673    switch (cmd) {
12674    case CLI_INIT:
12675       e->command = "dahdi show channels [trunkgroup|group|context]";
12676       e->usage = 
12677          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12678          "  Shows a list of available channels with optional filtering\n"
12679          "  <group> must be a number between 0 and 63\n";
12680       return NULL;
12681    case CLI_GENERATE:
12682       return NULL;   
12683    }
12684 
12685    lock = &iflock;
12686    start = iflist;
12687 
12688    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12689 
12690    if (!((a->argc == 3) || (a->argc == 5)))
12691       return CLI_SHOWUSAGE;
12692 
12693    if (a->argc == 5) {
12694 #ifdef HAVE_PRI
12695       if (!strcasecmp(a->argv[3], "trunkgroup")) {
12696          /* this option requires no special handling, so leave filtertype to zero */
12697          if ((trunkgroup = atoi(a->argv[4])) < 1)
12698             return CLI_SHOWUSAGE;
12699          for (x = 0; x < NUM_SPANS; x++) {
12700             if (pris[x].trunkgroup == trunkgroup) {
12701                pri = pris + x;
12702                break;
12703             }
12704          }
12705          if (pri) {
12706             start = pri->crvs;
12707             lock = &pri->lock;
12708          } else {
12709             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12710             return CLI_FAILURE;
12711          }
12712       } else
12713 #endif   
12714       if (!strcasecmp(a->argv[3], "group")) {
12715          targetnum = atoi(a->argv[4]);
12716          if ((targetnum < 0) || (targetnum > 63))
12717             return CLI_SHOWUSAGE;
12718          targetnum = 1 << targetnum;
12719          filtertype = 1;
12720       } else if (!strcasecmp(a->argv[3], "context")) {
12721          filtertype = 2;
12722       }
12723    }
12724 
12725    ast_mutex_lock(lock);
12726 #ifdef HAVE_PRI
12727    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12728 #else
12729    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12730 #endif   
12731    
12732    tmp = start;
12733    while (tmp) {
12734       if (filtertype) {
12735          switch(filtertype) {
12736          case 1: /* dahdi show channels group <group> */
12737             if (!(tmp->group & targetnum)) {
12738                tmp = tmp->next;
12739                continue;
12740             }
12741             break;
12742          case 2: /* dahdi show channels context <context> */
12743             if (strcasecmp(tmp->context, a->argv[4])) {
12744                tmp = tmp->next;
12745                continue;
12746             }
12747             break;
12748          default:
12749             ;
12750          }
12751       }
12752       if (tmp->channel > 0) {
12753          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12754       } else
12755          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12756 
12757       if (tmp->locallyblocked)
12758          blockstr[0] = 'L';
12759       else
12760          blockstr[0] = ' ';
12761 
12762       if (tmp->remotelyblocked)
12763          blockstr[1] = 'R';
12764       else
12765          blockstr[1] = ' ';
12766 
12767       blockstr[2] = '\0';
12768 
12769       snprintf(statestr, sizeof(statestr), "%s", "In Service");
12770 
12771       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12772       tmp = tmp->next;
12773    }
12774    ast_mutex_unlock(lock);
12775    return CLI_SUCCESS;
12776 #undef FORMAT
12777 #undef FORMAT2
12778 }
12779 
12780 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12781 {
12782    int channel;
12783    struct dahdi_pvt *tmp = NULL;
12784    struct dahdi_confinfo ci;
12785    struct dahdi_params ps;
12786    int x;
12787    ast_mutex_t *lock;
12788    struct dahdi_pvt *start;
12789 #ifdef HAVE_PRI
12790    char *c;
12791    int trunkgroup;
12792    struct dahdi_pri *pri=NULL;
12793 #endif
12794    switch (cmd) {
12795    case CLI_INIT:
12796       e->command = "dahdi show channel";
12797       e->usage = 
12798          "Usage: dahdi show channel <chan num>\n"
12799          "  Detailed information about a given channel\n";
12800       return NULL;
12801    case CLI_GENERATE:
12802       return NULL;   
12803    }
12804 
12805    lock = &iflock;
12806    start = iflist;
12807 
12808    if (a->argc != 4)
12809       return CLI_SHOWUSAGE;
12810 #ifdef HAVE_PRI
12811    if ((c = strchr(a->argv[3], ':'))) {
12812       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12813          return CLI_SHOWUSAGE;
12814       if ((trunkgroup < 1) || (channel < 1))
12815          return CLI_SHOWUSAGE;
12816       for (x = 0; x < NUM_SPANS; x++) {
12817          if (pris[x].trunkgroup == trunkgroup) {
12818             pri = pris + x;
12819             break;
12820          }
12821       }
12822       if (pri) {
12823          start = pri->crvs;
12824          lock = &pri->lock;
12825       } else {
12826          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12827          return CLI_FAILURE;
12828       }
12829    } else
12830 #endif
12831       channel = atoi(a->argv[3]);
12832 
12833    ast_mutex_lock(lock);
12834    tmp = start;
12835    while (tmp) {
12836       if (tmp->channel == channel) {
12837 #ifdef HAVE_PRI
12838          if (pri) 
12839             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12840          else
12841 #endif         
12842          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12843          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12844          ast_cli(a->fd, "Span: %d\n", tmp->span);
12845          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12846          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12847          ast_cli(a->fd, "Context: %s\n", tmp->context);
12848          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12849          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12850          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12851          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12852          if (tmp->vars) {
12853             struct ast_variable *v;
12854             ast_cli(a->fd, "Variables:\n");
12855             for (v = tmp->vars ; v ; v = v->next)
12856                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
12857          }
12858          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12859          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12860          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12861          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12862          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12863          ast_cli(a->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)" : "");
12864          ast_cli(a->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)" : "");
12865          ast_cli(a->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)" : "");
12866          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12867          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12868          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12869          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12870          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12871          if (tmp->busydetect) {
12872 #if defined(BUSYDETECT_TONEONLY)
12873             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12874 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12875             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12876 #endif
12877 #ifdef BUSYDETECT_DEBUG
12878             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
12879 #endif
12880             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
12881             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
12882          }
12883          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12884          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12885          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12886          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12887          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12888          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12889          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12890          ast_cli(a->fd, "Echo Cancellation:\n");
12891 
12892          if (tmp->echocancel.head.tap_length) {
12893             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12894             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12895                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12896             }
12897             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12898          } else {
12899             ast_cli(a->fd, "\tnone\n");
12900          }
12901          if (tmp->master)
12902             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12903          for (x = 0; x < MAX_SLAVES; x++) {
12904             if (tmp->slaves[x])
12905                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12906          }
12907 #ifdef HAVE_SS7
12908          if (tmp->ss7) {
12909             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12910          }
12911 #endif
12912 #ifdef HAVE_PRI
12913          if (tmp->pri) {
12914             ast_cli(a->fd, "PRI Flags: ");
12915             if (tmp->resetting)
12916                ast_cli(a->fd, "Resetting ");
12917             if (tmp->call)
12918                ast_cli(a->fd, "Call ");
12919             if (tmp->bearer)
12920                ast_cli(a->fd, "Bearer ");
12921             ast_cli(a->fd, "\n");
12922             if (tmp->logicalspan) 
12923                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12924             else
12925                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12926          }
12927             
12928 #endif
12929          memset(&ci, 0, sizeof(ci));
12930          ps.channo = tmp->channel;
12931          if (tmp->subs[SUB_REAL].dfd > -1) {
12932             memset(&ci, 0, sizeof(ci));
12933             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12934                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12935             }
12936             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12937                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12938             }
12939             memset(&ps, 0, sizeof(ps));
12940             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12941                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12942             } else {
12943                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12944             }
12945          }
12946          ast_mutex_unlock(lock);
12947          return CLI_SUCCESS;
12948       }
12949       tmp = tmp->next;
12950    }
12951    
12952    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12953    ast_mutex_unlock(lock);
12954    return CLI_FAILURE;
12955 }
12956 
12957 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12958 {
12959    int i, j;
12960    switch (cmd) {
12961    case CLI_INIT:
12962       e->command = "dahdi show cadences";
12963       e->usage = 
12964          "Usage: dahdi show cadences\n"
12965          "       Shows all cadences currently defined\n";
12966       return NULL;
12967    case CLI_GENERATE:
12968       return NULL;   
12969    }
12970    for (i = 0; i < num_cadence; i++) {
12971       char output[1024];
12972       char tmp[16], tmp2[64];
12973       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12974       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12975 
12976       for (j = 0; j < 16; j++) {
12977          if (cadences[i].ringcadence[j] == 0)
12978             break;
12979          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12980          if (cidrings[i] * 2 - 1 == j)
12981             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12982          else
12983             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12984          if (j != 0)
12985             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12986          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12987       }
12988       ast_cli(a->fd,"%s\n",output);
12989    }
12990    return CLI_SUCCESS;
12991 }
12992 
12993 /* Based on irqmiss.c */
12994 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) 
12995 {
12996    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12997    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12998    int span;
12999    int res;
13000    char alarmstr[50];
13001 
13002    int ctl;
13003    struct dahdi_spaninfo s;
13004 
13005    switch (cmd) {
13006    case CLI_INIT:
13007       e->command = "dahdi show status";
13008       e->usage = 
13009          "Usage: dahdi show status\n"
13010          "       Shows a list of DAHDI cards with status\n";
13011       return NULL;
13012    case CLI_GENERATE:
13013       return NULL;   
13014    }
13015    ctl = open("/dev/dahdi/ctl", O_RDWR);
13016    if (ctl < 0) {
13017       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13018       return CLI_FAILURE;
13019    }
13020    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13021 
13022    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13023       s.spanno = span;
13024       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13025       if (res) {
13026          continue;
13027       }
13028       alarmstr[0] = '\0';
13029       if (s.alarms > 0) {
13030          if (s.alarms & DAHDI_ALARM_BLUE)
13031             strcat(alarmstr, "BLU/");
13032          if (s.alarms & DAHDI_ALARM_YELLOW)
13033             strcat(alarmstr, "YEL/");
13034          if (s.alarms & DAHDI_ALARM_RED)
13035             strcat(alarmstr, "RED/");
13036          if (s.alarms & DAHDI_ALARM_LOOPBACK)
13037             strcat(alarmstr, "LB/");
13038          if (s.alarms & DAHDI_ALARM_RECOVER)
13039             strcat(alarmstr, "REC/");
13040          if (s.alarms & DAHDI_ALARM_NOTOPEN)
13041             strcat(alarmstr, "NOP/");
13042          if (!strlen(alarmstr))
13043             strcat(alarmstr, "UUU/");
13044          if (strlen(alarmstr)) {
13045             /* Strip trailing / */
13046             alarmstr[strlen(alarmstr) - 1] = '\0';
13047          }
13048       } else {
13049          if (s.numchans)
13050             strcpy(alarmstr, "OK");
13051          else
13052             strcpy(alarmstr, "UNCONFIGURED");
13053       }
13054 
13055       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13056             , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13057               s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13058               s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13059               "CAS"
13060             , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13061               s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13062               s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13063               "Unk"
13064             , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13065               s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13066             , lbostr[s.lbo]
13067          );
13068    }
13069    close(ctl);
13070 
13071    return CLI_SUCCESS;
13072 #undef FORMAT
13073 #undef FORMAT2
13074 }
13075 
13076 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13077 {
13078    int pseudo_fd = -1;
13079    struct dahdi_versioninfo vi;
13080 
13081    switch (cmd) {
13082    case CLI_INIT:
13083       e->command = "dahdi show version";
13084       e->usage = 
13085          "Usage: dahdi show version\n"
13086          "       Shows the DAHDI version in use\n";
13087       return NULL;
13088    case CLI_GENERATE:
13089       return NULL;
13090    }
13091    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13092       ast_cli(a->fd, "Failed to open control file to get version.\n");
13093       return CLI_SUCCESS;
13094    }
13095 
13096    strcpy(vi.version, "Unknown");
13097    strcpy(vi.echo_canceller, "Unknown");
13098 
13099    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13100       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13101    else
13102       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13103 
13104    close(pseudo_fd);
13105 
13106    return CLI_SUCCESS;
13107 }
13108 
13109 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13110 {
13111    int channel;
13112    int gain;
13113    int tx;
13114    struct dahdi_hwgain hwgain;
13115    struct dahdi_pvt *tmp = NULL;
13116 
13117    switch (cmd) {
13118    case CLI_INIT:
13119       e->command = "dahdi set hwgain";
13120       e->usage = 
13121          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13122          "  Sets the hardware gain on a a given channel, overriding the\n"
13123          "   value provided at module loadtime, whether the channel is in\n"
13124          "   use or not.  Changes take effect immediately.\n"
13125          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13126          "   <chan num> is the channel number relative to the device\n"
13127          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13128       return NULL;
13129    case CLI_GENERATE:
13130       return NULL;   
13131    }
13132 
13133    if (a->argc != 6)
13134       return CLI_SHOWUSAGE;
13135    
13136    if (!strcasecmp("rx", a->argv[3]))
13137       tx = 0; /* rx */
13138    else if (!strcasecmp("tx", a->argv[3]))
13139       tx = 1; /* tx */
13140    else
13141       return CLI_SHOWUSAGE;
13142 
13143    channel = atoi(a->argv[4]);
13144    gain = atof(a->argv[5])*10.0;
13145 
13146    ast_mutex_lock(&iflock);
13147 
13148    for (tmp = iflist; tmp; tmp = tmp->next) {
13149 
13150       if (tmp->channel != channel)
13151          continue;
13152 
13153       if (tmp->subs[SUB_REAL].dfd == -1)
13154          break;
13155 
13156       hwgain.newgain = gain;
13157       hwgain.tx = tx;
13158       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13159          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13160          ast_mutex_unlock(&iflock);
13161          return CLI_FAILURE;
13162       }
13163       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13164          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13165       break;
13166    }
13167 
13168    ast_mutex_unlock(&iflock);
13169 
13170    if (tmp)
13171       return CLI_SUCCESS;
13172 
13173    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13174    return CLI_FAILURE;
13175 
13176 }
13177 
13178 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13179 {
13180    int channel;
13181    float gain;
13182    int tx;
13183    int res;
13184    ast_mutex_t *lock;
13185    struct dahdi_pvt *tmp = NULL;
13186 
13187    switch (cmd) {
13188    case CLI_INIT:
13189       e->command = "dahdi set swgain";
13190       e->usage = 
13191          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13192          "  Sets the software gain on a a given channel, overriding the\n"
13193          "   value provided at module loadtime, whether the channel is in\n"
13194          "   use or not.  Changes take effect immediately.\n"
13195          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13196          "   <chan num> is the channel number relative to the device\n"
13197          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13198       return NULL;
13199    case CLI_GENERATE:
13200       return NULL;   
13201    }
13202 
13203    lock = &iflock;
13204 
13205    if (a->argc != 6)
13206       return CLI_SHOWUSAGE;
13207    
13208    if (!strcasecmp("rx", a->argv[3]))
13209       tx = 0; /* rx */
13210    else if (!strcasecmp("tx", a->argv[3]))
13211       tx = 1; /* tx */
13212    else
13213       return CLI_SHOWUSAGE;
13214 
13215    channel = atoi(a->argv[4]);
13216    gain = atof(a->argv[5]);
13217 
13218    ast_mutex_lock(lock);
13219    for (tmp = iflist; tmp; tmp = tmp->next) {
13220 
13221       if (tmp->channel != channel)
13222          continue;
13223 
13224       if (tmp->subs[SUB_REAL].dfd == -1)
13225          break;
13226 
13227       if (tx)
13228          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13229       else
13230          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13231 
13232       if (res) {
13233          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13234          ast_mutex_unlock(lock);
13235          return CLI_FAILURE;
13236       }
13237 
13238       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13239          tx ? "tx" : "rx", gain, channel);
13240       break;
13241    }
13242    ast_mutex_unlock(lock);
13243 
13244    if (tmp)
13245       return CLI_SUCCESS;
13246 
13247    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13248    return CLI_FAILURE;
13249 
13250 }
13251 
13252 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13253 {
13254    int channel;
13255    int on;
13256    struct dahdi_pvt *dahdi_chan = NULL;
13257 
13258    switch (cmd) {
13259    case CLI_INIT:
13260       e->command = "dahdi set dnd";
13261       e->usage = 
13262          "Usage: dahdi set dnd <chan#> <on|off>\n"
13263          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13264          "  Changes take effect immediately.\n"
13265          "  <chan num> is the channel number\n"
13266          "  <on|off> Enable or disable DND mode?\n"
13267          ;
13268       return NULL;
13269    case CLI_GENERATE:
13270       return NULL;   
13271    }
13272 
13273    if (a->argc != 5)
13274       return CLI_SHOWUSAGE;
13275 
13276    if ((channel = atoi(a->argv[3])) <= 0) {
13277       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13278       return CLI_SHOWUSAGE;
13279    }
13280    
13281    if (ast_true(a->argv[4]))
13282       on = 1;
13283    else if (ast_false(a->argv[4]))
13284       on = 0;
13285    else {
13286       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13287       return CLI_SHOWUSAGE;
13288    }
13289 
13290    ast_mutex_lock(&iflock);
13291    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13292       if (dahdi_chan->channel != channel)
13293          continue;
13294 
13295       /* Found the channel. Actually set it */
13296       dahdi_dnd(dahdi_chan, on);
13297       break;
13298    }
13299    ast_mutex_unlock(&iflock);
13300 
13301    if (!dahdi_chan) {
13302       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13303       return CLI_FAILURE;
13304    }
13305 
13306    return CLI_SUCCESS;
13307 }
13308 
13309 static struct ast_cli_entry dahdi_cli[] = {
13310    AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
13311    AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
13312    AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
13313    AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
13314    AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
13315    AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
13316    AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
13317    AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
13318    AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
13319    AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
13320 };
13321 
13322 #define TRANSFER  0
13323 #define HANGUP    1
13324 
13325 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
13326 {
13327    if (p) {
13328       switch (mode) {
13329          case TRANSFER:
13330             p->fake_event = DAHDI_EVENT_WINKFLASH;
13331             break;
13332          case HANGUP:
13333             p->fake_event = DAHDI_EVENT_ONHOOK;
13334             break;
13335          default:
13336             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
13337       }
13338    }
13339    return 0;
13340 }
13341 static struct dahdi_pvt *find_channel(int channel)
13342 {
13343    struct dahdi_pvt *p = iflist;
13344    while (p) {
13345       if (p->channel == channel) {
13346          break;
13347       }
13348       p = p->next;
13349    }
13350    return p;
13351 }
13352 
13353 static int action_dahdidndon(struct mansession *s, const struct message *m)
13354 {
13355    struct dahdi_pvt *p = NULL;
13356    const char *channel = astman_get_header(m, "DAHDIChannel");
13357 
13358    if (ast_strlen_zero(channel)) {
13359       astman_send_error(s, m, "No channel specified");
13360       return 0;
13361    }
13362    p = find_channel(atoi(channel));
13363    if (!p) {
13364       astman_send_error(s, m, "No such channel");
13365       return 0;
13366    }
13367    p->dnd = 1;
13368    astman_send_ack(s, m, "DND Enabled");
13369    return 0;
13370 }
13371 
13372 static int action_dahdidndoff(struct mansession *s, const struct message *m)
13373 {
13374    struct dahdi_pvt *p = NULL;
13375    const char *channel = astman_get_header(m, "DAHDIChannel");
13376 
13377    if (ast_strlen_zero(channel)) {
13378       astman_send_error(s, m, "No channel specified");
13379       return 0;
13380    }
13381    p = find_channel(atoi(channel));
13382    if (!p) {
13383       astman_send_error(s, m, "No such channel");
13384       return 0;
13385    }
13386    p->dnd = 0;
13387    astman_send_ack(s, m, "DND Disabled");
13388    return 0;
13389 }
13390 
13391 static int action_transfer(struct mansession *s, const struct message *m)
13392 {
13393    struct dahdi_pvt *p = NULL;
13394    const char *channel = astman_get_header(m, "DAHDIChannel");
13395 
13396    if (ast_strlen_zero(channel)) {
13397       astman_send_error(s, m, "No channel specified");
13398       return 0;
13399    }
13400    p = find_channel(atoi(channel));
13401    if (!p) {
13402       astman_send_error(s, m, "No such channel");
13403       return 0;
13404    }
13405    dahdi_fake_event(p,TRANSFER);
13406    astman_send_ack(s, m, "DAHDITransfer");
13407    return 0;
13408 }
13409 
13410 static int action_transferhangup(struct mansession *s, const struct message *m)
13411 {
13412    struct dahdi_pvt *p = NULL;
13413    const char *channel = astman_get_header(m, "DAHDIChannel");
13414 
13415    if (ast_strlen_zero(channel)) {
13416       astman_send_error(s, m, "No channel specified");
13417       return 0;
13418    }
13419    p = find_channel(atoi(channel));
13420    if (!p) {
13421       astman_send_error(s, m, "No such channel");
13422       return 0;
13423    }
13424    dahdi_fake_event(p,HANGUP);
13425    astman_send_ack(s, m, "DAHDIHangup");
13426    return 0;
13427 }
13428 
13429 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
13430 {
13431    struct dahdi_pvt *p = NULL;
13432    const char *channel = astman_get_header(m, "DAHDIChannel");
13433    const char *number = astman_get_header(m, "Number");
13434    int i;
13435 
13436    if (ast_strlen_zero(channel)) {
13437       astman_send_error(s, m, "No channel specified");
13438       return 0;
13439    }
13440    if (ast_strlen_zero(number)) {
13441       astman_send_error(s, m, "No number specified");
13442       return 0;
13443    }
13444    p = find_channel(atoi(channel));
13445    if (!p) {
13446       astman_send_error(s, m, "No such channel");
13447       return 0;
13448    }
13449    if (!p->owner) {
13450       astman_send_error(s, m, "Channel does not have it's owner");
13451       return 0;
13452    }
13453    for (i = 0; i < strlen(number); i++) {
13454       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13455       dahdi_queue_frame(p, &f, NULL); 
13456    }
13457    astman_send_ack(s, m, "DAHDIDialOffhook");
13458    return 0;
13459 }
13460 
13461 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
13462 {
13463    struct dahdi_pvt *tmp = NULL;
13464    const char *id = astman_get_header(m, "ActionID");
13465    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13466    char idText[256] = "";
13467    int channels = 0;
13468    int dahdichanquery = -1;
13469    if (!ast_strlen_zero(dahdichannel)) {
13470       dahdichanquery = atoi(dahdichannel);
13471    }
13472 
13473    astman_send_ack(s, m, "DAHDI channel status will follow");
13474    if (!ast_strlen_zero(id))
13475       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13476 
13477    ast_mutex_lock(&iflock);
13478    
13479    tmp = iflist;
13480    while (tmp) {
13481       if (tmp->channel > 0) {
13482          int alm = get_alarms(tmp);
13483 
13484          /* If a specific channel is queried for, only deliver status for that channel */
13485          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13486             continue;
13487 
13488          channels++;
13489          if (tmp->owner) {
13490             /* Add data if we have a current call */
13491             astman_append(s,
13492                "Event: DAHDIShowChannels\r\n"
13493                "DAHDIChannel: %d\r\n"
13494                "Channel: %s\r\n"
13495                "Uniqueid: %s\r\n"
13496                "AccountCode: %s\r\n"
13497                "Signalling: %s\r\n"
13498                "SignallingCode: %d\r\n"
13499                "Context: %s\r\n"
13500                "DND: %s\r\n"
13501                "Alarm: %s\r\n"
13502                "%s"
13503                "\r\n",
13504                tmp->channel, 
13505                tmp->owner->name,
13506                tmp->owner->uniqueid,
13507                tmp->owner->accountcode,
13508                sig2str(tmp->sig), 
13509                tmp->sig,
13510                tmp->context, 
13511                tmp->dnd ? "Enabled" : "Disabled",
13512                alarm2str(alm), idText);
13513          } else {
13514             astman_append(s,
13515                "Event: DAHDIShowChannels\r\n"
13516                "DAHDIChannel: %d\r\n"
13517                "Signalling: %s\r\n"
13518                "SignallingCode: %d\r\n"
13519                "Context: %s\r\n"
13520                "DND: %s\r\n"
13521                "Alarm: %s\r\n"
13522                "%s"
13523                "\r\n",
13524                tmp->channel, sig2str(tmp->sig), tmp->sig, 
13525                tmp->context, 
13526                tmp->dnd ? "Enabled" : "Disabled",
13527                alarm2str(alm), idText);
13528          }
13529       } 
13530 
13531       tmp = tmp->next;
13532    }
13533 
13534    ast_mutex_unlock(&iflock);
13535    
13536    astman_append(s, 
13537       "Event: DAHDIShowChannelsComplete\r\n"
13538       "%s"
13539       "Items: %d\r\n"
13540       "\r\n", 
13541       idText,
13542       channels);
13543    return 0;
13544 }
13545 
13546 #ifdef HAVE_SS7
13547 static int linkset_addsigchan(int sigchan)
13548 {
13549    struct dahdi_ss7 *link;
13550    int res;
13551    int curfd;
13552    struct dahdi_params p;
13553    struct dahdi_bufferinfo bi;
13554    struct dahdi_spaninfo si;
13555 
13556 
13557    link = ss7_resolve_linkset(cur_linkset);
13558    if (!link) {
13559       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
13560       return -1;
13561    }
13562 
13563    if (cur_ss7type < 0) {
13564       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13565       return -1;
13566    }
13567 
13568    if (!link->ss7)
13569       link->ss7 = ss7_new(cur_ss7type);
13570 
13571    if (!link->ss7) {
13572       ast_log(LOG_ERROR, "Can't create new SS7!\n");
13573       return -1;
13574    }
13575 
13576    link->type = cur_ss7type;
13577 
13578    if (cur_pointcode < 0) {
13579       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13580       return -1;
13581    } else
13582       ss7_set_pc(link->ss7, cur_pointcode);
13583 
13584    if (sigchan < 0) {
13585       ast_log(LOG_ERROR, "Invalid sigchan!\n");
13586       return -1;
13587    } else {
13588       if (link->numsigchans >= NUM_DCHANS) {
13589          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13590          return -1;
13591       }
13592       curfd = link->numsigchans;
13593 
13594       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13595       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13596          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13597          return -1;
13598       }
13599       memset(&p, 0, sizeof(p));
13600       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13601       if (res) {
13602          dahdi_close_ss7_fd(link, curfd);
13603          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13604          return -1;
13605       }
13606       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13607          dahdi_close_ss7_fd(link, curfd);
13608          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13609          return -1;
13610       }
13611 
13612       memset(&bi, 0, sizeof(bi));
13613       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13614       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13615       bi.numbufs = 32;
13616       bi.bufsize = 512;
13617 
13618       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13619          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13620          dahdi_close_ss7_fd(link, curfd);
13621          return -1;
13622       }
13623 
13624       if (p.sigtype == DAHDI_SIG_MTP2)
13625          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13626       else
13627          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13628 
13629       link->numsigchans++;
13630 
13631       memset(&si, 0, sizeof(si));
13632       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13633       if (res) {
13634          dahdi_close_ss7_fd(link, curfd);
13635          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13636       }
13637 
13638       if (!si.alarms) {
13639          link->linkstate[curfd] = LINKSTATE_DOWN;
13640          ss7_link_noalarm(link->ss7, link->fds[curfd]);
13641       } else {
13642          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13643          ss7_link_alarm(link->ss7, link->fds[curfd]);
13644       }
13645    }
13646 
13647    if (cur_adjpointcode < 0) {
13648       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13649       return -1;
13650    } else {
13651       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13652    }
13653 
13654    if (cur_defaultdpc < 0) {
13655       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13656       return -1;
13657    }
13658 
13659    if (cur_networkindicator < 0) {
13660       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13661       return -1;
13662    } else
13663       ss7_set_network_ind(link->ss7, cur_networkindicator);
13664 
13665    return 0;
13666 }
13667 
13668 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13669 {
13670    int span;
13671    switch (cmd) {
13672    case CLI_INIT:
13673       e->command = "ss7 no debug linkset";
13674       e->usage = 
13675          "Usage: ss7 no debug linkset <span>\n"
13676          "       Disables debugging on a given SS7 linkset\n";
13677       return NULL;
13678    case CLI_GENERATE:
13679       return NULL;
13680    }
13681    if (a->argc < 5)
13682       return CLI_SHOWUSAGE;
13683    span = atoi(a->argv[4]);
13684    if ((span < 1) || (span > NUM_SPANS)) {
13685       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13686       return CLI_SUCCESS;
13687    }
13688    if (!linksets[span-1].ss7) {
13689       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13690       return CLI_SUCCESS;
13691    }
13692    if (linksets[span-1].ss7)
13693       ss7_set_debug(linksets[span-1].ss7, 0);
13694 
13695    ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13696    return CLI_SUCCESS;
13697 }
13698 
13699 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13700 {
13701    int span;
13702    switch (cmd) {
13703    case CLI_INIT:
13704       e->command = "ss7 debug linkset";
13705       e->usage = 
13706          "Usage: ss7 debug linkset <linkset>\n"
13707          "       Enables debugging on a given SS7 linkset\n";
13708       return NULL;
13709    case CLI_GENERATE:
13710       return NULL;
13711    }
13712    if (a->argc < 4)
13713       return CLI_SHOWUSAGE;
13714    span = atoi(a->argv[3]);
13715    if ((span < 1) || (span > NUM_SPANS)) {
13716       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13717       return CLI_SUCCESS;
13718    }
13719    if (!linksets[span-1].ss7) {
13720       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13721       return CLI_SUCCESS;
13722    }
13723    if (linksets[span-1].ss7)
13724       ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13725 
13726    ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13727    return CLI_SUCCESS;
13728 }
13729 
13730 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13731 {
13732    int linkset, cic;
13733    int blocked = -1, i;
13734    switch (cmd) {
13735    case CLI_INIT:
13736       e->command = "ss7 block cic";
13737       e->usage = 
13738          "Usage: ss7 block cic <linkset> <CIC>\n"
13739          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
13740       return NULL;
13741    case CLI_GENERATE:
13742       return NULL;
13743    }
13744    if (a->argc == 5)
13745       linkset = atoi(a->argv[3]);
13746    else
13747       return CLI_SHOWUSAGE;
13748 
13749    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13750       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13751       return CLI_SUCCESS;
13752    }
13753 
13754    if (!linksets[linkset-1].ss7) {
13755       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13756       return CLI_SUCCESS;
13757    }
13758 
13759    cic = atoi(a->argv[4]);
13760 
13761    if (cic < 1) {
13762       ast_cli(a->fd, "Invalid CIC specified!\n");
13763       return CLI_SUCCESS;
13764    }
13765 
13766    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13767       if (linksets[linkset-1].pvts[i]->cic == cic) {
13768          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13769          if (!blocked) {
13770             ast_mutex_lock(&linksets[linkset-1].lock);
13771             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13772             ast_mutex_unlock(&linksets[linkset-1].lock);
13773          }
13774       }
13775    }
13776 
13777    if (blocked < 0) {
13778       ast_cli(a->fd, "Invalid CIC specified!\n");
13779       return CLI_SUCCESS;
13780    }
13781 
13782    if (!blocked)
13783       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13784    else
13785       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13786 
13787    /* Break poll on the linkset so it sends our messages */
13788    pthread_kill(linksets[linkset-1].master, SIGURG);
13789 
13790    return CLI_SUCCESS;
13791 }
13792 
13793 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13794 {
13795    int linkset;
13796    int i;
13797    switch (cmd) {
13798    case CLI_INIT:
13799       e->command = "ss7 block linkset";
13800       e->usage = 
13801          "Usage: ss7 block linkset <linkset number>\n"
13802          "       Sends a remote blocking request for all CICs on the given linkset\n";
13803       return NULL;
13804    case CLI_GENERATE:
13805       return NULL;
13806    }
13807    if (a->argc == 4)
13808       linkset = atoi(a->argv[3]);
13809    else
13810       return CLI_SHOWUSAGE;
13811 
13812    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13813       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13814       return CLI_SUCCESS;
13815    }
13816 
13817    if (!linksets[linkset-1].ss7) {
13818       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13819       return CLI_SUCCESS;
13820    }
13821 
13822    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13823       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13824       ast_mutex_lock(&linksets[linkset-1].lock);
13825       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13826       ast_mutex_unlock(&linksets[linkset-1].lock);
13827    }
13828 
13829    /* Break poll on the linkset so it sends our messages */
13830    pthread_kill(linksets[linkset-1].master, SIGURG);
13831 
13832    return CLI_SUCCESS;
13833 }
13834 
13835 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13836 {
13837    int linkset, cic;
13838    int i, blocked = -1;
13839    switch (cmd) {
13840    case CLI_INIT:
13841       e->command = "ss7 unblock cic";
13842       e->usage = 
13843          "Usage: ss7 unblock cic <linkset> <CIC>\n"
13844          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
13845       return NULL;
13846    case CLI_GENERATE:
13847       return NULL;
13848    }
13849 
13850    if (a->argc == 5)
13851       linkset = atoi(a->argv[3]);
13852    else
13853       return CLI_SHOWUSAGE;
13854 
13855    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13856       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13857       return CLI_SUCCESS;
13858    }
13859 
13860    if (!linksets[linkset-1].ss7) {
13861       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13862       return CLI_SUCCESS;
13863    }
13864 
13865    cic = atoi(a->argv[4]);
13866 
13867    if (cic < 1) {
13868       ast_cli(a->fd, "Invalid CIC specified!\n");
13869       return CLI_SUCCESS;
13870    }
13871 
13872    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13873       if (linksets[linkset-1].pvts[i]->cic == cic) {
13874          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13875          if (blocked) {
13876             ast_mutex_lock(&linksets[linkset-1].lock);
13877             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13878             ast_mutex_unlock(&linksets[linkset-1].lock);
13879          }
13880       }
13881    }
13882 
13883    if (blocked > 0)
13884       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13885 
13886    /* Break poll on the linkset so it sends our messages */
13887    pthread_kill(linksets[linkset-1].master, SIGURG);
13888 
13889    return CLI_SUCCESS;
13890 }
13891 
13892 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13893 {
13894    int linkset;
13895    int i;
13896    switch (cmd) {
13897    case CLI_INIT:
13898       e->command = "ss7 unblock linkset";
13899       e->usage = 
13900          "Usage: ss7 unblock linkset <linkset number>\n"
13901          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
13902       return NULL;
13903    case CLI_GENERATE:
13904       return NULL;
13905    }
13906 
13907    if (a->argc == 4)
13908       linkset = atoi(a->argv[3]);
13909    else
13910       return CLI_SHOWUSAGE;
13911 
13912    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13913       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13914       return CLI_SUCCESS;
13915    }
13916 
13917    if (!linksets[linkset-1].ss7) {
13918       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13919       return CLI_SUCCESS;
13920    }
13921 
13922    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13923       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13924       ast_mutex_lock(&linksets[linkset-1].lock);
13925       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13926       ast_mutex_unlock(&linksets[linkset-1].lock);
13927    }
13928 
13929    /* Break poll on the linkset so it sends our messages */
13930    pthread_kill(linksets[linkset-1].master, SIGURG);
13931 
13932    return CLI_SUCCESS;
13933 }
13934 
13935 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13936 {
13937    int linkset;
13938    struct dahdi_ss7 *ss7;
13939    switch (cmd) {
13940    case CLI_INIT:
13941       e->command = "ss7 show linkset";
13942       e->usage = 
13943          "Usage: ss7 show linkset <span>\n"
13944          "       Shows the status of an SS7 linkset.\n";
13945       return NULL;
13946    case CLI_GENERATE:
13947       return NULL;
13948    }
13949 
13950    if (a->argc < 4)
13951       return CLI_SHOWUSAGE;
13952    linkset = atoi(a->argv[3]);
13953    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13954       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13955       return CLI_SUCCESS;
13956    }
13957    if (!linksets[linkset-1].ss7) {
13958       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13959       return CLI_SUCCESS;
13960    }
13961    if (linksets[linkset-1].ss7)
13962       ss7 = &linksets[linkset-1];
13963 
13964    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13965 
13966    return CLI_SUCCESS;
13967 }
13968 
13969 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13970 {
13971    switch (cmd) {
13972    case CLI_INIT:
13973       e->command = "ss7 show version";
13974       e->usage = 
13975          "Usage: ss7 show version\n"
13976          "  Show the libss7 version\n";
13977       return NULL;
13978    case CLI_GENERATE:
13979       return NULL;
13980    }
13981 
13982    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
13983 
13984    return CLI_SUCCESS;
13985 }
13986 
13987 static struct ast_cli_entry dahdi_ss7_cli[] = {
13988    AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"), 
13989    AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"), 
13990    AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
13991    AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
13992    AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
13993    AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
13994    AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
13995    AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
13996 };
13997 #endif /* HAVE_SS7 */
13998 
13999 static int __unload_module(void)
14000 {
14001    struct dahdi_pvt *p;
14002 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14003    int i, j;
14004 #endif
14005 
14006 #ifdef HAVE_PRI
14007    for (i = 0; i < NUM_SPANS; i++) {
14008       if (pris[i].master != AST_PTHREADT_NULL) 
14009          pthread_cancel(pris[i].master);
14010    }
14011    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14012    ast_unregister_application(dahdi_send_keypad_facility_app);
14013 #endif
14014 #if defined(HAVE_SS7)
14015    for (i = 0; i < NUM_SPANS; i++) {
14016       if (linksets[i].master != AST_PTHREADT_NULL)
14017          pthread_cancel(linksets[i].master);
14018       }
14019    ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14020 #endif
14021 
14022    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14023    ast_manager_unregister( "DAHDIDialOffhook" );
14024    ast_manager_unregister( "DAHDIHangup" );
14025    ast_manager_unregister( "DAHDITransfer" );
14026    ast_manager_unregister( "DAHDIDNDoff" );
14027    ast_manager_unregister( "DAHDIDNDon" );
14028    ast_manager_unregister("DAHDIShowChannels");
14029    ast_manager_unregister("DAHDIRestart");
14030    ast_channel_unregister(&dahdi_tech);
14031    ast_mutex_lock(&iflock);
14032    /* Hangup all interfaces if they have an owner */
14033    p = iflist;
14034    while (p) {
14035       if (p->owner)
14036          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14037       p = p->next;
14038    }
14039    ast_mutex_unlock(&iflock);
14040    ast_mutex_lock(&monlock);
14041    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14042       pthread_cancel(monitor_thread);
14043       pthread_kill(monitor_thread, SIGURG);
14044       pthread_join(monitor_thread, NULL);
14045    }
14046    monitor_thread = AST_PTHREADT_STOP;
14047    ast_mutex_unlock(&monlock);
14048 
14049    destroy_all_channels();
14050 
14051 #if defined(HAVE_PRI)
14052    for (i = 0; i < NUM_SPANS; i++) {
14053       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14054          pthread_join(pris[i].master, NULL);
14055       for (j = 0; j < NUM_DCHANS; j++) {
14056          dahdi_close_pri_fd(&(pris[i]), j);
14057       }
14058    }
14059 #endif
14060 
14061 #if defined(HAVE_SS7)
14062    for (i = 0; i < NUM_SPANS; i++) {
14063       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14064          pthread_join(linksets[i].master, NULL);
14065       for (j = 0; j < NUM_DCHANS; j++) {
14066          dahdi_close_ss7_fd(&(linksets[i]), j);
14067       }
14068    }
14069 #endif
14070 
14071    ast_cond_destroy(&mwi_thread_complete);
14072    ast_cond_destroy(&ss_thread_complete);
14073    return 0;
14074 }
14075 
14076 static int unload_module(void)
14077 {
14078 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14079    int y;
14080 #endif
14081 #ifdef HAVE_PRI
14082    for (y = 0; y < NUM_SPANS; y++)
14083       ast_mutex_destroy(&pris[y].lock);
14084 #endif
14085 #ifdef HAVE_SS7
14086    for (y = 0; y < NUM_SPANS; y++)
14087       ast_mutex_destroy(&linksets[y].lock);
14088 #endif /* HAVE_SS7 */
14089    return __unload_module();
14090 }
14091 
14092 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
14093 {
14094    char *c, *chan;
14095    int x, start, finish;
14096    struct dahdi_pvt *tmp;
14097 #ifdef HAVE_PRI
14098    struct dahdi_pri *pri;
14099    int trunkgroup, y;
14100 #endif
14101    
14102    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14103       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14104       return -1;
14105    }
14106 
14107    c = ast_strdupa(value);
14108 
14109 #ifdef HAVE_PRI
14110    pri = NULL;
14111    if (iscrv) {
14112       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14113          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14114          return -1;
14115       }
14116       if (trunkgroup < 1) {
14117          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14118          return -1;
14119       }
14120       c += y;
14121       for (y = 0; y < NUM_SPANS; y++) {
14122          if (pris[y].trunkgroup == trunkgroup) {
14123             pri = pris + y;
14124             break;
14125          }
14126       }
14127       if (!pri) {
14128          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14129          return -1;
14130       }
14131    }
14132 #endif         
14133 
14134    while ((chan = strsep(&c, ","))) {
14135       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14136          /* Range */
14137       } else if (sscanf(chan, "%30d", &start)) {
14138          /* Just one */
14139          finish = start;
14140       } else if (!strcasecmp(chan, "pseudo")) {
14141          finish = start = CHAN_PSEUDO;
14142          if (found_pseudo)
14143             *found_pseudo = 1;
14144       } else {
14145          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14146          return -1;
14147       }
14148       if (finish < start) {
14149          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14150          x = finish;
14151          finish = start;
14152          start = x;
14153       }
14154 
14155       for (x = start; x <= finish; x++) {
14156 #ifdef HAVE_PRI
14157          tmp = mkintf(x, conf, pri, reload);
14158 #else       
14159          tmp = mkintf(x, conf, NULL, reload);
14160 #endif         
14161 
14162          if (tmp) {
14163 #ifdef HAVE_PRI
14164                if (pri)
14165                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14166                else
14167 #endif
14168                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14169          } else {
14170             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14171                (reload == 1) ? "reconfigure" : "register", value);
14172             return -1;
14173          }
14174       }
14175    }
14176 
14177    return 0;
14178 }
14179 
14180 /** The length of the parameters list of 'dahdichan'. 
14181  * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
14182 #define MAX_CHANLIST_LEN 80
14183 
14184 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
14185 {
14186    char *parse = ast_strdupa(data);
14187    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14188    unsigned int param_count;
14189    unsigned int x;
14190 
14191    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14192       return;
14193 
14194    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14195 
14196    /* first parameter is tap length, process it here */
14197 
14198    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14199    
14200    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14201       confp->chan.echocancel.head.tap_length = x;
14202    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14203       confp->chan.echocancel.head.tap_length = 128;
14204 
14205    /* now process any remaining parameters */
14206 
14207    for (x = 1; x < param_count; x++) {
14208       struct {
14209          char *name;
14210          char *value;
14211       } param;
14212 
14213       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
14214          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14215          continue;
14216       }
14217 
14218       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14219          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14220          continue;
14221       }
14222 
14223       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14224 
14225       if (param.value) {
14226          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14227             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14228             continue;
14229          }
14230       }
14231       confp->chan.echocancel.head.param_count++;
14232    }
14233 }
14234 
14235 /*! process_dahdi() - ignore keyword 'channel' and similar */
14236 #define PROC_DAHDI_OPT_NOCHAN  (1 << 0) 
14237 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
14238 #define PROC_DAHDI_OPT_NOWARN  (1 << 1) 
14239 
14240 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
14241 {
14242    struct dahdi_pvt *tmp;
14243    int y;
14244    int found_pseudo = 0;
14245    char dahdichan[MAX_CHANLIST_LEN] = {};
14246 
14247    for (; v; v = v->next) {
14248       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14249          continue;
14250 
14251       /* must have parkinglot in confp before build_channels is called */
14252       if (!strcasecmp(v->name, "parkinglot")) {
14253          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14254       }
14255 
14256       /* Create the interface list */
14257       if (!strcasecmp(v->name, "channel")
14258 #ifdef HAVE_PRI
14259           || !strcasecmp(v->name, "crv")
14260 #endif         
14261          ) {
14262          int iscrv;
14263          if (options & PROC_DAHDI_OPT_NOCHAN) {
14264             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14265             continue;
14266          }
14267          iscrv = !strcasecmp(v->name, "crv");
14268          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14269                return -1;
14270          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14271       } else if (!strcasecmp(v->name, "buffers")) {
14272          int res;
14273          char policy[21] = "";
14274 
14275          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
14276          if (res != 2) {
14277             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14278             confp->chan.buf_no = numbufs;
14279             continue;
14280          }
14281          if (confp->chan.buf_no < 0)
14282             confp->chan.buf_no = numbufs;
14283          if (!strcasecmp(policy, "full")) {
14284             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14285          } else if (!strcasecmp(policy, "immediate")) {
14286             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14287          } else {
14288             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14289          }
14290       } else if (!strcasecmp(v->name, "dahdichan")) {
14291          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14292       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14293          usedistinctiveringdetection = ast_true(v->value);
14294       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14295          distinctiveringaftercid = ast_true(v->value);
14296       } else if (!strcasecmp(v->name, "dring1context")) {
14297          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14298       } else if (!strcasecmp(v->name, "dring2context")) {
14299          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14300       } else if (!strcasecmp(v->name, "dring3context")) {
14301          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14302       } else if (!strcasecmp(v->name, "dring1range")) {
14303          confp->chan.drings.ringnum[0].range = atoi(v->value);
14304       } else if (!strcasecmp(v->name, "dring2range")) {
14305          confp->chan.drings.ringnum[1].range = atoi(v->value);
14306       } else if (!strcasecmp(v->name, "dring3range")) {
14307          confp->chan.drings.ringnum[2].range = atoi(v->value);
14308       } else if (!strcasecmp(v->name, "dring1")) {
14309          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
14310       } else if (!strcasecmp(v->name, "dring2")) {
14311          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
14312       } else if (!strcasecmp(v->name, "dring3")) {
14313          sscanf(v->value, "%30d,%30d,%30d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
14314       } else if (!strcasecmp(v->name, "usecallerid")) {
14315          confp->chan.use_callerid = ast_true(v->value);
14316       } else if (!strcasecmp(v->name, "cidsignalling")) {
14317          if (!strcasecmp(v->value, "bell"))
14318             confp->chan.cid_signalling = CID_SIG_BELL;
14319          else if (!strcasecmp(v->value, "v23"))
14320             confp->chan.cid_signalling = CID_SIG_V23;
14321          else if (!strcasecmp(v->value, "dtmf"))
14322             confp->chan.cid_signalling = CID_SIG_DTMF;
14323          else if (!strcasecmp(v->value, "smdi"))
14324             confp->chan.cid_signalling = CID_SIG_SMDI;
14325          else if (!strcasecmp(v->value, "v23_jp"))
14326             confp->chan.cid_signalling = CID_SIG_V23_JP;
14327          else if (ast_true(v->value))
14328             confp->chan.cid_signalling = CID_SIG_BELL;
14329       } else if (!strcasecmp(v->name, "cidstart")) {
14330          if (!strcasecmp(v->value, "ring"))
14331             confp->chan.cid_start = CID_START_RING;
14332          else if (!strcasecmp(v->value, "polarity_in"))
14333             confp->chan.cid_start = CID_START_POLARITY_IN;
14334          else if (!strcasecmp(v->value, "polarity"))
14335             confp->chan.cid_start = CID_START_POLARITY;
14336          else if (ast_true(v->value))
14337             confp->chan.cid_start = CID_START_RING;
14338       } else if (!strcasecmp(v->name, "threewaycalling")) {
14339          confp->chan.threewaycalling = ast_true(v->value);
14340       } else if (!strcasecmp(v->name, "cancallforward")) {
14341          confp->chan.cancallforward = ast_true(v->value);
14342       } else if (!strcasecmp(v->name, "relaxdtmf")) {
14343          if (ast_true(v->value)) 
14344             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14345          else
14346             confp->chan.dtmfrelax = 0;
14347       } else if (!strcasecmp(v->name, "mailbox")) {
14348          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14349       } else if (!strcasecmp(v->name, "hasvoicemail")) {
14350          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14351             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14352          }
14353       } else if (!strcasecmp(v->name, "adsi")) {
14354          confp->chan.adsi = ast_true(v->value);
14355       } else if (!strcasecmp(v->name, "usesmdi")) {
14356          confp->chan.use_smdi = ast_true(v->value);
14357       } else if (!strcasecmp(v->name, "smdiport")) {
14358          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14359       } else if (!strcasecmp(v->name, "transfer")) {
14360          confp->chan.transfer = ast_true(v->value);
14361       } else if (!strcasecmp(v->name, "canpark")) {
14362          confp->chan.canpark = ast_true(v->value);
14363       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14364          confp->chan.echocanbridged = ast_true(v->value);
14365       } else if (!strcasecmp(v->name, "busydetect")) {
14366          confp->chan.busydetect = ast_true(v->value);
14367       } else if (!strcasecmp(v->name, "busycount")) {
14368          confp->chan.busycount = atoi(v->value);
14369       } else if (!strcasecmp(v->name, "busypattern")) {
14370          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
14371             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14372          }
14373       } else if (!strcasecmp(v->name, "callprogress")) {
14374          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14375          if (ast_true(v->value))
14376             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14377       } else if (!strcasecmp(v->name, "faxdetect")) {
14378          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14379          if (!strcasecmp(v->value, "incoming")) {
14380             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14381          } else if (!strcasecmp(v->value, "outgoing")) {
14382             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14383          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14384             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14385       } else if (!strcasecmp(v->name, "echocancel")) {
14386          process_echocancel(confp, v->value, v->lineno);
14387       } else if (!strcasecmp(v->name, "echotraining")) {
14388          if (sscanf(v->value, "%30d", &y) == 1) {
14389             if ((y < 10) || (y > 4000)) {
14390                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);             
14391             } else {
14392                confp->chan.echotraining = y;
14393             }
14394          } else if (ast_true(v->value)) {
14395             confp->chan.echotraining = 400;
14396          } else
14397             confp->chan.echotraining = 0;
14398       } else if (!strcasecmp(v->name, "hidecallerid")) {
14399          confp->chan.hidecallerid = ast_true(v->value);
14400       } else if (!strcasecmp(v->name, "hidecalleridname")) {
14401          confp->chan.hidecalleridname = ast_true(v->value);
14402       } else if (!strcasecmp(v->name, "pulsedial")) {
14403          confp->chan.pulse = ast_true(v->value);
14404       } else if (!strcasecmp(v->name, "callreturn")) {
14405          confp->chan.callreturn = ast_true(v->value);
14406       } else if (!strcasecmp(v->name, "callwaiting")) {
14407          confp->chan.callwaiting = ast_true(v->value);
14408       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14409          confp->chan.callwaitingcallerid = ast_true(v->value);
14410       } else if (!strcasecmp(v->name, "context")) {
14411          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14412       } else if (!strcasecmp(v->name, "language")) {
14413          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14414       } else if (!strcasecmp(v->name, "progzone")) {
14415          ast_copy_string(progzone, v->value, sizeof(progzone));
14416       } else if (!strcasecmp(v->name, "mohinterpret") 
14417          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14418          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14419       } else if (!strcasecmp(v->name, "mohsuggest")) {
14420          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14421       } else if (!strcasecmp(v->name, "parkinglot")) {
14422          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14423       } else if (!strcasecmp(v->name, "stripmsd")) {
14424          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14425          confp->chan.stripmsd = atoi(v->value);
14426       } else if (!strcasecmp(v->name, "jitterbuffers")) {
14427          numbufs = atoi(v->value);
14428       } else if (!strcasecmp(v->name, "group")) {
14429          confp->chan.group = ast_get_group(v->value);
14430       } else if (!strcasecmp(v->name, "callgroup")) {
14431          if (!strcasecmp(v->value, "none"))
14432             confp->chan.callgroup = 0;
14433          else
14434             confp->chan.callgroup = ast_get_group(v->value);
14435       } else if (!strcasecmp(v->name, "pickupgroup")) {
14436          if (!strcasecmp(v->value, "none"))
14437             confp->chan.pickupgroup = 0;
14438          else
14439             confp->chan.pickupgroup = ast_get_group(v->value);
14440       } else if (!strcasecmp(v->name, "setvar")) {
14441          char *varname = ast_strdupa(v->value), *varval = NULL;
14442          struct ast_variable *tmpvar;
14443          if (varname && (varval = strchr(varname, '='))) {
14444             *varval++ = '\0';
14445             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14446                tmpvar->next = confp->chan.vars;
14447                confp->chan.vars = tmpvar;
14448             }
14449          }
14450       } else if (!strcasecmp(v->name, "immediate")) {
14451          confp->chan.immediate = ast_true(v->value);
14452       } else if (!strcasecmp(v->name, "transfertobusy")) {
14453          confp->chan.transfertobusy = ast_true(v->value);
14454       } else if (!strcasecmp(v->name, "mwimonitor")) {
14455          confp->chan.mwimonitor_neon = 0;
14456          confp->chan.mwimonitor_fsk  = 0;
14457          confp->chan.mwimonitor_rpas = 0;
14458          if (strcasestr(v->value, "fsk")) {
14459             confp->chan.mwimonitor_fsk = 1;
14460          }
14461          if (strcasestr(v->value, "rpas")) {
14462             confp->chan.mwimonitor_rpas = 1;
14463          }
14464          if (strcasestr(v->value, "neon")) {
14465             confp->chan.mwimonitor_neon = 1;
14466          }
14467          /* If set to true or yes, assume that simple fsk is desired */
14468          if (ast_true(v->value)) {
14469             confp->chan.mwimonitor_fsk = 1;
14470          } 
14471       } else if (!strcasecmp(v->name, "cid_rxgain")) {
14472          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
14473             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14474          }
14475       } else if (!strcasecmp(v->name, "rxgain")) {
14476          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
14477             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14478          }
14479       } else if (!strcasecmp(v->name, "txgain")) {
14480          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
14481             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14482          }
14483       } else if (!strcasecmp(v->name, "tonezone")) {
14484          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
14485             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14486          }
14487       } else if (!strcasecmp(v->name, "callerid")) {
14488          if (!strcasecmp(v->value, "asreceived")) {
14489             confp->chan.cid_num[0] = '\0';
14490             confp->chan.cid_name[0] = '\0';
14491          } else {
14492             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14493          } 
14494       } else if (!strcasecmp(v->name, "fullname")) {
14495          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14496       } else if (!strcasecmp(v->name, "cid_number")) {
14497          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14498       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14499          confp->chan.dahditrcallerid = ast_true(v->value);
14500       } else if (!strcasecmp(v->name, "restrictcid")) {
14501          confp->chan.restrictcid = ast_true(v->value);
14502       } else if (!strcasecmp(v->name, "usecallingpres")) {
14503          confp->chan.use_callingpres = ast_true(v->value);
14504       } else if (!strcasecmp(v->name, "accountcode")) {
14505          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14506       } else if (!strcasecmp(v->name, "amaflags")) {
14507          y = ast_cdr_amaflags2int(v->value);
14508          if (y < 0) 
14509             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14510          else
14511             confp->chan.amaflags = y;
14512       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14513          confp->chan.polarityonanswerdelay = atoi(v->value);
14514       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14515          confp->chan.answeronpolarityswitch = ast_true(v->value);
14516       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14517          confp->chan.hanguponpolarityswitch = ast_true(v->value);
14518       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14519          confp->chan.sendcalleridafter = atoi(v->value);
14520       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14521          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14522       } else if (!strcasecmp(v->name, "mwisendtype")) {
14523          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
14524             mwisend_rpas = 1;
14525          } else {
14526             mwisend_rpas = 0;
14527          }
14528       } else if (reload != 1) {
14529           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14530             int orig_radio = confp->chan.radio;
14531             int orig_outsigmod = confp->chan.outsigmod;
14532             int orig_auto = confp->is_sig_auto;
14533 
14534             confp->chan.radio = 0;
14535             confp->chan.outsigmod = -1;
14536             confp->is_sig_auto = 0;
14537             if (!strcasecmp(v->value, "em")) {
14538                confp->chan.sig = SIG_EM;
14539             } else if (!strcasecmp(v->value, "em_e1")) {
14540                confp->chan.sig = SIG_EM_E1;
14541             } else if (!strcasecmp(v->value, "em_w")) {
14542                confp->chan.sig = SIG_EMWINK;
14543             } else if (!strcasecmp(v->value, "fxs_ls")) {
14544                confp->chan.sig = SIG_FXSLS;
14545             } else if (!strcasecmp(v->value, "fxs_gs")) {
14546                confp->chan.sig = SIG_FXSGS;
14547             } else if (!strcasecmp(v->value, "fxs_ks")) {
14548                confp->chan.sig = SIG_FXSKS;
14549             } else if (!strcasecmp(v->value, "fxo_ls")) {
14550                confp->chan.sig = SIG_FXOLS;
14551             } else if (!strcasecmp(v->value, "fxo_gs")) {
14552                confp->chan.sig = SIG_FXOGS;
14553             } else if (!strcasecmp(v->value, "fxo_ks")) {
14554                confp->chan.sig = SIG_FXOKS;
14555             } else if (!strcasecmp(v->value, "fxs_rx")) {
14556                confp->chan.sig = SIG_FXSKS;
14557                confp->chan.radio = 1;
14558             } else if (!strcasecmp(v->value, "fxo_rx")) {
14559                confp->chan.sig = SIG_FXOLS;
14560                confp->chan.radio = 1;
14561             } else if (!strcasecmp(v->value, "fxs_tx")) {
14562                confp->chan.sig = SIG_FXSLS;
14563                confp->chan.radio = 1;
14564             } else if (!strcasecmp(v->value, "fxo_tx")) {
14565                confp->chan.sig = SIG_FXOGS;
14566                confp->chan.radio = 1;
14567             } else if (!strcasecmp(v->value, "em_rx")) {
14568                confp->chan.sig = SIG_EM;
14569                confp->chan.radio = 1;
14570             } else if (!strcasecmp(v->value, "em_tx")) {
14571                confp->chan.sig = SIG_EM;
14572                confp->chan.radio = 1;
14573             } else if (!strcasecmp(v->value, "em_rxtx")) {
14574                confp->chan.sig = SIG_EM;
14575                confp->chan.radio = 2;
14576             } else if (!strcasecmp(v->value, "em_txrx")) {
14577                confp->chan.sig = SIG_EM;
14578                confp->chan.radio = 2;
14579             } else if (!strcasecmp(v->value, "sf")) {
14580                confp->chan.sig = SIG_SF;
14581             } else if (!strcasecmp(v->value, "sf_w")) {
14582                confp->chan.sig = SIG_SFWINK;
14583             } else if (!strcasecmp(v->value, "sf_featd")) {
14584                confp->chan.sig = SIG_FEATD;
14585             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14586                confp->chan.sig = SIG_FEATDMF;
14587             } else if (!strcasecmp(v->value, "sf_featb")) {
14588                confp->chan.sig = SIG_SF_FEATB;
14589             } else if (!strcasecmp(v->value, "sf")) {
14590                confp->chan.sig = SIG_SF;
14591             } else if (!strcasecmp(v->value, "sf_rx")) {
14592                confp->chan.sig = SIG_SF;
14593                confp->chan.radio = 1;
14594             } else if (!strcasecmp(v->value, "sf_tx")) {
14595                confp->chan.sig = SIG_SF;
14596                confp->chan.radio = 1;
14597             } else if (!strcasecmp(v->value, "sf_rxtx")) {
14598                confp->chan.sig = SIG_SF;
14599                confp->chan.radio = 2;
14600             } else if (!strcasecmp(v->value, "sf_txrx")) {
14601                confp->chan.sig = SIG_SF;
14602                confp->chan.radio = 2;
14603             } else if (!strcasecmp(v->value, "featd")) {
14604                confp->chan.sig = SIG_FEATD;
14605             } else if (!strcasecmp(v->value, "featdmf")) {
14606                confp->chan.sig = SIG_FEATDMF;
14607             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14608                confp->chan.sig = SIG_FEATDMF_TA;
14609             } else if (!strcasecmp(v->value, "e911")) {
14610                confp->chan.sig = SIG_E911;
14611             } else if (!strcasecmp(v->value, "fgccama")) {
14612                confp->chan.sig = SIG_FGC_CAMA;
14613             } else if (!strcasecmp(v->value, "fgccamamf")) {
14614                confp->chan.sig = SIG_FGC_CAMAMF;
14615             } else if (!strcasecmp(v->value, "featb")) {
14616                confp->chan.sig = SIG_FEATB;
14617 #ifdef HAVE_PRI
14618             } else if (!strcasecmp(v->value, "pri_net")) {
14619                confp->chan.sig = SIG_PRI;
14620                confp->pri.nodetype = PRI_NETWORK;
14621             } else if (!strcasecmp(v->value, "pri_cpe")) {
14622                confp->chan.sig = SIG_PRI;
14623                confp->pri.nodetype = PRI_CPE;
14624             } else if (!strcasecmp(v->value, "bri_cpe")) {
14625                confp->chan.sig = SIG_BRI;
14626                confp->pri.nodetype = PRI_CPE;
14627             } else if (!strcasecmp(v->value, "bri_net")) {
14628                confp->chan.sig = SIG_BRI;
14629                confp->pri.nodetype = PRI_NETWORK;
14630             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14631                confp->chan.sig = SIG_BRI_PTMP;
14632                confp->pri.nodetype = PRI_CPE;
14633             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14634                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
14635             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14636                confp->chan.sig = SIG_GR303FXOKS;
14637                confp->pri.nodetype = PRI_NETWORK;
14638             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14639                confp->chan.sig = SIG_GR303FXSKS;
14640                confp->pri.nodetype = PRI_CPE;
14641 #endif
14642 #ifdef HAVE_SS7
14643             } else if (!strcasecmp(v->value, "ss7")) {
14644                confp->chan.sig = SIG_SS7;
14645 #endif
14646             } else if (!strcasecmp(v->value, "auto")) {
14647                confp->is_sig_auto = 1;
14648             } else {
14649                confp->chan.outsigmod = orig_outsigmod;
14650                confp->chan.radio = orig_radio;
14651                confp->is_sig_auto = orig_auto;
14652                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14653             }
14654           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14655             if (!strcasecmp(v->value, "em")) {
14656                confp->chan.outsigmod = SIG_EM;
14657             } else if (!strcasecmp(v->value, "em_e1")) {
14658                confp->chan.outsigmod = SIG_EM_E1;
14659             } else if (!strcasecmp(v->value, "em_w")) {
14660                confp->chan.outsigmod = SIG_EMWINK;
14661             } else if (!strcasecmp(v->value, "sf")) {
14662                confp->chan.outsigmod = SIG_SF;
14663             } else if (!strcasecmp(v->value, "sf_w")) {
14664                confp->chan.outsigmod = SIG_SFWINK;
14665             } else if (!strcasecmp(v->value, "sf_featd")) {
14666                confp->chan.outsigmod = SIG_FEATD;
14667             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14668                confp->chan.outsigmod = SIG_FEATDMF;
14669             } else if (!strcasecmp(v->value, "sf_featb")) {
14670                confp->chan.outsigmod = SIG_SF_FEATB;
14671             } else if (!strcasecmp(v->value, "sf")) {
14672                confp->chan.outsigmod = SIG_SF;
14673             } else if (!strcasecmp(v->value, "featd")) {
14674                confp->chan.outsigmod = SIG_FEATD;
14675             } else if (!strcasecmp(v->value, "featdmf")) {
14676                confp->chan.outsigmod = SIG_FEATDMF;
14677             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14678                confp->chan.outsigmod = SIG_FEATDMF_TA;
14679             } else if (!strcasecmp(v->value, "e911")) {
14680                confp->chan.outsigmod = SIG_E911;
14681             } else if (!strcasecmp(v->value, "fgccama")) {
14682                confp->chan.outsigmod = SIG_FGC_CAMA;
14683             } else if (!strcasecmp(v->value, "fgccamamf")) {
14684                confp->chan.outsigmod = SIG_FGC_CAMAMF;
14685             } else if (!strcasecmp(v->value, "featb")) {
14686                confp->chan.outsigmod = SIG_FEATB;
14687             } else {
14688                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14689             }
14690 #ifdef HAVE_PRI
14691          } else if (!strcasecmp(v->name, "pridialplan")) {
14692             if (!strcasecmp(v->value, "national")) {
14693                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14694             } else if (!strcasecmp(v->value, "unknown")) {
14695                confp->pri.dialplan = PRI_UNKNOWN + 1;
14696             } else if (!strcasecmp(v->value, "private")) {
14697                confp->pri.dialplan = PRI_PRIVATE + 1;
14698             } else if (!strcasecmp(v->value, "international")) {
14699                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14700             } else if (!strcasecmp(v->value, "local")) {
14701                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14702             } else if (!strcasecmp(v->value, "dynamic")) {
14703                confp->pri.dialplan = -1;
14704             } else if (!strcasecmp(v->value, "redundant")) {
14705                confp->pri.dialplan = -2;
14706             } else {
14707                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14708             }
14709          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14710             if (!strcasecmp(v->value, "national")) {
14711                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14712             } else if (!strcasecmp(v->value, "unknown")) {
14713                confp->pri.localdialplan = PRI_UNKNOWN + 1;
14714             } else if (!strcasecmp(v->value, "private")) {
14715                confp->pri.localdialplan = PRI_PRIVATE + 1;
14716             } else if (!strcasecmp(v->value, "international")) {
14717                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14718             } else if (!strcasecmp(v->value, "local")) {
14719                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14720             } else if (!strcasecmp(v->value, "dynamic")) {
14721                confp->pri.localdialplan = -1;
14722             } else if (!strcasecmp(v->value, "redundant")) {
14723                confp->pri.localdialplan = -2;
14724             } else {
14725                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14726             }
14727          } else if (!strcasecmp(v->name, "switchtype")) {
14728             if (!strcasecmp(v->value, "national")) 
14729                confp->pri.switchtype = PRI_SWITCH_NI2;
14730             else if (!strcasecmp(v->value, "ni1"))
14731                confp->pri.switchtype = PRI_SWITCH_NI1;
14732             else if (!strcasecmp(v->value, "dms100"))
14733                confp->pri.switchtype = PRI_SWITCH_DMS100;
14734             else if (!strcasecmp(v->value, "4ess"))
14735                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14736             else if (!strcasecmp(v->value, "5ess"))
14737                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14738             else if (!strcasecmp(v->value, "euroisdn"))
14739                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14740             else if (!strcasecmp(v->value, "qsig"))
14741                confp->pri.switchtype = PRI_SWITCH_QSIG;
14742             else {
14743                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14744                return -1;
14745             }
14746          } else if (!strcasecmp(v->name, "nsf")) {
14747             if (!strcasecmp(v->value, "sdn"))
14748                confp->pri.nsf = PRI_NSF_SDN;
14749             else if (!strcasecmp(v->value, "megacom"))
14750                confp->pri.nsf = PRI_NSF_MEGACOM;
14751             else if (!strcasecmp(v->value, "tollfreemegacom"))
14752                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
14753             else if (!strcasecmp(v->value, "accunet"))
14754                confp->pri.nsf = PRI_NSF_ACCUNET;
14755             else if (!strcasecmp(v->value, "none"))
14756                confp->pri.nsf = PRI_NSF_NONE;
14757             else {
14758                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14759                confp->pri.nsf = PRI_NSF_NONE;
14760             }
14761          } else if (!strcasecmp(v->name, "priindication")) {
14762             if (!strcasecmp(v->value, "outofband"))
14763                confp->chan.priindication_oob = 1;
14764             else if (!strcasecmp(v->value, "inband"))
14765                confp->chan.priindication_oob = 0;
14766             else
14767                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14768                   v->value, v->lineno);
14769          } else if (!strcasecmp(v->name, "priexclusive")) {
14770             confp->chan.priexclusive = ast_true(v->value);
14771          } else if (!strcasecmp(v->name, "internationalprefix")) {
14772             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14773          } else if (!strcasecmp(v->name, "nationalprefix")) {
14774             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14775          } else if (!strcasecmp(v->name, "localprefix")) {
14776             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14777          } else if (!strcasecmp(v->name, "privateprefix")) {
14778             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14779          } else if (!strcasecmp(v->name, "unknownprefix")) {
14780             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14781          } else if (!strcasecmp(v->name, "resetinterval")) {
14782             if (!strcasecmp(v->value, "never"))
14783                confp->pri.resetinterval = -1;
14784             else if (atoi(v->value) >= 60)
14785                confp->pri.resetinterval = atoi(v->value);
14786             else
14787                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14788                   v->value, v->lineno);
14789          } else if (!strcasecmp(v->name, "minunused")) {
14790             confp->pri.minunused = atoi(v->value);
14791          } else if (!strcasecmp(v->name, "minidle")) {
14792             confp->pri.minidle = atoi(v->value); 
14793          } else if (!strcasecmp(v->name, "idleext")) {
14794             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14795          } else if (!strcasecmp(v->name, "idledial")) {
14796             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14797          } else if (!strcasecmp(v->name, "overlapdial")) {
14798             if (ast_true(v->value)) {
14799                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14800             } else if (!strcasecmp(v->value, "incoming")) {
14801                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14802             } else if (!strcasecmp(v->value, "outgoing")) {
14803                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14804             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14805                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14806             } else {
14807                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14808             }
14809 #ifdef HAVE_PRI_INBANDDISCONNECT
14810          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14811             confp->pri.inbanddisconnect = ast_true(v->value);
14812 #endif
14813          } else if (!strcasecmp(v->name, "pritimer")) {
14814 #ifdef PRI_GETSET_TIMERS
14815             char tmp[20];
14816             char *timerc;
14817             char *c;
14818             int timer;
14819             int timeridx;
14820 
14821             ast_copy_string(tmp, v->value, sizeof(tmp));
14822             c = tmp;
14823             timerc = strsep(&c, ",");
14824             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
14825                timeridx = pri_timer2idx(timerc);
14826                timer = atoi(c);
14827                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
14828                   ast_log(LOG_WARNING,
14829                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
14830                      v->lineno);
14831                } else if (!timer) {
14832                   ast_log(LOG_WARNING,
14833                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
14834                      c, timerc, v->lineno);
14835                } else {
14836                   pritimers[timeridx] = timer;
14837                }
14838             } else {
14839                ast_log(LOG_WARNING,
14840                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
14841                   v->value, v->lineno);
14842             }
14843 
14844          } else if (!strcasecmp(v->name, "facilityenable")) {
14845             confp->pri.facilityenable = ast_true(v->value);
14846 #endif /* PRI_GETSET_TIMERS */
14847 #endif /* HAVE_PRI */
14848 #ifdef HAVE_SS7
14849          } else if (!strcasecmp(v->name, "ss7type")) {
14850             if (!strcasecmp(v->value, "itu")) {
14851                cur_ss7type = SS7_ITU;
14852             } else if (!strcasecmp(v->value, "ansi")) {
14853                cur_ss7type = SS7_ANSI;
14854             } else
14855                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14856          } else if (!strcasecmp(v->name, "linkset")) {
14857             cur_linkset = atoi(v->value);
14858          } else if (!strcasecmp(v->name, "pointcode")) {
14859             cur_pointcode = parse_pointcode(v->value);
14860          } else if (!strcasecmp(v->name, "adjpointcode")) {
14861             cur_adjpointcode = parse_pointcode(v->value);
14862          } else if (!strcasecmp(v->name, "defaultdpc")) {
14863             cur_defaultdpc = parse_pointcode(v->value);
14864          } else if (!strcasecmp(v->name, "cicbeginswith")) {
14865             cur_cicbeginswith = atoi(v->value);
14866          } else if (!strcasecmp(v->name, "networkindicator")) {
14867             if (!strcasecmp(v->value, "national"))
14868                cur_networkindicator = SS7_NI_NAT;
14869             else if (!strcasecmp(v->value, "national_spare"))
14870                cur_networkindicator = SS7_NI_NAT_SPARE;
14871             else if (!strcasecmp(v->value, "international"))
14872                cur_networkindicator = SS7_NI_INT;
14873             else if (!strcasecmp(v->value, "international_spare"))
14874                cur_networkindicator = SS7_NI_INT_SPARE;
14875             else
14876                cur_networkindicator = -1;
14877          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14878             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14879          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14880             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14881          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14882             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14883          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14884             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14885          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14886             if (!strcasecmp(v->value, "national")) {
14887                confp->ss7.called_nai = SS7_NAI_NATIONAL;
14888             } else if (!strcasecmp(v->value, "international")) {
14889                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14890             } else if (!strcasecmp(v->value, "subscriber")) {
14891                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14892             } else if (!strcasecmp(v->value, "dynamic")) {
14893                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14894             } else {
14895                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14896             }
14897          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14898             if (!strcasecmp(v->value, "national")) {
14899                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14900             } else if (!strcasecmp(v->value, "international")) {
14901                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14902             } else if (!strcasecmp(v->value, "subscriber")) {
14903                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14904             } else if (!strcasecmp(v->value, "dynamic")) {
14905                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14906             } else {
14907                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14908             }
14909          } else if (!strcasecmp(v->name, "sigchan")) {
14910             int sigchan, res;
14911             sigchan = atoi(v->value);
14912             res = linkset_addsigchan(sigchan);
14913             if (res < 0)
14914                return -1;
14915 
14916          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14917             struct dahdi_ss7 *link;
14918             link = ss7_resolve_linkset(cur_linkset);
14919             if (!link) {
14920                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
14921                return -1;
14922             }
14923             if (ast_true(v->value))
14924                link->flags |= LINKSET_FLAG_EXPLICITACM;
14925 
14926 #endif /* HAVE_SS7 */
14927          } else if (!strcasecmp(v->name, "cadence")) {
14928             /* setup to scan our argument */
14929             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14930             int i;
14931             struct dahdi_ring_cadence new_cadence;
14932             int cid_location = -1;
14933             int firstcadencepos = 0;
14934             char original_args[80];
14935             int cadence_is_ok = 1;
14936 
14937             ast_copy_string(original_args, v->value, sizeof(original_args));
14938             /* 16 cadences allowed (8 pairs) */
14939             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
14940    
14941             /* Cadence must be even (on/off) */
14942             if (element_count % 2 == 1) {
14943                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14944                cadence_is_ok = 0;
14945             }
14946    
14947             /* Ring cadences cannot be negative */
14948             for (i = 0; i < element_count; i++) {
14949                if (c[i] == 0) {
14950                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14951                   cadence_is_ok = 0;
14952                   break;
14953                } else if (c[i] < 0) {
14954                   if (i % 2 == 1) {
14955                      /* Silence duration, negative possibly okay */
14956                      if (cid_location == -1) {
14957                         cid_location = i;
14958                         c[i] *= -1;
14959                      } else {
14960                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14961                         cadence_is_ok = 0;
14962                         break;
14963                      }
14964                   } else {
14965                      if (firstcadencepos == 0) {
14966                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
14967                                  /* duration will be passed negative to the DAHDI driver */
14968                      } else {
14969                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14970                         cadence_is_ok = 0;
14971                         break;
14972                      }
14973                   }
14974                }
14975             }
14976    
14977             /* Substitute our scanned cadence */
14978             for (i = 0; i < 16; i++) {
14979                new_cadence.ringcadence[i] = c[i];
14980             }
14981    
14982             if (cadence_is_ok) {
14983                /* ---we scanned it without getting annoyed; now some sanity checks--- */
14984                if (element_count < 2) {
14985                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14986                } else {
14987                   if (cid_location == -1) {
14988                      /* user didn't say; default to first pause */
14989                      cid_location = 1;
14990                   } else {
14991                      /* convert element_index to cidrings value */
14992                      cid_location = (cid_location + 1) / 2;
14993                   }
14994                   /* ---we like their cadence; try to install it--- */
14995                   if (!user_has_defined_cadences++)
14996                      /* this is the first user-defined cadence; clear the default user cadences */
14997                      num_cadence = 0;
14998                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
14999                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
15000                   else {
15001                      cadences[num_cadence] = new_cadence;
15002                      cidrings[num_cadence++] = cid_location;
15003                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
15004                   }
15005                }
15006             }
15007          } else if (!strcasecmp(v->name, "ringtimeout")) {
15008             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15009          } else if (!strcasecmp(v->name, "prewink")) {
15010             confp->timing.prewinktime = atoi(v->value);
15011          } else if (!strcasecmp(v->name, "preflash")) {
15012             confp->timing.preflashtime = atoi(v->value);
15013          } else if (!strcasecmp(v->name, "wink")) {
15014             confp->timing.winktime = atoi(v->value);
15015          } else if (!strcasecmp(v->name, "flash")) {
15016             confp->timing.flashtime = atoi(v->value);
15017          } else if (!strcasecmp(v->name, "start")) {
15018             confp->timing.starttime = atoi(v->value);
15019          } else if (!strcasecmp(v->name, "rxwink")) {
15020             confp->timing.rxwinktime = atoi(v->value);
15021          } else if (!strcasecmp(v->name, "rxflash")) {
15022             confp->timing.rxflashtime = atoi(v->value);
15023          } else if (!strcasecmp(v->name, "debounce")) {
15024             confp->timing.debouncetime = atoi(v->value);
15025          } else if (!strcasecmp(v->name, "toneduration")) {
15026             int toneduration;
15027             int ctlfd;
15028             int res;
15029             struct dahdi_dialparams dps;
15030 
15031             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15032             if (ctlfd == -1) {
15033                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15034                return -1;
15035             }
15036 
15037             toneduration = atoi(v->value);
15038             if (toneduration > -1) {
15039                memset(&dps, 0, sizeof(dps));
15040 
15041                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15042                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15043                if (res < 0) {
15044                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15045                   return -1;
15046                }
15047             }
15048             close(ctlfd);
15049          } else if (!strcasecmp(v->name, "defaultcic")) {
15050             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15051          } else if (!strcasecmp(v->name, "defaultozz")) {
15052             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15053          } else if (!strcasecmp(v->name, "mwilevel")) {
15054             mwilevel = atoi(v->value);
15055          }
15056       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15057          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15058    }
15059    if (dahdichan[0]) { 
15060       /* The user has set 'dahdichan' */
15061       /*< \todo pass proper line number instead of 0 */
15062       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15063          return -1;
15064       }
15065    }
15066    /*< \todo why check for the pseudo in the per-channel section.
15067     * Any actual use for manual setup of the pseudo channel? */
15068    if (!found_pseudo && reload != 1) {
15069       /* use the default configuration for a channel, so
15070          that any settings from real configured channels
15071          don't "leak" into the pseudo channel config
15072       */
15073       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15074 
15075       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15076 
15077       if (tmp) {
15078          ast_verb(3, "Automatically generated pseudo channel\n");
15079       } else {
15080          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15081       }
15082    }
15083    return 0;
15084 }
15085       
15086 static int setup_dahdi(int reload)
15087 {
15088    struct ast_config *cfg, *ucfg;
15089    struct ast_variable *v;
15090    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15091    struct dahdi_chan_conf conf;
15092    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15093    const char *cat;
15094    int res;
15095 
15096 #ifdef HAVE_PRI
15097    char *c;
15098    int spanno;
15099    int i;
15100    int logicalspan;
15101    int trunkgroup;
15102    int dchannels[NUM_DCHANS];
15103 #endif
15104 
15105    cfg = ast_config_load(config, config_flags);
15106 
15107    /* Error if we have no config file */
15108    if (!cfg) {
15109       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15110       return 0;
15111    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15112       ucfg = ast_config_load("users.conf", config_flags);
15113       if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15114          return 0;
15115       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15116       cfg = ast_config_load(config, config_flags);
15117    } else {
15118       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15119       ucfg = ast_config_load("users.conf", config_flags);
15120    }
15121 
15122    /* It's a little silly to lock it, but we mind as well just to be sure */
15123    ast_mutex_lock(&iflock);
15124 #ifdef HAVE_PRI
15125    if (reload != 1) {
15126       /* Process trunkgroups first */
15127       v = ast_variable_browse(cfg, "trunkgroups");
15128       while (v) {
15129          if (!strcasecmp(v->name, "trunkgroup")) {
15130             trunkgroup = atoi(v->value);
15131             if (trunkgroup > 0) {
15132                if ((c = strchr(v->value, ','))) {
15133                   i = 0;
15134                   memset(dchannels, 0, sizeof(dchannels));
15135                   while (c && (i < NUM_DCHANS)) {
15136                      dchannels[i] = atoi(c + 1);
15137                      if (dchannels[i] < 0) {
15138                         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);
15139                      } else
15140                         i++;
15141                      c = strchr(c + 1, ',');
15142                   }
15143                   if (i) {
15144                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15145                         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);
15146                   } else
15147                         ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
15148                   } else
15149                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15150                } else
15151                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15152             } else
15153                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15154          } else if (!strcasecmp(v->name, "spanmap")) {
15155             spanno = atoi(v->value);
15156             if (spanno > 0) {
15157                if ((c = strchr(v->value, ','))) {
15158                   trunkgroup = atoi(c + 1);
15159                   if (trunkgroup > 0) {
15160                      if ((c = strchr(c + 1, ','))) 
15161                         logicalspan = atoi(c + 1);
15162                      else
15163                         logicalspan = 0;
15164                      if (logicalspan >= 0) {
15165                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15166                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15167                      } else
15168                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15169                      } else
15170                         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);
15171                   } else
15172                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15173                } else
15174                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15175             } else
15176                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15177          } else {
15178             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15179          }
15180          v = v->next;
15181       }
15182    }
15183 #endif
15184    
15185    /* Copy the default jb config over global_jbconf */
15186    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15187 
15188    mwimonitornotify[0] = '\0';
15189 
15190    v = ast_variable_browse(cfg, "channels");
15191    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15192       ast_mutex_unlock(&iflock);
15193       ast_config_destroy(cfg);
15194       if (ucfg) {
15195          ast_config_destroy(ucfg);
15196       }
15197       return res;
15198    }
15199 
15200    /* Now get configuration from all normal sections in chan_dahdi.conf: */
15201    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15202       /* [channels] and [trunkgroups] are used. Let's also reserve
15203        * [globals] and [general] for future use
15204        */
15205       if (!strcasecmp(cat, "general") || 
15206           !strcasecmp(cat, "trunkgroups") ||
15207           !strcasecmp(cat, "globals") ||
15208           !strcasecmp(cat, "channels")) {
15209          continue;
15210       }
15211 
15212       memcpy(&conf, &base_conf, sizeof(conf));
15213 
15214       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15215          ast_mutex_unlock(&iflock);
15216          ast_config_destroy(cfg);
15217          if (ucfg) {
15218             ast_config_destroy(cfg);
15219          }
15220          return res;
15221       }
15222    }
15223 
15224    ast_config_destroy(cfg);
15225 
15226    if (ucfg) {
15227       const char *chans;
15228 
15229       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15230 
15231       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15232          if (!strcasecmp(cat, "general")) {
15233             continue;
15234          }
15235 
15236          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15237 
15238          if (ast_strlen_zero(chans)) {
15239             continue;
15240          }
15241 
15242          memcpy(&conf, &base_conf, sizeof(conf));
15243 
15244          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15245             ast_config_destroy(ucfg);
15246             ast_mutex_unlock(&iflock);
15247             return res;
15248          }
15249       }
15250       ast_config_destroy(ucfg);
15251    }
15252    ast_mutex_unlock(&iflock);
15253 
15254 #ifdef HAVE_PRI
15255    if (reload != 1) {
15256       int x;
15257       for (x = 0; x < NUM_SPANS; x++) {
15258          if (pris[x].pvts[0]) {
15259             if (start_pri(pris + x)) {
15260                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15261                return -1;
15262             } else
15263                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15264          }
15265       }
15266    }
15267 #endif
15268 #ifdef HAVE_SS7
15269    if (reload != 1) {
15270       int x;
15271       for (x = 0; x < NUM_SPANS; x++) {
15272          if (linksets[x].ss7) {
15273             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15274                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15275                return -1;
15276             } else
15277                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15278          }
15279       }
15280    }
15281 #endif
15282    /* And start the monitor for the first time */
15283    restart_monitor();
15284    return 0;
15285 }
15286 
15287 static int load_module(void)
15288 {
15289    int res;
15290 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15291    int y, i;
15292 #endif
15293 
15294 #ifdef HAVE_PRI
15295    memset(pris, 0, sizeof(pris));
15296    for (y = 0; y < NUM_SPANS; y++) {
15297       ast_mutex_init(&pris[y].lock);
15298       pris[y].offset = -1;
15299       pris[y].master = AST_PTHREADT_NULL;
15300       for (i = 0; i < NUM_DCHANS; i++)
15301          pris[y].fds[i] = -1;
15302    }
15303    pri_set_error(dahdi_pri_error);
15304    pri_set_message(dahdi_pri_message);
15305    ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15306          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15307 #endif
15308 #ifdef HAVE_SS7
15309    memset(linksets, 0, sizeof(linksets));
15310    for (y = 0; y < NUM_SPANS; y++) {
15311       ast_mutex_init(&linksets[y].lock);
15312       linksets[y].master = AST_PTHREADT_NULL;
15313       for (i = 0; i < NUM_DCHANS; i++)
15314          linksets[y].fds[i] = -1;
15315    }
15316    ss7_set_error(dahdi_ss7_error);
15317    ss7_set_message(dahdi_ss7_message);
15318 #endif /* HAVE_SS7 */
15319    res = setup_dahdi(0);
15320    /* Make sure we can register our DAHDI channel type */
15321    if (res)
15322       return AST_MODULE_LOAD_DECLINE;
15323    if (ast_channel_register(&dahdi_tech)) {
15324       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15325       __unload_module();
15326       return AST_MODULE_LOAD_FAILURE;
15327    }
15328 #ifdef HAVE_PRI
15329    ast_string_field_init(&inuse, 16);
15330    ast_string_field_set(&inuse, name, "GR-303InUse");
15331    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15332 #endif   
15333 #ifdef HAVE_SS7
15334    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15335 #endif
15336 
15337    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15338    
15339    memset(round_robin, 0, sizeof(round_robin));
15340    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15341    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15342    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15343    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15344    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15345    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15346    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15347 
15348    ast_cond_init(&mwi_thread_complete, NULL);
15349    ast_cond_init(&ss_thread_complete, NULL);
15350 
15351    return res;
15352 }
15353 
15354 static int dahdi_sendtext(struct ast_channel *c, const char *text)
15355 {
15356 #define  END_SILENCE_LEN 400
15357 #define  HEADER_MS 50
15358 #define  TRAILER_MS 5
15359 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15360 #define  ASCII_BYTES_PER_CHAR 80
15361 
15362    unsigned char *buf,*mybuf;
15363    struct dahdi_pvt *p = c->tech_pvt;
15364    struct pollfd fds[1];
15365    int size,res,fd,len,x;
15366    int bytes=0;
15367    /* Initial carrier (imaginary) */
15368    float cr = 1.0;
15369    float ci = 0.0;
15370    float scont = 0.0;
15371    int idx;
15372 
15373    idx = dahdi_get_index(c, p, 0);
15374    if (idx < 0) {
15375       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
15376       return -1;
15377    }
15378    if (!text[0]) return(0); /* if nothing to send, dont */
15379    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
15380    if (p->mate) 
15381       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15382    else
15383       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15384    if (!buf)
15385       return -1;
15386    mybuf = buf;
15387    if (p->mate) {
15388       int codec = AST_LAW(p);
15389       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
15390          PUT_CLID_MARKMS;
15391       }
15392       /* Put actual message */
15393       for (x = 0; text[x]; x++) {
15394          PUT_CLID(text[x]);
15395       }
15396       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
15397          PUT_CLID_MARKMS;
15398       }
15399       len = bytes;
15400       buf = mybuf;
15401    } else {
15402       len = tdd_generate(p->tdd, buf, text);
15403       if (len < 1) {
15404          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15405          ast_free(mybuf);
15406          return -1;
15407       }
15408    }
15409    memset(buf + len, 0x7f, END_SILENCE_LEN);
15410    len += END_SILENCE_LEN;
15411    fd = p->subs[idx].dfd;
15412    while (len) {
15413       if (ast_check_hangup(c)) {
15414          ast_free(mybuf);
15415          return -1;
15416       }
15417       size = len;
15418       if (size > READ_SIZE)
15419          size = READ_SIZE;
15420       fds[0].fd = fd;
15421       fds[0].events = POLLOUT | POLLPRI;
15422       fds[0].revents = 0;
15423       res = poll(fds, 1, -1);
15424       if (!res) {
15425          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15426          continue;
15427       }
15428         /* if got exception */
15429       if (fds[0].revents & POLLPRI) {
15430          ast_free(mybuf);
15431          return -1;
15432       }
15433       if (!(fds[0].revents & POLLOUT)) {
15434          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15435          continue;
15436       }
15437       res = write(fd, buf, size);
15438       if (res != size) {
15439          if (res == -1) {
15440             ast_free(mybuf);
15441             return -1;
15442          }
15443          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15444          break;
15445       }
15446       len -= size;
15447       buf += size;
15448    }
15449    ast_free(mybuf);
15450    return(0);
15451 }
15452 
15453 
15454 static int reload(void)
15455 {
15456    int res = 0;
15457 
15458    res = setup_dahdi(1);
15459    if (res) {
15460       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15461       return -1;
15462    }
15463    return 0;
15464 }
15465 
15466 /* This is a workaround so that menuselect displays a proper description
15467  * AST_MODULE_INFO(, , "DAHDI Telephony"
15468  */
15469 
15470 #ifdef HAVE_PRI
15471 #ifdef HAVE_SS7
15472 #define tdesc "DAHDI Telephony w/PRI & SS7"
15473 #else
15474 #define tdesc "DAHDI Telephony w/PRI"
15475 #endif
15476 #else
15477 #ifdef HAVE_SS7
15478 #define tdesc "DAHDI Telephony w/SS7"
15479 #else
15480 #define tdesc "DAHDI Telephony"
15481 #endif
15482 #endif
15483 
15484 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
15485       .load = load_module,
15486       .unload = unload_module,
15487       .reload = reload,
15488           );
15489 
15490 

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